24 game/Solve: Difference between revisions

m (→‎{{header|REXX}}: realigned statements.)
Line 5,188:
 
8 solutions
</pre>
 
=={{header|Picat}}==
<lang Picat>import util.
 
main =>
Target=24,
Nums = [5,6,7,8],
All=findall(Expr, solve_num(Nums,Target,Expr)),
foreach(Expr in All) println(Expr.flatten()) end,
println(len=All.length),
nl.
 
% A string based approach, inspired by - among others - the Perl6 solution.
solve_num(Nums, Target,Expr) =>
Patterns = [
"A X B Y C Z D",
"(A X B) Y C Z D",
"(A X B Y C) Z D",
"((A X B) Y C) Z D",
"(A X B) Y (C Z D)",
"A X (B Y C Z D)",
"A X (B Y (C Z D))"
],
permutation(Nums,[A,B,C,D]),
Syms = [+,-,*,/],
member(X ,Syms),
member(Y ,Syms),
member(Z ,Syms),
member(Pattern,Patterns),
Expr = replace_all(Pattern,
"ABCDXYZ",
[A,B,C,D,X,Y,Z]),
catch(Target =:= Expr.eval(), E, ignore(E)).
 
eval(Expr) = parse_term(Expr.flatten()).apply().
 
ignore(_E) => fail. % ignore zero_divisor errors
 
% Replace all occurrences in S with From -> To.
replace_all(S,From,To) = Res =>
R = S,
foreach({F,T} in zip(From,To))
R := replace(R, F,T.to_string())
end,
Res = R.
 
</lang>
 
Test:
 
<pre>
Picat> main
 
(5 + 7 - 8) * 6
((5 + 7) - 8) * 6
(5 + 7) * (8 - 6)
(5 - 8 + 7) * 6
((5 - 8) + 7) * 6
6 * (5 + 7 - 8)
6 * (5 + (7 - 8))
6 * (5 - 8 + 7)
6 * (5 - (8 - 7))
6 * (7 + 5 - 8)
6 * (7 + (5 - 8))
6 * (7 - 8 + 5)
6 * (7 - (8 - 5))
(6 * 8) / (7 - 5)
6 * (8 / (7 - 5))
(7 + 5 - 8) * 6
((7 + 5) - 8) * 6
(7 + 5) * (8 - 6)
(7 - 8 + 5) * 6
((7 - 8) + 5) * 6
(8 - 6) * (5 + 7)
(8 - 6) * (7 + 5)
(8 * 6) / (7 - 5)
8 * (6 / (7 - 5))
len = 24
 
</pre>
 
Another approach:
 
<lang Picat>import util.
 
main =>
Target=24,
Nums = [5,6,7,8],
_ = findall(Expr, solve_num2(Nums,Target)),
nl.
 
 
solve_num2(Nums, Target) =>
Syms = [+,-,*,/],
Perms = permutations([I.to_string() : I in Nums]),
Seen = new_map(), % weed out duplicates
foreach(X in Syms,Y in Syms, Z in Syms)
foreach(P in Perms)
[A,B,C,D] = P,
if catch(check(A,X,B,Y,C,Z,D,Target,Expr),E,ignore(E)),
not Seen.has_key(Expr) then
println(Expr.flatten()=Expr.eval().round()),
Seen.put(Expr,1)
end
end
end.
 
to_string2(Expr) = [E.to_string() : E in Expr].flatten().
 
ignore(_E) => fail. % ignore zero_divisor errors
 
check(A,X,B,Y,C,Z,D,Target,Expr) ?=>
Expr = ["(",A,Y,B,")",X,"(",C,Z,D,")"].to_string2(),
Target =:= Expr.eval().
 
check(A,X,B,Y,C,Z,D,Target,Expr) ?=>
Expr = [A,X,"(",B,Y,"(",C,Z,D,")",")"].to_string2(),
Target =:= Expr.eval().
 
check(A,X,B,Y,C,Z,D,Target,Expr) ?=>
Expr = ["(","(",C,Z,D,")",Y,B,")",X,A].to_string2(),
Target =:= Expr.eval().
 
check(A,X,B,Y,C,Z,D,Target,Expr) ?=>
Expr = ["(",B,Y,"(",C,Z,D,")",")",X,A].to_string2(),
Target =:= Expr.eval().
 
check(A,X,B,Y,C,Z,D,Target,Expr) =>
Expr = [A,X,"(","(",B,Y,C,")", Z,D,")"].to_string2(),
Target =:= Expr.eval().
</lang>
 
Test:
 
<pre>
> main
6*(5+(7-8)) = 24
6*(7+(5-8)) = 24
(5+7)*(8-6) = 24
(7+5)*(8-6) = 24
6*((7-8)+5) = 24
6*((5-8)+7) = 24
((5+7)-8)*6 = 24
((7+5)-8)*6 = 24
(8-6)*(5+7) = 24
(8-6)*(7+5) = 24
6*(7-(8-5)) = 24
6*(5-(8-7)) = 24
6*(8/(7-5)) = 24
8*(6/(7-5)) = 24
6/((7-5)/8) = 24
8/((7-5)/6) = 24
(6*8)/(7-5) = 24
(8*6)/(7-5) = 24
 
</pre>
 
495

edits