/* N-Queens problem in Picat. Model created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import util. import cp. main => go. % % Note that $Q[I] is needed here. % queens3(N, Q) => Q=new_list(N), Q :: 1..N, all_different(Q), all_different([$Q[I]-I : I in 1..N]), all_different([$Q[I]+I : I in 1..N]), solve([ff],Q). queens3(N) => queens3_all(N, Solutions), % writeln(Solutions), writeln(len=Solutions.length). % generate all solutions via solve_all (don't work right now) queens3_all(N, Solutions) => Q=new_list(N), Q :: 1..N, all_different(Q), all_different([$Q[I]-I : I in 1..N]), all_different([$Q[I]+I : I in 1..N]), Solutions = solve_all([ff],Q). % This works: % Solutions = findall(Q, $solve($Q)). % Using all_distinct instead queens3b(N, Q) => Q=new_list(N), Q :: 1..N, all_distinct(Q), all_distinct([$Q[I]-I : I in 1..N]), all_distinct([$Q[I]+I : I in 1..N]), solve([ff],Q). % alternative approaches queens4(N, Q) => Q = new_list(N), Q :: 1..N, foreach(A in [-1,0,1]) all_different([$Q[I]+I*A : I in 1..N]) end, solve([ff],Q). % Decomposition of alldifferent all_different_me(L) => Len = length(L), foreach(I in 1..Len, J in I+1..Len) L[I] #!= L[J] end. % Using all_different_me (my decomposition) queens5(N, Q) => Q=new_list(N), Q :: 1..N, all_different_me(Q), all_different_me([$Q[I]-I : I in 1..N]), all_different_me([$Q[I]+I : I in 1..N]), solve([ff],Q). go => queens3(8,Q), writeln(Q), N2 = 12, queens3_all(8, Solutions), % writeln(Solutions), Len=Solutions.length, writef("N:%w %w solutions.\n%w\n", N2, Len, Solutions). go2 => garbage_collect(20000000), foreach(N in 2..14) statistics(backtracks, Backtracks), statistics(runtime, [_, _Runtime1]), queens3_all(N, Solutions), Len=Solutions.length, statistics(backtracks, Backtracks2), B = Backtracks2 - Backtracks, Backtracks := Backtracks2, statistics(runtime, [_, Runtime2]), writef("N:%3d %10d solutions (%d backtracks, %d millis)\n", N, Len, B, Runtime2) end. % % Times per Picat v 0.1-beta 10: % queens3 : 6.7s (2 backtracks) % queens3b: 10.83s (0 backtracks) % queens4 : 4.25s (2 backtracks) % queens5 : 6.86s (2 backtracks) % go3 => Ps = [queens3=1000, queens3b=1000, queens4=1000,queens5=1000], foreach(P=N in Ps) printf("%w(%d)\n", P, N), time2(once(call(P,N,Q))), writeln(Q), nl end. % Using permutations/1. Very slow. go4 => N = 8, C = 0, foreach(P in permutations(1..N)) if check4(P) then % writeln(P), C := C +1 end end, writeln(sols=C), nl. go5 => N=100, queens3(N,Q), writeln(Q), nl. % N=10000 probably exhaust the RAM... % go6 => % N = 10000, % println("timing queens4(10000,Q)"), % time2(queens4(N,_Q)), % nl. go7 => Ns = [8,10,50,100,400,500,700,1000,1500], foreach(N in Ns) println(n=N), time2(queens3(N,_)), nl end, nl. check4(P) => N = length(P), foreach(I in 1..N, J in I+1..N) P[I]-I != P[J]-J, P[I]+I != P[J]+J end.