Last active
February 1, 2026 20:01
-
-
Save mietek/f81cc80d1dffc40f97738a3912480c99 to your computer and use it in GitHub Desktop.
solution to the clock tower puzzle in Blue Prince
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| % ------------------------------------------------------------------------------ | |
| % 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