with open("day04_input.txt", "r") as f:
- lines = f.read().splitlines()
+
Advent of Code 2021
Day 01
| 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)
|
| 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
Day 02
| 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)
|
| 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
Day 03
| 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))
|
| | 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
Day 04
| | 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)
|
| 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
Day 05
| 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]))
|
| 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
| 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]))
|
| 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
Day 11
Day 08
| 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)
|
| 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
Day 09
| 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:]))
|
| 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
Day 10
| 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
| 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])
+
|
| 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
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}")
+ |
| | 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
| 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))
+ |
| | 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
| | 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()
+ |
| 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
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])
+ |
| 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
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}")
+ |
| | 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
| | 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)}")
|