From 51288a299bbcf96b67869e390f8ce3453552c86d Mon Sep 17 00:00:00 2001 From: <> Date: Wed, 13 Dec 2023 17:49:04 +0000 Subject: [PATCH] Deployed 5a555b0 with MkDocs version: 1.5.3 --- 2021/index.html | 3182 +++++++++++++++++++------------------- 2022/index.html | 404 ++--- search/search_index.json | 2 +- sitemap.xml.gz | Bin 127 -> 127 bytes 4 files changed, 1794 insertions(+), 1794 deletions(-) diff --git a/2021/index.html b/2021/index.html index b453351..229731a 100644 --- a/2021/index.html +++ b/2021/index.html @@ -9,147 +9,23 @@ body[data-md-color-scheme="slate"] .gdesc-inner { background: var(--md-default-bg-color);} body[data-md-color-scheme="slate"] .gslide-title { color: var(--md-default-fg-color);} body[data-md-color-scheme="slate"] .gslide-desc { color: var(--md-default-fg-color);} -
Skip to content

Advent of Code 2021

Day 04
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
with open("day04_input.txt", "r") as f:
-    lines = f.read().splitlines()
+                  

Advent of Code 2021

Day 01
1
+2
+3
+4
+5
+6
+7
+8
+9
with open("day01_input.txt", "r") as f:
+    data = [int(i) for i in f.read().splitlines()]
 
