Skip to content

Instantly share code, notes, and snippets.

@mietek
Last active February 1, 2026 20:01
Show Gist options
  • Select an option

  • Save mietek/f81cc80d1dffc40f97738a3912480c99 to your computer and use it in GitHub Desktop.

Select an option

Save mietek/f81cc80d1dffc40f97738a3912480c99 to your computer and use it in GitHub Desktop.
solution to the clock tower puzzle in Blue Prince
% ------------------------------------------------------------------------------
% solution to the clock tower puzzle in Blue Prince
% tested with SWI-Prolog 10.0
% NOTE: in Prolog X-Y denotes the pair (X,Y)
:- use_module(library(clpfd)).
% ------------------------------------------------------------------------------
% rule 1.
% each clock is set to a different time
% NOTE: subsumed by rule 8
rule1(Ts) :-
pairwise(Ts,different).
pairwise([],_).
pairwise([X|Xs],R) :-
maplist(call(R,X),Xs),
pairwise(Xs,R).
different(Hx-Mx,Hy-My) :-
(Hx #\= Hy) #\/ (Hx #= Hy #/\ Mx #\= My).
% ------------------------------------------------------------------------------
% rule 2.
% five clocks are set to a time that ends in :00
rule2(Ts) :-
pairs_values(Ts,Ms),
% NOTE: we must list all the other values even though we do not care
global_cardinality(Ms, [0-5,
5-_,6-_,7-_,8-_,9-_,55-_,56-_,57-_,58-_,59-_]).
% ------------------------------------------------------------------------------
% rule 3.
% unclear
rule3(_).
% ------------------------------------------------------------------------------
% rule 4.
% the third and fifth clocks are set to a time that contains the digit 7
% NOTE: partially subsumed by rule 5
rule4(Ts) :-
nth1(3,Ts,T3),
nth1(5,Ts,T5),
has7(T3),
has7(T5).
has7(H-M) :-
H #= 7 #\/ M #= 7 #\/ M #= 57.
% ------------------------------------------------------------------------------
% rule 5.
% the fifth clock is set to 7:00
rule5(Ts) :-
nth1(5,Ts,7-0).
% ------------------------------------------------------------------------------
% rule 6.
% a valid time does not contain any of the digits 1,2,3,4
rule6(Ts) :-
maplist(time,Ts).
time(H-M) :-
hour(H),
minute(M).
hour(H) :-
H in 5..9.
minute(M) :-
M in 0\/5..9\/55..59.
% ------------------------------------------------------------------------------
% rule 7.
% the seventh clock is set to a time that is the reverse of the time to which
% some other clock is set
rule7(Ts) :-
X in 1..6\/8,
nth1(7,Ts,T7),
nth1(X,Ts,Tx),
flip(T7,Tx).
% TODO: how to say this in a compact way without generating duplicate solutions?
flip(5-5,5-5).
flip(5-6,6-5).
flip(5-7,7-5).
flip(5-8,8-5).
flip(5-9,9-5).
flip(5-55,5-55).
flip(5-56,6-55).
flip(5-57,7-55).
flip(5-58,8-55).
flip(5-59,9-55).
flip(6-5,5-6).
flip(6-6,6-6).
flip(6-7,7-6).
flip(6-8,8-6).
flip(6-9,9-6).
flip(6-55,5-56).
flip(6-56,6-56).
flip(6-57,7-56).
flip(6-58,8-56).
flip(6-59,9-56).
flip(7-5,5-7).
flip(7-6,6-7).
flip(7-7,7-7).
flip(7-8,8-7).
flip(7-9,9-7).
flip(7-55,5-57).
flip(7-56,6-57).
flip(7-57,7-57).
flip(7-58,8-57).
flip(7-59,9-57).
flip(8-5,5-8).
flip(8-6,6-8).
flip(8-7,7-8).
flip(8-8,8-8).
flip(8-9,9-8).
flip(8-55,5-58).
flip(8-56,6-58).
flip(8-57,7-58).
flip(8-58,8-58).
flip(8-59,9-58).
flip(9-5,5-9).
flip(9-6,6-9).
flip(9-7,7-9).
flip(9-8,8-9).
flip(9-9,9-9).
flip(9-55,5-59).
flip(9-56,6-59).
flip(9-57,7-59).
flip(9-58,8-59).
flip(9-59,9-59).
% ------------------------------------------------------------------------------
% rule 8.
% the clocks are set to times given in ascending order
rule8(Ts) :-
ordered(Ts,ascending).
ordered([],_).
ordered([_],_).
ordered([X1,X2|Xs],R) :-
call(R,X1,X2),
ordered([X2|Xs],R).
ascending(Hx-Mx,Hy-My) :-
(Hx #< Hy) #\/ (Hx #= Hy #/\ Mx #< My).
% ------------------------------------------------------------------------------
% solutions
% - 5:00 5:08 5:57 6:00 7:00 8:00 8:05 9:00
% - 5:00 6:00 6:07 6:08 7:00 8:00 8:06 9:00
% - 5:00 6:00 6:07 6:58 7:00 8:00 8:56 9:00
% - 5:00 6:00 6:57 6:58 7:00 8:00 8:56 9:00
solve(Ts) :-
rules(Ts),
pairs_keys_values(Ts,Hs,Ms),
append(Hs,Ms,Vs),
label(Vs).
rules(Ts) :-
length(Ts,8),
rule1(Ts),
rule2(Ts),
rule3(Ts),
rule4(Ts),
rule5(Ts),
rule6(Ts),
rule7(Ts),
rule8(Ts).
% NOTE: future Prolog will be able to use QUADs for unit tests
% https://git.liminal.cafe/byakuren/flowlog/src/branch/main/docs/QUAD_TESTS.md
% ?- solve(Ts).
% Ts = [5-0, 5-8, 5-57, 6-0, 7-0, 8-0, 8-5, 9-0];
% Ts = [5-0, 6-0, 6-7, 6-8, 7-0, 8-0, 8-6, 9-0];
% Ts = [5-0, 6-0, 6-7, 6-58, 7-0, 8-0, 8-56, 9-0];
% Ts = [5-0, 6-0, 6-57, 6-58, 7-0, 8-0, 8-56, 9-0].
% ------------------------------------------------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment