/* Tantalizer 45: Logic by numbers in Picat. From https://enigmaticcode.wordpress.com/2024/07/24/tantalizer-45-logic-by-numbers/ """ From New Scientist #594, 25th April 1968 [https://enigmaticcode.wordpress.com/wp-content/uploads/2024/07/tantalizer-45-original.jpg] "Yes, of course I can tell you my telephone number", said Barbara Bocardo, the well-known lady logician, "but I'm sure you'd rather I made a puzzle of it". So saying, she wrote down: 03962 18391 24751 31825 49700 52025 68477 73660 87063 96034 "Now", she went on mercilessly, "each of those numbers contains exactly one of the digits of my phone number in its correct position. Thus, as far as the first on the list goes, my number might be 00000 or 02693 but not 03456. Perhaps you would like to give me a ring this evening?" Perhaps. At what number? A version of this puzzle also appears in the book Tantalizers (1970). """ Solution: [9,8,7,6,5] This program was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import util. import cp. import utils_me. % http://hakank.org/picat/utils_me.pi for all_comb/2 in go3/ main => go. /* [9,8,7,6,5] CPU time 0.002 seconds. Backtracks: 743 */ go ?=> Numbers = numbers(), N = Numbers.first.len, X = new_list(N), X :: 0..9, foreach(Number in Numbers) Ds = Number.map(to_int), sum([X[I] #= Ds[I] : I in 1..N]) #= 1 end, solve(X), println(X), fail, nl. go => true. /* Non-cp: Using non-det member/2. A little slower: [9,8,7,6,5] CPU time 0.051 seconds. Backtracks: 0 */ go2 ?=> Numbers = numbers().map(string_to_digits), N = 5, X = new_list(N), foreach(I in 1..N) member(X[I],0..9) end, foreach(Number in Numbers) sum([1 : I in 1..N,X[I] == Number[I]]) == 1 end, println(X), fail, nl. go2 => true. /* Another non-cp approach: Using member/2, permutations/1 and all_comb/2 (from utils_me.pi) [9,8,7,6,5] CPU time 0.02 seconds. Backtracks: 0 */ go3 ?=> Numbers = numbers().map(string_to_digits), N = 5, member(C,all_comb(N,0..9)), % all_comb/2 is available in http://hakank.org/picat/utils_me.pi member(P, permutations(C)), foreach(Number in Numbers) sum([1 : I in 1..N, Number[I] == P[I]]) == 1 end, println(P), fail, nl. go3 => true. string_to_digits(S) = S.map(to_int). numbers() = ["03962", "18391", "24751", "31825", "49700", "52025", "68477", "73660", "87063", "96034"].