Task: Pentomino tiling







Python: from itertools import product

minos = (((197123, 7, 6), (1797, 6, 7), (1287, 6, 7), (196867, 7, 6)),
        ((263937, 6, 6), (197126, 6, 6), (393731, 6, 6), (67332, 6, 6)),
        ((16843011, 7, 5), (2063, 5, 7), (3841, 5, 7), (271, 5, 7), (3848, 5, 7), (50463234, 7, 5), (50397441, 7, 5), (33686019, 7, 5)),
        ((131843, 7, 6), (1798, 6, 7), (775, 6, 7), (1795, 6, 7), (1543, 6, 7), (197377, 7, 6), (197378, 7, 6), (66307, 7, 6)),
        ((132865, 6, 6), (131846, 6, 6), (198146, 6, 6), (132611, 6, 6), (393986, 6, 6), (263938, 6, 6), (67330, 6, 6), (132868, 6, 6)),
        ((1039, 5, 7), (33751554, 7, 5), (16843521, 7, 5), (16974081, 7, 5), (33686274, 7, 5), (3842, 5, 7), (3844, 5, 7), (527, 5, 7)),
        ((1804, 5, 7), (33751297, 7, 5), (33686273, 7, 5), (16974338, 7, 5), (16843522, 7, 5), (782, 5, 7), (3079, 5, 7), (3587, 5, 7)),
        ((263683, 6, 6), (198148, 6, 6), (66310, 6, 6), (393985, 6, 6)),
        ((67329, 6, 6), (131591, 6, 6), (459266, 6, 6), (263940, 6, 6)),
        ((459780, 6, 6), (459009, 6, 6), (263175, 6, 6), (65799, 6, 6)),
        ((4311810305, 8, 4), (31, 4, 8)),
        ((132866, 6, 6),))

boxchar_double_width = ' ╶╺╵└┕╹┖┗╴─╼┘┴┶┚┸┺╸╾━┙┵┷┛┹┻╷┌┍│├┝╿┞┡┐┬┮┤┼┾┦╀╄┑┭┯┥┽┿┩╃╇╻┎┏╽┟┢┃┠┣┒┰┲┧╁╆┨╂╊┓┱┳┪╅╈┫╉╋'
boxchar_single_width = [c + ' ─━'[i%3] for i, c in enumerate(boxchar_double_width)]


patterns = boxchar_single_width

tiles = []
for row in reversed(minos):
    tiles.append([])
    for n, x, y in row:
        for shift in (b*8 + a for a, b in product(range(x), range(y))):
            tiles[-1].append(n << shift)

def img(seq):
    b = [[0]*10 for _ in range(10)]

    for i, s in enumerate(seq):
        for j, k in product(range(8), range(8)):
            if s & (1<<(j*8 + k)):
                b[j + 1][k + 1] = i + 1

    idices = [[0]*9 for _ in range(9)]
    for i, j in product(range(9), range(9)):
        n = (b[i+1][j+1], b[i][j+1], b[i][j], b[i+1][j], b[i+1][j+1])
        idices[i][j] = sum((a != b)*(1 + (not a or not b))*3**i for i, (a,b) in enumerate(zip(n, n[1:])))

    return '\n'.join(''.join(patterns[i] for i in row) for row in idices)

def tile(board=0, seq=tuple(), tiles=tiles):
    if not tiles:
        yield img(seq)
        return

    for c in tiles[0]:
        b = board | c

        tnext = [] 
        for t in tiles[1:]:
            tnext.append(tuple(n for n in t if not n&b))
            if not tnext[-1]: break 
        else:
            yield from tile(b, seq + (c,), tnext)

for x in tile():
    print(x)


