2020/20.py
def part2() -> int:
    """
    I used a very inefficient and stupid algorithm for this. For each orientation, I am
    just checking every single possible start (row, col) pair of a monster (which is
    really highly unnecessary because monsters cannot overlap).
    """
    sidelen = len(list(TILES.values())[0])

    if debug:
        for row in assignments:
            print(row)

    seamonster = [
        "                  # ",
        "#    ##    ##    ###",
        " #  #  #  #  #  #   ",
    ]
    seamonster_r = len(seamonster)
    seamonster_c = len(seamonster[0])

    # This part just stitches together the picture. Making sure to delete the borders.
    alllines = []
    for row in assignments:
        rowlines = [[] for _ in range(sidelen - 2)]

        for col, rotation, flip in row:
            pic = TILES[col]
            if flip:
                pic = [list(reversed(x)) for x in pic]
            for _ in range(rotation):
                pic = list(zip(*pic[::-1]))

            for i, row in list(enumerate(pic[1:-1])):
                rowlines[i].extend([".#"[int(x)] for x in row[1:-1]])

        if debug:
            for row in rowlines:
                print("".join(row))

        alllines.extend(rowlines)

    def turbulence(lines) -> Optional[int]:
        """
        Returns the turbulence if there are monsters in this orientation. It's
        guaranteed that there will be only one configuration that has monsters, so if
        there are no monsters, then this is not the correct orientation.
        """
        R = len(lines)
        C = len(lines[0])
        for r0 in range(R):
            for c0 in range(C):
                is_seamonster = True

                for r, c in it.product(range(seamonster_r), range(seamonster_c)):
                    if debug:
                        print(r, c, r0 + r, c0 + c)
                    if not (0 <= r0 + r < R and 0 <= c0 + c < C):
                        is_seamonster = False
                        break
                    if seamonster[r][c] == "#" and lines[r0 + r][c0 + c] not in "#O":
                        is_seamonster = False
                        break

                if is_seamonster:
                    for r, c in it.product(range(seamonster_r), range(seamonster_c)):
                        if seamonster[r][c] == "#":
                            lines[r0 + r][c0 + c] = "O"

        t = 0
        anyseamonster = False
        for l in lines:
            for c in l:
                if c == "#":
                    t += 1
                if c == "O":
                    anyseamonster = True

        if anyseamonster and debug:
            print("SEAMONSTERS:")
            for row in lines:
                print("".join(row))
        return t if anyseamonster else None

    for rot, flip in it.product(ROTS, (True, False)):
        rotated = deepcopy(alllines)
        if flip:
            rotated = [tuple(reversed(x)) for x in rotated]
        for _ in range(rot):
            rotated = list(zip(*rotated[::-1]))
        rotated = [list(x) for x in rotated]

        t = turbulence(rotated)
        if t:
            return t

    assert False

    I used a very inefficient and stupid algorithm for this. For each orientation, I am
    just checking every single possible start (row, col) pair of a monster (which is
    really highly unnecessary because monsters cannot overlap).
    
I used a very inefficient and stupid algorithm for this. For each orientation, I am
just checking every single possible start (row, col) pair of a monster (which is
really highly unnecessary because monsters cannot overlap).
I used a very inefficient and stupid algorithm for this . For each orientation I am just checking every single possible start ( row col ) pair of a monster ( which is really highly unnecessary because monsters cannot overlap ) .
def part2() -> int:
    sidelen = len(list(TILES.values())[0])
    if debug:
        for row in assignments:
            print(row)
    seamonster = [
        "                  # ",
        "#    ##    ##    ###",
        " #  #  #  #  #  #   ",
    ]
    seamonster_r = len(seamonster)
    seamonster_c = len(seamonster[0])
    alllines = []
    for row in assignments:
        rowlines = [[] for _ in range(sidelen - 2)]
        for col, rotation, flip in row:
            pic = TILES[col]
            if flip:
                pic = [list(reversed(x)) for x in pic]
            for _ in range(rotation):
                pic = list(zip(*pic[::-1]))
            for i, row in list(enumerate(pic[1:-1])):
                rowlines[i].extend([".#"[int(x)] for x in row[1:-1]])
        if debug:
            for row in rowlines:
                print("".join(row))
        alllines.extend(rowlines)
    def turbulence(lines) -> Optional[int]:
        R = len(lines)
        C = len(lines[0])
        for r0 in range(R):
            for c0 in range(C):
                is_seamonster = True
                for r, c in it.product(range(seamonster_r), range(seamonster_c)):
                    if debug:
                        print(r, c, r0 + r, c0 + c)
                    if not (0 <= r0 + r < R and 0 <= c0 + c < C):
                        is_seamonster = False
                        break
                    if seamonster[r][c] == "#" and lines[r0 + r][c0 + c] not in "#O":
                        is_seamonster = False
                        break
                if is_seamonster:
                    for r, c in it.product(range(seamonster_r), range(seamonster_c)):
                        if seamonster[r][c] == "#":
                            lines[r0 + r][c0 + c] = "O"
        t = 0
        anyseamonster = False
        for l in lines:
            for c in l:
                if c == "#":
                    t += 1
                if c == "O":
                    anyseamonster = True
        if anyseamonster and debug:
            print("SEAMONSTERS:")
            for row in lines:
                print("".join(row))
        return t if anyseamonster else None
    for rot, flip in it.product(ROTS, (True, False)):
        rotated = deepcopy(alllines)
        if flip:
            rotated = [tuple(reversed(x)) for x in rotated]
        for _ in range(rot):
            rotated = list(zip(*rotated[::-1]))
        rotated = [list(x) for x in rotated]
        t = turbulence(rotated)
        if t:
            return t
    assert False
