Last active
December 7, 2021 15:37
-
-
Save pjhoberman/76ed9487660af8ab0c62739a065c2fd7 to your computer and use it in GitHub Desktop.
Advent of Code 2021
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
inp = """199 | |
200 | |
208 | |
210 | |
200 | |
207 | |
240 | |
269 | |
260 | |
263""" | |
inp = [int(val) for val in inp.split()] | |
prev = inp[0] | |
counter = 0 | |
for val in inp[1:]: | |
if val > prev: | |
counter += 1 | |
prev = val | |
# counter --> 7 | |
# replace inp with actual input |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from more_itertools import triplewise # this is cheating, but here we are | |
inp = """199 | |
200 | |
208 | |
210 | |
200 | |
207 | |
240 | |
269 | |
260 | |
263""" | |
inp = [int(val) for val in inp.split()] | |
c = 0 | |
first = True | |
for trip in triplewise(inp): | |
if first: | |
prev = sum(trip) | |
first = False | |
continue | |
else: | |
if sum(trip) > prev: | |
c += 1 | |
prev = sum(trip) | |
# counter --> 5 | |
# replace inp with actual input |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# day 2.1 | |
inp = """forward 5 | |
down 5 | |
forward 8 | |
up 3 | |
down 8 | |
forward 2""" | |
inp = [line.split() for line in inp.split("\n")] | |
x = 0 | |
y = 0 | |
for instr in inp: | |
direction, value = instr | |
value = int(value) | |
if direction == "forward": | |
x += value | |
elif direction == "down": | |
y += value | |
elif direction == "up": | |
y -= value | |
else: | |
print(f"bad instruction: {instr}") | |
print(x,y) | |
print(x*y) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## day2.2 | |
inp = """forward 5 | |
down 5 | |
forward 8 | |
up 3 | |
down 8 | |
forward 2""" | |
inp = [line.split() for line in inp.split("\n")] | |
x = 0 | |
y = 0 | |
aim = 0 | |
for instr in inp: | |
direction, value = instr | |
value = int(value) | |
if direction == "forward": | |
x += value | |
y += aim * value | |
elif direction == "down": | |
# y += value | |
aim += value | |
elif direction == "up": | |
# y -= value | |
aim -= value | |
else: | |
print(f"bad instruction: {instr}") | |
print(x*y) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# day 3.1 | |
inp = """00100 | |
11110 | |
10110 | |
10111 | |
10101 | |
01111 | |
00111 | |
11100 | |
10000 | |
11001 | |
00010 | |
01010""" | |
from collections import Counter, defaultdict | |
inp = inp.split("\n") | |
bit_counter = defaultdict(Counter) | |
for line in inp: | |
for pos, val in enumerate(line): | |
bit_counter[pos].update([val]) | |
gamma = "" | |
epsilon = "" | |
for pos, res in bit_counter.items(): | |
most_common = res.most_common(1)[0][0] | |
gamma += most_common | |
epsilon += "0" if most_common == "1" else "1" | |
gamma = int(gamma, 2) | |
epsilon = int(epsilon, 2) | |
answer = gamma * epsilon | |
# part 2 | |
o2_inp = inp.copy() | |
co2_inp = inp.copy() | |
i = 0 | |
while len(o2_inp) > 1 and i < len(o2_inp[0]): | |
# calc most common for i | |
c = Counter() | |
for line in o2_inp: | |
c.update([line[i]]) | |
# check for ties | |
if c['1'] == c['0']: | |
most_common = '1' | |
else: | |
most_common = c.most_common(1)[0][0] | |
o2_inp = filter(lambda item: item[i] == most_common, o2_inp) | |
o2_inp = list(o2_inp) | |
i += 1 | |
i = 0 | |
while len(co2_inp) > 1 and i < len(co2_inp[0]): | |
# calc most common for i | |
c = Counter() | |
for line in co2_inp: | |
c.update([line[i]]) | |
# check for ties | |
if c['1'] == c['0']: | |
least_common = '0' | |
else: | |
least_common = c.most_common(2)[1][0] | |
co2_inp = filter(lambda item: item[i] == least_common, co2_inp) | |
co2_inp = list(co2_inp) | |
i += 1 | |
answer = int(o2_inp[0], 2) * int(co2_inp[0], 2) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
draws = (7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1) | |
boards = """ | |
22 13 17 11 0 | |
8 2 23 4 24 | |
21 9 14 16 7 | |
6 10 3 18 5 | |
1 12 20 15 19 | |
3 15 0 2 22 | |
9 18 13 17 5 | |
19 8 7 25 23 | |
20 11 10 24 4 | |
14 21 16 12 6 | |
14 21 17 24 4 | |
10 16 15 9 19 | |
18 8 23 26 20 | |
22 11 13 6 5 | |
2 0 12 3 7 | |
""" | |
class Puzzle: | |
def __init__(self, board): | |
self.score = None | |
self.board_input = board | |
self.rows = None | |
self.cols = None | |
self.build_board() | |
def build_board(self): | |
self.rows = [row.split() for row in self.board_input.split("\n") if row] | |
col_length = len(self.rows[0]) | |
self.cols = [[] for i in range(col_length)] | |
for row in self.rows: | |
for i, val in enumerate(row): | |
self.cols[i].append(val) | |
def calculate_unmarked(self): | |
total = 0 | |
for row in self.rows: | |
for val in row: | |
if val != "x": | |
total += int(val) | |
return total | |
def mark_board(self, n): | |
for row in self.rows: | |
for i, val in enumerate(row): | |
if val == n: | |
row[i] = "x" | |
for col in self.cols: | |
for i, val in enumerate(col): | |
if val == n: | |
col[i] = "x" | |
if self.check_cols() or self.check_rows(): | |
self.score = self.calculate_unmarked() * int(n) | |
return self.calculate_unmarked() * int(n) | |
return False | |
def check_rows(self): | |
for row in self.rows: | |
if all([val == "x" for val in row]): | |
return True | |
return False | |
def check_cols(self): | |
for col in self.cols: | |
if all([val == "x" for val in col]): | |
return True | |
return False | |
puzzles = [Puzzle(board) for board in boards.split("\n\n")] | |
bingo = False | |
for draw in draws: | |
for puzzle in puzzles: | |
bingo = puzzle.mark_board(str(draw)) | |
if bingo: | |
print(bingo) | |
break | |
if bingo: | |
break | |
# part 2 | |
puzzles = [Puzzle(board) for board in boards.split("\n\n")] | |
winning_boards = [] | |
for draw in draws: | |
for puzzle in puzzles: | |
if puzzle in winning_boards: | |
continue | |
bingo = puzzle.mark_board(str(draw)) | |
if bingo: | |
winning_boards.append(puzzle) | |
print(bingo) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This is only part 2. Part 1, just put a `pass` on the diagonal else around line 60 | |
""" | |
data = """0,9 -> 5,9 | |
8,0 -> 0,8 | |
9,4 -> 3,4 | |
2,2 -> 2,1 | |
7,0 -> 7,4 | |
6,4 -> 2,0 | |
0,9 -> 2,9 | |
3,4 -> 1,4 | |
0,0 -> 8,8 | |
5,5 -> 8,2""" | |
data = data.split("\n") | |
class Line: | |
def __init__(self, data): | |
self.data = data | |
self.x_start = None | |
self.x_end = None | |
self.y_start = None | |
self.y_end = None | |
self.points = [] | |
self.parse_data() | |
self.all_points() | |
def parse_data(self): | |
start, end = self.data.split(" -> ") | |
self.x_start, self.y_start = [int(x) for x in start.split(",")] | |
self.x_end, self.y_end = [int(x) for x in end.split(",")] | |
@property | |
def coords(self): | |
return { | |
"x_start": self.x_start, | |
"x_end": self.x_end, | |
"y_start": self.y_start, | |
"y_end": self.y_end, | |
} | |
def all_points(self): | |
if self.x_start == self.x_end: | |
if self.y_start < self.y_end: | |
for i in range(self.y_start, self.y_end + 1): | |
self.points.append((self.x_start, i)) | |
else: | |
for i in range(self.y_end, self.y_start + 1): | |
self.points.append((self.x_start, i)) | |
elif self.y_start == self.y_end: | |
if self.x_start < self.x_end: | |
for i in range(self.x_start, self.x_end + 1): | |
self.points.append((i, self.y_start)) | |
else: | |
for i in range(self.x_end, self.x_start + 1): | |
self.points.append((i, self.y_start)) | |
else: | |
# diagonal, added for part 2 | |
x_step = 1 if self.x_start < self.x_end else -1 | |
x = range(self.x_start, self.x_end + x_step, x_step) | |
y_step = 1 if self.y_start < self.y_end else -1 | |
y = range(self.y_start, self.y_end + y_step, y_step) | |
self.points += list(zip(list(x),list(y))) | |
# parse lines and find shape | |
lines = [] | |
max_x = 1 | |
max_y = 1 | |
for line in data: | |
_line = Line(line) | |
lines.append(_line) | |
if max(_line.x_start, _line.x_end) > max_x: | |
max_x = max(_line.x_start, _line.x_end) | |
if max(_line.y_start, _line.y_end) > max_y: | |
max_y = max(_line.y_start, _line.y_end) | |
# build shape | |
class Grid: | |
def __init__(self, x, y): | |
self.max_x = x | |
self.max_y = y | |
self.rows = [] | |
self.build_grid() | |
def build_grid(self): | |
for i in range(self.max_x+1): | |
self.rows.append([]) | |
for j in range(self.max_y+1): | |
self.rows[i].append(0) | |
def update_point(self, x, y): | |
self.rows[y][x] += 1 | |
def get_dangerous_points(self, danger=2): | |
dangerous_points = 0 | |
for row in self.rows: | |
for cell in row: | |
if cell >= danger: | |
dangerous_points += 1 | |
return dangerous_points | |
def __repr__(self): | |
return "\n".join([" ".join([str(cell) for cell in row]) for row in self.rows]) | |
grid = Grid(max_x, max_y) | |
for line in lines: | |
points = line.points | |
for point in points: | |
grid.update_point(*point) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# actual answer toward the bottom | |
# this works for part 1 but very slowly, part 2 chokes | |
def make_more_fish(days=18, starting_fish=None): | |
schedule = defaultdict(int) | |
fish = starting_fish.copy() if starting_fish is not None else [3,4,3,1,2] | |
for f in fish: | |
schedule[f] += 1 | |
for day in range(days): | |
new_fish = 0 | |
for i, f in enumerate(fish): | |
if fish[i] == 0: | |
fish[i] = 6 | |
new_fish += 1 | |
else: | |
fish[i] -= 1 | |
fish += [8]*new_fish | |
return len(fish) | |
# Better and actually works for part 2 | |
from collections import defaultdict | |
def make_more_fish(days=18, starting_fish=None): | |
fish = starting_fish.copy() if starting_fish is not None else [3,4,3,1,2] | |
_fish = defaultdict(int) | |
for f in fish: | |
_fish[f] += 1 | |
for day in range(days): | |
new_fish = defaultdict(int) | |
for _day, count in _fish.items(): | |
if _day == 0: | |
new_fish[8] += count | |
new_fish[6] += count | |
else: | |
new_fish[_day-1] += count | |
_fish = new_fish.copy() | |
return sum(_fish.values()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# day 7 | |
import statistics | |
data = [16,1,2,0,4,2,7,1,2,14] | |
# part 1 | |
median = statistics.median(data) | |
gas = 0 | |
for d in data: | |
gas += abs(d-median) | |
assert gas == 37 | |
# part 2 | |
gas = 0 | |
# rounding down worked on this for actual input... but not round. Round worked for the test data (which rounded up) | |
mean = round(statistics.mean(data)) | |
for d in data: | |
gas += sum(range(abs(d-mean)+1)) | |
assert gas == 168 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment