|
That's a neat puzzle! Here is the Prolog code I posted earlier, extended and adapted to solve such tasks: First, let us again start with a suitable operator definition, so that we can use × as an infix operator in expressions: :- op(400, yfx, ×).
Next, let us declaratively describe what we mean by a "clock", using integer constraints: clock(Vs) :-
Vs = [H0,H1,M1,M2],
Vs ins 0..9,
H0*10 + H1 #< 24,
M1*10 + M2 #< 60,
label(Vs).
For example: ?- clock(Vs).
Vs = [0, 0, 0, 0] ;
Vs = [0, 0, 0, 1] ;
Vs = [0, 0, 0, 2] ;
Vs = [0, 0, 0, 3] .
We can collect all solutions as a quick verification: ?- findall(., clock(Vs), Ls), length(Ls, L).
Ls = ['.', '.', '.', '.', '.', '.', '.', '.', '.'|...],
L = 1440.
This confirms that there are 1440 puzzles of this kind, one for each possible clock time.The puzzle now asks for expressions that evaluate to 0. We can relate any given clock display to an expression like this: clock_solution(Vs, Expr) :-
clock(Vs),
numbers_tree(Vs, T),
tree_op_expr_value(T, _, Expr, 0).
This reuses predicates I posted earlier, which I only need to slightly modify to prohibit multiplication by zero, and which I repeat here for completeness: numbers_tree([N], leaf(N)).
numbers_tree(Vs0, binary(Left, Right)) :-
permutation(Vs0, Vs),
append([L|Ls], [R|Rs], Vs),
numbers_tree([L|Ls], Left),
numbers_tree([R|Rs], Right).
tree_op_expr_value(leaf(N), _, N, N).
tree_op_expr_value(binary(Left0, Right0), Op, Expr, Value) :-
tree_op_expr_value(Left0, _, Left, VL),
tree_op_expr_value(Right0, _, Right, VR),
op_values_value(Op, VL, VR, Value),
Expr =.. [Op,Left,Right].
op_values_value(+, A, B, V) :- V is A + B.
op_values_value(-, A, B, V) :- V is A - B.
op_values_value(×, A, B, V) :- A =\= 0, B =\= 0, V is A * B.
op_values_value(/, A, B, V) :- B =\= 0, V is A rdiv B.
We can use this to enumerate all times that have a solution: ?- clock(C),
once(clock_solution(C, S)).
C = [0, 0, 0, 0],
S = 0+(0+(0+0)) ;
C = [0, 0, 0, 1],
S = 0/(0+(0+1)) ;
C = [0, 0, 0, 2],
S = 0/(0+(0+2)) ;
C = [0, 0, 0, 3],
S = 0/(0+(0+3)) .
And here is the list of all times that don't have a solution: ?- clock(C),
\+ clock_solution(C, S).
C = [1, 6, 4, 8] ;
C = [1, 7, 4, 9] ;
C = [1, 7, 5, 9] ;
C = [1, 8, 4, 6] ;
C = [1, 9, 4, 7] ;
C = [1, 9, 5, 7] ;
false.
|