I tried to solve the polyomino 127 from Groza using exact cover problem (but not DEK algorithm).
Solution came in 13s, all 8 in 56s. No idea how to solve p's with holes.
import sat, util.
mainx => polyomino(127, _Vysl, 1).
main(Pol) =>
Polyomino = Pol[1].to_int(),
Results = findall(Results, polyomino(Polyomino, Results, 0)).sort().remove_dups(),
nl,
foreach ( Res in Results )
vypis(Res),
nl
end,
printf("Number of solutions: %d\n", Results.len()).
% gets the Tiles, Pr 0/1 if print or not
polyomino(Polident, Result, Pr) =>
once genmatrix(Polident, Numberoftiles, Boardheight, Boardwidth, Tlnumbers, Matr),
Mc = Matr.columns(),
Numberofcolumns = Mc.len(),
Indexes = [],
foreach ( T in 1..Numberoftiles )
element(Ind, Tlnumbers, T),
Indexes := [Ind|Indexes]
end,
Totvals = [],
foreach ( Col in 1..Numberofcolumns )
Vals = [],
foreach ( I in 1..Numberoftiles )
element( Indexes[I], Mc[Col], Val ),
Vals := [Val|Vals]
end,
Totvals := [Vals|Totvals],
sum(Vals) #= 1
end,
if Pr == 1 then println("Solving...") end,
% solve(Indexes), % slower
solve(Indexes ++ Totvals.vars()),
if Pr == 1 then println("Solved"), nl end,
once getresults(Matr, Indexes, Boardheight, Boardwidth, Numberoftiles, Result),
if ( Pr == 1 ) then
printf("Polyomino: %w Number of tiles: %d Size: %dx%d\n", Polident, Numberoftiles, Boardheight, Boardheight),
printf("Matrix dimension: %d x %d\n\n", Matr.len(), Numberofcolumns),
println("Lines selected from the matrix:"),nl,
foreach ( I in Indexes )
printf("%4d: %w\n", I, Matr[I])
end,
nl,
println("Result:"), nl,
vypis(Result),
nl
end.
% Matrix Result with different integers for each tile
getresults(Matr, Indexes, Rownum, Colnum, Numberoftiles, Result) =>
Result = new_array(Rownum, Colnum),
foreach ( Tileno in 1..Numberoftiles )
Line = Matr[Indexes[Tileno]],
foreach ( N in 1..Line.len() )
if ( Line[N] > 0 ) then
rowcol(N, Row, Col, Colnum),
Result[Row,Col] = Tileno
end
end
end.
rowcol(N, Row, Col, Boardwidth) => % ...
Row = 1 + floor(N / (Boardwidth+0.1)),
Col = N - floor(N / (Boardwidth+0.1) ) * Boardwidth.
% output
vypis(Result) =>
Rows = Result.len(),
Cols = Result[1].len(),
foreach ( Row in 1..Rows )
foreach ( Col in 1..Cols )
printf(" %2d", Result[Row,Col])
end,
nl
end,
nl.
% generates (big) matrix, lines are "flattened" tiles
genmatrix(Polyident, Numberoftiles, Boardheight, Boardwidth, Tlnumbers, Matrix) =>
polyomino(Polyident, Tilelist, Boardheight, Boardwidth, Numberoftiles, Rotations),
findtiles(Tilelist, Numberoftiles, Polytiles),
findmaxdim(Polytiles, Maxtiledim),
Matrixtmp = [],
Tlnumberstmp = [],
foreach ( I in 1..Numberoftiles )
Polytiles[I] = {Polynum, Polytile},
transftile(Polytile, Rotations[I], Boardheight, Boardwidth, Polytiletrans),
foreach ( Polytiletran in Polytiletrans )
Polyheight = Polytiletran.len(),
Polywidth = Polytiletran[1].len(),
foreach ( Rowstart in 0..Boardheight-Polyheight )
foreach ( Colstart in 0..Boardwidth-Polywidth )
flattenpol(Polytiletran, Polynum, Maxtiledim, Boardheight, Boardwidth, Rowstart, Colstart, Row),
Matrixtmp := [Row|Matrixtmp],
Tlnumberstmp := [Polynum|Tlnumberstmp]
end
end
end
end,
Tlnumbers = Tlnumberstmp.reverse(),
Matrix = Matrixtmp.reverse().
findtiles(Tilelist, Numberoftiles, Tiles) =>
Tiles = new_list(Numberoftiles),
foreach ( I in 1..Numberoftiles )
p(Tilelist[I], Tile),
Tiles[I] = {I,Tile}
end.
% generates instances of each tile: no rotate, rotate, rotate+flip
% removes duplicates and oversize tile variants
transftile(Polytile, norot, _, _, Poltiletrans) =>
Poltiletrans = [Polytile].
transftile(Polytile, rot, Boardheight, Boardwidth, Poltiletrans) =>
rotate90(Polytile, Polytile90),
rotate180(Polytile, Polytile180),
rotate270(Polytile, Polytile270),
Dtmp = [ Polytile, Polytile90, Polytile180, Polytile270 ].remove_dups(),
Poltiletrans = [ X : X in Dtmp, X.len() <= Boardheight, X[1].len() <= Boardwidth ].
transftile(Polytile, rotfl, Boardheight, Boardwidth, Poltiletrans) =>
rotate90(Polytile, Polytile90),
rotate180(Polytile, Polytile180),
rotate270(Polytile, Polytile270),
horizontal_flip(Polytile, Polytilefliph),
rotate90(Polytilefliph, Polytilefliph90),
rotate180(Polytilefliph, Polytilefliph180),
rotate270(Polytilefliph, Polytilefliph270),
Dtmp = [ Polytile, Polytile90, Polytile180, Polytile270, Polytilefliph, Polytilefliph90, Polytilefliph180, Polytilefliph270 ].remove_dups(),
Poltiletrans = [ X : X in Dtmp, X.len() <= Boardheight, X[1].len() <= Boardwidth ].
findmaxdim(Tiles, Maxtiledim) =>
findmaxdim(Tiles, 0, Maxtiledim).
findmaxdim([{_,Polytile}|Polytiles], Tmp, Maxtiledim) ?=>
Tmp1 = max( [Polytile.len(), Polytile[1].len(), Tmp]),
findmaxdim(Polytiles, Tmp1, Maxtiledim).
findmaxdim([], Tmp, Maxtiledim) =>
Maxtiledim = Tmp.
% flattens the tile, background zero
flattenpol(Polytile, Polynum, Maxtiledim, Boardheight, Boardwidth, Rowstart, Colstart, Row) =>
Polyheight = Polytile.len(),
Polywidth = Polytile[1].len(),
Row = new_list(Boardheight*Boardwidth),
Row :: [0,1],
foreach ( R in 1..Polyheight )
foreach ( C in 1..Polywidth )
if ( Polytile[R,C] > 0 ) then
Row[(R-1)*Boardwidth + Rowstart*Boardwidth + C + Colstart] = 1
end
end
end,
foreach ( I in 1..Row.len() )
( Row[I] = 0 ; true )
end.
% stolen from / inspired by:
http://hakank.org/picat/rectangle_symmetries.pi% Rotate 90 degrees
rotate90(Shape, Rotated) =>
transpose(Shape, Transposed),
reverse_each_row(Transposed, Rotated).
% Rotate 180 degrees
rotate180(Shape, Rotated) =>
rotate90(Shape, Tmp),
rotate90(Tmp, Rotated).
% Rotate 270 degrees
rotate270(Shape, Rotated) =>
rotate90(Shape, Tmp1),
rotate90(Tmp1, Tmp2),
rotate90(Tmp2, Rotated).
% Horizontal Flip
horizontal_flip(Shape, Flipped) =>
reverse(Shape, Flipped).
% Helper function to reverse each row
reverse_each_row([], []).
reverse_each_row([Row|Rows], [ReversedRow|ReversedRows]) :-
reverse(Row, ReversedRow),
reverse_each_row(Rows, ReversedRows).
transpose(Matrix,Transposed) =>
Transposed = [[Matrix[J,I] : J in 1..Matrix.len] : I in 1..Matrix[1].len].
reverse(L, Rev) =>
Rev = reverse(L).
% --------< DATA >--------------------------
polyomino(122, Tilelist, Rownum, Colnum, Tilesnum, Rotations) =>
Tilelist = [ i3, l2, i2, dot ],
Rownum = 3,
Colnum = 3,
Tilesnum = Tilelist.len(),
Rotations = [norot,norot,norot,norot].
polyomino(123, Tilelist, Rownum, Colnum, Tilesnum, Rotations) =>
Tilelist = [ i3, l2, i2, dot ],
Rownum = 3,
Colnum = 3,
Tilesnum = Tilelist.len(),
Rotations = [rot,rot,rot,rot].
polyomino(124, Tilelist, Rownum, Colnum, Tilesnum, Rotations) =>
Tilelist = [ u, dot, zi, i3, li3, zf, ti, tis, dash2, li2 ],
Rownum = 6,
Colnum = 6,
Tilesnum = Tilelist.len(),
Rotations = [norot,norot,norot,rot,norot,norot,norot,norot,rot,rot].
polyomino(125, Tilelist, Rownum, Colnum, Tilesnum, Rotations) =>
Tilelist = [ u, dot, zi, i3, li3, zf, ti, tis, dash2, li2 ],
Rownum = 6,
Colnum = 6,
Tilesnum = Tilelist.len(),
Rotations = [norot,norot,norot,norot,norot,norot,norot,norot,norot,norot].
polyomino(126, Tilelist, Rownum, Colnum, Tilesnum, Rotations) =>
Tilelist = [ l, pi, yi, w ],
Rownum = 4,
Colnum = 5,
Tilesnum = Tilelist.len(),
Rotations = [rot,rot,rot,rot].
polyomino(127, Tilelist, Rownum, Colnum, Tilesnum, Rotations) =>
Tilelist = [ t, u, w, v, x, yi, z, f, i5, l, pi, n ],
Rownum = 3,
Colnum = 20,
Tilesnum = Tilelist.len(),
Rotations = [rotfl,rotfl,rotfl,rotfl,rotfl,rotfl,rotfl,rotfl,rotfl,rotfl,rotfl,rotfl].
polyomino(128, Tilelist, Rownum, Colnum, Tilesnum, Rotations) =>
Tilelist = [ t, w, yi, z, i5, l ],
Rownum = 5,
Colnum = 6,
Tilesnum = Tilelist.len(),
Rotations = [rotfl,rotfl,rotfl,rotfl,rotfl,rotfl].
polyomino(129, Tilelist, Rownum, Colnum, Tilesnum, Rotations) =>
Tilelist = [ u, v, x, f, pi, n ],
Rownum = 5,
Colnum = 6,
Tilesnum = Tilelist.len(),
Rotations = [rotfl,rotfl,rotfl,rotfl,rotfl,rotfl].
p(i3, [[1],
[1],
[1]]).
p(l2, [[1,0],
[1,1]]).
p(i2, [[1],
[1]]).
p(dot, [[1]]).
p(u, [[1,0,1],
[1,1,1]]).
p(zi, [[0,1,1],
[0,1,0],
[1,1,0]]).
p(li3, [[1,1],
[1,0],
[1,0]]).
p(zf, [[1,1,0],
[0,1,1]]).
p(ti, [[0,1,0],
[0,1,0],
[1,1,1]]).
p(tis, [[0,1,0],
[1,1,1]]).
p(dash2, [[1,1]]).
p(li2, [[10,10],
[0,10]]).
p(l, [[1,0],
[1,0],
[1,0],
[1,1]]).
p(pi, [[0,1],
[1,1],
[1,1]]).
p(yi, [[0,1],
[1,1],
[0,1],
[0,1]]).
p(w, [[1,0,0],
[1,1,0],
[0,1,1]]).
p(t, [[1,1,1],
[0,1,0],
[0,1,0]]).
p(v, [[1,0,0],
[1,0,0],
[1,1,1]]).
p(x, [[0,1,0],
[1,1,1],
[0,1,0]]).
p(z, [[1,1,0],
[0,1,0],
[0,1,1]]).
p(f, [[0,1,1],
[1,1,0],
[0,1,0]]).
p(i5, [[1],
[1],
[1],
[1],
[1]]).
p(n, [[0,1],
[0,1],
[1,1],
[1,0]]).
p(zero22, [[1,1],
[1,1]]).