Pentomino tiling: Difference between revisions

Content added Content deleted
m (→‎{{header|Wren}}: Minor tidy)
 
Line 1,068: Line 1,068:
U X U W Y T T T
U X U W Y T T T
U U U Y Y Y Y T </pre>
U U U Y Y Y Y T </pre>

=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''

'''Works with jq, the C implementation of jq'''

'''Works with gojq, the Go implementation of jq'''

The following solution takes advantage of jq's support for backtracking.
This means, for example, that there is no need for `removeOrientation`.

Since jq does not currently have a built-in PRNG,
/dev/random is used as a source of entropy. An invocation
of jq along the lines of the following would therefore be appropriate
in a typical command-line environment:
<pre>
< /dev/random tr -cd '0-9' | fold -w 1 | jq -cnr -f pentomino.jq
</pre>
where "pentomino.jq" is the name of a file containing the following jq program.
<syntaxhighlight lang="jq">
# Output: a PRN in range(0; .)
def prn:
if . == 1 then 0
else . as $n
| (($n-1)|tostring|length) as $w
| [limit($w; inputs)] | join("") | tonumber
| if . < $n then . else ($n | prn) end
end;

### Generic functions

def array($n): . as $in | [range(0;$n)|$in];

def array_swap($i; $j):
if $i < $j then array_swap($j;$i)
elif $i == $j then .
else .[$i] as $t | .[:$j] + [$t] + .[$j:$i] + .[$i + 1:]
end ;

### Pentominos

def F: [
[1, -1, 1, 0, 1, 1, 2, 1], [0, 1, 1, -1, 1, 0, 2, 0],
[1, 0, 1, 1, 1, 2, 2, 1], [1, 0, 1, 1, 2, -1, 2, 0],
[1, -2, 1, -1, 1, 0, 2, -1], [0, 1, 1, 1, 1, 2, 2, 1],
[1, -1, 1, 0, 1, 1, 2, -1], [1, -1, 1, 0, 2, 0, 2, 1]
];

def I: [
[0, 1, 0, 2, 0, 3, 0, 4], [1, 0, 2, 0, 3, 0, 4, 0]
];

def L: [
[1, 0, 1, 1, 1, 2, 1, 3], [1, 0, 2, 0, 3, -1, 3, 0],
[0, 1, 0, 2, 0, 3, 1, 3], [0, 1, 1, 0, 2, 0, 3, 0],
[0, 1, 1, 1, 2, 1, 3, 1], [0, 1, 0, 2, 0, 3, 1, 0],
[1, 0, 2, 0, 3, 0, 3, 1], [1, -3, 1, -2, 1, -1, 1, 0]
];

def N: [
[0, 1, 1, -2, 1, -1, 1, 0], [1, 0, 1, 1, 2, 1, 3, 1],
[0, 1, 0, 2, 1, -1, 1, 0], [1, 0, 2, 0, 2, 1, 3, 1],
[0, 1, 1, 1, 1, 2, 1, 3], [1, 0, 2, -1, 2, 0, 3, -1],
[0, 1, 0, 2, 1, 2, 1, 3], [1, -1, 1, 0, 2, -1, 3, -1]
];

def P: [
[0, 1, 1, 0, 1, 1, 2, 1], [0, 1, 0, 2, 1, 0, 1, 1],
[1, 0, 1, 1, 2, 0, 2, 1], [0, 1, 1, -1, 1, 0, 1, 1],
[0, 1, 1, 0, 1, 1, 1, 2], [1, -1, 1, 0, 2, -1, 2, 0],
[0, 1, 0, 2, 1, 1, 1, 2], [0, 1, 1, 0, 1, 1, 2, 0]
];

def T: [
[0, 1, 0, 2, 1, 1, 2, 1], [1, -2, 1, -1, 1, 0, 2, 0],
[1, 0, 2, -1, 2, 0, 2, 1], [1, 0, 1, 1, 1, 2, 2, 0]
];

def U: [
[0, 1, 0, 2, 1, 0, 1, 2], [0, 1, 1, 1, 2, 0, 2, 1],
[0, 2, 1, 0, 1, 1, 1, 2], [0, 1, 1, 0, 2, 0, 2, 1]
];

def V: [
[1, 0, 2, 0, 2, 1, 2, 2], [0, 1, 0, 2, 1, 0, 2, 0],
[1, 0, 2, -2, 2, -1, 2, 0], [0, 1, 0, 2, 1, 2, 2, 2]
];