-
-draws = lines[0].split(",")
-
-
-lines = [line for line in lines[1:] if line]
-boards = []
-for i in range(0, len(lines) // 5):
-    boards.append([])
-    for j in range(5):
-        boards[i].append(lines[i * 5 + j].split())
-
-
-marks = {}
-for i in range(len(boards)):
-    marks[i] = {}
-    for row in range(5):
-        for col in range(5):
-            marks[i][boards[i][row][col]] = (row, col)
-
-
-winning_locations = []
-for row in range(5):
-    winning_locations.append([(row, col) for col in range(5)])
-for col in range(5):
-    winning_locations.append([(row, col) for row in range(5)])
-
-
-def wins(locations, winning_locations=winning_locations):
-    for winning_location in winning_locations:
-        if all(loc in locations for loc in winning_location):
-            return winning_location
-
-    return None
-
-
-plays = {}
-for i in range(len(boards)):
-    plays[i] = []
-
-num_plays = {}
-for i in range(len(boards)):
-    count = 0
-    for draw in draws:
-        count += 1
-        if draw in marks[i]:
-            plays[i].append(marks[i][draw])
-
-        if wins(plays[i]):
-            num_plays[i] = count, len(plays[i])
-            break
-
-
-last_win = max(num_plays, key=lambda x: num_plays[x][0])
-print(last_win)
-
-
-sum_unmarked = 0
-for row in range(5):
-    for col in range(5):
-        if (row, col) not in plays[last_win]:
-            sum_unmarked += int(boards[last_win][row][col])
-
-row, col = plays[last_win][-1]
-num_call = int(boards[last_win][row][col])
-
-
-print(sum_unmarked, num_call)
-print(sum_unmarked * num_call)
+count = 0
+for i in range(1, len(data)):
+    if data[i] > data[i - 1]:
+        count += 1
+
+print(count)
 
 1
  2
  3
@@ -162,136 +38,20 @@
 10
 11
 12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
with open("day04_input.txt", "r") as f:
-    lines = f.read().splitlines()
+13
with open("day01_input.txt", "r") as f:
+    data = [int(i) for i in f.read().splitlines()]
 
-
-draws = lines[0].split(",")
-
+three_measurement_data = []
+for i in range(2, len(data)):
+    three_measurement_data.append(sum(data[i - 2 : i + 1]))
 
-lines = [line for line in lines[1:] if line]
-boards = []
-for i in range(0, len(lines) // 5):
-    boards.append([])
-    for j in range(5):
-        boards[i].append(lines[i * 5 + j].split())
-
-
-marks = {}
-for i in range(len(boards)):
-    marks[i] = {}
-    for row in range(5):
-        for col in range(5):
-            marks[i][boards[i][row][col]] = (row, col)
-
-
-winning_locations = []
-for row in range(5):
-    winning_locations.append([(row, col) for col in range(5)])
-for col in range(5):
-    winning_locations.append([(row, col) for row in range(5)])
-
-
-def wins(locations, winning_locations=winning_locations):
-    for winning_location in winning_locations:
-        if all(loc in locations for loc in winning_location):
-            return winning_location
-
-    return None
-
-
-plays = {}
-for i in range(len(boards)):
-    plays[i] = []
-
-num_plays = {}
-for i in range(len(boards)):
-    count = 0
-    for draw in draws:
-        count += 1
-        if draw in marks[i]:
-            plays[i].append(marks[i][draw])
-
-        if wins(plays[i]):
-            num_plays[i] = count, len(plays[i])
-            break
-
-
-fastest_win = min(num_plays, key=lambda x: num_plays[x][0])
-print(fastest_win)
-
-
-sum_unmarked = 0
-for row in range(5):
-    for col in range(5):
-        if (row, col) not in plays[fastest_win]:
-            sum_unmarked += int(boards[fastest_win][row][col])
-
-row, col = plays[fastest_win][-1]
-num_call = int(boards[fastest_win][row][col])
-
-
-print(sum_unmarked, num_call)
-print(sum_unmarked * num_call)
-
Day 10
 1
+count = 0
+for i in range(1, len(three_measurement_data)):
+    if three_measurement_data[i] > three_measurement_data[i - 1]:
+        count += 1
+
+print(count)
+
Day 02
 1
  2
  3
  4
@@ -307,83 +67,23 @@
 14
 15
 16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
with open("day10_input.txt", "r") as f:
-    lines = f.read().splitlines()
+17
with open("day02_input.txt", "r") as f:
+    data = [cmd.split() for cmd in f.read().splitlines()]
 
-
-mapping = {
-    "(": 1,
-    "[": 2,
-    "{": 3,
-    "<": 4,
-}
-
-match = {
-    ")": "(",
-    "]": "[",
-    "}": "{",
-    ">": "<",
-}
-
-
-def check(line):
-    stack = []
-    for c in line:
-        if c in match.values():
-            stack.append(c)
-        elif c in match.keys():
-            if len(stack) == 0:
-                return 0
-            last = stack.pop()
-            if last != match[c]:
-                return 0
-
-    if len(stack) == 0:
-        return 0
-
-    score = 0
-    while len(stack) > 0:
-        last = stack.pop()
-        score *= 5
-        score += mapping[last]
-
-    return score
-
-
-scores = [check(line) for line in lines]
-scores = [s for s in scores if s > 0]
-print(len(scores))
-print(sorted(scores)[len(scores) // 2])
+horizontal_position, depth = 0, 0
+
+for action, value in data:
+    value = int(value)
+    if action == "forward":
+        horizontal_position += value
+    elif action == "up":
+        depth -= value
+    elif action == "down":
+        depth += value
+
+print(horizontal_position, depth)
+
+print(horizontal_position * depth)
 
 1
  2
  3
@@ -402,58 +102,26 @@
 16
 17
 18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
with open("day10_input.txt", "r") as f:
-    lines = f.read().splitlines()
+19
with open("day02_input.txt", "r") as f:
+    data = [cmd.split() for cmd in f.read().splitlines()]
 
-
-mapping = {
-    ")": 3,
-    "]": 57,
-    "}": 1197,
-    ">": 25137,
-}
-
-match = {
-    ")": "(",
-    "]": "[",
-    "}": "{",
-    ">": "<",
-}
+horizontal_position, depth, aim = 0, 0, 0
+
+for action, value in data:
+    value = int(value)
+    if action == "forward":
+        horizontal_position += value
+        depth += aim * value
+    elif action == "up":
+        aim -= value
+    elif action == "down":
+        aim += value
+
+
+print(horizontal_position, depth, aim)
 
-
-def check(line):
-    stack = []
-    for c in line:
-        if c in match.values():
-            stack.append(c)
-        elif c in match.keys():
-            if len(stack) == 0:
-                return mapping[c]
-            last = stack.pop()
-            if last != match[c]:
-                return mapping[c]
-
-    return 0
-
-
-print(sum(check(line) for line in lines))
-
Day 06
 1
+print(horizontal_position * depth)
+
Day 03
 1
  2
  3
  4
@@ -472,26 +140,34 @@
 17
 18
 19
-20
with open("day06_input.txt", "r") as f:
-    fish = [int(i) for i in f.read().strip().split(",")]
+20
+21
+22
+23
+24
with open("day03_input.txt", "r") as f:
+    data = f.read().splitlines()
 
-
-from collections import Counter
+cols = len(data[0])
+rows = len(data)
 
-fish = Counter(fish)
-print(fish)
-
-for _ in range(256):
-    for i in range(-1, 9):
-        if i == 8:
-            fish[i] = fish[-1]
-        elif i != 6:
-            fish[i] = fish[i + 1]
-        else:
-            fish[i] = fish[-1] + fish[i + 1]
-
-
-print(sum([v for k, v in fish.items() if k >= 0]))
+gamma_rate, epsilon_rate = "", ""
+
+for col in range(cols):
+    ones = 0
+    for row in range(rows):
+        if data[row][col] == "1":
+            ones += 1
+
+    if ones > rows / 2:
+        gamma_rate += "1"
+        epsilon_rate += "0"
+    else:
+        gamma_rate += "0"
+        epsilon_rate += "1"
+
+print(gamma_rate, epsilon_rate)
+
+print(int(gamma_rate, 2) * int(epsilon_rate, 2))
 
 1
  2
  3
@@ -511,27 +187,73 @@
 17
 18
 19
-20
with open("day06_input.txt", "r") as f:
-    fish = [int(i) for i in f.read().strip().split(",")]
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
with open("day03_input.txt", "r") as f:
+    data = f.read().splitlines()
 
-print(f"Initial state: {fish}")
+cols = len(data[0])
 
-for _ in range(80):
-    new_fish = []
-    for i in range(len(fish)):
-
-        fish[i] -= 1
-
-        if fish[i] < 0:
-            fish[i] = 6
-            new_fish.append(8)
-
-    fish.extend(new_fish)
-
-    print(f"After {str(_+1):2s} day{'s' if _ else ''}: {fish}")
+oxygen_generator_rating, co2_scrubber_rating = "", ""
+
+selections = data[:]
+for col in range(cols):
+    ones = 0
+    for row in selections:
+        if row[col] == "1":
+            ones += 1
+
+    if ones >= len(selections) / 2:
+        selections = [row for row in selections if row[col] == "1"]
+    else:
+        selections = [row for row in selections if row[col] == "0"]
 
-print(len(fish))
-
Day 15
 1
+    if len(selections) == 1:
+        oxygen_generator_rating += selections[0]
+        break
+
+selections = data[:]
+for col in range(cols):
+    ones = 0
+    for row in selections:
+        if row[col] == "1":
+            ones += 1
+
+    if ones < len(selections) / 2:
+        selections = [row for row in selections if row[col] == "1"]
+    else:
+        selections = [row for row in selections if row[col] == "0"]
+
+    if len(selections) == 1:
+        co2_scrubber_rating += selections[0]
+        break
+
+
+print(oxygen_generator_rating, co2_scrubber_rating)
+
+print(int(oxygen_generator_rating, 2) * int(co2_scrubber_rating, 2))
+
Day 04
 1
  2
  3
  4
@@ -578,54 +300,100 @@
 45
 46
 47
-48
with open("day15_input.txt", "r") as f:
-    lines = [[int(d) for d in line] for line in f.read().splitlines()]
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
with open("day04_input.txt", "r") as f:
+    lines = f.read().splitlines()
 
-rows, cols = len(lines), len(lines[0])
-
+
+draws = lines[0].split(",")
 
-lines_5x = [[0] * cols * 5 for i in range(rows * 5)]
-for ii in range(5):
-    for jj in range(5):
-        for i in range(rows):
-            for j in range(cols):
-                lines_5x[ii * rows + i][jj * cols + j] = (
-                    lines[i][j] + ii + jj - 1
-                ) % 9 + 1
+
+lines = [line for line in lines[1:] if line]
+boards = []
+for i in range(0, len(lines) // 5):
+    boards.append([])
+    for j in range(5):
+        boards[i].append(lines[i * 5 + j].split())
+
 
-
-# Using the networkx library instead
-
-import networkx as nx
-
-g = nx.DiGraph()
-rows *= 5
-cols *= 5
-
-for i in range(rows):
-    for j in range(cols):
-        if i < rows - 1:
-            g.add_edge((i, j), (i + 1, j), weight=lines_5x[i + 1][j])
-            g.add_edge((i + 1, j), (i, j), weight=lines_5x[i][j])
+marks = {}
+for i in range(len(boards)):
+    marks[i] = {}
+    for row in range(5):
+        for col in range(5):
+            marks[i][boards[i][row][col]] = (row, col)
+
+
+winning_locations = []
+for row in range(5):
+    winning_locations.append([(row, col) for col in range(5)])
+for col in range(5):
+    winning_locations.append([(row, col) for row in range(5)])
+
 
-        if j < cols - 1:
-            g.add_edge((i, j), (i, j + 1), weight=lines_5x[i][j + 1])
-            g.add_edge((i, j + 1), (i, j), weight=lines_5x[i][j])
-
-paths = nx.shortest_path(
-    g,
-    source=(0, 0),
-    target=(rows - 1, cols - 1),
-    weight="weight",
-)
-
-# print(paths)
-
-cost = 0
-for i, j in paths[1:]:
-    cost += lines_5x[i][j]
-
-print(f"Cost of shortest path is {cost}")
+def wins(locations, winning_locations=winning_locations):
+    for winning_location in winning_locations:
+        if all(loc in locations for loc in winning_location):
+            return winning_location
+
+    return None
+
+
+plays = {}
+for i in range(len(boards)):
+    plays[i] = []
+
+num_plays = {}
+for i in range(len(boards)):
+    count = 0
+    for draw in draws:
+        count += 1
+        if draw in marks[i]:
+            plays[i].append(marks[i][draw])
+
+        if wins(plays[i]):
+            num_plays[i] = count, len(plays[i])
+            break
+
+
+last_win = max(num_plays, key=lambda x: num_plays[x][0])
+print(last_win)
+
+
+sum_unmarked = 0
+for row in range(5):
+    for col in range(5):
+        if (row, col) not in plays[last_win]:
+            sum_unmarked += int(boards[last_win][row][col])
+
+row, col = plays[last_win][-1]
+num_call = int(boards[last_win][row][col])
+
+
+print(sum_unmarked, num_call)
+print(sum_unmarked * num_call)
 
 1
  2
  3
@@ -685,67 +453,89 @@
 57
 58
 59
-60
with open("day15_input.txt", "r") as f:
-    risks = [[int(d) for d in line] for line in f.read().splitlines()]
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
with open("day04_input.txt", "r") as f:
+    lines = f.read().splitlines()
 
-rows, cols = len(risks), len(risks[0])
-
-# reference: https://stackabuse.com/dijkstras-algorithm-in-python/
+
+draws = lines[0].split(",")
+
 
-from queue import PriorityQueue
-
-
-class Graph:
-    def __init__(self, num_of_vertices):
-        self.v = num_of_vertices
-        self.edges = [
-            [-1 for i in range(num_of_vertices)] for j in range(num_of_vertices)
-        ]
-        self.visited = []
-
-    def add_edge(self, u, v, weight):
-        self.edges[u][v] = weight
-
+lines = [line for line in lines[1:] if line]
+boards = []
+for i in range(0, len(lines) // 5):
+    boards.append([])
+    for j in range(5):
+        boards[i].append(lines[i * 5 + j].split())
+
+
+marks = {}
+for i in range(len(boards)):
+    marks[i] = {}
+    for row in range(5):
+        for col in range(5):
+            marks[i][boards[i][row][col]] = (row, col)
 
-def dijkstra(graph, start_vertex):
-    D = {v: float("inf") for v in range(graph.v)}
-    D[start_vertex] = 0
-
-    pq = PriorityQueue()
-    pq.put((0, start_vertex))
+
+winning_locations = []
+for row in range(5):
+    winning_locations.append([(row, col) for col in range(5)])
+for col in range(5):
+    winning_locations.append([(row, col) for row in range(5)])
 
-    while not pq.empty():
-        (dist, current_vertex) = pq.get()
-        graph.visited.append(current_vertex)
-
-        for neighbor in range(graph.v):
-            if graph.edges[current_vertex][neighbor] != -1:
-                distance = graph.edges[current_vertex][neighbor]
-                if neighbor not in graph.visited:
-                    old_cost = D[neighbor]
-                    new_cost = D[current_vertex] + distance
-                    if new_cost < old_cost:
-                        pq.put((new_cost, neighbor))
-                        D[neighbor] = new_cost
-    return D
-
-
-g = Graph(rows * cols)
-for i in range(rows):
-    for j in range(cols):
-
-        if i < rows - 1:
-            g.add_edge((i + 1) * cols + j, i * cols + j, risks[i][j])
-            g.add_edge(i * cols + j, (i + 1) * cols + j, risks[i + 1][j])
-
-        if j < cols - 1:
-            g.add_edge(i * cols + j + 1, i * cols + j, risks[i][j])
-            g.add_edge(i * cols + j, i * cols + j + 1, risks[i][j + 1])
-
+
+def wins(locations, winning_locations=winning_locations):
+    for winning_location in winning_locations:
+        if all(loc in locations for loc in winning_location):
+            return winning_location
+
+    return None
+
+
+plays = {}
+for i in range(len(boards)):
+    plays[i] = []
+
+num_plays = {}
+for i in range(len(boards)):
+    count = 0
+    for draw in draws:
+        count += 1
+        if draw in marks[i]:
+            plays[i].append(marks[i][draw])
+
+        if wins(plays[i]):
+            num_plays[i] = count, len(plays[i])
+            break
+
+
+fastest_win = min(num_plays, key=lambda x: num_plays[x][0])
+print(fastest_win)
 
-D = dijkstra(g, 0)
-print(f"Cost of shortest path is {D[rows*cols-1]}")
-
Day 13
 1
+
+sum_unmarked = 0
+for row in range(5):
+    for col in range(5):
+        if (row, col) not in plays[fastest_win]:
+            sum_unmarked += int(boards[fastest_win][row][col])
+
+row, col = plays[fastest_win][-1]
+num_call = int(boards[fastest_win][row][col])
+
+
+print(sum_unmarked, num_call)
+print(sum_unmarked * num_call)
+
Day 05
 1
  2
  3
  4
@@ -776,88 +566,38 @@
 29
 30
 31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
with open("day13_input.txt", "r") as f:
+32
with open("day05_input.txt", "r") as f:
     lines = f.read().splitlines()
 
-
-dots = []
-actions = []
-for line in lines:
-    if not line:
-        continue
-    if "," in line:
-        x, y = line.split(",")
-        dots.append((int(x), int(y)))
-    else:
-        actions.append(line.split()[-1].split("="))
-
-previous = dots[:]
-
-for axis, value in actions:
-    result = []
-    value = int(value)
-    if axis == "x":
-        for dot in previous:
-            if dot[0] < value:
-                result.append((dot[0], dot[1]))
-            else:
-                result.append((2 * value - dot[0], dot[1]))
-
-    elif axis == "y":
-        for dot in previous:
-            if dot[1] < value:
-                result.append((dot[0], dot[1]))
-            else:
-                result.append((dot[0], 2 * value - dot[1]))
-
-    print(len(set(result)))
-
-    previous = result[:]
-
-max_x = max(result, key=lambda x: x[0])[0]
-max_y = max(result, key=lambda x: x[1])[1]
-print(max_x, max_y)
-
-for y in range(max_y + 1):
-    for x in range(max_x + 1):
-        if (x, y) in result:
-            print("#", end="")
-        else:
-            print(" ", end="")
-    print()
-
-from PIL import Image
-
-img = Image.new("RGB", (max_x + 1, max_y + 1), "black")
-pixels = img.load()
-for dot in set(result):
-    pixels[dot[0], dot[1]] = (255, 255, 255)
-img.show()
+lines = [line.split(" -> ") for line in lines]
+lines = [(tuple(line[0].split(",")), tuple(line[1].split(","))) for line in lines]
+print(len(lines))
+
+lines = [
+    ((int(coord1[0]), int(coord1[1])), (int(coord2[0]), int(coord2[1])))
+    for coord1, coord2 in lines
+]
+
+from collections import Counter
+
+diagram = Counter()
+for coord1, coord2 in lines:
+    if coord1[0] == coord2[0]:
+        for i in range(min(coord1[1], coord2[1]), max(coord1[1], coord2[1]) + 1):
+            diagram[(coord1[0], i)] += 1
+    elif coord1[1] == coord2[1]:
+        for i in range(min(coord1[0], coord2[0]), max(coord1[0], coord2[0]) + 1):
+            diagram[(i, coord1[1])] += 1
+    else:
+        step_x = -1 if coord1[0] - coord2[0] > 0 else 1
+        step_y = -1 if coord1[1] - coord2[1] > 0 else 1
+        for x, y in zip(
+            range(coord1[0], coord2[0] + (1 if step_x > 0 else -1), step_x),
+            range(coord1[1], coord2[1] + (1 if step_y > 0 else -1), step_y),
+        ):
+            diagram[(x, y)] += 1
+
+print(len([i for i in diagram.values() if i > 1]))
 
 1
  2
  3
@@ -883,55 +623,33 @@
 23
 24
 25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
with open("day13_input.txt", "r") as f:
+26
with open("day05_input.txt", "r") as f:
     lines = f.read().splitlines()
 
-
-dots = []
-actions = []
-for line in lines:
-    if not line:
-        continue
-    if "," in line:
-        x, y = line.split(",")
-        dots.append((int(x), int(y)))
-    else:
-        actions.append(line.split()[-1].split("="))
-
-previous = dots[:]
-
-for axis, value in actions:
-    result = []
-    value = int(value)
-    if axis == "x":
-        for dot in previous:
-            if dot[0] < value:
-                result.append((dot[0], dot[1]))
-            else:
-                result.append((2 * value - dot[0], dot[1]))
-
-    elif axis == "y":
-        for dot in previous:
-            if dot[1] < value:
-                result.append((dot[0], dot[1]))
-            else:
-                result.append((dot[0], 2 * value - dot[1]))
-
-    print(len(set(result)))
-
-    previous = result[:]
-
Day 03
 1
+lines = [line.split(" -> ") for line in lines]
+lines = [(tuple(line[0].split(",")), tuple(line[1].split(","))) for line in lines]
+print(len(lines))
+
+lines = [
+    ((int(coord1[0]), int(coord1[1])), (int(coord2[0]), int(coord2[1])))
+    for coord1, coord2 in lines
+    if coord1[0] == coord2[0] or coord1[1] == coord2[1]
+]
+print(len(lines))
+
+from collections import Counter
+
+diagram = Counter()
+for coord1, coord2 in lines:
+    if coord1[0] == coord2[0]:
+        for i in range(min(coord1[1], coord2[1]), max(coord1[1], coord2[1]) + 1):
+            diagram[(coord1[0], i)] += 1
+    elif coord1[1] == coord2[1]:
+        for i in range(min(coord1[0], coord2[0]), max(coord1[0], coord2[0]) + 1):
+            diagram[(i, coord1[1])] += 1
+
+print(len([i for i in diagram.values() if i > 1]))
+
Day 06
 1
  2
  3
  4
@@ -950,34 +668,26 @@
 17
 18
 19
-20
-21
-22
-23
-24
with open("day03_input.txt", "r") as f:
-    data = f.read().splitlines()
+20
with open("day06_input.txt", "r") as f:
+    fish = [int(i) for i in f.read().strip().split(",")]
 
-cols = len(data[0])
-rows = len(data)
+
+from collections import Counter
 
-gamma_rate, epsilon_rate = "", ""
-
-for col in range(cols):
-    ones = 0
-    for row in range(rows):
-        if data[row][col] == "1":
-            ones += 1
-
-    if ones > rows / 2:
-        gamma_rate += "1"
-        epsilon_rate += "0"
-    else:
-        gamma_rate += "0"
-        epsilon_rate += "1"
-
-print(gamma_rate, epsilon_rate)
-
-print(int(gamma_rate, 2) * int(epsilon_rate, 2))
+fish = Counter(fish)
+print(fish)
+
+for _ in range(256):
+    for i in range(-1, 9):
+        if i == 8:
+            fish[i] = fish[-1]
+        elif i != 6:
+            fish[i] = fish[i + 1]
+        else:
+            fish[i] = fish[-1] + fish[i + 1]
+
+
+print(sum([v for k, v in fish.items() if k >= 0]))
 
 1
  2
  3
@@ -997,72 +707,26 @@
 17
 18
 19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
with open("day03_input.txt", "r") as f:
-    data = f.read().splitlines()
+20
with open("day06_input.txt", "r") as f:
+    fish = [int(i) for i in f.read().strip().split(",")]
 
-cols = len(data[0])
+print(f"Initial state: {fish}")
 
-oxygen_generator_rating, co2_scrubber_rating = "", ""
-
-selections = data[:]
-for col in range(cols):
-    ones = 0
-    for row in selections:
-        if row[col] == "1":
-            ones += 1
-
-    if ones >= len(selections) / 2:
-        selections = [row for row in selections if row[col] == "1"]
-    else:
-        selections = [row for row in selections if row[col] == "0"]
+for _ in range(80):
+    new_fish = []
+    for i in range(len(fish)):
+
+        fish[i] -= 1
+
+        if fish[i] < 0:
+            fish[i] = 6
+            new_fish.append(8)
+
+    fish.extend(new_fish)
+
+    print(f"After {str(_+1):2s} day{'s' if _ else ''}: {fish}")
 
-    if len(selections) == 1:
-        oxygen_generator_rating += selections[0]
-        break
-
-selections = data[:]
-for col in range(cols):
-    ones = 0
-    for row in selections:
-        if row[col] == "1":
-            ones += 1
-
-    if ones < len(selections) / 2:
-        selections = [row for row in selections if row[col] == "1"]
-    else:
-        selections = [row for row in selections if row[col] == "0"]
-
-    if len(selections) == 1:
-        co2_scrubber_rating += selections[0]
-        break
-
-
-print(oxygen_generator_rating, co2_scrubber_rating)
-
-print(int(oxygen_generator_rating, 2) * int(co2_scrubber_rating, 2))
+print(len(fish))
 
Day 07
 1
  2
  3
@@ -1145,7 +809,7 @@
 min_key = min(outcome, key=outcome.get)
 print(min_key)
 print(outcome[min_key])
-
Day 11
 1
+
Day 08
 1
  2
  3
  4
@@ -1212,96 +876,74 @@
 65
 66
 67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
with open("day11_input.txt", "r") as f:
-    obs = [[int(i) for i in line] for line in f.read().splitlines()]
+68
with open("day08_input.txt", "r") as f:
+    obs = [line.split(" | ") for line in f.read().splitlines()]
 
 
-def increase(obs):
-    for i in range(len(obs)):
-        for j in range(len(obs[i])):
-            obs[i][j] += 1
-
-
-def has_flash(obs):
-    locations = []
-    for i in range(len(obs)):
-        for j in range(len(obs[i])):
-            if obs[i][j] > 9:
-                locations.append((i, j))
-    return locations
-
-
-def display(obs):
-    for i in range(len(obs)):
-        print("".join([str(i) for i in obs[i]]))
-
-
-from collections import Counter
-
-
-print("Before any steps:")
-display(obs)
-print()
-
+def _sorted(digit):
+    return "".join(sorted(digit))
+
+
+def solve(digits):
+    mapping = {}
+    five_segs = []
+    six_segs = []
+
+    cf, bcdf, acf, abcdefg = None, None, None, None
+    for digit in digits:
+        if len(digit) == 2:
+            mapping[_sorted(digit)] = "1"
+            cf = digit
+        elif len(digit) == 3:
+            mapping[_sorted(digit)] = "7"
+            acf = digit
+        elif len(digit) == 4:
+            mapping[_sorted(digit)] = "4"
+            bcdf = digit
+        elif len(digit) == 7:
+            mapping[_sorted(digit)] = "8"
+            abcdefg = digit
+        elif len(digit) == 5:
+            five_segs.append(digit)
+        elif len(digit) == 6:
+            six_segs.append(digit)
 
-count = 0
-octopuses = sum([len(obs[i]) for i in range(len(obs))])
-while True:
-    increase(obs)
-
-    flashes = set()
-    while True:
-        locations = has_flash(obs)
-        flashes.update(locations)
-
-        if locations:
-            c = Counter()
-            for i, j in locations:
-                obs[i][j] = 0
-                if i > 0:
-                    c[(i - 1, j)] += 1
-                    if j > 0:
-                        c[(i - 1, j - 1)] += 1
-                    if j < len(obs[i]) - 1:
-                        c[(i - 1, j + 1)] += 1
-                if i < len(obs) - 1:
-                    c[(i + 1, j)] += 1
-                    if j > 0:
-                        c[(i + 1, j - 1)] += 1
-                    if j < len(obs[i]) - 1:
-                        c[(i + 1, j + 1)] += 1
-                if j > 0:
-                    c[(i, j - 1)] += 1
-                if j < len(obs[i]) - 1:
-                    c[(i, j + 1)] += 1
-            for i, j in c:
-                if (i, j) not in flashes:
-                    obs[i][j] += c[(i, j)]
-            if c:
-                continue
-        break
-
-    print(f"After step {count+1}:")
-    display(obs)
-    print(f"Flashes: {len(flashes)}")
-    print()
-
-    count += 1
-    if len(flashes) == octopuses:
-        break
-
-print(f"Total steps: {count}")
+    bd = set(bcdf) - set(cf)
+    eg = set(abcdefg) - (set(cf) | set(bcdf) | set(acf))
+
+    for digit in six_segs:
+        _digit = set(digit)
+        if _digit >= bd and _digit >= eg:
+            mapping[_sorted(digit)] = "6"
+        elif _digit >= bd:
+            mapping[_sorted(digit)] = "9"
+        elif _digit >= eg:
+            mapping[_sorted(digit)] = "0"
+
+    for digit in five_segs:
+        _digit = set(digit)
+        if _digit >= bd:
+            mapping[_sorted(digit)] = "5"
+        elif _digit >= eg:
+            mapping[_sorted(digit)] = "2"
+        else:
+            mapping[_sorted(digit)] = "3"
+
+    return mapping
+
+
+count = 0
+for o in obs:
+    output_values = o[1].split()
+    digits = o[0].split()
+    mapping = solve(digits)
+    value = ""
+    for digit in output_values:
+        value += mapping[_sorted(digit)]
+
+    count += int(value)
+
+print(count)
 
 1
  2
  3
@@ -1312,144 +954,18 @@
  8
  9
 10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
-28
-29
-30
-31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
with open("day11_input.txt", "r") as f:
-    obs = [[int(i) for i in line] for line in f.read().splitlines()]
+11
with open("day08_input.txt", "r") as f:
+    obs = [line.split(" | ") for line in f.read().splitlines()]
 
-
-def increase(obs):
-    for i in range(len(obs)):
-        for j in range(len(obs[i])):
-            obs[i][j] += 1
-
+count = 0
+for o in obs:
+    output_values = o[1].split()
+    for output_value in output_values:
+        if len(output_value) in [2, 3, 4, 7]:
+            count += 1
 
-def has_flash(obs):
-    locations = []
-    for i in range(len(obs)):
-        for j in range(len(obs[i])):
-            if obs[i][j] > 9:
-                locations.append((i, j))
-    return locations
-
-
-def display(obs):
-    for i in range(len(obs)):
-        print("".join([str(i) for i in obs[i]]))
-
-
-from collections import Counter
-
-print("Before any steps:")
-display(obs)
-print()
-
-count = 0
-for s in range(100):
-    increase(obs)
-
-    flashes = set()
-    while True:
-        locations = has_flash(obs)
-        flashes.update(locations)
-
-        if locations:
-            c = Counter()
-            for i, j in locations:
-                obs[i][j] = 0
-                if i > 0:
-                    c[(i - 1, j)] += 1
-                    if j > 0:
-                        c[(i - 1, j - 1)] += 1
-                    if j < len(obs[i]) - 1:
-                        c[(i - 1, j + 1)] += 1
-                if i < len(obs) - 1:
-                    c[(i + 1, j)] += 1
-                    if j > 0:
-                        c[(i + 1, j - 1)] += 1
-                    if j < len(obs[i]) - 1:
-                        c[(i + 1, j + 1)] += 1
-                if j > 0:
-                    c[(i, j - 1)] += 1
-                if j < len(obs[i]) - 1:
-                    c[(i, j + 1)] += 1
-            for i, j in c:
-                if (i, j) not in flashes:
-                    obs[i][j] += c[(i, j)]
-            if c:
-                continue
-        break
-
-    print(f"After step {s+1}:")
-    display(obs)
-    print(f"Flashes: {len(flashes)}")
-    print()
-
-    count += len(flashes)
-
-print(f"Total flashes: {count}")
-
Day 08
 1
+print(count)
+
Day 09
 1
  2
  3
  4
@@ -1516,74 +1032,96 @@
 65
 66
 67
-68
with open("day08_input.txt", "r") as f:
-    obs = [line.split(" | ") for line in f.read().splitlines()]
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
with open("day09_input.txt", "r") as f:
+    obs = [[int(i) for i in line] for line in f.read().splitlines()]
 
 
-def _sorted(digit):
-    return "".join(sorted(digit))
-
-
-def solve(digits):
-    mapping = {}
-    five_segs = []
-    six_segs = []
-
-    cf, bcdf, acf, abcdefg = None, None, None, None
-    for digit in digits:
-        if len(digit) == 2:
-            mapping[_sorted(digit)] = "1"
-            cf = digit
-        elif len(digit) == 3:
-            mapping[_sorted(digit)] = "7"
-            acf = digit
-        elif len(digit) == 4:
-            mapping[_sorted(digit)] = "4"
-            bcdf = digit
-        elif len(digit) == 7:
-            mapping[_sorted(digit)] = "8"
-            abcdefg = digit
-        elif len(digit) == 5:
-            five_segs.append(digit)
-        elif len(digit) == 6:
-            six_segs.append(digit)
-
-    bd = set(bcdf) - set(cf)
-    eg = set(abcdefg) - (set(cf) | set(bcdf) | set(acf))
-
-    for digit in six_segs:
-        _digit = set(digit)
-        if _digit >= bd and _digit >= eg:
-            mapping[_sorted(digit)] = "6"
-        elif _digit >= bd:
-            mapping[_sorted(digit)] = "9"
-        elif _digit >= eg:
-            mapping[_sorted(digit)] = "0"
-
-    for digit in five_segs:
-        _digit = set(digit)
-        if _digit >= bd:
-            mapping[_sorted(digit)] = "5"
-        elif _digit >= eg:
-            mapping[_sorted(digit)] = "2"
-        else:
-            mapping[_sorted(digit)] = "3"
-
-    return mapping
-
-
-count = 0
-for o in obs:
-    output_values = o[1].split()
-    digits = o[0].split()
-    mapping = solve(digits)
-    value = ""
-    for digit in output_values:
-        value += mapping[_sorted(digit)]
-
-    count += int(value)
-
-print(count)
+low_points = []
+for i in range(0, len(obs)):
+    for j in range(0, len(obs[i])):
+        to_compare = []
+        if i > 0:
+            to_compare.append(obs[i - 1][j])
+        if i < len(obs) - 1:
+            to_compare.append(obs[i + 1][j])
+        if j > 0:
+            to_compare.append(obs[i][j - 1])
+        if j < len(obs[i]) - 1:
+            to_compare.append(obs[i][j + 1])
+
+        if all(obs[i][j] < x for x in to_compare):
+            low_points.append((i, j))
+
+basin_sizes = []
+
+
+def find_basin(i, j, points):
+    points.append((i, j))
+
+    up = i
+    while True:
+        if up > 0:
+            if obs[up - 1][j] > obs[up][j] and obs[up - 1][j] < 9:
+                find_basin(up - 1, j, points)
+                up -= 1
+            else:
+                break
+        else:
+            break
+
+    down = i
+    while True:
+        if down < len(obs) - 1:
+            if obs[down + 1][j] > obs[down][j] and obs[down + 1][j] < 9:
+                find_basin(down + 1, j, points)
+                down += 1
+            else:
+                break
+        else:
+            break
+
+    left = j
+    while True:
+        if left > 0:
+            if obs[i][left - 1] > obs[i][left] and obs[i][left - 1] < 9:
+                find_basin(i, left - 1, points)
+                left -= 1
+            else:
+                break
+        else:
+            break
+
+    right = j
+    while True:
+        if right < len(obs[i]) - 1:
+            if obs[i][right + 1] > obs[i][right] and obs[i][right + 1] < 9:
+                find_basin(i, right + 1, points)
+                right += 1
+            else:
+                break
+        else:
+            break
+
+
+for i, j in low_points:
+    points = []
+    find_basin(i, j, points)
+    basin_sizes.append(len(set(points)))
+
+import functools
+
+print(functools.reduce(lambda x, y: x * y, sorted(basin_sizes)[-3:]))
 
 1
  2
  3
@@ -1594,18 +1132,40 @@
  8
  9
 10
-11
with open("day08_input.txt", "r") as f:
-    obs = [line.split(" | ") for line in f.read().splitlines()]
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
with open("day09_input.txt", "r") as f:
+    obs = [[int(i) for i in line] for line in f.read().splitlines()]
 
-count = 0
-for o in obs:
-    output_values = o[1].split()
-    for output_value in output_values:
-        if len(output_value) in [2, 3, 4, 7]:
-            count += 1
-
-print(count)
-
Day 16
 1
+
+low_points = []
+for i in range(0, len(obs)):
+    for j in range(0, len(obs[i])):
+        to_compare = []
+        if i > 0:
+            to_compare.append(obs[i - 1][j])
+        if i < len(obs) - 1:
+            to_compare.append(obs[i + 1][j])
+        if j > 0:
+            to_compare.append(obs[i][j - 1])
+        if j < len(obs[i]) - 1:
+            to_compare.append(obs[i][j + 1])
+
+        if all(obs[i][j] < x for x in to_compare):
+            low_points.append(obs[i][j])
+
+
+print(sum(low_points) + len(low_points))
+
Day 10
 1
  2
  3
  4
@@ -1651,149 +1211,123 @@
 44
 45
 46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
-80
-81
-82
-83
-84
-85
-86
with open("day16_input.txt", "r") as f:
-    hexadecimal = f.read().strip()
+47
with open("day10_input.txt", "r") as f:
+    lines = f.read().splitlines()
 
-print(f"Hex: {hexadecimal}")
-
-
-def hex2bin(h):
-    return bin(int(h, 16))[2:].zfill(len(h) * 4)
-
-
-b = hex2bin(hexadecimal)
-print(f"Bin: {b}")
-
-print()
-
-
-def decode_header(b):
-    packet_version = b[:3]
-    packet_type_id = b[3:6]
-
-    return int(packet_version, 2), int(packet_type_id, 2), b[6:]
-
-
-def decode_literal(b):
-    value = ""
-
-    while b:
-        seg = b[:5]
-        value += seg[-4:]
-        b = b[5:]
-        if seg[0] == "0":
-            break
-
-    return value, b
-
-
-def decode_operator(b):
-    length_type_id = b[:1]
-
-    if length_type_id == "0":
-        length_of_subpackets = int(b[1:16], 2)
+
+mapping = {
+    "(": 1,
+    "[": 2,
+    "{": 3,
+    "<": 4,
+}
+
+match = {
+    ")": "(",
+    "]": "[",
+    "}": "{",
+    ">": "<",
+}
+
+
+def check(line):
+    stack = []
+    for c in line:
+        if c in match.values():
+            stack.append(c)
+        elif c in match.keys():
+            if len(stack) == 0:
+                return 0
+            last = stack.pop()
+            if last != match[c]:
+                return 0
+
+    if len(stack) == 0:
+        return 0
+
+    score = 0
+    while len(stack) > 0:
+        last = stack.pop()
+        score *= 5
+        score += mapping[last]
+
+    return score
 
-        remaining = b[16 + length_of_subpackets :]
-        b = b[16 : 16 + length_of_subpackets]
-        number_of_subpackets = -1
-    else:
-        number_of_subpackets = int(b[1:12], 2)
-        b = b[12:]
-        remaining = None
-
-    return length_type_id, number_of_subpackets, b, remaining
-
-
-result = []
-
-
-def decode(b):
-    while b:
-        if all(c == "0" for c in b):
-            return
-
-        packet_version, packet_type_id, b = decode_header(b)
-        result.append(packet_version)
-        print(f"packet_version: {packet_version}, packet_type_id: {packet_type_id}")
-        if packet_type_id == 4:
-            value, b = decode_literal(b)
-            print(f"Literal value {value} is {int(value, 2)}.")
-        else:
-            length_type_id, number_of_subpackets, block, remaining = decode_operator(b)
-            print(
-                f"length_type_id: {length_type_id},",
-                f"number_of_subpackets: {number_of_subpackets},",
-            )
-            if number_of_subpackets == -1:
-                b = remaining
-                decode(block)
-            else:
-                b = block
-                return decode(b)
-
-    return
-
-
-decode(b)
-print()
-print(f"Result: {result} -> {sum(result)}")
-
Day 01
1
-2
-3
-4
-5
-6
-7
-8
-9
with open("day01_input.txt", "r") as f:
-    data = [int(i) for i in f.read().splitlines()]
+
+scores = [check(line) for line in lines]
+scores = [s for s in scores if s > 0]
+print(len(scores))
+print(sorted(scores)[len(scores) // 2])
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
with open("day10_input.txt", "r") as f:
+    lines = f.read().splitlines()
 
-count = 0
-for i in range(1, len(data)):
-    if data[i] > data[i - 1]:
-        count += 1
-
-print(count)
-
 1
+
+mapping = {
+    ")": 3,
+    "]": 57,
+    "}": 1197,
+    ">": 25137,
+}
+
+match = {
+    ")": "(",
+    "]": "[",
+    "}": "{",
+    ">": "<",
+}
+
+
+def check(line):
+    stack = []
+    for c in line:
+        if c in match.values():
+            stack.append(c)
+        elif c in match.keys():
+            if len(stack) == 0:
+                return mapping[c]
+            last = stack.pop()
+            if last != match[c]:
+                return mapping[c]
+
+    return 0
+
+
+print(sum(check(line) for line in lines))
+
Day 11
 1
  2
  3
  4
@@ -1805,20 +1339,152 @@
 10
 11
 12
-13
with open("day01_input.txt", "r") as f:
-    data = [int(i) for i in f.read().splitlines()]
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
with open("day11_input.txt", "r") as f:
+    obs = [[int(i) for i in line] for line in f.read().splitlines()]
 
-three_measurement_data = []
-for i in range(2, len(data)):
-    three_measurement_data.append(sum(data[i - 2 : i + 1]))
-
-count = 0
-for i in range(1, len(three_measurement_data)):
-    if three_measurement_data[i] > three_measurement_data[i - 1]:
-        count += 1
-
-print(count)
-
Day 12
 1
+
+def increase(obs):
+    for i in range(len(obs)):
+        for j in range(len(obs[i])):
+            obs[i][j] += 1
+
+
+def has_flash(obs):
+    locations = []
+    for i in range(len(obs)):
+        for j in range(len(obs[i])):
+            if obs[i][j] > 9:
+                locations.append((i, j))
+    return locations
+
+
+def display(obs):
+    for i in range(len(obs)):
+        print("".join([str(i) for i in obs[i]]))
+
+
+from collections import Counter
+
+
+print("Before any steps:")
+display(obs)
+print()
+
+
+count = 0
+octopuses = sum([len(obs[i]) for i in range(len(obs))])
+while True:
+    increase(obs)
+
+    flashes = set()
+    while True:
+        locations = has_flash(obs)
+        flashes.update(locations)
+
+        if locations:
+            c = Counter()
+            for i, j in locations:
+                obs[i][j] = 0
+                if i > 0:
+                    c[(i - 1, j)] += 1
+                    if j > 0:
+                        c[(i - 1, j - 1)] += 1
+                    if j < len(obs[i]) - 1:
+                        c[(i - 1, j + 1)] += 1
+                if i < len(obs) - 1:
+                    c[(i + 1, j)] += 1
+                    if j > 0:
+                        c[(i + 1, j - 1)] += 1
+                    if j < len(obs[i]) - 1:
+                        c[(i + 1, j + 1)] += 1
+                if j > 0:
+                    c[(i, j - 1)] += 1
+                if j < len(obs[i]) - 1:
+                    c[(i, j + 1)] += 1
+            for i, j in c:
+                if (i, j) not in flashes:
+                    obs[i][j] += c[(i, j)]
+            if c:
+                continue
+        break
+
+    print(f"After step {count+1}:")
+    display(obs)
+    print(f"Flashes: {len(flashes)}")
+    print()
+
+    count += 1
+    if len(flashes) == octopuses:
+        break
+
+print(f"Total steps: {count}")
+
 1
  2
  3
  4
@@ -1862,52 +1528,110 @@
 42
 43
 44
-45
with open("day12_input.txt", "r") as f:
-    segs = f.read().splitlines()
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
with open("day11_input.txt", "r") as f:
+    obs = [[int(i) for i in line] for line in f.read().splitlines()]
 
 
-graph = {}
-for seg in segs:
-    node1, node2 = seg.split("-")
-    if node1 not in graph:
-        graph[node1] = [node2]
-    else:
-        graph[node1].append(node2)
-
-    if node2 not in graph:
-        graph[node2] = [node1]
-    else:
-        graph[node2].append(node1)
-
-from pprint import pprint
+def increase(obs):
+    for i in range(len(obs)):
+        for j in range(len(obs[i])):
+            obs[i][j] += 1
+
+
+def has_flash(obs):
+    locations = []
+    for i in range(len(obs)):
+        for j in range(len(obs[i])):
+            if obs[i][j] > 9:
+                locations.append((i, j))
+    return locations
+
 
-pprint(graph)
-
-
-paths = []
+def display(obs):
+    for i in range(len(obs)):
+        print("".join([str(i) for i in obs[i]]))
+
 
-
-def breadth_first_search(graph, start, end, path=[]):
-    path = path + [start]
-    if start == end:
-        paths.append(path)
-    if start not in graph:
-        return None
-    for node in graph[start]:
-        if node not in path or node.isupper():
-            newpath = breadth_first_search(graph, node, end, path)
-            if newpath:
-                paths.append(newpath)
-    return None
-
+from collections import Counter
+
+print("Before any steps:")
+display(obs)
+print()
+
+count = 0
+for s in range(100):
+    increase(obs)
+
+    flashes = set()
+    while True:
+        locations = has_flash(obs)
+        flashes.update(locations)
 
-breadth_first_search(graph, "start", "end")
-
-for path in paths:
-    print(",".join(path))
-
-print(len(paths))
-
 1
+        if locations:
+            c = Counter()
+            for i, j in locations:
+                obs[i][j] = 0
+                if i > 0:
+                    c[(i - 1, j)] += 1
+                    if j > 0:
+                        c[(i - 1, j - 1)] += 1
+                    if j < len(obs[i]) - 1:
+                        c[(i - 1, j + 1)] += 1
+                if i < len(obs) - 1:
+                    c[(i + 1, j)] += 1
+                    if j > 0:
+                        c[(i + 1, j - 1)] += 1
+                    if j < len(obs[i]) - 1:
+                        c[(i + 1, j + 1)] += 1
+                if j > 0:
+                    c[(i, j - 1)] += 1
+                if j < len(obs[i]) - 1:
+                    c[(i, j + 1)] += 1
+            for i, j in c:
+                if (i, j) not in flashes:
+                    obs[i][j] += c[(i, j)]
+            if c:
+                continue
+        break
+
+    print(f"After step {s+1}:")
+    display(obs)
+    print(f"Flashes: {len(flashes)}")
+    print()
+
+    count += len(flashes)
+
+print(f"Total flashes: {count}")
+
Day 12
 1
  2
  3
  4
@@ -1951,25 +1675,7 @@
 42
 43
 44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
with open("day12_input.txt", "r") as f:
+45
with open("day12_input.txt", "r") as f:
     segs = f.read().splitlines()
 
 
@@ -1994,45 +1700,27 @@
 paths = []
 
 
-def remaining(path, node):
-    others = [
-        n for n in path if n != node and n.islower() and n not in ["start", "end"]
-    ]
-
-    return all(path.count(n) <= 1 for n in others)
-
-
-def breadth_first_search(graph, start, end, path=[]):
-
-    path = path + [start]
-    if start == end:
-        paths.append(path)
-    if start not in graph:
-        return None
-    for node in graph[start]:
-        if (
-            node not in path
-            or node.isupper()
-            or (
-                node not in ["start", "end"]
-                and node.islower()
-                and path.count(node) < 2
-                and remaining(path, node)
-            )
-        ):
-            newpath = breadth_first_search(graph, node, end, path)
-            if newpath:
-                paths.append(newpath)
-    return None
-
-
-breadth_first_search(graph, "start", "end")
-
-for path in paths:
-    print(",".join(path))
-
-print(len(paths))
-
Day 02
 1
+def breadth_first_search(graph, start, end, path=[]):
+    path = path + [start]
+    if start == end:
+        paths.append(path)
+    if start not in graph:
+        return None
+    for node in graph[start]:
+        if node not in path or node.isupper():
+            newpath = breadth_first_search(graph, node, end, path)
+            if newpath:
+                paths.append(newpath)
+    return None
+
+
+breadth_first_search(graph, "start", "end")
+
+for path in paths:
+    print(",".join(path))
+
+print(len(paths))
+
 1
  2
  3
  4
@@ -2048,24 +1736,116 @@
 14
 15
 16
-17
with open("day02_input.txt", "r") as f:
-    data = [cmd.split() for cmd in f.read().splitlines()]
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
with open("day12_input.txt", "r") as f:
+    segs = f.read().splitlines()
 
-horizontal_position, depth = 0, 0
-
-for action, value in data:
-    value = int(value)
-    if action == "forward":
-        horizontal_position += value
-    elif action == "up":
-        depth -= value
-    elif action == "down":
-        depth += value
-
-print(horizontal_position, depth)
-
-print(horizontal_position * depth)
-
 1
+
+graph = {}
+for seg in segs:
+    node1, node2 = seg.split("-")
+    if node1 not in graph:
+        graph[node1] = [node2]
+    else:
+        graph[node1].append(node2)
+
+    if node2 not in graph:
+        graph[node2] = [node1]
+    else:
+        graph[node2].append(node1)
+
+from pprint import pprint
+
+pprint(graph)
+
+
+paths = []
+
+
+def remaining(path, node):
+    others = [
+        n for n in path if n != node and n.islower() and n not in ["start", "end"]
+    ]
+
+    return all(path.count(n) <= 1 for n in others)
+
+
+def breadth_first_search(graph, start, end, path=[]):
+
+    path = path + [start]
+    if start == end:
+        paths.append(path)
+    if start not in graph:
+        return None
+    for node in graph[start]:
+        if (
+            node not in path
+            or node.isupper()
+            or (
+                node not in ["start", "end"]
+                and node.islower()
+                and path.count(node) < 2
+                and remaining(path, node)
+            )
+        ):
+            newpath = breadth_first_search(graph, node, end, path)
+            if newpath:
+                paths.append(newpath)
+    return None
+
+
+breadth_first_search(graph, "start", "end")
+
+for path in paths:
+    print(",".join(path))
+
+print(len(paths))
+
Day 13
 1
  2
  3
  4
@@ -2083,26 +1863,102 @@
 16
 17
 18
-19
with open("day02_input.txt", "r") as f:
-    data = [cmd.split() for cmd in f.read().splitlines()]
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
with open("day13_input.txt", "r") as f:
+    lines = f.read().splitlines()
 
-horizontal_position, depth, aim = 0, 0, 0
-
-for action, value in data:
-    value = int(value)
-    if action == "forward":
-        horizontal_position += value
-        depth += aim * value
-    elif action == "up":
-        aim -= value
-    elif action == "down":
-        aim += value
+
+dots = []
+actions = []
+for line in lines:
+    if not line:
+        continue
+    if "," in line:
+        x, y = line.split(",")
+        dots.append((int(x), int(y)))
+    else:
+        actions.append(line.split()[-1].split("="))
 
-
-print(horizontal_position, depth, aim)
-
-print(horizontal_position * depth)
-
Day 14
 1
+previous = dots[:]
+
+for axis, value in actions:
+    result = []
+    value = int(value)
+    if axis == "x":
+        for dot in previous:
+            if dot[0] < value:
+                result.append((dot[0], dot[1]))
+            else:
+                result.append((2 * value - dot[0], dot[1]))
+
+    elif axis == "y":
+        for dot in previous:
+            if dot[1] < value:
+                result.append((dot[0], dot[1]))
+            else:
+                result.append((dot[0], 2 * value - dot[1]))
+
+    print(len(set(result)))
+
+    previous = result[:]
+
+max_x = max(result, key=lambda x: x[0])[0]
+max_y = max(result, key=lambda x: x[1])[1]
+print(max_x, max_y)
+
+for y in range(max_y + 1):
+    for x in range(max_x + 1):
+        if (x, y) in result:
+            print("#", end="")
+        else:
+            print(" ", end="")
+    print()
+
+from PIL import Image
+
+img = Image.new("RGB", (max_x + 1, max_y + 1), "black")
+pixels = img.load()
+for dot in set(result):
+    pixels[dot[0], dot[1]] = (255, 255, 255)
+img.show()
+
 1
  2
  3
  4
@@ -2138,54 +1994,44 @@
 34
 35
 36
-37
-38
-39
-40
-41
-42
with open("day14_input.txt", "r") as f:
+37
with open("day13_input.txt", "r") as f:
     lines = f.read().splitlines()
 
 
-template = None
-pairs = []
+dots = []
+actions = []
 for line in lines:
     if not line:
         continue
-    if " -> " in line:
-        pairs.append(line.split(" -> "))
-    else:
-        template = line
-
-print(f"Template: {template}")
-segs = [template[j : j + 2] for j in range(0, len(template) - 1)]
+    if "," in line:
+        x, y = line.split(",")
+        dots.append((int(x), int(y)))
+    else:
+        actions.append(line.split()[-1].split("="))
+
+previous = dots[:]
 
-from collections import Counter
-
-counts = Counter(segs)
-
-
-for i in range(40):
-    result = Counter()
-    for key in counts:
-        for pair in pairs:
-            if key == pair[0]:
-                result[key[0] + pair[1]] += counts[key]
-                result[pair[1] + key[1]] += counts[pair[0]]
-
-    counts = result
-
-
-chars = Counter()
-chars[template[0]] += 1
+for axis, value in actions:
+    result = []
+    value = int(value)
+    if axis == "x":
+        for dot in previous:
+            if dot[0] < value:
+                result.append((dot[0], dot[1]))
+            else:
+                result.append((2 * value - dot[0], dot[1]))
+
+    elif axis == "y":
+        for dot in previous:
+            if dot[1] < value:
+                result.append((dot[0], dot[1]))
+            else:
+                result.append((dot[0], 2 * value - dot[1]))
+
+    print(len(set(result)))
 
-for key, value in counts.items():
-    chars[key[1]] += value
-
-chars = chars.most_common()
-print(chars)
-print(chars[0][1] - chars[-1][1])
-
 1
+    previous = result[:]
+
Day 14
 1
  2
  3
  4
@@ -2219,7 +2065,14 @@
 32
 33
 34
-35
with open("day14_input.txt", "r") as f:
+35
+36
+37
+38
+39
+40
+41
+42
with open("day14_input.txt", "r") as f:
     lines = f.read().splitlines()
 
 
@@ -2234,27 +2087,34 @@
         template = line
 
 print(f"Template: {template}")
-
-for i in range(10):
-    segs = [template[j : j + 2] for j in range(0, len(template) - 1)]
+segs = [template[j : j + 2] for j in range(0, len(template) - 1)]
+
+from collections import Counter
 
-    for k in range(len(segs)):
-        for pair in pairs:
-            if segs[k] == pair[0]:
-                segs[k] = pair[0][0] + pair[1] + pair[0][1]
-
-    template = segs[0]
-    for seg in segs[1:]:
-        template += seg[-2:]
-
-    print(f"After step {i+1}: {template}")
+counts = Counter(segs)
+
+
+for i in range(40):
+    result = Counter()
+    for key in counts:
+        for pair in pairs:
+            if key == pair[0]:
+                result[key[0] + pair[1]] += counts[key]
+                result[pair[1] + key[1]] += counts[pair[0]]
 
-from collections import Counter
+    counts = result
 
-counts = Counter(template).most_common()
-
-print(counts[0][1] - counts[-1][1])
-
Day 09
 1
+
+chars = Counter()
+chars[template[0]] += 1
+
+for key, value in counts.items():
+    chars[key[1]] += value
+
+chars = chars.most_common()
+print(chars)
+print(chars[0][1] - chars[-1][1])
+
 1
  2
  3
  4
@@ -2288,130 +2148,42 @@
 32
 33
 34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
-45
-46
-47
-48
-49
-50
-51
-52
-53
-54
-55
-56
-57
-58
-59
-60
-61
-62
-63
-64
-65
-66
-67
-68
-69
-70
-71
-72
-73
-74
-75
-76
-77
-78
-79
with open("day09_input.txt", "r") as f:
-    obs = [[int(i) for i in line] for line in f.read().splitlines()]
+35
with open("day14_input.txt", "r") as f:
+    lines = f.read().splitlines()
 
 
-low_points = []
-for i in range(0, len(obs)):
-    for j in range(0, len(obs[i])):
-        to_compare = []
-        if i > 0:
-            to_compare.append(obs[i - 1][j])
-        if i < len(obs) - 1:
-            to_compare.append(obs[i + 1][j])
-        if j > 0:
-            to_compare.append(obs[i][j - 1])
-        if j < len(obs[i]) - 1:
-            to_compare.append(obs[i][j + 1])
-
-        if all(obs[i][j] < x for x in to_compare):
-            low_points.append((i, j))
-
-basin_sizes = []
-
-
-def find_basin(i, j, points):
-    points.append((i, j))
-
-    up = i
-    while True:
-        if up > 0:
-            if obs[up - 1][j] > obs[up][j] and obs[up - 1][j] < 9:
-                find_basin(up - 1, j, points)
-                up -= 1
-            else:
-                break
-        else:
-            break
-
-    down = i
-    while True:
-        if down < len(obs) - 1:
-            if obs[down + 1][j] > obs[down][j] and obs[down + 1][j] < 9:
-                find_basin(down + 1, j, points)
-                down += 1
-            else:
-                break
-        else:
-            break
-
-    left = j
-    while True:
-        if left > 0:
-            if obs[i][left - 1] > obs[i][left] and obs[i][left - 1] < 9:
-                find_basin(i, left - 1, points)
-                left -= 1
-            else:
-                break
-        else:
-            break
-
-    right = j
-    while True:
-        if right < len(obs[i]) - 1:
-            if obs[i][right + 1] > obs[i][right] and obs[i][right + 1] < 9:
-                find_basin(i, right + 1, points)
-                right += 1
-            else:
-                break
-        else:
-            break
-
-
-for i, j in low_points:
-    points = []
-    find_basin(i, j, points)
-    basin_sizes.append(len(set(points)))
-
-import functools
-
-print(functools.reduce(lambda x, y: x * y, sorted(basin_sizes)[-3:]))
-
 1
+template = None
+pairs = []
+for line in lines:
+    if not line:
+        continue
+    if " -> " in line:
+        pairs.append(line.split(" -> "))
+    else:
+        template = line
+
+print(f"Template: {template}")
+
+for i in range(10):
+    segs = [template[j : j + 2] for j in range(0, len(template) - 1)]
+
+    for k in range(len(segs)):
+        for pair in pairs:
+            if segs[k] == pair[0]:
+                segs[k] = pair[0][0] + pair[1] + pair[0][1]
+
+    template = segs[0]
+    for seg in segs[1:]:
+        template += seg[-2:]
+
+    print(f"After step {i+1}: {template}")
+
+from collections import Counter
+
+counts = Counter(template).most_common()
+
+print(counts[0][1] - counts[-1][1])
+
Day 15
 1
  2
  3
  4
@@ -2432,29 +2204,81 @@
 19
 20
 21
-22
with open("day09_input.txt", "r") as f:
-    obs = [[int(i) for i in line] for line in f.read().splitlines()]
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
with open("day15_input.txt", "r") as f:
+    lines = [[int(d) for d in line] for line in f.read().splitlines()]
 
-
-low_points = []
-for i in range(0, len(obs)):
-    for j in range(0, len(obs[i])):
-        to_compare = []
-        if i > 0:
-            to_compare.append(obs[i - 1][j])
-        if i < len(obs) - 1:
-            to_compare.append(obs[i + 1][j])
-        if j > 0:
-            to_compare.append(obs[i][j - 1])
-        if j < len(obs[i]) - 1:
-            to_compare.append(obs[i][j + 1])
-
-        if all(obs[i][j] < x for x in to_compare):
-            low_points.append(obs[i][j])
+rows, cols = len(lines), len(lines[0])
+
+
+lines_5x = [[0] * cols * 5 for i in range(rows * 5)]
+for ii in range(5):
+    for jj in range(5):
+        for i in range(rows):
+            for j in range(cols):
+                lines_5x[ii * rows + i][jj * cols + j] = (
+                    lines[i][j] + ii + jj - 1
+                ) % 9 + 1
+
+
+# Using the networkx library instead
+
+import networkx as nx
 
-
-print(sum(low_points) + len(low_points))
-
Day 05
 1
+g = nx.DiGraph()
+rows *= 5
+cols *= 5
+
+for i in range(rows):
+    for j in range(cols):
+        if i < rows - 1:
+            g.add_edge((i, j), (i + 1, j), weight=lines_5x[i + 1][j])
+            g.add_edge((i + 1, j), (i, j), weight=lines_5x[i][j])
+
+        if j < cols - 1:
+            g.add_edge((i, j), (i, j + 1), weight=lines_5x[i][j + 1])
+            g.add_edge((i, j + 1), (i, j), weight=lines_5x[i][j])
+
+paths = nx.shortest_path(
+    g,
+    source=(0, 0),
+    target=(rows - 1, cols - 1),
+    weight="weight",
+)
+
+# print(paths)
+
+cost = 0
+for i, j in paths[1:]:
+    cost += lines_5x[i][j]
+
+print(f"Cost of shortest path is {cost}")
+
 1
  2
  3
  4
@@ -2485,39 +2309,95 @@
 29
 30
 31
-32
with open("day05_input.txt", "r") as f:
-    lines = f.read().splitlines()
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
with open("day15_input.txt", "r") as f:
+    risks = [[int(d) for d in line] for line in f.read().splitlines()]
 
-lines = [line.split(" -> ") for line in lines]
-lines = [(tuple(line[0].split(",")), tuple(line[1].split(","))) for line in lines]
-print(len(lines))
+rows, cols = len(risks), len(risks[0])
+
+# reference: https://stackabuse.com/dijkstras-algorithm-in-python/
 
-lines = [
-    ((int(coord1[0]), int(coord1[1])), (int(coord2[0]), int(coord2[1])))
-    for coord1, coord2 in lines
-]
-
-from collections import Counter
-
-diagram = Counter()
-for coord1, coord2 in lines:
-    if coord1[0] == coord2[0]:
-        for i in range(min(coord1[1], coord2[1]), max(coord1[1], coord2[1]) + 1):
-            diagram[(coord1[0], i)] += 1
-    elif coord1[1] == coord2[1]:
-        for i in range(min(coord1[0], coord2[0]), max(coord1[0], coord2[0]) + 1):
-            diagram[(i, coord1[1])] += 1
-    else:
-        step_x = -1 if coord1[0] - coord2[0] > 0 else 1
-        step_y = -1 if coord1[1] - coord2[1] > 0 else 1
-        for x, y in zip(
-            range(coord1[0], coord2[0] + (1 if step_x > 0 else -1), step_x),
-            range(coord1[1], coord2[1] + (1 if step_y > 0 else -1), step_y),
-        ):
-            diagram[(x, y)] += 1
-
-print(len([i for i in diagram.values() if i > 1]))
-
 1
+from queue import PriorityQueue
+
+
+class Graph:
+    def __init__(self, num_of_vertices):
+        self.v = num_of_vertices
+        self.edges = [
+            [-1 for i in range(num_of_vertices)] for j in range(num_of_vertices)
+        ]
+        self.visited = []
+
+    def add_edge(self, u, v, weight):
+        self.edges[u][v] = weight
+
+
+def dijkstra(graph, start_vertex):
+    D = {v: float("inf") for v in range(graph.v)}
+    D[start_vertex] = 0
+
+    pq = PriorityQueue()
+    pq.put((0, start_vertex))
+
+    while not pq.empty():
+        (dist, current_vertex) = pq.get()
+        graph.visited.append(current_vertex)
+
+        for neighbor in range(graph.v):
+            if graph.edges[current_vertex][neighbor] != -1:
+                distance = graph.edges[current_vertex][neighbor]
+                if neighbor not in graph.visited:
+                    old_cost = D[neighbor]
+                    new_cost = D[current_vertex] + distance
+                    if new_cost < old_cost:
+                        pq.put((new_cost, neighbor))
+                        D[neighbor] = new_cost
+    return D
+
+
+g = Graph(rows * cols)
+for i in range(rows):
+    for j in range(cols):
+
+        if i < rows - 1:
+            g.add_edge((i + 1) * cols + j, i * cols + j, risks[i][j])
+            g.add_edge(i * cols + j, (i + 1) * cols + j, risks[i + 1][j])
+
+        if j < cols - 1:
+            g.add_edge(i * cols + j + 1, i * cols + j, risks[i][j])
+            g.add_edge(i * cols + j, i * cols + j + 1, risks[i][j + 1])
+
+
+D = dijkstra(g, 0)
+print(f"Cost of shortest path is {D[rows*cols-1]}")
+
Day 16
 1
  2
  3
  4
@@ -2542,30 +2422,150 @@
 23
 24
 25
-26
with open("day05_input.txt", "r") as f:
-    lines = f.read().splitlines()
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
with open("day16_input.txt", "r") as f:
+    hexadecimal = f.read().strip()
 
-lines = [line.split(" -> ") for line in lines]
-lines = [(tuple(line[0].split(",")), tuple(line[1].split(","))) for line in lines]
-print(len(lines))
-
-lines = [
-    ((int(coord1[0]), int(coord1[1])), (int(coord2[0]), int(coord2[1])))
-    for coord1, coord2 in lines
-    if coord1[0] == coord2[0] or coord1[1] == coord2[1]
-]
-print(len(lines))
-
-from collections import Counter
+print(f"Hex: {hexadecimal}")
+
+
+def hex2bin(h):
+    return bin(int(h, 16))[2:].zfill(len(h) * 4)
+
+
+b = hex2bin(hexadecimal)
+print(f"Bin: {b}")
+
+print()
+
 
-diagram = Counter()
-for coord1, coord2 in lines:
-    if coord1[0] == coord2[0]:
-        for i in range(min(coord1[1], coord2[1]), max(coord1[1], coord2[1]) + 1):
-            diagram[(coord1[0], i)] += 1
-    elif coord1[1] == coord2[1]:
-        for i in range(min(coord1[0], coord2[0]), max(coord1[0], coord2[0]) + 1):
-            diagram[(i, coord1[1])] += 1
-
-print(len([i for i in diagram.values() if i > 1]))
+def decode_header(b):
+    packet_version = b[:3]
+    packet_type_id = b[3:6]
+
+    return int(packet_version, 2), int(packet_type_id, 2), b[6:]
+
+
+def decode_literal(b):
+    value = ""
+
+    while b:
+        seg = b[:5]
+        value += seg[-4:]
+        b = b[5:]
+        if seg[0] == "0":
+            break
+
+    return value, b
+
+
+def decode_operator(b):
+    length_type_id = b[:1]
+
+    if length_type_id == "0":
+        length_of_subpackets = int(b[1:16], 2)
+
+        remaining = b[16 + length_of_subpackets :]
+        b = b[16 : 16 + length_of_subpackets]
+        number_of_subpackets = -1
+    else:
+        number_of_subpackets = int(b[1:12], 2)
+        b = b[12:]
+        remaining = None
+
+    return length_type_id, number_of_subpackets, b, remaining
+
+
+result = []
+
+
+def decode(b):
+    while b:
+        if all(c == "0" for c in b):
+            return
+
+        packet_version, packet_type_id, b = decode_header(b)
+        result.append(packet_version)
+        print(f"packet_version: {packet_version}, packet_type_id: {packet_type_id}")
+        if packet_type_id == 4:
+            value, b = decode_literal(b)
+            print(f"Literal value {value} is {int(value, 2)}.")
+        else:
+            length_type_id, number_of_subpackets, block, remaining = decode_operator(b)
+            print(
+                f"length_type_id: {length_type_id},",
+                f"number_of_subpackets: {number_of_subpackets},",
+            )
+            if number_of_subpackets == -1:
+                b = remaining
+                decode(block)
+            else:
+                b = block
+                return decode(b)
+
+    return
+
+
+decode(b)
+print()
+print(f"Result: {result} -> {sum(result)}")
 
\ No newline at end of file diff --git a/2022/index.html b/2022/index.html index d28d955..bef3702 100644 --- a/2022/index.html +++ b/2022/index.html @@ -9,7 +9,7 @@ body[data-md-color-scheme="slate"] .gdesc-inner { background: var(--md-default-bg-color);} body[data-md-color-scheme="slate"] .gslide-title { color: var(--md-default-fg-color);} body[data-md-color-scheme="slate"] .gslide-desc { color: var(--md-default-fg-color);} -

Advent of Code 2022

Day 04
 1
+                  

Advent of Code 2022

Day 01
 1
  2
  3
  4
@@ -21,29 +21,19 @@
 10
 11
 12
-13
-14
-15
-16
-17
-18
count = 0
-
-with open("day04_input.txt") as f:
-    sections = f.readlines()
-    for section in sections:
-        section = section.strip()
-        r1, r2 = section.split(",")
-
-        r1_start, r1_stop = int(r1.split("-")[0]), int(r1.split("-")[1]) + 1
-        r1 = set(range(r1_start, r1_stop))
-
-        r2_start, r2_stop = int(r2.split("-")[0]), int(r2.split("-")[1]) + 1
-        r2 = set(range(r2_start, r2_stop))
-
-        if r1.intersection(r2):
-            count += 1
-
-print(count)
+13
max_calories = 0
+calories = 0
+
+with open("day01_input.txt") as f:
+    for line in f:
+        if not line.strip():
+            if calories > max_calories:
+                max_calories = calories
+            calories = 0
+            continue
+        calories += int(line)
+
+print(max_calories)
 
 1
  2
  3
@@ -55,62 +45,116 @@
  9
 10
 11
-12
-13
-14
-15
-16
-17
-18
count = 0
-
-with open("day04_input.txt") as f:
-    sections = f.readlines()
-    for section in sections:
-        section = section.strip()
-        r1, r2 = section.split(",")
-
-        r1_start, r1_stop = int(r1.split("-")[0]), int(r1.split("-")[1]) + 1
-        r1 = set(range(r1_start, r1_stop))
+12
all_calories = []
+calories = 0
+
+with open("day01_input.txt") as f:
+    for line in f:
+        if not line.strip():
+            all_calories.append(calories)
+            calories = 0
+            continue
+        calories += int(line)
 
-        r2_start, r2_stop = int(r2.split("-")[0]), int(r2.split("-")[1]) + 1
-        r2 = set(range(r2_start, r2_stop))
-
-        if r1.issuperset(r2) or r2.issuperset(r1):
-            count += 1
-
-print(count)
-
Day 06
1
-2
-3
-4
-5
-6
-7
-8
-9
with open("day06_input.txt") as f:
-    buffer = f.read()
-
-    offset = 14
-    for i in range(0, len(buffer) - offset):
-        if len(set(buffer[i : i + offset])) == offset:
-            break
-
-    print(i + offset)
-
1
-2
-3
-4
-5
-6
-7
-8
with open("day06_input.txt") as f:
-    buffer = f.read()
-
-    for i in range(0, len(buffer) - 4):
-        if len(set(buffer[i : i + 4])) == 4:
-            break
-
-    print(i + 4)
+print(sum(sorted(all_calories)[-3:]))
+
Day 02
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
score = 0
+
+op_order = ["A", "B", "C"]
+me_order = ["X", "Y", "Z"]
+with open("day02_input.txt") as f:
+    for line in f:
+        op, me = line.strip().split()
+        ind_op = op_order.index(op)
+        ind_me = me_order.index(me)
+        if ind_me == ind_op:
+            score += ind_me + 1 + 3
+        elif any(
+            [
+                ind_me == 1 and ind_op == 0,
+                ind_me == 2 and ind_op == 1,
+                ind_me == 0 and ind_op == 2,
+            ]
+        ):
+            score += ind_me + 1 + 6
+        else:
+            score += ind_me + 1 + 0
+
+print(score)
+
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
score = 0
+
+op_order = ["A", "B", "C"]
+me_order = ["X", "Y", "Z"]
+with open("day02_input.txt") as f:
+    for line in f:
+        op, me = line.strip().split()
+        ind_op = op_order.index(op)
+        ind_me = me_order.index(me)
+        if ind_me == 1:
+            score += ind_op + 1 + 3
+        elif ind_me == 2:
+            shape_map = {
+                0: 1 + 1,
+                1: 2 + 1,
+                2: 0 + 1,
+            }
+            score += shape_map[ind_op] + 6
+        else:
+            shape_map = {
+                0: 2 + 1,
+                1: 0 + 1,
+                2: 1 + 1,
+            }
+            score += shape_map[ind_op] + 0
+
+print(score)
 
Day 03
 1
  2
  3
@@ -183,7 +227,7 @@
             priorities += ord(overlap) - ord("a") + 1
 
 print(priorities)
-
Day 01
 1
+
Day 04
 1
  2
  3
  4
@@ -195,19 +239,29 @@
 10
 11
 12
-13
max_calories = 0
-calories = 0
-
-with open("day01_input.txt") as f:
-    for line in f:
-        if not line.strip():
-            if calories > max_calories:
-                max_calories = calories
-            calories = 0
-            continue
-        calories += int(line)
-
-print(max_calories)
+13
+14
+15
+16
+17
+18
count = 0
+
+with open("day04_input.txt") as f:
+    sections = f.readlines()
+    for section in sections:
+        section = section.strip()
+        r1, r2 = section.split(",")
+
+        r1_start, r1_stop = int(r1.split("-")[0]), int(r1.split("-")[1]) + 1
+        r1 = set(range(r1_start, r1_stop))
+
+        r2_start, r2_stop = int(r2.split("-")[0]), int(r2.split("-")[1]) + 1
+        r2 = set(range(r2_start, r2_stop))
+
+        if r1.intersection(r2):
+            count += 1
+
+print(count)
 
 1
  2
  3
@@ -219,114 +273,60 @@
  9
 10
 11
-12
all_calories = []
-calories = 0
-
-with open("day01_input.txt") as f:
-    for line in f:
-        if not line.strip():
-            all_calories.append(calories)
-            calories = 0
-            continue
-        calories += int(line)
+12
+13
+14
+15
+16
+17
+18
count = 0
+
+with open("day04_input.txt") as f:
+    sections = f.readlines()
+    for section in sections:
+        section = section.strip()
+        r1, r2 = section.split(",")
+
+        r1_start, r1_stop = int(r1.split("-")[0]), int(r1.split("-")[1]) + 1
+        r1 = set(range(r1_start, r1_stop))
 
-print(sum(sorted(all_calories)[-3:]))
-
Day 02
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
score = 0
-
-op_order = ["A", "B", "C"]
-me_order = ["X", "Y", "Z"]
-with open("day02_input.txt") as f:
-    for line in f:
-        op, me = line.strip().split()
-        ind_op = op_order.index(op)
-        ind_me = me_order.index(me)
-        if ind_me == ind_op:
-            score += ind_me + 1 + 3
-        elif any(
-            [
-                ind_me == 1 and ind_op == 0,
-                ind_me == 2 and ind_op == 1,
-                ind_me == 0 and ind_op == 2,
-            ]
-        ):
-            score += ind_me + 1 + 6
-        else:
-            score += ind_me + 1 + 0
-
-print(score)
-
 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-10
-11
-12
-13
-14
-15
-16
-17
-18
-19
-20
-21
-22
-23
-24
-25
-26
-27
score = 0
-
-op_order = ["A", "B", "C"]
-me_order = ["X", "Y", "Z"]
-with open("day02_input.txt") as f:
-    for line in f:
-        op, me = line.strip().split()
-        ind_op = op_order.index(op)
-        ind_me = me_order.index(me)
-        if ind_me == 1:
-            score += ind_op + 1 + 3
-        elif ind_me == 2:
-            shape_map = {
-                0: 1 + 1,
-                1: 2 + 1,
-                2: 0 + 1,
-            }
-            score += shape_map[ind_op] + 6
-        else:
-            shape_map = {
-                0: 2 + 1,
-                1: 0 + 1,
-                2: 1 + 1,
-            }
-            score += shape_map[ind_op] + 0
-
-print(score)
+        r2_start, r2_stop = int(r2.split("-")[0]), int(r2.split("-")[1]) + 1
+        r2 = set(range(r2_start, r2_stop))
+
+        if r1.issuperset(r2) or r2.issuperset(r1):
+            count += 1
+
+print(count)
+
Day 06
1
+2
+3
+4
+5
+6
+7
+8
+9
with open("day06_input.txt") as f:
+    buffer = f.read()
+
+    offset = 14
+    for i in range(0, len(buffer) - offset):
+        if len(set(buffer[i : i + offset])) == offset:
+            break
+
+    print(i + offset)
+
1
+2
+3
+4
+5
+6
+7
+8
with open("day06_input.txt") as f:
+    buffer = f.read()
+
+    for i in range(0, len(buffer) - 4):
+        if len(set(buffer[i : i + 4])) == 4:
+            break
+
+    print(i + 4)
 
\ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json index 2a25c8e..6459f4e 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":""},{"location":"#advent-of-code","title":"Advent of Code","text":"
  • 2023
  • 2022
  • 2021
"},{"location":"2021/","title":"Advent of Code 2021","text":"Day 04 Part 2Part 1
with open(\"day04_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\ndraws = lines[0].split(\",\")\n\n\nlines = [line for line in lines[1:] if line]\nboards = []\nfor i in range(0, len(lines) // 5):\n    boards.append([])\n    for j in range(5):\n        boards[i].append(lines[i * 5 + j].split())\n\n\nmarks = {}\nfor i in range(len(boards)):\n    marks[i] = {}\n    for row in range(5):\n        for col in range(5):\n            marks[i][boards[i][row][col]] = (row, col)\n\n\nwinning_locations = []\nfor row in range(5):\n    winning_locations.append([(row, col) for col in range(5)])\nfor col in range(5):\n    winning_locations.append([(row, col) for row in range(5)])\n\n\ndef wins(locations, winning_locations=winning_locations):\n    for winning_location in winning_locations:\n        if all(loc in locations for loc in winning_location):\n            return winning_location\n\n    return None\n\n\nplays = {}\nfor i in range(len(boards)):\n    plays[i] = []\n\nnum_plays = {}\nfor i in range(len(boards)):\n    count = 0\n    for draw in draws:\n        count += 1\n        if draw in marks[i]:\n            plays[i].append(marks[i][draw])\n\n        if wins(plays[i]):\n            num_plays[i] = count, len(plays[i])\n            break\n\n\nlast_win = max(num_plays, key=lambda x: num_plays[x][0])\nprint(last_win)\n\n\nsum_unmarked = 0\nfor row in range(5):\n    for col in range(5):\n        if (row, col) not in plays[last_win]:\n            sum_unmarked += int(boards[last_win][row][col])\n\nrow, col = plays[last_win][-1]\nnum_call = int(boards[last_win][row][col])\n\n\nprint(sum_unmarked, num_call)\nprint(sum_unmarked * num_call)\n
with open(\"day04_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\ndraws = lines[0].split(\",\")\n\n\nlines = [line for line in lines[1:] if line]\nboards = []\nfor i in range(0, len(lines) // 5):\n    boards.append([])\n    for j in range(5):\n        boards[i].append(lines[i * 5 + j].split())\n\n\nmarks = {}\nfor i in range(len(boards)):\n    marks[i] = {}\n    for row in range(5):\n        for col in range(5):\n            marks[i][boards[i][row][col]] = (row, col)\n\n\nwinning_locations = []\nfor row in range(5):\n    winning_locations.append([(row, col) for col in range(5)])\nfor col in range(5):\n    winning_locations.append([(row, col) for row in range(5)])\n\n\ndef wins(locations, winning_locations=winning_locations):\n    for winning_location in winning_locations:\n        if all(loc in locations for loc in winning_location):\n            return winning_location\n\n    return None\n\n\nplays = {}\nfor i in range(len(boards)):\n    plays[i] = []\n\nnum_plays = {}\nfor i in range(len(boards)):\n    count = 0\n    for draw in draws:\n        count += 1\n        if draw in marks[i]:\n            plays[i].append(marks[i][draw])\n\n        if wins(plays[i]):\n            num_plays[i] = count, len(plays[i])\n            break\n\n\nfastest_win = min(num_plays, key=lambda x: num_plays[x][0])\nprint(fastest_win)\n\n\nsum_unmarked = 0\nfor row in range(5):\n    for col in range(5):\n        if (row, col) not in plays[fastest_win]:\n            sum_unmarked += int(boards[fastest_win][row][col])\n\nrow, col = plays[fastest_win][-1]\nnum_call = int(boards[fastest_win][row][col])\n\n\nprint(sum_unmarked, num_call)\nprint(sum_unmarked * num_call)\n
Day 10 Part 2Part 1
with open(\"day10_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\nmapping = {\n    \"(\": 1,\n    \"[\": 2,\n    \"{\": 3,\n    \"<\": 4,\n}\n\nmatch = {\n    \")\": \"(\",\n    \"]\": \"[\",\n    \"}\": \"{\",\n    \">\": \"<\",\n}\n\n\ndef check(line):\n    stack = []\n    for c in line:\n        if c in match.values():\n            stack.append(c)\n        elif c in match.keys():\n            if len(stack) == 0:\n                return 0\n            last = stack.pop()\n            if last != match[c]:\n                return 0\n\n    if len(stack) == 0:\n        return 0\n\n    score = 0\n    while len(stack) > 0:\n        last = stack.pop()\n        score *= 5\n        score += mapping[last]\n\n    return score\n\n\nscores = [check(line) for line in lines]\nscores = [s for s in scores if s > 0]\nprint(len(scores))\nprint(sorted(scores)[len(scores) // 2])\n
with open(\"day10_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\nmapping = {\n    \")\": 3,\n    \"]\": 57,\n    \"}\": 1197,\n    \">\": 25137,\n}\n\nmatch = {\n    \")\": \"(\",\n    \"]\": \"[\",\n    \"}\": \"{\",\n    \">\": \"<\",\n}\n\n\ndef check(line):\n    stack = []\n    for c in line:\n        if c in match.values():\n            stack.append(c)\n        elif c in match.keys():\n            if len(stack) == 0:\n                return mapping[c]\n            last = stack.pop()\n            if last != match[c]:\n                return mapping[c]\n\n    return 0\n\n\nprint(sum(check(line) for line in lines))\n
Day 06 Part 2Part 1
with open(\"day06_input.txt\", \"r\") as f:\n    fish = [int(i) for i in f.read().strip().split(\",\")]\n\n\nfrom collections import Counter\n\nfish = Counter(fish)\nprint(fish)\n\nfor _ in range(256):\n    for i in range(-1, 9):\n        if i == 8:\n            fish[i] = fish[-1]\n        elif i != 6:\n            fish[i] = fish[i + 1]\n        else:\n            fish[i] = fish[-1] + fish[i + 1]\n\n\nprint(sum([v for k, v in fish.items() if k >= 0]))\n
with open(\"day06_input.txt\", \"r\") as f:\n    fish = [int(i) for i in f.read().strip().split(\",\")]\n\nprint(f\"Initial state: {fish}\")\n\nfor _ in range(80):\n    new_fish = []\n    for i in range(len(fish)):\n\n        fish[i] -= 1\n\n        if fish[i] < 0:\n            fish[i] = 6\n            new_fish.append(8)\n\n    fish.extend(new_fish)\n\n    print(f\"After {str(_+1):2s} day{'s' if _ else ''}: {fish}\")\n\nprint(len(fish))\n
Day 15 Part 2Part 1
with open(\"day15_input.txt\", \"r\") as f:\n    lines = [[int(d) for d in line] for line in f.read().splitlines()]\n\nrows, cols = len(lines), len(lines[0])\n\n\nlines_5x = [[0] * cols * 5 for i in range(rows * 5)]\nfor ii in range(5):\n    for jj in range(5):\n        for i in range(rows):\n            for j in range(cols):\n                lines_5x[ii * rows + i][jj * cols + j] = (\n                    lines[i][j] + ii + jj - 1\n                ) % 9 + 1\n\n\n# Using the networkx library instead\n\nimport networkx as nx\n\ng = nx.DiGraph()\nrows *= 5\ncols *= 5\n\nfor i in range(rows):\n    for j in range(cols):\n        if i < rows - 1:\n            g.add_edge((i, j), (i + 1, j), weight=lines_5x[i + 1][j])\n            g.add_edge((i + 1, j), (i, j), weight=lines_5x[i][j])\n\n        if j < cols - 1:\n            g.add_edge((i, j), (i, j + 1), weight=lines_5x[i][j + 1])\n            g.add_edge((i, j + 1), (i, j), weight=lines_5x[i][j])\n\npaths = nx.shortest_path(\n    g,\n    source=(0, 0),\n    target=(rows - 1, cols - 1),\n    weight=\"weight\",\n)\n\n# print(paths)\n\ncost = 0\nfor i, j in paths[1:]:\n    cost += lines_5x[i][j]\n\nprint(f\"Cost of shortest path is {cost}\")\n
with open(\"day15_input.txt\", \"r\") as f:\n    risks = [[int(d) for d in line] for line in f.read().splitlines()]\n\nrows, cols = len(risks), len(risks[0])\n\n# reference: https://stackabuse.com/dijkstras-algorithm-in-python/\n\nfrom queue import PriorityQueue\n\n\nclass Graph:\n    def __init__(self, num_of_vertices):\n        self.v = num_of_vertices\n        self.edges = [\n            [-1 for i in range(num_of_vertices)] for j in range(num_of_vertices)\n        ]\n        self.visited = []\n\n    def add_edge(self, u, v, weight):\n        self.edges[u][v] = weight\n\n\ndef dijkstra(graph, start_vertex):\n    D = {v: float(\"inf\") for v in range(graph.v)}\n    D[start_vertex] = 0\n\n    pq = PriorityQueue()\n    pq.put((0, start_vertex))\n\n    while not pq.empty():\n        (dist, current_vertex) = pq.get()\n        graph.visited.append(current_vertex)\n\n        for neighbor in range(graph.v):\n            if graph.edges[current_vertex][neighbor] != -1:\n                distance = graph.edges[current_vertex][neighbor]\n                if neighbor not in graph.visited:\n                    old_cost = D[neighbor]\n                    new_cost = D[current_vertex] + distance\n                    if new_cost < old_cost:\n                        pq.put((new_cost, neighbor))\n                        D[neighbor] = new_cost\n    return D\n\n\ng = Graph(rows * cols)\nfor i in range(rows):\n    for j in range(cols):\n\n        if i < rows - 1:\n            g.add_edge((i + 1) * cols + j, i * cols + j, risks[i][j])\n            g.add_edge(i * cols + j, (i + 1) * cols + j, risks[i + 1][j])\n\n        if j < cols - 1:\n            g.add_edge(i * cols + j + 1, i * cols + j, risks[i][j])\n            g.add_edge(i * cols + j, i * cols + j + 1, risks[i][j + 1])\n\n\nD = dijkstra(g, 0)\nprint(f\"Cost of shortest path is {D[rows*cols-1]}\")\n
Day 13 Part 2Part 1
with open(\"day13_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\ndots = []\nactions = []\nfor line in lines:\n    if not line:\n        continue\n    if \",\" in line:\n        x, y = line.split(\",\")\n        dots.append((int(x), int(y)))\n    else:\n        actions.append(line.split()[-1].split(\"=\"))\n\nprevious = dots[:]\n\nfor axis, value in actions:\n    result = []\n    value = int(value)\n    if axis == \"x\":\n        for dot in previous:\n            if dot[0] < value:\n                result.append((dot[0], dot[1]))\n            else:\n                result.append((2 * value - dot[0], dot[1]))\n\n    elif axis == \"y\":\n        for dot in previous:\n            if dot[1] < value:\n                result.append((dot[0], dot[1]))\n            else:\n                result.append((dot[0], 2 * value - dot[1]))\n\n    print(len(set(result)))\n\n    previous = result[:]\n\nmax_x = max(result, key=lambda x: x[0])[0]\nmax_y = max(result, key=lambda x: x[1])[1]\nprint(max_x, max_y)\n\nfor y in range(max_y + 1):\n    for x in range(max_x + 1):\n        if (x, y) in result:\n            print(\"#\", end=\"\")\n        else:\n            print(\" \", end=\"\")\n    print()\n\nfrom PIL import Image\n\nimg = Image.new(\"RGB\", (max_x + 1, max_y + 1), \"black\")\npixels = img.load()\nfor dot in set(result):\n    pixels[dot[0], dot[1]] = (255, 255, 255)\nimg.show()\n
with open(\"day13_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\ndots = []\nactions = []\nfor line in lines:\n    if not line:\n        continue\n    if \",\" in line:\n        x, y = line.split(\",\")\n        dots.append((int(x), int(y)))\n    else:\n        actions.append(line.split()[-1].split(\"=\"))\n\nprevious = dots[:]\n\nfor axis, value in actions:\n    result = []\n    value = int(value)\n    if axis == \"x\":\n        for dot in previous:\n            if dot[0] < value:\n                result.append((dot[0], dot[1]))\n            else:\n                result.append((2 * value - dot[0], dot[1]))\n\n    elif axis == \"y\":\n        for dot in previous:\n            if dot[1] < value:\n                result.append((dot[0], dot[1]))\n            else:\n                result.append((dot[0], 2 * value - dot[1]))\n\n    print(len(set(result)))\n\n    previous = result[:]\n
Day 03 Part 1Part 2
with open(\"day03_input.txt\", \"r\") as f:\n    data = f.read().splitlines()\n\ncols = len(data[0])\nrows = len(data)\n\ngamma_rate, epsilon_rate = \"\", \"\"\n\nfor col in range(cols):\n    ones = 0\n    for row in range(rows):\n        if data[row][col] == \"1\":\n            ones += 1\n\n    if ones > rows / 2:\n        gamma_rate += \"1\"\n        epsilon_rate += \"0\"\n    else:\n        gamma_rate += \"0\"\n        epsilon_rate += \"1\"\n\nprint(gamma_rate, epsilon_rate)\n\nprint(int(gamma_rate, 2) * int(epsilon_rate, 2))\n
with open(\"day03_input.txt\", \"r\") as f:\n    data = f.read().splitlines()\n\ncols = len(data[0])\n\noxygen_generator_rating, co2_scrubber_rating = \"\", \"\"\n\nselections = data[:]\nfor col in range(cols):\n    ones = 0\n    for row in selections:\n        if row[col] == \"1\":\n            ones += 1\n\n    if ones >= len(selections) / 2:\n        selections = [row for row in selections if row[col] == \"1\"]\n    else:\n        selections = [row for row in selections if row[col] == \"0\"]\n\n    if len(selections) == 1:\n        oxygen_generator_rating += selections[0]\n        break\n\nselections = data[:]\nfor col in range(cols):\n    ones = 0\n    for row in selections:\n        if row[col] == \"1\":\n            ones += 1\n\n    if ones < len(selections) / 2:\n        selections = [row for row in selections if row[col] == \"1\"]\n    else:\n        selections = [row for row in selections if row[col] == \"0\"]\n\n    if len(selections) == 1:\n        co2_scrubber_rating += selections[0]\n        break\n\n\nprint(oxygen_generator_rating, co2_scrubber_rating)\n\nprint(int(oxygen_generator_rating, 2) * int(co2_scrubber_rating, 2))\n
Day 07 Part 1Part 2
with open(\"day07_input.txt\", \"r\") as f:\n    crabs = [int(i) for i in f.read().strip().split(\",\")]\n\nprint(len(crabs))\n\nfrom collections import Counter\n\ncrabs = Counter(crabs)\n\n\noutcome = {}\n\nfor key in crabs:\n    result = 0\n    for key2 in crabs:\n        result += abs(key2 - key) * crabs[key2]\n    outcome[key] = result\n\nmin_key = min(outcome, key=outcome.get)\nprint(min_key)\nprint(outcome[min_key])\n
with open(\"day07_input.txt\", \"r\") as f:\n    crabs = [int(i) for i in f.read().strip().split(\",\")]\n\nprint(len(crabs))\n\nfrom collections import Counter\n\ncrabs = Counter(crabs)\n\n\noutcome = {}\n\nfor key in range(0, max(crabs.keys()) + 1):\n    result = 0\n    for key2 in crabs:\n        result += sum(range(1, abs(key2 - key) + 1)) * crabs[key2]\n    outcome[key] = result\n\nmin_key = min(outcome, key=outcome.get)\nprint(min_key)\nprint(outcome[min_key])\n
Day 11 Part 2Part 1
with open(\"day11_input.txt\", \"r\") as f:\n    obs = [[int(i) for i in line] for line in f.read().splitlines()]\n\n\ndef increase(obs):\n    for i in range(len(obs)):\n        for j in range(len(obs[i])):\n            obs[i][j] += 1\n\n\ndef has_flash(obs):\n    locations = []\n    for i in range(len(obs)):\n        for j in range(len(obs[i])):\n            if obs[i][j] > 9:\n                locations.append((i, j))\n    return locations\n\n\ndef display(obs):\n    for i in range(len(obs)):\n        print(\"\".join([str(i) for i in obs[i]]))\n\n\nfrom collections import Counter\n\n\nprint(\"Before any steps:\")\ndisplay(obs)\nprint()\n\n\ncount = 0\noctopuses = sum([len(obs[i]) for i in range(len(obs))])\nwhile True:\n    increase(obs)\n\n    flashes = set()\n    while True:\n        locations = has_flash(obs)\n        flashes.update(locations)\n\n        if locations:\n            c = Counter()\n            for i, j in locations:\n                obs[i][j] = 0\n                if i > 0:\n                    c[(i - 1, j)] += 1\n                    if j > 0:\n                        c[(i - 1, j - 1)] += 1\n                    if j < len(obs[i]) - 1:\n                        c[(i - 1, j + 1)] += 1\n                if i < len(obs) - 1:\n                    c[(i + 1, j)] += 1\n                    if j > 0:\n                        c[(i + 1, j - 1)] += 1\n                    if j < len(obs[i]) - 1:\n                        c[(i + 1, j + 1)] += 1\n                if j > 0:\n                    c[(i, j - 1)] += 1\n                if j < len(obs[i]) - 1:\n                    c[(i, j + 1)] += 1\n            for i, j in c:\n                if (i, j) not in flashes:\n                    obs[i][j] += c[(i, j)]\n            if c:\n                continue\n        break\n\n    print(f\"After step {count+1}:\")\n    display(obs)\n    print(f\"Flashes: {len(flashes)}\")\n    print()\n\n    count += 1\n    if len(flashes) == octopuses:\n        break\n\nprint(f\"Total steps: {count}\")\n
with open(\"day11_input.txt\", \"r\") as f:\n    obs = [[int(i) for i in line] for line in f.read().splitlines()]\n\n\ndef increase(obs):\n    for i in range(len(obs)):\n        for j in range(len(obs[i])):\n            obs[i][j] += 1\n\n\ndef has_flash(obs):\n    locations = []\n    for i in range(len(obs)):\n        for j in range(len(obs[i])):\n            if obs[i][j] > 9:\n                locations.append((i, j))\n    return locations\n\n\ndef display(obs):\n    for i in range(len(obs)):\n        print(\"\".join([str(i) for i in obs[i]]))\n\n\nfrom collections import Counter\n\nprint(\"Before any steps:\")\ndisplay(obs)\nprint()\n\ncount = 0\nfor s in range(100):\n    increase(obs)\n\n    flashes = set()\n    while True:\n        locations = has_flash(obs)\n        flashes.update(locations)\n\n        if locations:\n            c = Counter()\n            for i, j in locations:\n                obs[i][j] = 0\n                if i > 0:\n                    c[(i - 1, j)] += 1\n                    if j > 0:\n                        c[(i - 1, j - 1)] += 1\n                    if j < len(obs[i]) - 1:\n                        c[(i - 1, j + 1)] += 1\n                if i < len(obs) - 1:\n                    c[(i + 1, j)] += 1\n                    if j > 0:\n                        c[(i + 1, j - 1)] += 1\n                    if j < len(obs[i]) - 1:\n                        c[(i + 1, j + 1)] += 1\n                if j > 0:\n                    c[(i, j - 1)] += 1\n                if j < len(obs[i]) - 1:\n                    c[(i, j + 1)] += 1\n            for i, j in c:\n                if (i, j) not in flashes:\n                    obs[i][j] += c[(i, j)]\n            if c:\n                continue\n        break\n\n    print(f\"After step {s+1}:\")\n    display(obs)\n    print(f\"Flashes: {len(flashes)}\")\n    print()\n\n    count += len(flashes)\n\nprint(f\"Total flashes: {count}\")\n
Day 08 Part 2Part 1
with open(\"day08_input.txt\", \"r\") as f:\n    obs = [line.split(\" | \") for line in f.read().splitlines()]\n\n\ndef _sorted(digit):\n    return \"\".join(sorted(digit))\n\n\ndef solve(digits):\n    mapping = {}\n    five_segs = []\n    six_segs = []\n\n    cf, bcdf, acf, abcdefg = None, None, None, None\n    for digit in digits:\n        if len(digit) == 2:\n            mapping[_sorted(digit)] = \"1\"\n            cf = digit\n        elif len(digit) == 3:\n            mapping[_sorted(digit)] = \"7\"\n            acf = digit\n        elif len(digit) == 4:\n            mapping[_sorted(digit)] = \"4\"\n            bcdf = digit\n        elif len(digit) == 7:\n            mapping[_sorted(digit)] = \"8\"\n            abcdefg = digit\n        elif len(digit) == 5:\n            five_segs.append(digit)\n        elif len(digit) == 6:\n            six_segs.append(digit)\n\n    bd = set(bcdf) - set(cf)\n    eg = set(abcdefg) - (set(cf) | set(bcdf) | set(acf))\n\n    for digit in six_segs:\n        _digit = set(digit)\n        if _digit >= bd and _digit >= eg:\n            mapping[_sorted(digit)] = \"6\"\n        elif _digit >= bd:\n            mapping[_sorted(digit)] = \"9\"\n        elif _digit >= eg:\n            mapping[_sorted(digit)] = \"0\"\n\n    for digit in five_segs:\n        _digit = set(digit)\n        if _digit >= bd:\n            mapping[_sorted(digit)] = \"5\"\n        elif _digit >= eg:\n            mapping[_sorted(digit)] = \"2\"\n        else:\n            mapping[_sorted(digit)] = \"3\"\n\n    return mapping\n\n\ncount = 0\nfor o in obs:\n    output_values = o[1].split()\n    digits = o[0].split()\n    mapping = solve(digits)\n    value = \"\"\n    for digit in output_values:\n        value += mapping[_sorted(digit)]\n\n    count += int(value)\n\nprint(count)\n
with open(\"day08_input.txt\", \"r\") as f:\n    obs = [line.split(\" | \") for line in f.read().splitlines()]\n\ncount = 0\nfor o in obs:\n    output_values = o[1].split()\n    for output_value in output_values:\n        if len(output_value) in [2, 3, 4, 7]:\n            count += 1\n\nprint(count)\n
Day 16 Part 1
with open(\"day16_input.txt\", \"r\") as f:\n    hexadecimal = f.read().strip()\n\nprint(f\"Hex: {hexadecimal}\")\n\n\ndef hex2bin(h):\n    return bin(int(h, 16))[2:].zfill(len(h) * 4)\n\n\nb = hex2bin(hexadecimal)\nprint(f\"Bin: {b}\")\n\nprint()\n\n\ndef decode_header(b):\n    packet_version = b[:3]\n    packet_type_id = b[3:6]\n\n    return int(packet_version, 2), int(packet_type_id, 2), b[6:]\n\n\ndef decode_literal(b):\n    value = \"\"\n\n    while b:\n        seg = b[:5]\n        value += seg[-4:]\n        b = b[5:]\n        if seg[0] == \"0\":\n            break\n\n    return value, b\n\n\ndef decode_operator(b):\n    length_type_id = b[:1]\n\n    if length_type_id == \"0\":\n        length_of_subpackets = int(b[1:16], 2)\n\n        remaining = b[16 + length_of_subpackets :]\n        b = b[16 : 16 + length_of_subpackets]\n        number_of_subpackets = -1\n    else:\n        number_of_subpackets = int(b[1:12], 2)\n        b = b[12:]\n        remaining = None\n\n    return length_type_id, number_of_subpackets, b, remaining\n\n\nresult = []\n\n\ndef decode(b):\n    while b:\n        if all(c == \"0\" for c in b):\n            return\n\n        packet_version, packet_type_id, b = decode_header(b)\n        result.append(packet_version)\n        print(f\"packet_version: {packet_version}, packet_type_id: {packet_type_id}\")\n        if packet_type_id == 4:\n            value, b = decode_literal(b)\n            print(f\"Literal value {value} is {int(value, 2)}.\")\n        else:\n            length_type_id, number_of_subpackets, block, remaining = decode_operator(b)\n            print(\n                f\"length_type_id: {length_type_id},\",\n                f\"number_of_subpackets: {number_of_subpackets},\",\n            )\n            if number_of_subpackets == -1:\n                b = remaining\n                decode(block)\n            else:\n                b = block\n                return decode(b)\n\n    return\n\n\ndecode(b)\nprint()\nprint(f\"Result: {result} -> {sum(result)}\")\n
Day 01 Part 1Part 2
with open(\"day01_input.txt\", \"r\") as f:\n    data = [int(i) for i in f.read().splitlines()]\n\ncount = 0\nfor i in range(1, len(data)):\n    if data[i] > data[i - 1]:\n        count += 1\n\nprint(count)\n
with open(\"day01_input.txt\", \"r\") as f:\n    data = [int(i) for i in f.read().splitlines()]\n\nthree_measurement_data = []\nfor i in range(2, len(data)):\n    three_measurement_data.append(sum(data[i - 2 : i + 1]))\n\ncount = 0\nfor i in range(1, len(three_measurement_data)):\n    if three_measurement_data[i] > three_measurement_data[i - 1]:\n        count += 1\n\nprint(count)\n
Day 12 Part 1Part 2
with open(\"day12_input.txt\", \"r\") as f:\n    segs = f.read().splitlines()\n\n\ngraph = {}\nfor seg in segs:\n    node1, node2 = seg.split(\"-\")\n    if node1 not in graph:\n        graph[node1] = [node2]\n    else:\n        graph[node1].append(node2)\n\n    if node2 not in graph:\n        graph[node2] = [node1]\n    else:\n        graph[node2].append(node1)\n\nfrom pprint import pprint\n\npprint(graph)\n\n\npaths = []\n\n\ndef breadth_first_search(graph, start, end, path=[]):\n    path = path + [start]\n    if start == end:\n        paths.append(path)\n    if start not in graph:\n        return None\n    for node in graph[start]:\n        if node not in path or node.isupper():\n            newpath = breadth_first_search(graph, node, end, path)\n            if newpath:\n                paths.append(newpath)\n    return None\n\n\nbreadth_first_search(graph, \"start\", \"end\")\n\nfor path in paths:\n    print(\",\".join(path))\n\nprint(len(paths))\n
with open(\"day12_input.txt\", \"r\") as f:\n    segs = f.read().splitlines()\n\n\ngraph = {}\nfor seg in segs:\n    node1, node2 = seg.split(\"-\")\n    if node1 not in graph:\n        graph[node1] = [node2]\n    else:\n        graph[node1].append(node2)\n\n    if node2 not in graph:\n        graph[node2] = [node1]\n    else:\n        graph[node2].append(node1)\n\nfrom pprint import pprint\n\npprint(graph)\n\n\npaths = []\n\n\ndef remaining(path, node):\n    others = [\n        n for n in path if n != node and n.islower() and n not in [\"start\", \"end\"]\n    ]\n\n    return all(path.count(n) <= 1 for n in others)\n\n\ndef breadth_first_search(graph, start, end, path=[]):\n\n    path = path + [start]\n    if start == end:\n        paths.append(path)\n    if start not in graph:\n        return None\n    for node in graph[start]:\n        if (\n            node not in path\n            or node.isupper()\n            or (\n                node not in [\"start\", \"end\"]\n                and node.islower()\n                and path.count(node) < 2\n                and remaining(path, node)\n            )\n        ):\n            newpath = breadth_first_search(graph, node, end, path)\n            if newpath:\n                paths.append(newpath)\n    return None\n\n\nbreadth_first_search(graph, \"start\", \"end\")\n\nfor path in paths:\n    print(\",\".join(path))\n\nprint(len(paths))\n
Day 02 Part 1Part 2
with open(\"day02_input.txt\", \"r\") as f:\n    data = [cmd.split() for cmd in f.read().splitlines()]\n\nhorizontal_position, depth = 0, 0\n\nfor action, value in data:\n    value = int(value)\n    if action == \"forward\":\n        horizontal_position += value\n    elif action == \"up\":\n        depth -= value\n    elif action == \"down\":\n        depth += value\n\nprint(horizontal_position, depth)\n\nprint(horizontal_position * depth)\n
with open(\"day02_input.txt\", \"r\") as f:\n    data = [cmd.split() for cmd in f.read().splitlines()]\n\nhorizontal_position, depth, aim = 0, 0, 0\n\nfor action, value in data:\n    value = int(value)\n    if action == \"forward\":\n        horizontal_position += value\n        depth += aim * value\n    elif action == \"up\":\n        aim -= value\n    elif action == \"down\":\n        aim += value\n\n\nprint(horizontal_position, depth, aim)\n\nprint(horizontal_position * depth)\n
Day 14 Part 2Part 1
with open(\"day14_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\ntemplate = None\npairs = []\nfor line in lines:\n    if not line:\n        continue\n    if \" -> \" in line:\n        pairs.append(line.split(\" -> \"))\n    else:\n        template = line\n\nprint(f\"Template: {template}\")\nsegs = [template[j : j + 2] for j in range(0, len(template) - 1)]\n\nfrom collections import Counter\n\ncounts = Counter(segs)\n\n\nfor i in range(40):\n    result = Counter()\n    for key in counts:\n        for pair in pairs:\n            if key == pair[0]:\n                result[key[0] + pair[1]] += counts[key]\n                result[pair[1] + key[1]] += counts[pair[0]]\n\n    counts = result\n\n\nchars = Counter()\nchars[template[0]] += 1\n\nfor key, value in counts.items():\n    chars[key[1]] += value\n\nchars = chars.most_common()\nprint(chars)\nprint(chars[0][1] - chars[-1][1])\n
with open(\"day14_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\ntemplate = None\npairs = []\nfor line in lines:\n    if not line:\n        continue\n    if \" -> \" in line:\n        pairs.append(line.split(\" -> \"))\n    else:\n        template = line\n\nprint(f\"Template: {template}\")\n\nfor i in range(10):\n    segs = [template[j : j + 2] for j in range(0, len(template) - 1)]\n\n    for k in range(len(segs)):\n        for pair in pairs:\n            if segs[k] == pair[0]:\n                segs[k] = pair[0][0] + pair[1] + pair[0][1]\n\n    template = segs[0]\n    for seg in segs[1:]:\n        template += seg[-2:]\n\n    print(f\"After step {i+1}: {template}\")\n\nfrom collections import Counter\n\ncounts = Counter(template).most_common()\n\nprint(counts[0][1] - counts[-1][1])\n
Day 09 Part 2Part 1
with open(\"day09_input.txt\", \"r\") as f:\n    obs = [[int(i) for i in line] for line in f.read().splitlines()]\n\n\nlow_points = []\nfor i in range(0, len(obs)):\n    for j in range(0, len(obs[i])):\n        to_compare = []\n        if i > 0:\n            to_compare.append(obs[i - 1][j])\n        if i < len(obs) - 1:\n            to_compare.append(obs[i + 1][j])\n        if j > 0:\n            to_compare.append(obs[i][j - 1])\n        if j < len(obs[i]) - 1:\n            to_compare.append(obs[i][j + 1])\n\n        if all(obs[i][j] < x for x in to_compare):\n            low_points.append((i, j))\n\nbasin_sizes = []\n\n\ndef find_basin(i, j, points):\n    points.append((i, j))\n\n    up = i\n    while True:\n        if up > 0:\n            if obs[up - 1][j] > obs[up][j] and obs[up - 1][j] < 9:\n                find_basin(up - 1, j, points)\n                up -= 1\n            else:\n                break\n        else:\n            break\n\n    down = i\n    while True:\n        if down < len(obs) - 1:\n            if obs[down + 1][j] > obs[down][j] and obs[down + 1][j] < 9:\n                find_basin(down + 1, j, points)\n                down += 1\n            else:\n                break\n        else:\n            break\n\n    left = j\n    while True:\n        if left > 0:\n            if obs[i][left - 1] > obs[i][left] and obs[i][left - 1] < 9:\n                find_basin(i, left - 1, points)\n                left -= 1\n            else:\n                break\n        else:\n            break\n\n    right = j\n    while True:\n        if right < len(obs[i]) - 1:\n            if obs[i][right + 1] > obs[i][right] and obs[i][right + 1] < 9:\n                find_basin(i, right + 1, points)\n                right += 1\n            else:\n                break\n        else:\n            break\n\n\nfor i, j in low_points:\n    points = []\n    find_basin(i, j, points)\n    basin_sizes.append(len(set(points)))\n\nimport functools\n\nprint(functools.reduce(lambda x, y: x * y, sorted(basin_sizes)[-3:]))\n
with open(\"day09_input.txt\", \"r\") as f:\n    obs = [[int(i) for i in line] for line in f.read().splitlines()]\n\n\nlow_points = []\nfor i in range(0, len(obs)):\n    for j in range(0, len(obs[i])):\n        to_compare = []\n        if i > 0:\n            to_compare.append(obs[i - 1][j])\n        if i < len(obs) - 1:\n            to_compare.append(obs[i + 1][j])\n        if j > 0:\n            to_compare.append(obs[i][j - 1])\n        if j < len(obs[i]) - 1:\n            to_compare.append(obs[i][j + 1])\n\n        if all(obs[i][j] < x for x in to_compare):\n            low_points.append(obs[i][j])\n\n\nprint(sum(low_points) + len(low_points))\n
Day 05 Part 2Part 1
with open(\"day05_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\nlines = [line.split(\" -> \") for line in lines]\nlines = [(tuple(line[0].split(\",\")), tuple(line[1].split(\",\"))) for line in lines]\nprint(len(lines))\n\nlines = [\n    ((int(coord1[0]), int(coord1[1])), (int(coord2[0]), int(coord2[1])))\n    for coord1, coord2 in lines\n]\n\nfrom collections import Counter\n\ndiagram = Counter()\nfor coord1, coord2 in lines:\n    if coord1[0] == coord2[0]:\n        for i in range(min(coord1[1], coord2[1]), max(coord1[1], coord2[1]) + 1):\n            diagram[(coord1[0], i)] += 1\n    elif coord1[1] == coord2[1]:\n        for i in range(min(coord1[0], coord2[0]), max(coord1[0], coord2[0]) + 1):\n            diagram[(i, coord1[1])] += 1\n    else:\n        step_x = -1 if coord1[0] - coord2[0] > 0 else 1\n        step_y = -1 if coord1[1] - coord2[1] > 0 else 1\n        for x, y in zip(\n            range(coord1[0], coord2[0] + (1 if step_x > 0 else -1), step_x),\n            range(coord1[1], coord2[1] + (1 if step_y > 0 else -1), step_y),\n        ):\n            diagram[(x, y)] += 1\n\nprint(len([i for i in diagram.values() if i > 1]))\n
with open(\"day05_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\nlines = [line.split(\" -> \") for line in lines]\nlines = [(tuple(line[0].split(\",\")), tuple(line[1].split(\",\"))) for line in lines]\nprint(len(lines))\n\nlines = [\n    ((int(coord1[0]), int(coord1[1])), (int(coord2[0]), int(coord2[1])))\n    for coord1, coord2 in lines\n    if coord1[0] == coord2[0] or coord1[1] == coord2[1]\n]\nprint(len(lines))\n\nfrom collections import Counter\n\ndiagram = Counter()\nfor coord1, coord2 in lines:\n    if coord1[0] == coord2[0]:\n        for i in range(min(coord1[1], coord2[1]), max(coord1[1], coord2[1]) + 1):\n            diagram[(coord1[0], i)] += 1\n    elif coord1[1] == coord2[1]:\n        for i in range(min(coord1[0], coord2[0]), max(coord1[0], coord2[0]) + 1):\n            diagram[(i, coord1[1])] += 1\n\nprint(len([i for i in diagram.values() if i > 1]))\n
"},{"location":"2022/","title":"Advent of Code 2022","text":"Day 04 Part 2Part 1
count = 0\n\nwith open(\"day04_input.txt\") as f:\n    sections = f.readlines()\n    for section in sections:\n        section = section.strip()\n        r1, r2 = section.split(\",\")\n\n        r1_start, r1_stop = int(r1.split(\"-\")[0]), int(r1.split(\"-\")[1]) + 1\n        r1 = set(range(r1_start, r1_stop))\n\n        r2_start, r2_stop = int(r2.split(\"-\")[0]), int(r2.split(\"-\")[1]) + 1\n        r2 = set(range(r2_start, r2_stop))\n\n        if r1.intersection(r2):\n            count += 1\n\nprint(count)\n
count = 0\n\nwith open(\"day04_input.txt\") as f:\n    sections = f.readlines()\n    for section in sections:\n        section = section.strip()\n        r1, r2 = section.split(\",\")\n\n        r1_start, r1_stop = int(r1.split(\"-\")[0]), int(r1.split(\"-\")[1]) + 1\n        r1 = set(range(r1_start, r1_stop))\n\n        r2_start, r2_stop = int(r2.split(\"-\")[0]), int(r2.split(\"-\")[1]) + 1\n        r2 = set(range(r2_start, r2_stop))\n\n        if r1.issuperset(r2) or r2.issuperset(r1):\n            count += 1\n\nprint(count)\n
Day 06 Part 2Part 1
with open(\"day06_input.txt\") as f:\n    buffer = f.read()\n\n    offset = 14\n    for i in range(0, len(buffer) - offset):\n        if len(set(buffer[i : i + offset])) == offset:\n            break\n\n    print(i + offset)\n
with open(\"day06_input.txt\") as f:\n    buffer = f.read()\n\n    for i in range(0, len(buffer) - 4):\n        if len(set(buffer[i : i + 4])) == 4:\n            break\n\n    print(i + 4)\n
Day 03 Part 1Part 2
priorities = 0\n\nwith open(\"day03_input.txt\") as f:\n    for line in f:\n        line = line.strip()\n        if not line:\n            continue\n        first, second = line[: len(line) // 2], line[len(line) // 2 :]\n        overlap = set(first).intersection(set(second)).pop()\n        if overlap.isupper():\n            priorities += ord(overlap) - ord(\"A\") + 27\n        else:\n            priorities += ord(overlap) - ord(\"a\") + 1\n\nprint(priorities)\n
priorities = 0\n\nwith open(\"day03_input.txt\") as f:\n    groups = f.readlines()\n    groups = [groups[3 * i : 3 * i + 3] for i in range(0, len(groups) // 3)]\n\n    for g in groups:\n        items = None\n        for line in g:\n            line = line.strip()\n            if not items:\n                items = set(line)\n            else:\n                items = items.intersection(set(line))\n        overlap = items.pop()\n\n        if overlap.isupper():\n            priorities += ord(overlap) - ord(\"A\") + 27\n        else:\n            priorities += ord(overlap) - ord(\"a\") + 1\n\nprint(priorities)\n
Day 01 Part 1Part 2
max_calories = 0\ncalories = 0\n\nwith open(\"day01_input.txt\") as f:\n    for line in f:\n        if not line.strip():\n            if calories > max_calories:\n                max_calories = calories\n            calories = 0\n            continue\n        calories += int(line)\n\nprint(max_calories)\n
all_calories = []\ncalories = 0\n\nwith open(\"day01_input.txt\") as f:\n    for line in f:\n        if not line.strip():\n            all_calories.append(calories)\n            calories = 0\n            continue\n        calories += int(line)\n\nprint(sum(sorted(all_calories)[-3:]))\n
Day 02 Part 1Part 2
score = 0\n\nop_order = [\"A\", \"B\", \"C\"]\nme_order = [\"X\", \"Y\", \"Z\"]\nwith open(\"day02_input.txt\") as f:\n    for line in f:\n        op, me = line.strip().split()\n        ind_op = op_order.index(op)\n        ind_me = me_order.index(me)\n        if ind_me == ind_op:\n            score += ind_me + 1 + 3\n        elif any(\n            [\n                ind_me == 1 and ind_op == 0,\n                ind_me == 2 and ind_op == 1,\n                ind_me == 0 and ind_op == 2,\n            ]\n        ):\n            score += ind_me + 1 + 6\n        else:\n            score += ind_me + 1 + 0\n\nprint(score)\n
score = 0\n\nop_order = [\"A\", \"B\", \"C\"]\nme_order = [\"X\", \"Y\", \"Z\"]\nwith open(\"day02_input.txt\") as f:\n    for line in f:\n        op, me = line.strip().split()\n        ind_op = op_order.index(op)\n        ind_me = me_order.index(me)\n        if ind_me == 1:\n            score += ind_op + 1 + 3\n        elif ind_me == 2:\n            shape_map = {\n                0: 1 + 1,\n                1: 2 + 1,\n                2: 0 + 1,\n            }\n            score += shape_map[ind_op] + 6\n        else:\n            shape_map = {\n                0: 2 + 1,\n                1: 0 + 1,\n                2: 1 + 1,\n            }\n            score += shape_map[ind_op] + 0\n\nprint(score)\n
"},{"location":"2023/","title":"Advent of Code 2023","text":"Day 01 Part 1
with open(\"day01_input.txt\", \"r\") as f:\n    data = [\"\".join(c for c in row if c.isdigit()) for row in f.read().splitlines()]\n\nvalues = [int(d[0] + d[-1]) for d in data]\nprint(sum(values))\n
"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":""},{"location":"#advent-of-code","title":"Advent of Code","text":"
  • 2023
  • 2022
  • 2021
"},{"location":"2021/","title":"Advent of Code 2021","text":"Day 01 Part 1Part 2
with open(\"day01_input.txt\", \"r\") as f:\n    data = [int(i) for i in f.read().splitlines()]\n\ncount = 0\nfor i in range(1, len(data)):\n    if data[i] > data[i - 1]:\n        count += 1\n\nprint(count)\n
with open(\"day01_input.txt\", \"r\") as f:\n    data = [int(i) for i in f.read().splitlines()]\n\nthree_measurement_data = []\nfor i in range(2, len(data)):\n    three_measurement_data.append(sum(data[i - 2 : i + 1]))\n\ncount = 0\nfor i in range(1, len(three_measurement_data)):\n    if three_measurement_data[i] > three_measurement_data[i - 1]:\n        count += 1\n\nprint(count)\n
Day 02 Part 1Part 2
with open(\"day02_input.txt\", \"r\") as f:\n    data = [cmd.split() for cmd in f.read().splitlines()]\n\nhorizontal_position, depth = 0, 0\n\nfor action, value in data:\n    value = int(value)\n    if action == \"forward\":\n        horizontal_position += value\n    elif action == \"up\":\n        depth -= value\n    elif action == \"down\":\n        depth += value\n\nprint(horizontal_position, depth)\n\nprint(horizontal_position * depth)\n
with open(\"day02_input.txt\", \"r\") as f:\n    data = [cmd.split() for cmd in f.read().splitlines()]\n\nhorizontal_position, depth, aim = 0, 0, 0\n\nfor action, value in data:\n    value = int(value)\n    if action == \"forward\":\n        horizontal_position += value\n        depth += aim * value\n    elif action == \"up\":\n        aim -= value\n    elif action == \"down\":\n        aim += value\n\n\nprint(horizontal_position, depth, aim)\n\nprint(horizontal_position * depth)\n
Day 03 Part 1Part 2
with open(\"day03_input.txt\", \"r\") as f:\n    data = f.read().splitlines()\n\ncols = len(data[0])\nrows = len(data)\n\ngamma_rate, epsilon_rate = \"\", \"\"\n\nfor col in range(cols):\n    ones = 0\n    for row in range(rows):\n        if data[row][col] == \"1\":\n            ones += 1\n\n    if ones > rows / 2:\n        gamma_rate += \"1\"\n        epsilon_rate += \"0\"\n    else:\n        gamma_rate += \"0\"\n        epsilon_rate += \"1\"\n\nprint(gamma_rate, epsilon_rate)\n\nprint(int(gamma_rate, 2) * int(epsilon_rate, 2))\n
with open(\"day03_input.txt\", \"r\") as f:\n    data = f.read().splitlines()\n\ncols = len(data[0])\n\noxygen_generator_rating, co2_scrubber_rating = \"\", \"\"\n\nselections = data[:]\nfor col in range(cols):\n    ones = 0\n    for row in selections:\n        if row[col] == \"1\":\n            ones += 1\n\n    if ones >= len(selections) / 2:\n        selections = [row for row in selections if row[col] == \"1\"]\n    else:\n        selections = [row for row in selections if row[col] == \"0\"]\n\n    if len(selections) == 1:\n        oxygen_generator_rating += selections[0]\n        break\n\nselections = data[:]\nfor col in range(cols):\n    ones = 0\n    for row in selections:\n        if row[col] == \"1\":\n            ones += 1\n\n    if ones < len(selections) / 2:\n        selections = [row for row in selections if row[col] == \"1\"]\n    else:\n        selections = [row for row in selections if row[col] == \"0\"]\n\n    if len(selections) == 1:\n        co2_scrubber_rating += selections[0]\n        break\n\n\nprint(oxygen_generator_rating, co2_scrubber_rating)\n\nprint(int(oxygen_generator_rating, 2) * int(co2_scrubber_rating, 2))\n
Day 04 Part 2Part 1
with open(\"day04_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\ndraws = lines[0].split(\",\")\n\n\nlines = [line for line in lines[1:] if line]\nboards = []\nfor i in range(0, len(lines) // 5):\n    boards.append([])\n    for j in range(5):\n        boards[i].append(lines[i * 5 + j].split())\n\n\nmarks = {}\nfor i in range(len(boards)):\n    marks[i] = {}\n    for row in range(5):\n        for col in range(5):\n            marks[i][boards[i][row][col]] = (row, col)\n\n\nwinning_locations = []\nfor row in range(5):\n    winning_locations.append([(row, col) for col in range(5)])\nfor col in range(5):\n    winning_locations.append([(row, col) for row in range(5)])\n\n\ndef wins(locations, winning_locations=winning_locations):\n    for winning_location in winning_locations:\n        if all(loc in locations for loc in winning_location):\n            return winning_location\n\n    return None\n\n\nplays = {}\nfor i in range(len(boards)):\n    plays[i] = []\n\nnum_plays = {}\nfor i in range(len(boards)):\n    count = 0\n    for draw in draws:\n        count += 1\n        if draw in marks[i]:\n            plays[i].append(marks[i][draw])\n\n        if wins(plays[i]):\n            num_plays[i] = count, len(plays[i])\n            break\n\n\nlast_win = max(num_plays, key=lambda x: num_plays[x][0])\nprint(last_win)\n\n\nsum_unmarked = 0\nfor row in range(5):\n    for col in range(5):\n        if (row, col) not in plays[last_win]:\n            sum_unmarked += int(boards[last_win][row][col])\n\nrow, col = plays[last_win][-1]\nnum_call = int(boards[last_win][row][col])\n\n\nprint(sum_unmarked, num_call)\nprint(sum_unmarked * num_call)\n
with open(\"day04_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\ndraws = lines[0].split(\",\")\n\n\nlines = [line for line in lines[1:] if line]\nboards = []\nfor i in range(0, len(lines) // 5):\n    boards.append([])\n    for j in range(5):\n        boards[i].append(lines[i * 5 + j].split())\n\n\nmarks = {}\nfor i in range(len(boards)):\n    marks[i] = {}\n    for row in range(5):\n        for col in range(5):\n            marks[i][boards[i][row][col]] = (row, col)\n\n\nwinning_locations = []\nfor row in range(5):\n    winning_locations.append([(row, col) for col in range(5)])\nfor col in range(5):\n    winning_locations.append([(row, col) for row in range(5)])\n\n\ndef wins(locations, winning_locations=winning_locations):\n    for winning_location in winning_locations:\n        if all(loc in locations for loc in winning_location):\n            return winning_location\n\n    return None\n\n\nplays = {}\nfor i in range(len(boards)):\n    plays[i] = []\n\nnum_plays = {}\nfor i in range(len(boards)):\n    count = 0\n    for draw in draws:\n        count += 1\n        if draw in marks[i]:\n            plays[i].append(marks[i][draw])\n\n        if wins(plays[i]):\n            num_plays[i] = count, len(plays[i])\n            break\n\n\nfastest_win = min(num_plays, key=lambda x: num_plays[x][0])\nprint(fastest_win)\n\n\nsum_unmarked = 0\nfor row in range(5):\n    for col in range(5):\n        if (row, col) not in plays[fastest_win]:\n            sum_unmarked += int(boards[fastest_win][row][col])\n\nrow, col = plays[fastest_win][-1]\nnum_call = int(boards[fastest_win][row][col])\n\n\nprint(sum_unmarked, num_call)\nprint(sum_unmarked * num_call)\n
Day 05 Part 2Part 1
with open(\"day05_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\nlines = [line.split(\" -> \") for line in lines]\nlines = [(tuple(line[0].split(\",\")), tuple(line[1].split(\",\"))) for line in lines]\nprint(len(lines))\n\nlines = [\n    ((int(coord1[0]), int(coord1[1])), (int(coord2[0]), int(coord2[1])))\n    for coord1, coord2 in lines\n]\n\nfrom collections import Counter\n\ndiagram = Counter()\nfor coord1, coord2 in lines:\n    if coord1[0] == coord2[0]:\n        for i in range(min(coord1[1], coord2[1]), max(coord1[1], coord2[1]) + 1):\n            diagram[(coord1[0], i)] += 1\n    elif coord1[1] == coord2[1]:\n        for i in range(min(coord1[0], coord2[0]), max(coord1[0], coord2[0]) + 1):\n            diagram[(i, coord1[1])] += 1\n    else:\n        step_x = -1 if coord1[0] - coord2[0] > 0 else 1\n        step_y = -1 if coord1[1] - coord2[1] > 0 else 1\n        for x, y in zip(\n            range(coord1[0], coord2[0] + (1 if step_x > 0 else -1), step_x),\n            range(coord1[1], coord2[1] + (1 if step_y > 0 else -1), step_y),\n        ):\n            diagram[(x, y)] += 1\n\nprint(len([i for i in diagram.values() if i > 1]))\n
with open(\"day05_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\nlines = [line.split(\" -> \") for line in lines]\nlines = [(tuple(line[0].split(\",\")), tuple(line[1].split(\",\"))) for line in lines]\nprint(len(lines))\n\nlines = [\n    ((int(coord1[0]), int(coord1[1])), (int(coord2[0]), int(coord2[1])))\n    for coord1, coord2 in lines\n    if coord1[0] == coord2[0] or coord1[1] == coord2[1]\n]\nprint(len(lines))\n\nfrom collections import Counter\n\ndiagram = Counter()\nfor coord1, coord2 in lines:\n    if coord1[0] == coord2[0]:\n        for i in range(min(coord1[1], coord2[1]), max(coord1[1], coord2[1]) + 1):\n            diagram[(coord1[0], i)] += 1\n    elif coord1[1] == coord2[1]:\n        for i in range(min(coord1[0], coord2[0]), max(coord1[0], coord2[0]) + 1):\n            diagram[(i, coord1[1])] += 1\n\nprint(len([i for i in diagram.values() if i > 1]))\n
Day 06 Part 2Part 1
with open(\"day06_input.txt\", \"r\") as f:\n    fish = [int(i) for i in f.read().strip().split(\",\")]\n\n\nfrom collections import Counter\n\nfish = Counter(fish)\nprint(fish)\n\nfor _ in range(256):\n    for i in range(-1, 9):\n        if i == 8:\n            fish[i] = fish[-1]\n        elif i != 6:\n            fish[i] = fish[i + 1]\n        else:\n            fish[i] = fish[-1] + fish[i + 1]\n\n\nprint(sum([v for k, v in fish.items() if k >= 0]))\n
with open(\"day06_input.txt\", \"r\") as f:\n    fish = [int(i) for i in f.read().strip().split(\",\")]\n\nprint(f\"Initial state: {fish}\")\n\nfor _ in range(80):\n    new_fish = []\n    for i in range(len(fish)):\n\n        fish[i] -= 1\n\n        if fish[i] < 0:\n            fish[i] = 6\n            new_fish.append(8)\n\n    fish.extend(new_fish)\n\n    print(f\"After {str(_+1):2s} day{'s' if _ else ''}: {fish}\")\n\nprint(len(fish))\n
Day 07 Part 1Part 2
with open(\"day07_input.txt\", \"r\") as f:\n    crabs = [int(i) for i in f.read().strip().split(\",\")]\n\nprint(len(crabs))\n\nfrom collections import Counter\n\ncrabs = Counter(crabs)\n\n\noutcome = {}\n\nfor key in crabs:\n    result = 0\n    for key2 in crabs:\n        result += abs(key2 - key) * crabs[key2]\n    outcome[key] = result\n\nmin_key = min(outcome, key=outcome.get)\nprint(min_key)\nprint(outcome[min_key])\n
with open(\"day07_input.txt\", \"r\") as f:\n    crabs = [int(i) for i in f.read().strip().split(\",\")]\n\nprint(len(crabs))\n\nfrom collections import Counter\n\ncrabs = Counter(crabs)\n\n\noutcome = {}\n\nfor key in range(0, max(crabs.keys()) + 1):\n    result = 0\n    for key2 in crabs:\n        result += sum(range(1, abs(key2 - key) + 1)) * crabs[key2]\n    outcome[key] = result\n\nmin_key = min(outcome, key=outcome.get)\nprint(min_key)\nprint(outcome[min_key])\n
Day 08 Part 2Part 1
with open(\"day08_input.txt\", \"r\") as f:\n    obs = [line.split(\" | \") for line in f.read().splitlines()]\n\n\ndef _sorted(digit):\n    return \"\".join(sorted(digit))\n\n\ndef solve(digits):\n    mapping = {}\n    five_segs = []\n    six_segs = []\n\n    cf, bcdf, acf, abcdefg = None, None, None, None\n    for digit in digits:\n        if len(digit) == 2:\n            mapping[_sorted(digit)] = \"1\"\n            cf = digit\n        elif len(digit) == 3:\n            mapping[_sorted(digit)] = \"7\"\n            acf = digit\n        elif len(digit) == 4:\n            mapping[_sorted(digit)] = \"4\"\n            bcdf = digit\n        elif len(digit) == 7:\n            mapping[_sorted(digit)] = \"8\"\n            abcdefg = digit\n        elif len(digit) == 5:\n            five_segs.append(digit)\n        elif len(digit) == 6:\n            six_segs.append(digit)\n\n    bd = set(bcdf) - set(cf)\n    eg = set(abcdefg) - (set(cf) | set(bcdf) | set(acf))\n\n    for digit in six_segs:\n        _digit = set(digit)\n        if _digit >= bd and _digit >= eg:\n            mapping[_sorted(digit)] = \"6\"\n        elif _digit >= bd:\n            mapping[_sorted(digit)] = \"9\"\n        elif _digit >= eg:\n            mapping[_sorted(digit)] = \"0\"\n\n    for digit in five_segs:\n        _digit = set(digit)\n        if _digit >= bd:\n            mapping[_sorted(digit)] = \"5\"\n        elif _digit >= eg:\n            mapping[_sorted(digit)] = \"2\"\n        else:\n            mapping[_sorted(digit)] = \"3\"\n\n    return mapping\n\n\ncount = 0\nfor o in obs:\n    output_values = o[1].split()\n    digits = o[0].split()\n    mapping = solve(digits)\n    value = \"\"\n    for digit in output_values:\n        value += mapping[_sorted(digit)]\n\n    count += int(value)\n\nprint(count)\n
with open(\"day08_input.txt\", \"r\") as f:\n    obs = [line.split(\" | \") for line in f.read().splitlines()]\n\ncount = 0\nfor o in obs:\n    output_values = o[1].split()\n    for output_value in output_values:\n        if len(output_value) in [2, 3, 4, 7]:\n            count += 1\n\nprint(count)\n
Day 09 Part 2Part 1
with open(\"day09_input.txt\", \"r\") as f:\n    obs = [[int(i) for i in line] for line in f.read().splitlines()]\n\n\nlow_points = []\nfor i in range(0, len(obs)):\n    for j in range(0, len(obs[i])):\n        to_compare = []\n        if i > 0:\n            to_compare.append(obs[i - 1][j])\n        if i < len(obs) - 1:\n            to_compare.append(obs[i + 1][j])\n        if j > 0:\n            to_compare.append(obs[i][j - 1])\n        if j < len(obs[i]) - 1:\n            to_compare.append(obs[i][j + 1])\n\n        if all(obs[i][j] < x for x in to_compare):\n            low_points.append((i, j))\n\nbasin_sizes = []\n\n\ndef find_basin(i, j, points):\n    points.append((i, j))\n\n    up = i\n    while True:\n        if up > 0:\n            if obs[up - 1][j] > obs[up][j] and obs[up - 1][j] < 9:\n                find_basin(up - 1, j, points)\n                up -= 1\n            else:\n                break\n        else:\n            break\n\n    down = i\n    while True:\n        if down < len(obs) - 1:\n            if obs[down + 1][j] > obs[down][j] and obs[down + 1][j] < 9:\n                find_basin(down + 1, j, points)\n                down += 1\n            else:\n                break\n        else:\n            break\n\n    left = j\n    while True:\n        if left > 0:\n            if obs[i][left - 1] > obs[i][left] and obs[i][left - 1] < 9:\n                find_basin(i, left - 1, points)\n                left -= 1\n            else:\n                break\n        else:\n            break\n\n    right = j\n    while True:\n        if right < len(obs[i]) - 1:\n            if obs[i][right + 1] > obs[i][right] and obs[i][right + 1] < 9:\n                find_basin(i, right + 1, points)\n                right += 1\n            else:\n                break\n        else:\n            break\n\n\nfor i, j in low_points:\n    points = []\n    find_basin(i, j, points)\n    basin_sizes.append(len(set(points)))\n\nimport functools\n\nprint(functools.reduce(lambda x, y: x * y, sorted(basin_sizes)[-3:]))\n
with open(\"day09_input.txt\", \"r\") as f:\n    obs = [[int(i) for i in line] for line in f.read().splitlines()]\n\n\nlow_points = []\nfor i in range(0, len(obs)):\n    for j in range(0, len(obs[i])):\n        to_compare = []\n        if i > 0:\n            to_compare.append(obs[i - 1][j])\n        if i < len(obs) - 1:\n            to_compare.append(obs[i + 1][j])\n        if j > 0:\n            to_compare.append(obs[i][j - 1])\n        if j < len(obs[i]) - 1:\n            to_compare.append(obs[i][j + 1])\n\n        if all(obs[i][j] < x for x in to_compare):\n            low_points.append(obs[i][j])\n\n\nprint(sum(low_points) + len(low_points))\n
Day 10 Part 2Part 1
with open(\"day10_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\nmapping = {\n    \"(\": 1,\n    \"[\": 2,\n    \"{\": 3,\n    \"<\": 4,\n}\n\nmatch = {\n    \")\": \"(\",\n    \"]\": \"[\",\n    \"}\": \"{\",\n    \">\": \"<\",\n}\n\n\ndef check(line):\n    stack = []\n    for c in line:\n        if c in match.values():\n            stack.append(c)\n        elif c in match.keys():\n            if len(stack) == 0:\n                return 0\n            last = stack.pop()\n            if last != match[c]:\n                return 0\n\n    if len(stack) == 0:\n        return 0\n\n    score = 0\n    while len(stack) > 0:\n        last = stack.pop()\n        score *= 5\n        score += mapping[last]\n\n    return score\n\n\nscores = [check(line) for line in lines]\nscores = [s for s in scores if s > 0]\nprint(len(scores))\nprint(sorted(scores)[len(scores) // 2])\n
with open(\"day10_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\nmapping = {\n    \")\": 3,\n    \"]\": 57,\n    \"}\": 1197,\n    \">\": 25137,\n}\n\nmatch = {\n    \")\": \"(\",\n    \"]\": \"[\",\n    \"}\": \"{\",\n    \">\": \"<\",\n}\n\n\ndef check(line):\n    stack = []\n    for c in line:\n        if c in match.values():\n            stack.append(c)\n        elif c in match.keys():\n            if len(stack) == 0:\n                return mapping[c]\n            last = stack.pop()\n            if last != match[c]:\n                return mapping[c]\n\n    return 0\n\n\nprint(sum(check(line) for line in lines))\n
Day 11 Part 2Part 1
with open(\"day11_input.txt\", \"r\") as f:\n    obs = [[int(i) for i in line] for line in f.read().splitlines()]\n\n\ndef increase(obs):\n    for i in range(len(obs)):\n        for j in range(len(obs[i])):\n            obs[i][j] += 1\n\n\ndef has_flash(obs):\n    locations = []\n    for i in range(len(obs)):\n        for j in range(len(obs[i])):\n            if obs[i][j] > 9:\n                locations.append((i, j))\n    return locations\n\n\ndef display(obs):\n    for i in range(len(obs)):\n        print(\"\".join([str(i) for i in obs[i]]))\n\n\nfrom collections import Counter\n\n\nprint(\"Before any steps:\")\ndisplay(obs)\nprint()\n\n\ncount = 0\noctopuses = sum([len(obs[i]) for i in range(len(obs))])\nwhile True:\n    increase(obs)\n\n    flashes = set()\n    while True:\n        locations = has_flash(obs)\n        flashes.update(locations)\n\n        if locations:\n            c = Counter()\n            for i, j in locations:\n                obs[i][j] = 0\n                if i > 0:\n                    c[(i - 1, j)] += 1\n                    if j > 0:\n                        c[(i - 1, j - 1)] += 1\n                    if j < len(obs[i]) - 1:\n                        c[(i - 1, j + 1)] += 1\n                if i < len(obs) - 1:\n                    c[(i + 1, j)] += 1\n                    if j > 0:\n                        c[(i + 1, j - 1)] += 1\n                    if j < len(obs[i]) - 1:\n                        c[(i + 1, j + 1)] += 1\n                if j > 0:\n                    c[(i, j - 1)] += 1\n                if j < len(obs[i]) - 1:\n                    c[(i, j + 1)] += 1\n            for i, j in c:\n                if (i, j) not in flashes:\n                    obs[i][j] += c[(i, j)]\n            if c:\n                continue\n        break\n\n    print(f\"After step {count+1}:\")\n    display(obs)\n    print(f\"Flashes: {len(flashes)}\")\n    print()\n\n    count += 1\n    if len(flashes) == octopuses:\n        break\n\nprint(f\"Total steps: {count}\")\n
with open(\"day11_input.txt\", \"r\") as f:\n    obs = [[int(i) for i in line] for line in f.read().splitlines()]\n\n\ndef increase(obs):\n    for i in range(len(obs)):\n        for j in range(len(obs[i])):\n            obs[i][j] += 1\n\n\ndef has_flash(obs):\n    locations = []\n    for i in range(len(obs)):\n        for j in range(len(obs[i])):\n            if obs[i][j] > 9:\n                locations.append((i, j))\n    return locations\n\n\ndef display(obs):\n    for i in range(len(obs)):\n        print(\"\".join([str(i) for i in obs[i]]))\n\n\nfrom collections import Counter\n\nprint(\"Before any steps:\")\ndisplay(obs)\nprint()\n\ncount = 0\nfor s in range(100):\n    increase(obs)\n\n    flashes = set()\n    while True:\n        locations = has_flash(obs)\n        flashes.update(locations)\n\n        if locations:\n            c = Counter()\n            for i, j in locations:\n                obs[i][j] = 0\n                if i > 0:\n                    c[(i - 1, j)] += 1\n                    if j > 0:\n                        c[(i - 1, j - 1)] += 1\n                    if j < len(obs[i]) - 1:\n                        c[(i - 1, j + 1)] += 1\n                if i < len(obs) - 1:\n                    c[(i + 1, j)] += 1\n                    if j > 0:\n                        c[(i + 1, j - 1)] += 1\n                    if j < len(obs[i]) - 1:\n                        c[(i + 1, j + 1)] += 1\n                if j > 0:\n                    c[(i, j - 1)] += 1\n                if j < len(obs[i]) - 1:\n                    c[(i, j + 1)] += 1\n            for i, j in c:\n                if (i, j) not in flashes:\n                    obs[i][j] += c[(i, j)]\n            if c:\n                continue\n        break\n\n    print(f\"After step {s+1}:\")\n    display(obs)\n    print(f\"Flashes: {len(flashes)}\")\n    print()\n\n    count += len(flashes)\n\nprint(f\"Total flashes: {count}\")\n
Day 12 Part 1Part 2
with open(\"day12_input.txt\", \"r\") as f:\n    segs = f.read().splitlines()\n\n\ngraph = {}\nfor seg in segs:\n    node1, node2 = seg.split(\"-\")\n    if node1 not in graph:\n        graph[node1] = [node2]\n    else:\n        graph[node1].append(node2)\n\n    if node2 not in graph:\n        graph[node2] = [node1]\n    else:\n        graph[node2].append(node1)\n\nfrom pprint import pprint\n\npprint(graph)\n\n\npaths = []\n\n\ndef breadth_first_search(graph, start, end, path=[]):\n    path = path + [start]\n    if start == end:\n        paths.append(path)\n    if start not in graph:\n        return None\n    for node in graph[start]:\n        if node not in path or node.isupper():\n            newpath = breadth_first_search(graph, node, end, path)\n            if newpath:\n                paths.append(newpath)\n    return None\n\n\nbreadth_first_search(graph, \"start\", \"end\")\n\nfor path in paths:\n    print(\",\".join(path))\n\nprint(len(paths))\n
with open(\"day12_input.txt\", \"r\") as f:\n    segs = f.read().splitlines()\n\n\ngraph = {}\nfor seg in segs:\n    node1, node2 = seg.split(\"-\")\n    if node1 not in graph:\n        graph[node1] = [node2]\n    else:\n        graph[node1].append(node2)\n\n    if node2 not in graph:\n        graph[node2] = [node1]\n    else:\n        graph[node2].append(node1)\n\nfrom pprint import pprint\n\npprint(graph)\n\n\npaths = []\n\n\ndef remaining(path, node):\n    others = [\n        n for n in path if n != node and n.islower() and n not in [\"start\", \"end\"]\n    ]\n\n    return all(path.count(n) <= 1 for n in others)\n\n\ndef breadth_first_search(graph, start, end, path=[]):\n\n    path = path + [start]\n    if start == end:\n        paths.append(path)\n    if start not in graph:\n        return None\n    for node in graph[start]:\n        if (\n            node not in path\n            or node.isupper()\n            or (\n                node not in [\"start\", \"end\"]\n                and node.islower()\n                and path.count(node) < 2\n                and remaining(path, node)\n            )\n        ):\n            newpath = breadth_first_search(graph, node, end, path)\n            if newpath:\n                paths.append(newpath)\n    return None\n\n\nbreadth_first_search(graph, \"start\", \"end\")\n\nfor path in paths:\n    print(\",\".join(path))\n\nprint(len(paths))\n
Day 13 Part 2Part 1
with open(\"day13_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\ndots = []\nactions = []\nfor line in lines:\n    if not line:\n        continue\n    if \",\" in line:\n        x, y = line.split(\",\")\n        dots.append((int(x), int(y)))\n    else:\n        actions.append(line.split()[-1].split(\"=\"))\n\nprevious = dots[:]\n\nfor axis, value in actions:\n    result = []\n    value = int(value)\n    if axis == \"x\":\n        for dot in previous:\n            if dot[0] < value:\n                result.append((dot[0], dot[1]))\n            else:\n                result.append((2 * value - dot[0], dot[1]))\n\n    elif axis == \"y\":\n        for dot in previous:\n            if dot[1] < value:\n                result.append((dot[0], dot[1]))\n            else:\n                result.append((dot[0], 2 * value - dot[1]))\n\n    print(len(set(result)))\n\n    previous = result[:]\n\nmax_x = max(result, key=lambda x: x[0])[0]\nmax_y = max(result, key=lambda x: x[1])[1]\nprint(max_x, max_y)\n\nfor y in range(max_y + 1):\n    for x in range(max_x + 1):\n        if (x, y) in result:\n            print(\"#\", end=\"\")\n        else:\n            print(\" \", end=\"\")\n    print()\n\nfrom PIL import Image\n\nimg = Image.new(\"RGB\", (max_x + 1, max_y + 1), \"black\")\npixels = img.load()\nfor dot in set(result):\n    pixels[dot[0], dot[1]] = (255, 255, 255)\nimg.show()\n
with open(\"day13_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\ndots = []\nactions = []\nfor line in lines:\n    if not line:\n        continue\n    if \",\" in line:\n        x, y = line.split(\",\")\n        dots.append((int(x), int(y)))\n    else:\n        actions.append(line.split()[-1].split(\"=\"))\n\nprevious = dots[:]\n\nfor axis, value in actions:\n    result = []\n    value = int(value)\n    if axis == \"x\":\n        for dot in previous:\n            if dot[0] < value:\n                result.append((dot[0], dot[1]))\n            else:\n                result.append((2 * value - dot[0], dot[1]))\n\n    elif axis == \"y\":\n        for dot in previous:\n            if dot[1] < value:\n                result.append((dot[0], dot[1]))\n            else:\n                result.append((dot[0], 2 * value - dot[1]))\n\n    print(len(set(result)))\n\n    previous = result[:]\n
Day 14 Part 2Part 1
with open(\"day14_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\ntemplate = None\npairs = []\nfor line in lines:\n    if not line:\n        continue\n    if \" -> \" in line:\n        pairs.append(line.split(\" -> \"))\n    else:\n        template = line\n\nprint(f\"Template: {template}\")\nsegs = [template[j : j + 2] for j in range(0, len(template) - 1)]\n\nfrom collections import Counter\n\ncounts = Counter(segs)\n\n\nfor i in range(40):\n    result = Counter()\n    for key in counts:\n        for pair in pairs:\n            if key == pair[0]:\n                result[key[0] + pair[1]] += counts[key]\n                result[pair[1] + key[1]] += counts[pair[0]]\n\n    counts = result\n\n\nchars = Counter()\nchars[template[0]] += 1\n\nfor key, value in counts.items():\n    chars[key[1]] += value\n\nchars = chars.most_common()\nprint(chars)\nprint(chars[0][1] - chars[-1][1])\n
with open(\"day14_input.txt\", \"r\") as f:\n    lines = f.read().splitlines()\n\n\ntemplate = None\npairs = []\nfor line in lines:\n    if not line:\n        continue\n    if \" -> \" in line:\n        pairs.append(line.split(\" -> \"))\n    else:\n        template = line\n\nprint(f\"Template: {template}\")\n\nfor i in range(10):\n    segs = [template[j : j + 2] for j in range(0, len(template) - 1)]\n\n    for k in range(len(segs)):\n        for pair in pairs:\n            if segs[k] == pair[0]:\n                segs[k] = pair[0][0] + pair[1] + pair[0][1]\n\n    template = segs[0]\n    for seg in segs[1:]:\n        template += seg[-2:]\n\n    print(f\"After step {i+1}: {template}\")\n\nfrom collections import Counter\n\ncounts = Counter(template).most_common()\n\nprint(counts[0][1] - counts[-1][1])\n
Day 15 Part 2Part 1
with open(\"day15_input.txt\", \"r\") as f:\n    lines = [[int(d) for d in line] for line in f.read().splitlines()]\n\nrows, cols = len(lines), len(lines[0])\n\n\nlines_5x = [[0] * cols * 5 for i in range(rows * 5)]\nfor ii in range(5):\n    for jj in range(5):\n        for i in range(rows):\n            for j in range(cols):\n                lines_5x[ii * rows + i][jj * cols + j] = (\n                    lines[i][j] + ii + jj - 1\n                ) % 9 + 1\n\n\n# Using the networkx library instead\n\nimport networkx as nx\n\ng = nx.DiGraph()\nrows *= 5\ncols *= 5\n\nfor i in range(rows):\n    for j in range(cols):\n        if i < rows - 1:\n            g.add_edge((i, j), (i + 1, j), weight=lines_5x[i + 1][j])\n            g.add_edge((i + 1, j), (i, j), weight=lines_5x[i][j])\n\n        if j < cols - 1:\n            g.add_edge((i, j), (i, j + 1), weight=lines_5x[i][j + 1])\n            g.add_edge((i, j + 1), (i, j), weight=lines_5x[i][j])\n\npaths = nx.shortest_path(\n    g,\n    source=(0, 0),\n    target=(rows - 1, cols - 1),\n    weight=\"weight\",\n)\n\n# print(paths)\n\ncost = 0\nfor i, j in paths[1:]:\n    cost += lines_5x[i][j]\n\nprint(f\"Cost of shortest path is {cost}\")\n
with open(\"day15_input.txt\", \"r\") as f:\n    risks = [[int(d) for d in line] for line in f.read().splitlines()]\n\nrows, cols = len(risks), len(risks[0])\n\n# reference: https://stackabuse.com/dijkstras-algorithm-in-python/\n\nfrom queue import PriorityQueue\n\n\nclass Graph:\n    def __init__(self, num_of_vertices):\n        self.v = num_of_vertices\n        self.edges = [\n            [-1 for i in range(num_of_vertices)] for j in range(num_of_vertices)\n        ]\n        self.visited = []\n\n    def add_edge(self, u, v, weight):\n        self.edges[u][v] = weight\n\n\ndef dijkstra(graph, start_vertex):\n    D = {v: float(\"inf\") for v in range(graph.v)}\n    D[start_vertex] = 0\n\n    pq = PriorityQueue()\n    pq.put((0, start_vertex))\n\n    while not pq.empty():\n        (dist, current_vertex) = pq.get()\n        graph.visited.append(current_vertex)\n\n        for neighbor in range(graph.v):\n            if graph.edges[current_vertex][neighbor] != -1:\n                distance = graph.edges[current_vertex][neighbor]\n                if neighbor not in graph.visited:\n                    old_cost = D[neighbor]\n                    new_cost = D[current_vertex] + distance\n                    if new_cost < old_cost:\n                        pq.put((new_cost, neighbor))\n                        D[neighbor] = new_cost\n    return D\n\n\ng = Graph(rows * cols)\nfor i in range(rows):\n    for j in range(cols):\n\n        if i < rows - 1:\n            g.add_edge((i + 1) * cols + j, i * cols + j, risks[i][j])\n            g.add_edge(i * cols + j, (i + 1) * cols + j, risks[i + 1][j])\n\n        if j < cols - 1:\n            g.add_edge(i * cols + j + 1, i * cols + j, risks[i][j])\n            g.add_edge(i * cols + j, i * cols + j + 1, risks[i][j + 1])\n\n\nD = dijkstra(g, 0)\nprint(f\"Cost of shortest path is {D[rows*cols-1]}\")\n
Day 16 Part 1
with open(\"day16_input.txt\", \"r\") as f:\n    hexadecimal = f.read().strip()\n\nprint(f\"Hex: {hexadecimal}\")\n\n\ndef hex2bin(h):\n    return bin(int(h, 16))[2:].zfill(len(h) * 4)\n\n\nb = hex2bin(hexadecimal)\nprint(f\"Bin: {b}\")\n\nprint()\n\n\ndef decode_header(b):\n    packet_version = b[:3]\n    packet_type_id = b[3:6]\n\n    return int(packet_version, 2), int(packet_type_id, 2), b[6:]\n\n\ndef decode_literal(b):\n    value = \"\"\n\n    while b:\n        seg = b[:5]\n        value += seg[-4:]\n        b = b[5:]\n        if seg[0] == \"0\":\n            break\n\n    return value, b\n\n\ndef decode_operator(b):\n    length_type_id = b[:1]\n\n    if length_type_id == \"0\":\n        length_of_subpackets = int(b[1:16], 2)\n\n        remaining = b[16 + length_of_subpackets :]\n        b = b[16 : 16 + length_of_subpackets]\n        number_of_subpackets = -1\n    else:\n        number_of_subpackets = int(b[1:12], 2)\n        b = b[12:]\n        remaining = None\n\n    return length_type_id, number_of_subpackets, b, remaining\n\n\nresult = []\n\n\ndef decode(b):\n    while b:\n        if all(c == \"0\" for c in b):\n            return\n\n        packet_version, packet_type_id, b = decode_header(b)\n        result.append(packet_version)\n        print(f\"packet_version: {packet_version}, packet_type_id: {packet_type_id}\")\n        if packet_type_id == 4:\n            value, b = decode_literal(b)\n            print(f\"Literal value {value} is {int(value, 2)}.\")\n        else:\n            length_type_id, number_of_subpackets, block, remaining = decode_operator(b)\n            print(\n                f\"length_type_id: {length_type_id},\",\n                f\"number_of_subpackets: {number_of_subpackets},\",\n            )\n            if number_of_subpackets == -1:\n                b = remaining\n                decode(block)\n            else:\n                b = block\n                return decode(b)\n\n    return\n\n\ndecode(b)\nprint()\nprint(f\"Result: {result} -> {sum(result)}\")\n
"},{"location":"2022/","title":"Advent of Code 2022","text":"Day 01 Part 1Part 2
max_calories = 0\ncalories = 0\n\nwith open(\"day01_input.txt\") as f:\n    for line in f:\n        if not line.strip():\n            if calories > max_calories:\n                max_calories = calories\n            calories = 0\n            continue\n        calories += int(line)\n\nprint(max_calories)\n
all_calories = []\ncalories = 0\n\nwith open(\"day01_input.txt\") as f:\n    for line in f:\n        if not line.strip():\n            all_calories.append(calories)\n            calories = 0\n            continue\n        calories += int(line)\n\nprint(sum(sorted(all_calories)[-3:]))\n
Day 02 Part 1Part 2
score = 0\n\nop_order = [\"A\", \"B\", \"C\"]\nme_order = [\"X\", \"Y\", \"Z\"]\nwith open(\"day02_input.txt\") as f:\n    for line in f:\n        op, me = line.strip().split()\n        ind_op = op_order.index(op)\n        ind_me = me_order.index(me)\n        if ind_me == ind_op:\n            score += ind_me + 1 + 3\n        elif any(\n            [\n                ind_me == 1 and ind_op == 0,\n                ind_me == 2 and ind_op == 1,\n                ind_me == 0 and ind_op == 2,\n            ]\n        ):\n            score += ind_me + 1 + 6\n        else:\n            score += ind_me + 1 + 0\n\nprint(score)\n
score = 0\n\nop_order = [\"A\", \"B\", \"C\"]\nme_order = [\"X\", \"Y\", \"Z\"]\nwith open(\"day02_input.txt\") as f:\n    for line in f:\n        op, me = line.strip().split()\n        ind_op = op_order.index(op)\n        ind_me = me_order.index(me)\n        if ind_me == 1:\n            score += ind_op + 1 + 3\n        elif ind_me == 2:\n            shape_map = {\n                0: 1 + 1,\n                1: 2 + 1,\n                2: 0 + 1,\n            }\n            score += shape_map[ind_op] + 6\n        else:\n            shape_map = {\n                0: 2 + 1,\n                1: 0 + 1,\n                2: 1 + 1,\n            }\n            score += shape_map[ind_op] + 0\n\nprint(score)\n
Day 03 Part 1Part 2
priorities = 0\n\nwith open(\"day03_input.txt\") as f:\n    for line in f:\n        line = line.strip()\n        if not line:\n            continue\n        first, second = line[: len(line) // 2], line[len(line) // 2 :]\n        overlap = set(first).intersection(set(second)).pop()\n        if overlap.isupper():\n            priorities += ord(overlap) - ord(\"A\") + 27\n        else:\n            priorities += ord(overlap) - ord(\"a\") + 1\n\nprint(priorities)\n
priorities = 0\n\nwith open(\"day03_input.txt\") as f:\n    groups = f.readlines()\n    groups = [groups[3 * i : 3 * i + 3] for i in range(0, len(groups) // 3)]\n\n    for g in groups:\n        items = None\n        for line in g:\n            line = line.strip()\n            if not items:\n                items = set(line)\n            else:\n                items = items.intersection(set(line))\n        overlap = items.pop()\n\n        if overlap.isupper():\n            priorities += ord(overlap) - ord(\"A\") + 27\n        else:\n            priorities += ord(overlap) - ord(\"a\") + 1\n\nprint(priorities)\n
Day 04 Part 2Part 1
count = 0\n\nwith open(\"day04_input.txt\") as f:\n    sections = f.readlines()\n    for section in sections:\n        section = section.strip()\n        r1, r2 = section.split(\",\")\n\n        r1_start, r1_stop = int(r1.split(\"-\")[0]), int(r1.split(\"-\")[1]) + 1\n        r1 = set(range(r1_start, r1_stop))\n\n        r2_start, r2_stop = int(r2.split(\"-\")[0]), int(r2.split(\"-\")[1]) + 1\n        r2 = set(range(r2_start, r2_stop))\n\n        if r1.intersection(r2):\n            count += 1\n\nprint(count)\n
count = 0\n\nwith open(\"day04_input.txt\") as f:\n    sections = f.readlines()\n    for section in sections:\n        section = section.strip()\n        r1, r2 = section.split(\",\")\n\n        r1_start, r1_stop = int(r1.split(\"-\")[0]), int(r1.split(\"-\")[1]) + 1\n        r1 = set(range(r1_start, r1_stop))\n\n        r2_start, r2_stop = int(r2.split(\"-\")[0]), int(r2.split(\"-\")[1]) + 1\n        r2 = set(range(r2_start, r2_stop))\n\n        if r1.issuperset(r2) or r2.issuperset(r1):\n            count += 1\n\nprint(count)\n
Day 06 Part 2Part 1
with open(\"day06_input.txt\") as f:\n    buffer = f.read()\n\n    offset = 14\n    for i in range(0, len(buffer) - offset):\n        if len(set(buffer[i : i + offset])) == offset:\n            break\n\n    print(i + offset)\n
with open(\"day06_input.txt\") as f:\n    buffer = f.read()\n\n    for i in range(0, len(buffer) - 4):\n        if len(set(buffer[i : i + 4])) == 4:\n            break\n\n    print(i + 4)\n
"},{"location":"2023/","title":"Advent of Code 2023","text":"Day 01 Part 1
with open(\"day01_input.txt\", \"r\") as f:\n    data = [\"\".join(c for c in row if c.isdigit()) for row in f.read().splitlines()]\n\nvalues = [int(d[0] + d[-1]) for d in data]\nprint(sum(values))\n
"}]} \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index c8810bce9adbf49fdbc1c2ffb69dbeed8f86d6c6..23718ffb72f9dd25485afb9f8c4ef3470c6c708b 100644 GIT binary patch delta 12 Tcmb=gXOr*d;OKuhk*yK{8bbt3 delta 12 Tcmb=gXOr*d;JE*GB3mT@8_xur