def part2 ( ) -> int : sidelen = len ( list ( TILES . values ( ) ) [ 0 ] ) if debug : for row in assignments : print ( row ) seamonster = [ "                  # " , "#    ##    ##    ###" , " #  #  #  #  #  #   " , ] seamonster_r = len ( seamonster ) seamonster_c = len ( seamonster [ 0 ] ) alllines = [ ] for row in assignments : rowlines = [ [ ] for _ in range ( sidelen - 2 ) ] for col , rotation , flip in row : pic = TILES [ col ] if flip : pic = [ list ( reversed ( x ) ) for x in pic ] for _ in range ( rotation ) : pic = list ( zip ( * pic [ : : - 1 ] ) ) for i , row in list ( enumerate ( pic [ 1 : - 1 ] ) ) : rowlines [ i ] . extend ( [ ".#" [ int ( x ) ] for x in row [ 1 : - 1 ] ] ) if debug : for row in rowlines : print ( "" . join ( row ) ) alllines . extend ( rowlines ) def turbulence ( lines ) -> Optional [ int ] : """
        Returns the turbulence if there are monsters in this orientation. It's
        guaranteed that there will be only one configuration that has monsters, so if
        there are no monsters, then this is not the correct orientation.
        """ R = len ( lines ) C = len ( lines [ 0 ] ) for r0 in range ( R ) : for c0 in range ( C ) : is_seamonster = True for r , c in it . product ( range ( seamonster_r ) , range ( seamonster_c ) ) : if debug : print ( r , c , r0 + r , c0 + c ) if not ( 0 <= r0 + r < R and 0 <= c0 + c < C ) : is_seamonster = False break if seamonster [ r ] [ c ] == "#" and lines [ r0 + r ] [ c0 + c ] not in "#O" : is_seamonster = False break if is_seamonster : for r , c in it . product ( range ( seamonster_r ) , range ( seamonster_c ) ) : if seamonster [ r ] [ c ] == "#" : lines [ r0 + r ] [ c0 + c ] = "O" t = 0 anyseamonster = False for l in lines : for c in l : if c == "#" : t += 1 if c == "O" : anyseamonster = True if anyseamonster and debug : print ( "SEAMONSTERS:" ) for row in lines : print ( "" . join ( row ) ) return t if anyseamonster else None for rot , flip in it . product ( ROTS , ( True , False ) ) : rotated = deepcopy ( alllines ) if flip : rotated = [ tuple ( reversed ( x ) ) for x in rotated ] for _ in range ( rot ) : rotated = list ( zip ( * rotated [ : : - 1 ] ) ) rotated = [ list ( x ) for x in rotated ] t = turbulence ( rotated ) if t : return t assert False
I used a very inefficient and stupid algorithm for this.
I used a very inefficient and stupid algorithm for this .
"""
    I used a very inefficient and stupid algorithm for this. For each orientation, I am
    just checking every single possible start (row, col) pair of a monster (which is
    really highly unnecessary because monsters cannot overlap).
    """ # This part just stitches together the picture. Making sure to delete the borders. """
        Returns the turbulence if there are monsters in this orientation. It's
        guaranteed that there will be only one configuration that has monsters, so if
        there are no monsters, then this is not the correct orientation.
        """