def W: [
[1, 0, 1, 1, 2, 1, 2, 2], [1, -1, 1, 0, 2, -2, 2, -1],
[0, 1, 1, 1, 1, 2, 2, 2], [0, 1, 1, -1, 1, 0, 2, -1]
];

def X: [[1, -1, 1, 0, 1, 1, 2, 0]];

def Y: [
[1, -2, 1, -1, 1, 0, 1, 1], [1, -1, 1, 0, 2, 0, 3, 0],
[0, 1, 0, 2, 0, 3, 1, 1], [1, 0, 2, 0, 2, 1, 3, 0],
[0, 1, 0, 2, 0, 3, 1, 2], [1, 0, 1, 1, 2, 0, 3, 0],
[1, -1, 1, 0, 1, 1, 1, 2], [1, 0, 2, -1, 2, 0, 3, 0]
];

def Z: [
[0, 1, 1, 0, 2, -1, 2, 0], [1, 0, 1, 1, 1, 2, 2, 2],
[0, 1, 1, 1, 2, 1, 2, 2], [1, -2, 1, -1, 1, 0, 2, -2]
];

def shapes: [F, I, L, N, P, T, U, V, W, X, Y, Z];

def symbols: "FILNPTUVWXYZ-" | split("");

def nRows: 8;
def nCols: 8;
def blank: 12;

def printResult:
.symbols as $symbols
| .grid[] as $row
| reduce $row[] as $i (""; . + $symbols[$i]);

# Input: {grid}
def placeOrientation($o; $r; $c; $shapeIndex):
.grid[$r][$c] = $shapeIndex
| reduce range(0; $o|length; 2) as $io (.;
.grid[$r + $o[$io]][$c + $o[$io + 1]] = $shapeIndex);

# Input and output: {grid}
# If the placement is feasible, call placeOrientation/3
def tryPlaceOrientation($o; $r; $c; $shapeIndex):
.grid as $grid
| if any( range(0; $o|length; 2);
. as $io
| ($c + $o[$io + 1]) as $x
| ($r + $o[$io] ) as $y
| $x < 0 or $x >= nCols or $y < 0 or $y >= nRows or $grid[$y][$x] != -1 )
then empty
else placeOrientation($o; $r; $c; $shapeIndex)
end
;

# Input: {grid, placed, shapes}
def solve($pos; $numPlaced):
if $numPlaced == (.shapes|length)
then .
else (($pos / nCols)|floor) as $row
| ($pos % nCols ) as $col
| if .grid[$row][$col] != -1
then solve($pos + 1; $numPlaced)
else .emit = false
| foreach range(0; .shapes|length) as $i (.;
if .placed[$i] then .
else foreach .shapes[$i][] as $orientation (.;
(tryPlaceOrientation($orientation; $row; $col; $i)
| .placed[$i] = true
| solve($pos + 1; $numPlaced + 1)
| .emit = true)
// .)
end )
| select(.emit)
end
end;

# input: {shapes, symbols}
def shuffleShapes:
(.shapes|length) as $n
| reduce range(0; $n) as $i (.;
($n | prn) as $r
| .shapes |= array_swap($r; $i)
| .symbols |= array_swap($r; $i) )
;

def task:
def grid:
0 | array(nCols) | array(nRows);
def placed:
false | array(symbols|length - 1);

{ shapes: shapes,
symbols: symbols,
grid: grid,
placed: placed}
| shuffleShapes
| reduce range(0; nRows) as $r (.;
reduce range(0; .grid[$r]|length) as $c (.;
.grid[$r][$c] = -1))
| reduce range(0; 4) as $i (.;
.done = false
| until(.done;
.randRow = (nRows | prn)
| .randCol = (nCols | prn)
| .done = (.grid[.randRow][.randCol] != blank) )
| .grid[.randRow][.randCol] = blank
)
| first(solve(0; 0))
| printResult
// "No solution"
;
task
</syntaxhighlight>
{{output}}
<pre>
TTTPPUUU
VTPPPUXU
VTZZWXXX
VVVZWWXL
YF-ZZWWL
YFFF-NNL
YYFNNNLL
YIIIII--
</pre>


=={{header|Julia}}==
=={{header|Julia}}==