diff --git a/README.md b/README.md index 9bd71de..3e42525 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,4 @@ - Day 10: 180:00; this one was hard for me. - Day 11: 68:00; okay but not elegant and way too slow ofc; x-ray solution would have been neat - Day 12: 52:00 and 22:00 for leaderboard; had the right idea and I am good at this type of problem +- Day 16: 00:27:30 745; best placement so far, of course still horribly slow diff --git a/d16.py b/d16.py new file mode 100644 index 0000000..a85a8aa --- /dev/null +++ b/d16.py @@ -0,0 +1,109 @@ +import lib + +EXAMPLE = r""" +.|...\.... +|.-.\..... +.....|-... +........|. +.......... +.........\ +..../.\\.. +.-.-/..|.. +.|....-|.\ +..//.|.... +""" + +NEW = { + '.': { + 'w': (0, -1, 'w'), + 'e': (0, 1, 'e'), + 's': (1, 0, 's'), + 'n': (-1, 0, 'n'), + }, + '|': { + 'w': [(1, 0, 's'), (-1, 0, 'n')], + 'e': [(1, 0, 's'), (-1, 0, 'n')], + 's': (1, 0, 's'), + 'n': (-1, 0, 'n'), + }, + '-': { + 's': [(0, -1, 'w'), (0, 1, 'e')], + 'n': [(0, -1, 'w'), (0, 1, 'e')], + 'e': (0, 1, 'e'), + 'w': (0, -1, 'w'), + }, + '/': { + 's': (0, -1, 'w'), + 'n': (0, 1, 'e'), + 'e': (-1, 0, 'n'), + 'w': (1, 0, 's'), + }, + '\\': { + 's': (0, 1, 'e'), + 'n': (0, -1, 'w'), + 'e': (1, 0, 's'), + 'w': (-1, 0, 'n'), + }, +} + +def solve(lines: list[str], second=False): + res = 0 + + g = list(map(list, lines)) + + rows = len(g) + cols = len(g[0]) + + if not second: + starts = [(0, 0, 'e')] + else: + starts = [(r, 0, 'e') for r in range(rows)] + starts += [(r, cols - 1, 'w') for r in range(rows)] + starts += [(0, c, 's') for c in range(cols)] + starts += [(rows - 1, c, 'n') for c in range(cols)] + + for start in starts: + visited = set() + beams = [start] + while beams: + b = beams.pop() + row, col, d = b + visited.add((row, col, d)) + + f = g[row][col] + new = NEW[f][d] + if isinstance(new, tuple): + r, c, nd = new + nr = row + r + nc = col + c + if nr >= 0 and nc >= 0 and nr < rows and nc < cols: + if not (nr, nc, nd) in visited: + beams.append((nr, nc, nd)) + else: + for r, c, nd in new: + nr = row + r + nc = col + c + if nr >= 0 and nc >= 0 and nr < rows and nc < cols: + if not (nr, nc, nd) in visited: + beams.append((nr, nc, nd)) + + v = set([(r, c) for (r, c, _) in list(visited)]) + res = max(res, len(v)) + return res + + +def main(): + lines = lib.str_to_lines_no_empty(EXAMPLE) + print("Example 1:", solve(lines)) + + lines = lib.str_to_lines_no_empty(open("i16.txt").read()) + print("Solution 1:", solve(lines)) + + lines = lib.str_to_lines_no_empty(EXAMPLE) + print("Example 2:", solve(lines, True)) + + lines = lib.str_to_lines_no_empty(open("i16.txt").read()) + print("Solution 2:", solve(lines, True)) + +if __name__ == "__main__": + main()