/* Sum 3 puzzle in Picat. From or-tools-discuss (2020-05-06, by Reza Kakooee) """ I am trying to solve a puzzle and in one part of the puzzle I need to solve the following problem: We have 5 numbers, let's say -1, 0, 1, 2, 3. We want to put them in a list such that all elements of list are different, and the sum of elements between -1 and 0 must be 3. This is one possible solution, where 1+2=3 -1, 1, 2, 0, 3 This is another solution: 2, 0, 3, -1, 1 And this is a wrong solution: 1, -1, 2, 0, 3 """ 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 ?=> L = [-1, 0, 1, 2, 3], puzzle(L, 3, X), show_sol(X), fail, nl. go => true. go2 => _ = random2(), foreach(N in 3..100) println(n=N), L = -1..N, % S = 1+random() mod 2*N, S = N*2, puzzle(L,S,X), show_sol(X), nl end, nl. show_sol(X) => println(x=X), nth(MinusOnePos,X,-1), nth(ZeroPos,X,0), println("-1 pos"=MinusOnePos), println(" 0 pos"=ZeroPos), if MinusOnePos < ZeroPos then println(ss=X[MinusOnePos+1..ZeroPos-1]) else println(ss=X[ZeroPos+1..MinusOnePos-1]) end, nl. puzzle(L,S, X) => println(l=L), println(s=S), Len = L.len, X = new_list(Len), X :: min(L)..max(L), all_different(X), % Find the positions of -1 and 0 element(MinusOnePos,X,-1), element(ZeroPos,X,0), % Ensure that the numbers between 0 and -1 sums to S % MinusOnePos #> ZeroPos #=> sum([(I #> ZeroPos #/\ I #< MinusOnePos)*X[I] : I in 1..Len ]) #= S, % ZeroPos #> MinusOnePos #=> sum([(I #> MinusOnePos #/\ I #< ZeroPos)*X[I] : I in 1..Len ]) #= S, % This is slightly faster sum([(I #> ZeroPos #/\ I #< MinusOnePos)*X[I] : I in 1..Len ]) #= S #\/ sum([(I #> MinusOnePos #/\ I #< ZeroPos)*X[I] : I in 1..Len ]) #= S, Vars = X ++ [MinusOnePos,ZeroPos], solve($[ffd],Vars).