# # SEND+MOST=MONEY optimization problem in Elixir. # # Alphametic problem were we maximize MONEY. # # This version is doing two things: # - find the maximum of MONEY # - and then find all solutions for the maximum value of MONEY. # # Problem from the lecture notes: # http://www.ict.kth.se/courses/ID2204/notes/L01.pdf # # There are two maximal solutions: # 9782 + 1094 = 10876 # 9784 + 1092 = 10876 # This program was created by Hakan Kjellerstrand, hakank@gmail.com # See also my Elixir page: http://www.hakank.org/elxir/ # ## Boris Okner: modified to sync with the latest API, ## change naming and result handling. ## defmodule CPSolver.Examples.Hakank.SendMostMoney do # import Hakank.CPUtils alias CPSolver.IntVariable alias CPSolver.Constraint.AllDifferent.FWC, as: AllDifferent alias CPSolver.Constraint.Sum # alias CPSolver.Constraint.LessOrEqual alias CPSolver.Constraint.NotEqual alias CPSolver.Constraint.Equal alias CPSolver.Model alias CPSolver.Objective import CPSolver.Constraint.Factory import CPSolver.Variable.View.Factory def run() do max_val = send_most_money() IO.puts("Found max_val: #{max_val}") send_most_money(max_val) end def send_most_money(max_val \\ nil) do n = 8 xs = for i <- 0..n-1 do IntVariable.new(0..9, name: "x[#{i}]") end [s,e,n,d,m,o,t,y] = xs {send_var,send_constraint} = sum([mul(s,1000),mul(e,100),mul(n,10),d]) {most_var,most_constraint} = sum([mul(m,1000),mul(o,100),mul(s,10),t]) # To maximize {money_var,money_constraint} = sum([mul(m,10_000),mul(o,1000),mul(n,100),mul(e,10),y]) max_val_constraint = max_val && Equal.new(money_var,max_val) || Equal.new(money_var,money_var) constraints = [send_constraint,most_constraint,money_constraint,max_val_constraint, AllDifferent.new(xs), Sum.new(money_var,[send_var,most_var]), # SEND+MOST = MONEY NotEqual.new(s,0),NotEqual.new(m,0) ] vars = xs++[money_var,send_var,most_var] model = max_val == nil && Model.new(vars, constraints,objective: Objective.maximize(money_var)) || Model.new(vars, constraints) Logger.configure(level: :info) opts = [ # search: {:first_fail, :indomain_min}, search: {:input_order, :indomain_min}, # search: {:first_fail, :indomain_random}, timeout: :infinity, # stop_on: {:max_solutions, 2}, ] {:ok, res} = CPSolver.solve(model, opts ) # IO.inspect(res.statistics) sols = if max_val == nil do [res.solutions |> List.last] else res.solutions end sols |> Enum.map(fn s -> money_val = Enum.at(s,8) send_val = Enum.at(s,9) most_val = Enum.at(s,10) :io.format("~w + ~w = ~w~n",[send_val,most_val,money_val]) end) if max_val == nil do Enum.at(sols |> hd,8) end end end