/* Locker puzzle in Picat. http://www-lp.doc.ic.ac.uk/UserPages/staff/ft/alp/humour/num """ Appeared in Volume 8/4, November 1995 1. My locker combination is made up of three numbers. 2. The numbers on the dial range from 1-40. 3. The second number is twice the first. 4. The third number is ten more than the second. 5. The first number has one even digit and one odd digit. 6. The second number has either two odd or two even digits. 7. The total of all the different digits used in the combination is 10. (For example: 22/22/22 would total 2, and 18/28/12 would total 11.) First: What is the combination? Second: Is there any way to rewrite this puzzle with 6 or less rules, without the answer being obvious? """ - go/0: Answer the first question. - go2/0: Rewrites it in 5 rules. 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 ?=> Digits = 1..40, D1 :: Digits, AD1 = new_list(2), AD1 :: 0..9, D2 :: Digits, AD2 = new_list(2), AD2 :: 0..9, D3 :: Digits, AD3 = new_list(2), AD3 :: 0..9, A = new_list(6), A :: Digits, A = AD1 ++ AD2 ++ AD3, % which digits is used in a? ADigits = new_list(10), ADigits :: 0..9, UsedDigitsSum #> 0, to_num(AD1, 10, D1), to_num(AD2, 10, D2), to_num(AD3, 10, D3), % 3. The second number is twice the first. D2 #= 2 * D1, % 4. The third number is ten more than the second. D3 #= 10 + D2, % 5. The first number has one even digit and one odd digit. (AD1[1] mod 2) + (AD1[2] mod 2) #= 1, % 6. The second number has either two odd or two even digits. (AD2[1] mod 2) + (AD2[2] mod 2) #!= 1, % 7. The total of all the different digits used in the combination is 10. % I.e. the sum of the _unique_ numbers. % % Use the gcc to get the numbers used... foreach(D in 0..9) ADigits[D+1] #= sum([A[I] #= D : I in 1..6]) end, % ... and then sum those numbers. UsedDigitsSum #= sum([D * (ADigits[D+1] #> 0): D in 0..9]), UsedDigitsSum #= 10, Vars = A ++ AD1 ++ AD2 ++ AD3 ++ ADigits ++ [D1,D2,D3,UsedDigitsSum], solve(Vars), println([D1,D2,D3]), fail, nl. go => true. % % """ % Second: Is there any way to rewrite this puzzle with 6 or less rules, % without the answer being obvious? % """ % % Here is a formulation in 5 rules, i.e. we simply skip the rules 5 and 6. % % 1. My locker combination is made up of three numbers. % 2. The numbers on the dial range from 1-40. % 3. The second number is twice the first. % 4. The third number is ten more than the second. % ###5. The first number has one even digit and one odd digit. % ###6. The second number has either two odd or two even digits. % 7. The total of all the different digits used in the combination is % 10. % (For example: 22/22/22 would total 2, and 18/28/12 would total 11.) go2 ?=> Digits = 1..40, D1 :: Digits, AD1 = new_list(2), AD1 :: 0..9, D2 :: Digits, AD2 = new_list(2), AD2 :: 0..9, D3 :: Digits, AD3 = new_list(2), AD3 :: 0..9, A = new_list(6), A :: Digits, A = AD1 ++ AD2 ++ AD3, % which digits is used in a? ADigits = new_list(10), ADigits :: 0..9, UsedDigitsSum #> 0, to_num(AD1, 10, D1), to_num(AD2, 10, D2), to_num(AD3, 10, D3), % 3. The second number is twice the first. D2 #= 2 * D1, % 4. The third number is ten more than the second. D3 #= 10 + D2, % Rule 5 and 6 are skipped % % 5. The first number has one even digit and one odd digit. % (AD1[1] mod 2) + (AD1[2] mod 2) #= 1, % 6. The second number has either two odd or two even digits. % (AD2[1] mod 2) + (AD2[2] mod 2) #!= 1, % 7. The total of all the different digits used in the combination is 10. % I.e. the sum of the _unique_ numbers. % % Use the gcc to get the numbers used... foreach(D in 0..9) ADigits[D+1] #= sum([A[I] #= D : I in 1..6]) end, % ... and then sum those numbers. UsedDigitsSum #= sum([D * (ADigits[D+1] #> 0): D in 0..9]), UsedDigitsSum #= 10, Vars = A ++ AD1 ++ AD2 ++ AD3 ++ ADigits ++ [D1,D2,D3,UsedDigitsSum], solve(Vars), println([D1,D2,D3]), fail, nl. go2 => 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]).