include "cumulative.mzn";
include "diffn.mzn";

int: n;
int: max_size;
array[1..n-1] of var 1..max_size: x;
array[1..n-1] of var 1..max_size: y;
var 0..max_size: w;
var 0..max_size: h;
var 0..max_size * max_size: area;

constraint diffn(x, y, [i+1 | i in 1..n-1], [i+1 | i in 1..n-1]);
constraint cumulative(x, [i+1 | i in 1..n-1], [i+1 | i in 1..n-1], h);
constraint cumulative(y, [i+1 | i in 1..n-1], [i+1 | i in 1..n-1], w);

constraint forall(i in 1..n-1) (x[i] <= w - i /\ y[i] <= h - i);
constraint w * h = area;
constraint sum([(i+1)*(i+1) | i in 1..n-1]) < area;
constraint x[n-1] <= (w - n + 2) div 2;
constraint y[n-1] <= (h + 1) div 2;
constraint w <= h;
constraint w >= 2 * n - 1 \/ h >= (n * n + n - ((w + 1) div 2 - 1) * ((w + 1) div 2 - 1) - ((w + 1) div 2 - 1)) div 2;

solve :: seq_search([
      int_search([area, w], input_order, indomain_min, complete),
      int_search([x[n-i] | i in 1..n-1] ++ [y[n-i] | i in 1..n-1],
                 input_order, indomain_split, complete)
   ]) satisfy;

output
   ["%Solution found: " ++ show(w) ++ "x" ++ show(h) ++ "(=" ++ show(area) ++ ")\n"]
   ++ ["\\draw (0, 0) rectangle (" ++ show(w) ++ ", " ++ show(h) ++ ");\n"]
   ++ ["\\draw (" ++ show(x[i]) ++ ", " ++ show(y[i]) ++ ") rectangle ++(" ++ show(i+1) ++ ", " ++ show(i+1) ++ ") ++(" ++ show(-int2float(i+1)/2.0) ++ ", " ++ show(-int2float(i+1)/2.0) ++ ") node {" ++ show(i+1) ++ "};\n" | i in 1..n-1];

n = 15;
max_size = 80;