diff --git a/README.md b/README.md index 948a238..1246e53 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ - Day 1: 40:00 (I don't know what I am doing.) - Day 2: 14:15 (Okay, but far way from leaderboard.) -- Day 3: 1st 20:00, 2nd 70:00... (I had a logic error that took me a while to find.) +- Day 3: 1st 20:00, 2nd 70:00... (I had a logic error that took me a while to find.) - Day 4: 1st 9:06, 2nd 22:31; it wasn't hard but I didn't think quick enough :/ - Day 5: 1st 25:00, 2nd 1:55:00; Required patience and accuracy - Day 6: 13:54; I was slow because I thought it is much harder? @@ -12,7 +12,9 @@ - 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 13: 90:00; pretty straightforward but way too slow +- Day 14: +- Day 15: - Day 16: 00:27:30 745; best placement so far, of course still horribly slow - Day 17: a couple of hours; I realized that I need A* after a while; reused implementation from Project Euler but improved with heapq which was super fun diff --git a/d13.py b/d13.py new file mode 100644 index 0000000..1c80e25 --- /dev/null +++ b/d13.py @@ -0,0 +1,92 @@ +from lib import * + +EXAMPLE = """ +#.##..##. +..#.##.#. +##......# +##......# +..#.##.#. +..##..##. +#.#.##.#. + +#...##..# +#....#..# +..##..### +#####.##. +#####.##. +..##..### +#....#..# +""".replace("\n", "", count=1) + + +def solve(i: Input, second=False): + res = 0 + ps = i.paras() + + for p in ps: + g = Input(p).grid2() + + row_res, col_res = [], [] + rows = g.rows() + cols = g.cols() + for i_row in range(len(rows) - 1): + for i in range(min(i_row + 1, len(rows) - i_row - 1)): + if rows[i_row - i] != rows[i_row + i + 1]: + break + else: + if not second: + res += (i_row + 1) * 100 + row_res.append(i_row) + + for i_col in range(len(cols) - 1): + for i in range(min(i_col + 1, len(cols) - i_col - 1)): + if cols[i_col - i] != cols[i_col + i + 1]: + break + else: + if not second: + res += (i_col + 1) + col_res.append(i_col) + + if not second: + continue + + for c in g.all_coords(): + g[c] = '.' if g[c] == '#' else '#' + rows = g.rows() + cols = g.cols() + for i_row in range(len(rows) - 1): + for i in range(min(i_row + 1, len(rows) - i_row - 1)): + if rows[i_row - i] != rows[i_row + i + 1]: + break + else: + if not i_row in row_res: + res += (i_row + 1) * 100 + row_res.append(i_row) + + for i_col in range(len(cols) - 1): + for i in range(min(i_col + 1, len(cols) - i_col - 1)): + if cols[i_col - i] != cols[i_col + i + 1]: + break + else: + if not i_col in col_res: + res += (i_col + 1) + col_res.append(i_col) + g[c] = '.' if g[c] == '#' else '#' + if len(row_res + col_res) != 2: + raise Exception("Unexpected amount of mirrors!!") + return res + + +def main(): + DAY_INPUT = "i13.txt" + + print("Example 1:", solve(Input(EXAMPLE))) + print("Solution 1:", solve(Input(DAY_INPUT))) + assert 29846 == solve(Input(DAY_INPUT)) + + print("Example 2:", solve(Input(EXAMPLE), True)) + print("Solution 2:", solve(Input(DAY_INPUT), True)) + assert 25401 == solve(Input(DAY_INPUT), True) + +if __name__ == "__main__": + main() diff --git a/d18.py b/d18.py index cf8b52c..26d4e63 100644 --- a/d18.py +++ b/d18.py @@ -51,8 +51,7 @@ def solve(i: Input, second=False): to_visit.append(nc) return len(set(coords)) - -def calc(ins): +def area(ins): c = (0, 0) corners = [] for i, (count, d) in enumerate(ins): @@ -86,6 +85,20 @@ def calc(ins): return int(shoelace_area(corners)) +def area2(ins): + # Solution based on Shoelace area and the idea that the outside area is + # perimate * 1 // 2, and then +1 (for four quarter corners). All other + # corners cancel out to zero. + c = (0, 0) + corners = [] + perimeter = 0 + for i, (count, d) in enumerate(ins): + c = (c[0] + count * d[0], c[1] + count * d[1]) + corners.append(c) + perimeter += count + return int(shoelace_area(corners)) + perimeter // 2 + 1 + + def solve2(i: Input, second=False): lines = i.lines() ins = [] @@ -97,7 +110,8 @@ def solve2(i: Input, second=False): d = int(c[:5], 16) m = {"0": Grid2D.E, "1": Grid2D.S, "2": Grid2D.W, "3": Grid2D.N}[c[5]] ins.append((d, m)) - return calc(ins) + assert area(ins) == area2(ins) + return area(ins) def debug(): @@ -113,7 +127,7 @@ def debug(): ] # Should be 14 but is 2 because it's going counter-clockwise, but mapping # only works for clockwise. - print(calc(ins)) + print(area(ins)) def main(): diff --git a/lib.py b/lib.py index 19644de..1a1abc3 100644 --- a/lib.py +++ b/lib.py @@ -133,7 +133,7 @@ class Input: return self.text.splitlines() def paras(self) -> list[list[str]]: - return [p.splitlines() for p in self.text.split("\n\n")] + return [p for p in self.text.split("\n\n")] def grid2(self) -> Grid2D: return Grid2D(self.text)