VB: Module Module1

    Dim symbols As Char() = "XYPFTVNLUZWI█".ToCharArray(),
        nRows As Integer = 8, nCols As Integer = 8,
        target As Integer = 12, blank As Integer = 12,
        grid As Integer()() = New Integer(nRows - 1)() {},
        placed As Boolean() = New Boolean(target - 1) {},
        pens As List(Of List(Of Integer())), rand As Random,
        seeds As Integer() = {291, 292, 293, 295, 297, 329, 330, 332, 333, 335, 378, 586}

    Sub Main()
        Unpack(seeds) : rand = New Random() : ShuffleShapes(2)
        For r As Integer = 0 To nRows - 1
            grid(r) = Enumerable.Repeat(-1, nCols).ToArray() : Next
        For i As Integer = 0 To 3
            Dim rRow, rCol As Integer : Do : rRow = rand.Next(nRows) : rCol = rand.Next(nCols)
            Loop While grid(rRow)(rCol) = blank : grid(rRow)(rCol) = blank
        Next
        If Solve(0, 0) Then
            PrintResult()
        Else
            Console.WriteLine("no solution for this configuration:") : PrintResult()
        End If
        If System.Diagnostics.Debugger.IsAttached Then Console.ReadKey()
    End Sub

    Sub ShuffleShapes(count As Integer) 
        For i As Integer = 0 To count : For j = 0 To pens.Count - 1
                Dim r As Integer : Do : r = rand.Next(pens.Count) : Loop Until r <> j
                Dim tmp As List(Of Integer()) = pens(r) : pens(r) = pens(j) : pens(j) = tmp
                Dim ch As Char = symbols(r) : symbols(r) = symbols(j) : symbols(j) = ch
            Next : Next
    End Sub

    Sub PrintResult() 
        For Each r As Integer() In grid : For Each i As Integer In r
                Console.Write("{0} ", If(i < 0, ".", symbols(i)))
            Next : Console.WriteLine() : Next
    End Sub

    
    Function Solve(ByVal pos As Integer, ByVal numPlaced As Integer) As Boolean
        If numPlaced = target Then Return True
        Dim row As Integer = pos \ nCols, col As Integer = pos Mod nCols
        If grid(row)(col) <> -1 Then Return Solve(pos + 1, numPlaced)
        For i As Integer = 0 To pens.Count - 1 : If Not placed(i) Then
                For Each orientation As Integer() In pens(i)
                    If Not TPO(orientation, row, col, i) Then Continue For
                    placed(i) = True : If Solve(pos + 1, numPlaced + 1) Then Return True
                    RmvO(orientation, row, col) : placed(i) = False
                Next : End If : Next : Return False
    End Function

    
    Sub RmvO(ByVal ori As Integer(), ByVal row As Integer, ByVal col As Integer)
        grid(row)(col) = -1 : For i As Integer = 0 To ori.Length - 1 Step 2
            grid(row + ori(i))(col + ori(i + 1)) = -1 : Next
    End Sub

    
    Function TPO(ByVal ori As Integer(), ByVal row As Integer, ByVal col As Integer,
                 ByVal sIdx As Integer) As Boolean
        For i As Integer = 0 To ori.Length - 1 Step 2
            Dim x As Integer = col + ori(i + 1), y As Integer = row + ori(i)
            If x < 0 OrElse x >= nCols OrElse y < 0 OrElse y >= nRows OrElse
                grid(y)(x) <> -1 Then Return False
        Next : grid(row)(col) = sIdx
        For i As Integer = 0 To ori.Length - 1 Step 2
            grid(row + ori(i))(col + ori(i + 1)) = sIdx
        Next : Return True
    End Function

    
    
    
    

    Sub Unpack(sv As Integer()) 
        pens = New List(Of List(Of Integer())) : For Each item In sv
            Dim Gen As New List(Of Integer()), exi As List(Of Integer) = Expand(item),
                fx As Integer() = ToP(exi) : Gen.Add(fx) : For i As Integer = 1 To 7
                If i = 4 Then Mir(exi) Else Rot(exi)
                fx = ToP(exi) : If Not Gen.Exists(Function(Red) TheSame(Red, fx)) Then Gen.Add(ToP(exi))
            Next : pens.Add(Gen) : Next
    End Sub

    
    Function Expand(i As Integer) As List(Of Integer)
        Expand = {0}.ToList() : For j As Integer = 0 To 3 : Expand.Insert(1, i And 15) : i >>= 4 : Next
    End Function

    
    Function ToP(p As List(Of Integer)) As Integer()
        Dim tmp As List(Of Integer) = {0}.ToList() : For Each item As Integer In p.Skip(1)
            tmp.Add(tmp.Item(item >> 2) + {1, 8, -1, -8}(item And 3)) : Next
        tmp.Sort() : For i As Integer = tmp.Count - 1 To 0 Step -1 : tmp.Item(i) -= tmp.Item(0) : Next
        Dim res As New List(Of Integer) : For Each item In tmp.Skip(1)
            Dim adj = If((item And 7) > 4, 8, 0)
            res.Add((adj + item) \ 8) : res.Add((item And 7) - adj)
        Next : Return res.ToArray()
    End Function

    
    Function TheSame(a As Integer(), b As Integer()) As Boolean
        For i As Integer = 0 To a.Count - 1 : If a(i) <> b(i) Then Return False
        Next : Return True
    End Function

    Sub Rot(ByRef p As List(Of Integer)) 
        For i As Integer = 0 To p.Count - 1 : p(i) = (p(i) And -4) Or ((p(i) + 1) And 3) : Next
    End Sub

    Sub Mir(ByRef p As List(Of Integer)) 
        For i As Integer = 0 To p.Count - 1 : p(i) = (p(i) And -4) Or (((p(i) Xor 1) + 1) And 3) : Next
    End Sub

End Module