2020/20.py
def solve(placements: Placements, d=0) -> Optional[Placements]:
    """
    This is a recursive function which, given a set of placements, returns a valid
    configuration of valid placements if it exists, and ``None`` otherwise.
    """
    indent = "  " * d
    if debug:
        print(indent, "solve")
        for row in placements:
            print(indent, [x[0] for x in row])

    # This is the base case of the recursion. If we have filled up the picture, then we
    # can return all of the placements.
    if len(placements) == SIDELEN and all(len(x) == SIDELEN for x in placements):
        return placements

    # Calculate the next tile location to place.
    num_placed = sum(map(len, placements))
    nextloc = (num_placed // SIDELEN, num_placed % SIDELEN)

    # Calculate the possible options for the next tile to place.
    nexttile_opts = set(TIDS) - {cell[0] for row in placements for cell in row}

    # Go through all of the options for theh next tile to place and see if any of them
    # work.
    while len(nexttile_opts):
        nexttile = nexttile_opts.pop()

        # Try all rotations and flips of the next tile
        for flip, rot in it.product((False, True), ROTS):

            # Get the left and top side of the tile to be placed (after handling the
            # rotation and flip) so that we can compare against the adjacent cells.
            left = getside(nexttile, rot, flip, "l")
            top = getside(nexttile, rot, flip, "t")
            row, col = nextloc

            # Check if it works. Only check top and left because we are working from the
            # top left to the bottom right, so we only will ever have to check to the
            # top and left!
            rotworks = True
            if row > 0:
                # Check above
                adj = placements[row - 1][col]
                if getside(*adj, "b") != top:
                    rotworks = False

            if rotworks and col > 0:
                # Check left
                adj = placements[row][col - 1]
                if getside(*adj, "r") != left:
                    rotworks = False

            # This rotation works, recursively call solve with the new placements tuple.
            # This is a fairly stupid way of doing things, but it works, and that's all
            # that matters.
            if rotworks:
                new_placements = [[p for p in r] for r in placements]
                if nextloc[0] >= len(new_placements):
                    new_placements.append([])
                new_placements[-1].append((nexttile, rot, flip))
                return solve(tuple(map(tuple, (p for p in new_placements))), d=d + 1)

    This is a recursive function which, given a set of placements, returns a valid
    configuration of valid placements if it exists, and ``None`` otherwise.
    
This is a recursive function which, given a set of placements, returns a valid
configuration of valid placements if it exists, and ``None`` otherwise.
This is a recursive function which given a set of placements returns a valid configuration of valid placements if it exists and ` ` None ` ` otherwise .
def solve(placements: Placements, d=0) -> Optional[Placements]:
    indent = "  " * d
    if debug:
        print(indent, "solve")
        for row in placements:
            print(indent, [x[0] for x in row])
    if len(placements) == SIDELEN and all(len(x) == SIDELEN for x in placements):
        return placements
    num_placed = sum(map(len, placements))
    nextloc = (num_placed // SIDELEN, num_placed % SIDELEN)
    nexttile_opts = set(TIDS) - {cell[0] for row in placements for cell in row}
    while len(nexttile_opts):
        nexttile = nexttile_opts.pop()
        for flip, rot in it.product((False, True), ROTS):
            left = getside(nexttile, rot, flip, "l")
            top = getside(nexttile, rot, flip, "t")
            row, col = nextloc
            rotworks = True
            if row > 0:
                adj = placements[row - 1][col]
                if getside(*adj, "b") != top:
                    rotworks = False
            if rotworks and col > 0:
                adj = placements[row][col - 1]
                if getside(*adj, "r") != left:
                    rotworks = False
            if rotworks:
                new_placements = [[p for p in r] for r in placements]
                if nextloc[0] >= len(new_placements):
                    new_placements.append([])
                new_placements[-1].append((nexttile, rot, flip))
                return solve(tuple(map(tuple, (p for p in new_placements))), d=d + 1)
def solve ( placements : Placements , d = 0 ) -> Optional [ Placements ] : indent = "  " * d if debug : print ( indent , "solve" ) for row in placements : print ( indent , [ x [ 0 ] for x in row ] ) if len ( placements ) == SIDELEN and all ( len ( x ) == SIDELEN for x in placements ) : return placements num_placed = sum ( map ( len , placements ) ) nextloc = ( num_placed // SIDELEN , num_placed % SIDELEN ) nexttile_opts = set ( TIDS ) - { cell [ 0 ] for row in placements for cell in row } while len ( nexttile_opts ) : nexttile = nexttile_opts . pop ( ) for flip , rot in it . product ( ( False , True ) , ROTS ) : left = getside ( nexttile , rot , flip , "l" ) top = getside ( nexttile , rot , flip , "t" ) row , col = nextloc rotworks = True if row > 0 : adj = placements [ row - 1 ] [ col ] if getside ( * adj , "b" ) != top : rotworks = False if rotworks and col > 0 : adj = placements [ row ] [ col - 1 ] if getside ( * adj , "r" ) != left : rotworks = False if rotworks : new_placements = [ [ p for p in r ] for r in placements ] if nextloc [ 0 ] >= len ( new_placements ) : new_placements . append ( [ ] ) new_placements [ - 1 ] . append ( ( nexttile , rot , flip ) ) return solve ( tuple ( map ( tuple , ( p for p in new_placements ) ) ) , d = d + 1 )
This is a recursive function which, given a set of placements, returns a valid
configuration of valid placements if it exists, and ``None`` otherwise.
This is a recursive function which given a set of placements returns a valid configuration of valid placements if it exists and ` ` None ` ` otherwise .
"""
    This is a recursive function which, given a set of placements, returns a valid
    configuration of valid placements if it exists, and ``None`` otherwise.
    """ # This is the base case of the recursion. If we have filled up the picture, then we # can return all of the placements. # Calculate the next tile location to place. # Calculate the possible options for the next tile to place. # Go through all of the options for theh next tile to place and see if any of them # work. # Try all rotations and flips of the next tile # Get the left and top side of the tile to be placed (after handling the # rotation and flip) so that we can compare against the adjacent cells. # Check if it works. Only check top and left because we are working from the # top left to the bottom right, so we only will ever have to check to the # top and left! # Check above # Check left # This rotation works, recursively call solve with the new placements tuple. # This is a fairly stupid way of doing things, but it works, and that's all # that matters.
placements
Placements
d