/* Unhelpful square (Enigma puzzle 1266) in Picat. https://enigmaticcode.wordpress.com/2015/01/03/enigma-1266-unhelpful-squares/ """ Here is a "cross-figure" for you to do, in which each answer is different: 1 2 X 3 _ X 4 _ _ X 5 _ X 6 _ Across: 1. A perfect square 2. A perfect square 3. A perfect square 4. A perfect square 5. A perfect square 6. A perfect square Down: 2. A perfect square 3. A perfect square The trouble with cross-figures like this is that there are already digits written in some of the boxes, and that can be confusing. But today whenever you put a digit in such a box it should be different from the digit that's already there. In fact, in half the cases it should be more than the digit already there, and in half the cases it should be less. """ Here is the unique solution: 2 5 X 1 6 X 7 8 4 X 3 6 X 4 9 This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. go ?=> % % Representation: % 1 2 3 4 5 % 6 7 8 9 10 % 11 12 13 14 15 % N = 3, M = 5, % the boxes for each number Boxes = { {1,2}, % 1 across {4,5}, % 3 across {7,8,9}, % 4 across {11,12}, % 5 across {14,15}, % 6 across {2,7,12}, % 2 down {4,9,14} % 3 down }, % position of the blanks Blanks = [3,6,10,13], % position of the digits (clue numbers) ClueNumbers = [1,2,4,7,11,14], NumBoxes = Boxes.len, PerfectSquares = [I*I : I in 4..31, I*I < 999], % decision variables X = new_array(N,M), % the matrix X :: 0..9, Y = new_list(N*M), % the digits Y :: 0..9, Nums = new_list(NumBoxes), % the numbers Nums :: PerfectSquares, % connect "x" (the matrix) and "y" (the digits) foreach(I in 1..N, J in 1..M) Y[(I-1)*M+J] #= X[I,J] end, % the numbers (answers) foreach(B in 1..NumBoxes) to_num([Y[D] : D in Boxes[B]],10,Nums[B]) end, all_different(Nums), % all answers should be distinct % set 0 for the blank cells foreach(B in Blanks) Y[B] #= 0 end, % % exactly 3 digits should be less and 3 greater than the clue number foreach(C in 1..ClueNumbers.len) Y[ClueNumbers[C]] #!= C end, sum([Y[ClueNumbers[C]] #< C : C in 1..ClueNumbers.len]) #= 3, Vars = X.vars ++ Y ++ Nums, solve(Vars), % println(x=X), foreach(I in 1..N) foreach(J in 1..M) if member((I-1)*M+J,Blanks) then print("X") else printf("%d",X[I,J]) end end, nl end, % println(y=Y), % println(nums=Nums), nl. go => true. % % converts a number Num to/from a list of integer List given a base Base % to_num(List, Base, Num) => Len = length(List), Num #= sum([List[I]*Base**(Len-I) : I in 1..Len]). to_num(List, Base) = Num => to_num(List,Base,Num).