I\'m trying to solve a constraint processing problem in prolog.
I need to pack 4 squares of 5x5,4x4,3x3 and 2x2 in a grid of 10x10. They may not overlap.
My
I coded in SWI-Prolog
/* File: pack_squares.lp
Author: Carlo,,,
Created: Nov 29 2012
Purpose: http://stackoverflow.com/questions/13623775/prolog-constraint-processing-packing-squares
*/
:- module(pack_squares, [pack_squares/0]).
:- [library(clpfd)].
pack_squares :-
maplist(square, [5,4,3,2], Squares),
flatten(Squares, Coords),
not_overlap(Squares),
Coords ins 1..10,
label(Coords),
maplist(writeln, Squares),
draw_squares(Squares).
draw_squares(Squares) :-
forall(between(1, 10, Y),
( forall(between(1, 10, X),
sumpts(X, Y, Squares, 0)),
nl
)).
sumpts(_, _, [], S) :- write(S).
sumpts(X, Y, [[X1,Y1, X2,Y2]|Qs], A) :-
( ( X >= X1, X =< X2, Y >= Y1, Y =< Y2 )
-> B is A+X2-X1+1
; B is A
),
sumpts(X, Y, Qs, B).
square(D, [X1,Y1, X2,Y2]) :-
X1 + D - 1 #= X2,
Y1 + D - 1 #= Y2.
not_overlap([_]).
not_overlap([A,B|L]) :-
not_overlap(A, [B|L]),
!, not_overlap([B|L]).
not_overlap(_, []).
not_overlap(Q, [R|Rs]) :-
not_overlap_c(Q, R),
not_overlap_c(R, Q),
not_overlap(Q, Rs).
not_overlap_c([X1,Y1, X2,Y2], Q) :-
not_inside(X1,Y1, Q),
not_inside(X1,Y2, Q),
not_inside(X2,Y1, Q),
not_inside(X2,Y2, Q).
not_inside(X,Y, [X1,Y1, X2,Y2]) :-
X #< X1 #\/ X #> X2 #\/ Y #< Y1 #\/ Y #> Y2.
here is the last lines displayed when running ?- aggregate_all(count,pack_squares,C)., notably C counts total placements
...
0002255555
0002255555
[6,6,10,10]
[7,2,10,5]
[4,3,6,5]
[5,1,6,2]
0000220000
0000224444
0003334444
0003334444
0003334444
0000055555
0000055555
0000055555
0000055555
0000055555
C = 169480.