AoC 2020 Advent of Code (Python)
By telleropnul, December 31, 2020
Advent of Code AoC) is an Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like. Go check it out: Advent of Code
Input files: adventofcode2020inputs.zip
2020 Day 25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| input = open('input').read().splitlines()
card_public, door_public = [int(key) for key in input]
value = 1
loop_size = 0
while value != card_public:
value = (value * 7) % 20201227
loop_size += 1
value = 1
for i in range(loop_size):
value = (value * door_public) % 20201227
print(value) |
input = open('input').read().splitlines()
card_public, door_public = [int(key) for key in input]
value = 1
loop_size = 0
while value != card_public:
value = (value * 7) % 20201227
loop_size += 1
value = 1
for i in range(loop_size):
value = (value * door_public) % 20201227
print(value)
2020 Day 24 Part 02
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
| from collections import defaultdict
from re import sub
def normalize(instruction):
directions = defaultdict(int)
for direction_pair in [("se", "nw"), ("sw", "ne"), ("e", "w")]:
directions[direction_pair[0]] = \
instruction.count(direction_pair[0]) - instruction.count(direction_pair[1])
for direction in direction_pair:
instruction = sub(direction, "", instruction)
return tuple((directions["sw"] + directions["se"], directions["e"] + directions["se"]))
def pass_day(this_day):
for tile in list(this_day.keys()):
if this_day[tile] == 0:
for neighbor in [( 1, 0), (0, 1), ( 1, 1),
(-1, 0), (0, -1), (-1, -1)]:
this_day[(tile[0] + neighbor[0], tile[1] + neighbor[1])]
next_day = this_day.copy()
for tile in list(this_day.keys()):
black_neighbors = sum([this_day[(tile[0] + neighbor[0],
tile[1] + neighbor[1])] == 0
for neighbor in [( 1, 0), (0, 1), ( 1, 1),
(-1, 0), (0, -1), (-1, -1)]])
if this_day[tile] == 0 and (not black_neighbors or black_neighbors > 2):
next_day[tile] = 1
elif this_day[tile] == 1 and black_neighbors == 2:
next_day[tile] = 0
return next_day
color_of_tiles = defaultdict(lambda: 1)
input = open('input').read().splitlines()
for instruction in input:
location = normalize(instruction)
color_of_tiles[location] = (color_of_tiles[location] + 1) % 2
for _ in range(100):
color_of_tiles = pass_day(color_of_tiles)
print(sum([color == 0 for color in color_of_tiles.values()])) |
from collections import defaultdict
from re import sub
def normalize(instruction):
directions = defaultdict(int)
for direction_pair in [("se", "nw"), ("sw", "ne"), ("e", "w")]:
directions[direction_pair[0]] = \
instruction.count(direction_pair[0]) - instruction.count(direction_pair[1])
for direction in direction_pair:
instruction = sub(direction, "", instruction)
return tuple((directions["sw"] + directions["se"], directions["e"] + directions["se"]))
def pass_day(this_day):
for tile in list(this_day.keys()):
if this_day[tile] == 0:
for neighbor in [( 1, 0), (0, 1), ( 1, 1),
(-1, 0), (0, -1), (-1, -1)]:
this_day[(tile[0] + neighbor[0], tile[1] + neighbor[1])]
next_day = this_day.copy()
for tile in list(this_day.keys()):
black_neighbors = sum([this_day[(tile[0] + neighbor[0],
tile[1] + neighbor[1])] == 0
for neighbor in [( 1, 0), (0, 1), ( 1, 1),
(-1, 0), (0, -1), (-1, -1)]])
if this_day[tile] == 0 and (not black_neighbors or black_neighbors > 2):
next_day[tile] = 1
elif this_day[tile] == 1 and black_neighbors == 2:
next_day[tile] = 0
return next_day
color_of_tiles = defaultdict(lambda: 1)
input = open('input').read().splitlines()
for instruction in input:
location = normalize(instruction)
color_of_tiles[location] = (color_of_tiles[location] + 1) % 2
for _ in range(100):
color_of_tiles = pass_day(color_of_tiles)
print(sum([color == 0 for color in color_of_tiles.values()]))
2020 Day 24 Part 01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| from collections import defaultdict
from re import sub
def normalize(instruction):
directions = defaultdict(int)
for direction_pair in [("se", "nw"), ("sw", "ne"), ("e", "w")]:
directions[direction_pair[0]] = \
instruction.count(direction_pair[0]) - instruction.count(direction_pair[1])
for direction in direction_pair:
instruction = sub(direction, "", instruction)
return tuple((directions["sw"] + directions["se"], directions["e"] + directions["se"]))
flips_per_tile = defaultdict(int)
input = open('input').read().splitlines()
for instruction in input:
flips_per_tile[normalize(instruction)] += 1
print(sum([flips % 2 for flips in flips_per_tile.values()])) |
from collections import defaultdict
from re import sub
def normalize(instruction):
directions = defaultdict(int)
for direction_pair in [("se", "nw"), ("sw", "ne"), ("e", "w")]:
directions[direction_pair[0]] = \
instruction.count(direction_pair[0]) - instruction.count(direction_pair[1])
for direction in direction_pair:
instruction = sub(direction, "", instruction)
return tuple((directions["sw"] + directions["se"], directions["e"] + directions["se"]))
flips_per_tile = defaultdict(int)
input = open('input').read().splitlines()
for instruction in input:
flips_per_tile[normalize(instruction)] += 1
print(sum([flips % 2 for flips in flips_per_tile.values()]))
2020 Day 23 Part 02
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
| def initialize():
input = open('input').read().splitlines()
input = [int(cup) for cup in input[0]]
cups = {**{cup: cup + 1 for cup in range(10, 1000000)},
**{input[i]: input[i + 1] for i in range(8)}}
cups[input[8]] = 10
cups[1000000] = input[0]
return cups, input[0]
def move(cups, current_cup):
cup = current_cup
taken = [(cup := cups[cup]) for i in range(3)]
destination = current_cup - 1
while not destination or destination in taken:
if not destination:
destination = 1000000
else:
destination -= 1
cups[current_cup], cups[destination], cups[taken[-1]] = cups[taken[-1]], cups[current_cup], cups[destination]
return cups, cups[current_cup]
cups, current_cup = initialize()
for _ in range(10000000):
cups, current_cup = move(cups, current_cup)
print(cups[1] * cups[cups[1]]) |
def initialize():
input = open('input').read().splitlines()
input = [int(cup) for cup in input[0]]
cups = {**{cup: cup + 1 for cup in range(10, 1000000)},
**{input[i]: input[i + 1] for i in range(8)}}
cups[input[8]] = 10
cups[1000000] = input[0]
return cups, input[0]
def move(cups, current_cup):
cup = current_cup
taken = [(cup := cups[cup]) for i in range(3)]
destination = current_cup - 1
while not destination or destination in taken:
if not destination:
destination = 1000000
else:
destination -= 1
cups[current_cup], cups[destination], cups[taken[-1]] = cups[taken[-1]], cups[current_cup], cups[destination]
return cups, cups[current_cup]
cups, current_cup = initialize()
for _ in range(10000000):
cups, current_cup = move(cups, current_cup)
print(cups[1] * cups[cups[1]])
2020 Day 23 Part 01
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
| def initialize():
input = open('input').read().splitlines()
input = [int(cup) for cup in input[0]]
cups = {input[i]: input[i + 1] for i in range(8)}
cups[input[8]] = input[0]
return cups, input[0]
def move(cups, current_cup):
cup = current_cup
taken = [(cup := cups[cup]) for i in range(3)]
destination = current_cup - 1
while not destination or destination in taken:
if not destination:
destination = 9
else:
destination -= 1
cups[current_cup], cups[destination], cups[taken[-1]] = cups[taken[-1]], cups[current_cup], cups[destination]
return cups, cups[current_cup]
cups, current_cup = initialize()
for _ in range(100):
cups, current_cup = move(cups, current_cup)
cup = 1
print("".join([str((cup := cups[cup])) for _ in range(8)])) |
def initialize():
input = open('input').read().splitlines()
input = [int(cup) for cup in input[0]]
cups = {input[i]: input[i + 1] for i in range(8)}
cups[input[8]] = input[0]
return cups, input[0]
def move(cups, current_cup):
cup = current_cup
taken = [(cup := cups[cup]) for i in range(3)]
destination = current_cup - 1
while not destination or destination in taken:
if not destination:
destination = 9
else:
destination -= 1
cups[current_cup], cups[destination], cups[taken[-1]] = cups[taken[-1]], cups[current_cup], cups[destination]
return cups, cups[current_cup]
cups, current_cup = initialize()
for _ in range(100):
cups, current_cup = move(cups, current_cup)
cup = 1
print("".join([str((cup := cups[cup])) for _ in range(8)]))
2020 Day 22 Part 02
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
| from collections import deque
def build_decks(raw_input):
player, decks = 0, [deque(), deque()]
for line in raw_input:
if not len(line):
player = 1
continue
if "Player" not in line:
decks[player].append(int(line))
return decks
def play(decks):
known = set()
while len(decks[0]) and len(decks[1]):
if (state := tuple(decks[0])) in known:
return 0, None
known.add(state)
card_0, card_1 = decks[0].popleft(), decks[1].popleft()
if len(decks[0]) < card_0 or len(decks[1]) < card_1:
if card_0 > card_1:
decks[0].extend([card_0, card_1])
else:
decks[1].extend([card_1, card_0])
else:
if not play([deque(list(decks[0])[:card_0]), deque(list(decks[1])[:card_1])])[0]:
decks[0].extend([card_0, card_1])
else:
decks[1].extend([card_1, card_0])
return min(len(decks[1]), 1), decks
input = open('input').read().splitlines()
winner, decks = play(build_decks(input))
winning_score = sum([decks[winner].pop() * multiplier for multiplier in range(1, len(decks[winner]) + 1)])
print(winning_score) |
from collections import deque
def build_decks(raw_input):
player, decks = 0, [deque(), deque()]
for line in raw_input:
if not len(line):
player = 1
continue
if "Player" not in line:
decks[player].append(int(line))
return decks
def play(decks):
known = set()
while len(decks[0]) and len(decks[1]):
if (state := tuple(decks[0])) in known:
return 0, None
known.add(state)
card_0, card_1 = decks[0].popleft(), decks[1].popleft()
if len(decks[0]) < card_0 or len(decks[1]) < card_1:
if card_0 > card_1:
decks[0].extend([card_0, card_1])
else:
decks[1].extend([card_1, card_0])
else:
if not play([deque(list(decks[0])[:card_0]), deque(list(decks[1])[:card_1])])[0]:
decks[0].extend([card_0, card_1])
else:
decks[1].extend([card_1, card_0])
return min(len(decks[1]), 1), decks
input = open('input').read().splitlines()
winner, decks = play(build_decks(input))
winning_score = sum([decks[winner].pop() * multiplier for multiplier in range(1, len(decks[winner]) + 1)])
print(winning_score)
2020 Day 22 Part 01
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
| from collections import deque
def build_decks(raw_input):
player, decks = 0, [deque(), deque()]
for line in raw_input:
if not len(line):
player = 1
continue
if "Player" not in line:
decks[player].append(int(line))
return decks
input = open('input').read().splitlines()
decks = build_decks(input)
while len(decks[0]) and len(decks[1]):
card_0, card_1 = decks[0].popleft(), decks[1].popleft()
if card_0 > card_1:
decks[0].extend([card_0, card_1])
else:
decks[1].extend([card_1, card_0])
winning_deck = sorted(decks, key = lambda deck: len(deck))[1]
winning_score = sum([winning_deck.pop() * multiplier for multiplier in range(1, len(winning_deck) + 1)])
print(winning_score) |
from collections import deque
def build_decks(raw_input):
player, decks = 0, [deque(), deque()]
for line in raw_input:
if not len(line):
player = 1
continue
if "Player" not in line:
decks[player].append(int(line))
return decks
input = open('input').read().splitlines()
decks = build_decks(input)
while len(decks[0]) and len(decks[1]):
card_0, card_1 = decks[0].popleft(), decks[1].popleft()
if card_0 > card_1:
decks[0].extend([card_0, card_1])
else:
decks[1].extend([card_1, card_0])
winning_deck = sorted(decks, key = lambda deck: len(deck))[1]
winning_score = sum([winning_deck.pop() * multiplier for multiplier in range(1, len(winning_deck) + 1)])
print(winning_score)
2020 Day 21 Part 02
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
| from re import match, sub
from collections import defaultdict
def analyse_input(raw_input):
allergens_dict = defaultdict(list)
all_ingredients = []
for line in raw_input:
ingredients, allergens = [words.split() for words in match(r"((?:(?:\w+) )+)\(contains ((?:(?:\w+) *)+)\)", sub(",", "", line)).group(1, 2)]
for allergen in allergens:
allergens_dict[allergen].append(set(ingredients))
all_ingredients.extend(ingredients)
return allergens_dict, all_ingredients
def identify_allergen(allergens_in_food):
for allergen, ingredients in allergens_in_food.items():
candidates = ingredients[0].intersection(*ingredients)
if len(candidates) == 1:
return allergen, list(candidates)[0]
def eliminate_combo(allergens_in_food, allergen, ingredient):
del allergens_in_food[allergen]
for allergen in allergens_in_food.keys():
for ingredients in allergens_in_food[allergen]:
ingredients.discard(ingredient)
input = open('input').read().splitlines()
allergens_in_food, all_ingredients = analyse_input(input)
identified_ingredients = []
while len(allergens_in_food):
allergen, ingredient = identify_allergen(allergens_in_food)
eliminate_combo(allergens_in_food, allergen, ingredient)
identified_ingredients.append((allergen, ingredient))
identified_ingredients.sort(key = lambda combo: combo[0])
result = ",".join([ingredient[1] for ingredient in identified_ingredients])
print(result) |
from re import match, sub
from collections import defaultdict
def analyse_input(raw_input):
allergens_dict = defaultdict(list)
all_ingredients = []
for line in raw_input:
ingredients, allergens = [words.split() for words in match(r"((?:(?:\w+) )+)\(contains ((?:(?:\w+) *)+)\)", sub(",", "", line)).group(1, 2)]
for allergen in allergens:
allergens_dict[allergen].append(set(ingredients))
all_ingredients.extend(ingredients)
return allergens_dict, all_ingredients
def identify_allergen(allergens_in_food):
for allergen, ingredients in allergens_in_food.items():
candidates = ingredients[0].intersection(*ingredients)
if len(candidates) == 1:
return allergen, list(candidates)[0]
def eliminate_combo(allergens_in_food, allergen, ingredient):
del allergens_in_food[allergen]
for allergen in allergens_in_food.keys():
for ingredients in allergens_in_food[allergen]:
ingredients.discard(ingredient)
input = open('input').read().splitlines()
allergens_in_food, all_ingredients = analyse_input(input)
identified_ingredients = []
while len(allergens_in_food):
allergen, ingredient = identify_allergen(allergens_in_food)
eliminate_combo(allergens_in_food, allergen, ingredient)
identified_ingredients.append((allergen, ingredient))
identified_ingredients.sort(key = lambda combo: combo[0])
result = ",".join([ingredient[1] for ingredient in identified_ingredients])
print(result)
2020 Day 21 Part 01
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
| from re import match, sub
from collections import defaultdict
def analyse_input(raw_input):
allergens_dict = defaultdict(list)
all_ingredients = []
for line in raw_input:
ingredients, allergens = [words.split() for words in match(r"((?:(?:\w+) )+)\(contains ((?:(?:\w+) *)+)\)", sub(",", "", line)).group(1, 2)]
for allergen in allergens:
allergens_dict[allergen].append(set(ingredients))
all_ingredients.extend(ingredients)
return allergens_dict, all_ingredients
def identify_allergen(allergens_in_food):
for allergen, ingredients in allergens_in_food.items():
candidates = ingredients[0].intersection(*ingredients)
if len(candidates) == 1:
return allergen, list(candidates)[0]
def eliminate_combo(allergens_in_food, allergen, ingredient):
del allergens_in_food[allergen]
for allergen in allergens_in_food.keys():
for ingredients in allergens_in_food[allergen]:
ingredients.discard(ingredient)
input = open('input').read().splitlines()
allergens_in_food, all_ingredients = analyse_input(input)
identified_ingredients = set()
while len(allergens_in_food):
allergen, ingredient = identify_allergen(allergens_in_food)
eliminate_combo(allergens_in_food, allergen, ingredient)
identified_ingredients.add(ingredient)
result = sum([ingredient not in identified_ingredients for ingredient in all_ingredients])
print(result) |
from re import match, sub
from collections import defaultdict
def analyse_input(raw_input):
allergens_dict = defaultdict(list)
all_ingredients = []
for line in raw_input:
ingredients, allergens = [words.split() for words in match(r"((?:(?:\w+) )+)\(contains ((?:(?:\w+) *)+)\)", sub(",", "", line)).group(1, 2)]
for allergen in allergens:
allergens_dict[allergen].append(set(ingredients))
all_ingredients.extend(ingredients)
return allergens_dict, all_ingredients
def identify_allergen(allergens_in_food):
for allergen, ingredients in allergens_in_food.items():
candidates = ingredients[0].intersection(*ingredients)
if len(candidates) == 1:
return allergen, list(candidates)[0]
def eliminate_combo(allergens_in_food, allergen, ingredient):
del allergens_in_food[allergen]
for allergen in allergens_in_food.keys():
for ingredients in allergens_in_food[allergen]:
ingredients.discard(ingredient)
input = open('input').read().splitlines()
allergens_in_food, all_ingredients = analyse_input(input)
identified_ingredients = set()
while len(allergens_in_food):
allergen, ingredient = identify_allergen(allergens_in_food)
eliminate_combo(allergens_in_food, allergen, ingredient)
identified_ingredients.add(ingredient)
result = sum([ingredient not in identified_ingredients for ingredient in all_ingredients])
print(result)
2020 Day 20 Part 02
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
| from re import findall
from collections import defaultdict
def build_tiles(raw_input):
tiles_pixels = defaultdict(list)
for line in raw_input:
if not len(line):
continue
elif (tile := findall(r"(\d+)", line)):
tile_id = tile[0]
else:
tiles_pixels[tile_id].append([pixel == "#" for pixel in line])
borders = defaultdict(list)
for tile, pixels in tiles_pixels.items():
borders_pixels = ["".join(["1" if pixel else "0" for pixel in pixels[0]]),
"".join(["1" if pixel else "0" for pixel in [p[0] for p in pixels]][::-1]),
"".join(["1" if pixel else "0" for pixel in pixels[9]][::-1]),
"".join(["1" if pixel else "0" for pixel in [p[9] for p in pixels]])]
borders[tile].append([int(borders_pixels[i], 2) for i in range(4)])
borders[tile].append([int(borders_pixels[i][::-1], 2) for i in range(4)])
borders[tile][1][0], borders[tile][1][2] = borders[tile][1][2], borders[tile][1][0]
for rotation in range(3):
for side in range(2):
borders[tile].append(borders[tile][side + 2 * rotation][1:] + \
[borders[tile][side + 2 * rotation][0]])
return tiles_pixels, borders
def transform(tile, orientation, tiles_pixels, tiles_borders):
tiles_pixels[tile] = tiles_pixels[tile][1:-1]
tiles_pixels[tile] = [tiles_pixels[tile][y][1:-1] for y in range(len(tiles_pixels[tile]))]
tiles_borders[tile] = tiles_borders[tile][orientation]
if orientation % 2:
tiles_pixels[tile] = tiles_pixels[tile][::-1]
for rotation in range(orientation // 2):
tiles_pixels[tile] = [[tiles_pixels[tile][x][y] for x in range(len(tiles_pixels[tile][y]))][::-1]
for y in range(len(tiles_pixels[tile]))]
def find_top_left(puzzle, tiles_borders, tiles_neighbors, tiles_pixels):
for tile, borders in tiles_borders.items():
for other_tile, other_border in tiles_borders.items():
if tile == other_tile:
continue
for border_variation in [borders[0]]:
for border in border_variation:
if border in (b for b_var in other_border for b in b_var):
tiles_neighbors[tile].add((other_tile, border, int(f"{border:08b}"[::-1], 2)))
for tile, neighbors in tiles_neighbors.items():
if len(neighbors) == 2:
puzzle[(0,0)] = tile
break
for orientation in range(8):
if sum([neighbor[1] in [tiles_borders[tile][orientation][side] for side in (2, 3)]
for neighbor in tiles_neighbors[tile]]) == 2:
break
transform(tile, orientation, tiles_pixels, tiles_borders)
def find_top_row(puzzle, puzzle_size, tiles_borders, tiles_pixels):
for position in range(1, puzzle_size):
next_border = int(f"{tiles_borders[puzzle[(position - 1, 0)]][3]:010b}"[::-1], 2)
for tile in tiles_pixels.keys():
if tile in puzzle.values():
continue
for orientation in range(8):
if next_border == tiles_borders[tile][orientation][1]:
break
else:
continue
break
transform(tile, orientation, tiles_pixels, tiles_borders)
puzzle[(position, 0)] = tile
def find_remaining_rows(puzzle, puzzle_size, tiles_borders, tiles_pixels):
for position_y in range(1, puzzle_size):
for position_x in range(puzzle_size):
next_border = int(f"{tiles_borders[puzzle[(position_x, position_y - 1)]][2]:010b}"[::-1], 2)
for tile in tiles_pixels.keys():
if tile in puzzle.values():
continue
for orientation in range(8):
if next_border == tiles_borders[tile][orientation][0]:
break
else:
continue
break
transform(tile, orientation, tiles_pixels, tiles_borders)
puzzle[(position_x, position_y)] = tile
def assemble_puzzle(puzzle, puzzle_size, tiles_pixels):
full_puzzle = []
for piece_y in range(puzzle_size):
for row in range(len(tiles_pixels[puzzle[(0, piece_y)]])):
full_row = []
for piece_x in range(puzzle_size):
full_row.extend(["#" if value else " " for value in tiles_pixels[puzzle[(piece_x, piece_y)]][row]])
full_puzzle.append(full_row)
return full_puzzle
def find_dragon(full_puzzle):
dragon = [" # ",
"# ## ## ###",
" # # # # # # "]
dragon_offsets = [(x, y) for x in range(len(dragon[0]))
for y in range(len(dragon))
if dragon[y][x] == "#"]
found = False
for flip in range(2):
for rotation in range(3):
for y in range(len(full_puzzle) - len(dragon)):
for x in range(len(full_puzzle[0]) - len(dragon[0])):
for x_dragon, y_dragon in dragon_offsets:
if not full_puzzle[y + y_dragon][x + x_dragon] == "#":
break
else:
found = True
for x_dragon, y_dragon in dragon_offsets:
full_puzzle[y + y_dragon][x + x_dragon] = "O"
if found:
return sum([line.count("#") for line in full_puzzle])
full_puzzle = [[full_puzzle[x][y] for x in range(len(full_puzzle[y]))][::-1]
for y in range(len(full_puzzle))]
full_puzzle = full_puzzle[::-1]
input = open('input').read().splitlines()
tiles_pixels, tiles_borders = build_tiles(input)
tiles_neighbors, puzzle = defaultdict(set), defaultdict(str)
puzzle_size = int(len(tiles_pixels)**0.5)
find_top_left(puzzle, tiles_borders, tiles_neighbors, tiles_pixels)
find_top_row(puzzle, puzzle_size, tiles_borders, tiles_pixels)
find_remaining_rows(puzzle, puzzle_size, tiles_borders, tiles_pixels)
full_puzzle = assemble_puzzle(puzzle, puzzle_size, tiles_pixels)
print(find_dragon(full_puzzle)) |
from re import findall
from collections import defaultdict
def build_tiles(raw_input):
tiles_pixels = defaultdict(list)
for line in raw_input:
if not len(line):
continue
elif (tile := findall(r"(\d+)", line)):
tile_id = tile[0]
else:
tiles_pixels[tile_id].append([pixel == "#" for pixel in line])
borders = defaultdict(list)
for tile, pixels in tiles_pixels.items():
borders_pixels = ["".join(["1" if pixel else "0" for pixel in pixels[0]]),
"".join(["1" if pixel else "0" for pixel in [p[0] for p in pixels]][::-1]),
"".join(["1" if pixel else "0" for pixel in pixels[9]][::-1]),
"".join(["1" if pixel else "0" for pixel in [p[9] for p in pixels]])]
borders[tile].append([int(borders_pixels[i], 2) for i in range(4)])
borders[tile].append([int(borders_pixels[i][::-1], 2) for i in range(4)])
borders[tile][1][0], borders[tile][1][2] = borders[tile][1][2], borders[tile][1][0]
for rotation in range(3):
for side in range(2):
borders[tile].append(borders[tile][side + 2 * rotation][1:] + \
[borders[tile][side + 2 * rotation][0]])
return tiles_pixels, borders
def transform(tile, orientation, tiles_pixels, tiles_borders):
tiles_pixels[tile] = tiles_pixels[tile][1:-1]
tiles_pixels[tile] = [tiles_pixels[tile][y][1:-1] for y in range(len(tiles_pixels[tile]))]
tiles_borders[tile] = tiles_borders[tile][orientation]
if orientation % 2:
tiles_pixels[tile] = tiles_pixels[tile][::-1]
for rotation in range(orientation // 2):
tiles_pixels[tile] = [[tiles_pixels[tile][x][y] for x in range(len(tiles_pixels[tile][y]))][::-1]
for y in range(len(tiles_pixels[tile]))]
def find_top_left(puzzle, tiles_borders, tiles_neighbors, tiles_pixels):
for tile, borders in tiles_borders.items():
for other_tile, other_border in tiles_borders.items():
if tile == other_tile:
continue
for border_variation in [borders[0]]:
for border in border_variation:
if border in (b for b_var in other_border for b in b_var):
tiles_neighbors[tile].add((other_tile, border, int(f"{border:08b}"[::-1], 2)))
for tile, neighbors in tiles_neighbors.items():
if len(neighbors) == 2:
puzzle[(0,0)] = tile
break
for orientation in range(8):
if sum([neighbor[1] in [tiles_borders[tile][orientation][side] for side in (2, 3)]
for neighbor in tiles_neighbors[tile]]) == 2:
break
transform(tile, orientation, tiles_pixels, tiles_borders)
def find_top_row(puzzle, puzzle_size, tiles_borders, tiles_pixels):
for position in range(1, puzzle_size):
next_border = int(f"{tiles_borders[puzzle[(position - 1, 0)]][3]:010b}"[::-1], 2)
for tile in tiles_pixels.keys():
if tile in puzzle.values():
continue
for orientation in range(8):
if next_border == tiles_borders[tile][orientation][1]:
break
else:
continue
break
transform(tile, orientation, tiles_pixels, tiles_borders)
puzzle[(position, 0)] = tile
def find_remaining_rows(puzzle, puzzle_size, tiles_borders, tiles_pixels):
for position_y in range(1, puzzle_size):
for position_x in range(puzzle_size):
next_border = int(f"{tiles_borders[puzzle[(position_x, position_y - 1)]][2]:010b}"[::-1], 2)
for tile in tiles_pixels.keys():
if tile in puzzle.values():
continue
for orientation in range(8):
if next_border == tiles_borders[tile][orientation][0]:
break
else:
continue
break
transform(tile, orientation, tiles_pixels, tiles_borders)
puzzle[(position_x, position_y)] = tile
def assemble_puzzle(puzzle, puzzle_size, tiles_pixels):
full_puzzle = []
for piece_y in range(puzzle_size):
for row in range(len(tiles_pixels[puzzle[(0, piece_y)]])):
full_row = []
for piece_x in range(puzzle_size):
full_row.extend(["#" if value else " " for value in tiles_pixels[puzzle[(piece_x, piece_y)]][row]])
full_puzzle.append(full_row)
return full_puzzle
def find_dragon(full_puzzle):
dragon = [" # ",
"# ## ## ###",
" # # # # # # "]
dragon_offsets = [(x, y) for x in range(len(dragon[0]))
for y in range(len(dragon))
if dragon[y][x] == "#"]
found = False
for flip in range(2):
for rotation in range(3):
for y in range(len(full_puzzle) - len(dragon)):
for x in range(len(full_puzzle[0]) - len(dragon[0])):
for x_dragon, y_dragon in dragon_offsets:
if not full_puzzle[y + y_dragon][x + x_dragon] == "#":
break
else:
found = True
for x_dragon, y_dragon in dragon_offsets:
full_puzzle[y + y_dragon][x + x_dragon] = "O"
if found:
return sum([line.count("#") for line in full_puzzle])
full_puzzle = [[full_puzzle[x][y] for x in range(len(full_puzzle[y]))][::-1]
for y in range(len(full_puzzle))]
full_puzzle = full_puzzle[::-1]
input = open('input').read().splitlines()
tiles_pixels, tiles_borders = build_tiles(input)
tiles_neighbors, puzzle = defaultdict(set), defaultdict(str)
puzzle_size = int(len(tiles_pixels)**0.5)
find_top_left(puzzle, tiles_borders, tiles_neighbors, tiles_pixels)
find_top_row(puzzle, puzzle_size, tiles_borders, tiles_pixels)
find_remaining_rows(puzzle, puzzle_size, tiles_borders, tiles_pixels)
full_puzzle = assemble_puzzle(puzzle, puzzle_size, tiles_pixels)
print(find_dragon(full_puzzle))
2020 Day 20 Part 01
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
| from re import findall
from collections import defaultdict
def get_borders(raw_input):
tiles = defaultdict(list)
for line in raw_input:
if not len(line):
continue
elif (tile := findall(r"(\d+)", line)):
tile_id = tile[0]
else:
tiles[tile_id].append([pixel == "#" for pixel in line])
borders = defaultdict(list)
for tile, pixels in tiles.items():
borders_pixels = ["".join(["1" if pixel else "0" for pixel in pixels[0]]),
"".join(["1" if pixel else "0" for pixel in [p[0] for p in pixels]][::-1]),
"".join(["1" if pixel else "0" for pixel in pixels[9]][::-1]),
"".join(["1" if pixel else "0" for pixel in [p[9] for p in pixels]])]
borders[tile] = [int(borders_pixels[i][::direction], 2) for i in range(4) for direction in (-1, 1)]
return borders
input = open('input').read().splitlines()
tile_borders = get_borders(input)
result = 1
for tile, borders in tile_borders.items():
neighbors = set()
for other_tile, other_borders in tile_borders.items():
if tile == other_tile:
continue
for border in borders:
if border in other_borders:
neighbors.add(other_tile)
if len(neighbors) == 2:
result *= int(tile)
print(result) |
from re import findall
from collections import defaultdict
def get_borders(raw_input):
tiles = defaultdict(list)
for line in raw_input:
if not len(line):
continue
elif (tile := findall(r"(\d+)", line)):
tile_id = tile[0]
else:
tiles[tile_id].append([pixel == "#" for pixel in line])
borders = defaultdict(list)
for tile, pixels in tiles.items():
borders_pixels = ["".join(["1" if pixel else "0" for pixel in pixels[0]]),
"".join(["1" if pixel else "0" for pixel in [p[0] for p in pixels]][::-1]),
"".join(["1" if pixel else "0" for pixel in pixels[9]][::-1]),
"".join(["1" if pixel else "0" for pixel in [p[9] for p in pixels]])]
borders[tile] = [int(borders_pixels[i][::direction], 2) for i in range(4) for direction in (-1, 1)]
return borders
input = open('input').read().splitlines()
tile_borders = get_borders(input)
result = 1
for tile, borders in tile_borders.items():
neighbors = set()
for other_tile, other_borders in tile_borders.items():
if tile == other_tile:
continue
for border in borders:
if border in other_borders:
neighbors.add(other_tile)
if len(neighbors) == 2:
result *= int(tile)
print(result)
2020 Day 19 Part 02
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
| def parseArg(a):
if a[0] == '"':
return ('letter', a[1])
else:
return ('rule', int(a))
def parseRules(text):
lines = text.split('\n')
rules = {}
for l in lines:
ruleNo, parts = l.split(': ')
ruleNo = int(ruleNo)
parts = parts.split(' | ')
parts = [[parseArg(p) for p in part.split(' ')] for part in parts]
rules[ruleNo] = parts
return rules
def matchRule(text, rules, rule, position):
matches = []
for attempt in rule:
positions = [position]
for rt, rv in attempt:
newPositions = []
for pos in positions:
if rt == 'rule':
for p in matchRule(text, rules, rules[rv], pos):
newPositions.append(p)
else:
if position < len(text) and text[position] == rv:
newPositions.append(pos + 1)
positions = newPositions
for pos in positions:
matches.append(pos)
return matches
rulesText, samplesText = open('input').read().split('\n\n')
rulesText += "\n8: 42 | 42 8\n11: 42 31 | 42 11 31"
rules = parseRules(rulesText)
if False:
for no in rules:
rule = rules[no]
print(str(no) + ': ' + str(rule))
samples = samplesText.split('\n')
matchCount = 0
for sample in samples:
res = matchRule(sample, rules, rules[0], 0)
print(sample + ', ' + str(len(sample)) + ', ' + str(res))
if len([mc for mc in res if mc == len(sample)]) > 0:
matchCount += 1
print(matchCount) |
def parseArg(a):
if a[0] == '"':
return ('letter', a[1])
else:
return ('rule', int(a))
def parseRules(text):
lines = text.split('\n')
rules = {}
for l in lines:
ruleNo, parts = l.split(': ')
ruleNo = int(ruleNo)
parts = parts.split(' | ')
parts = [[parseArg(p) for p in part.split(' ')] for part in parts]
rules[ruleNo] = parts
return rules
def matchRule(text, rules, rule, position):
matches = []
for attempt in rule:
positions = [position]
for rt, rv in attempt:
newPositions = []
for pos in positions:
if rt == 'rule':
for p in matchRule(text, rules, rules[rv], pos):
newPositions.append(p)
else:
if position < len(text) and text[position] == rv:
newPositions.append(pos + 1)
positions = newPositions
for pos in positions:
matches.append(pos)
return matches
rulesText, samplesText = open('input').read().split('\n\n')
rulesText += "\n8: 42 | 42 8\n11: 42 31 | 42 11 31"
rules = parseRules(rulesText)
if False:
for no in rules:
rule = rules[no]
print(str(no) + ': ' + str(rule))
samples = samplesText.split('\n')
matchCount = 0
for sample in samples:
res = matchRule(sample, rules, rules[0], 0)
print(sample + ', ' + str(len(sample)) + ', ' + str(res))
if len([mc for mc in res if mc == len(sample)]) > 0:
matchCount += 1
print(matchCount)
2020 Day 19 Part 01
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
| from re import findall
def substitute_rule(id, rules, known):
if id in known:
return known[id]
sequence = "("
for next_id in rules[id]:
if next_id == "|":
sequence += "|"
continue
next_sequence = substitute_rule(next_id, rules, known)
known[next_id] = next_sequence
sequence += next_sequence
return sequence + ")"
input = open('input').read().splitlines()
rules = input[:(index := input.index(''))]
messages = input[index + 1:]
rules = {(r := findall(r"(\d+): (.*)", rule)[0])[0]: r[1].split(" ") for rule in rules}
known = {}
for id, rule in rules.items():
if rule[0][0] == '"':
known[id] = rule[0][1]
rule_zero = substitute_rule("0", rules, known)
result= sum((len((best_match := findall(rule_zero, message))) and message == best_match[0][0] for message in messages))
print(result) |
from re import findall
def substitute_rule(id, rules, known):
if id in known:
return known[id]
sequence = "("
for next_id in rules[id]:
if next_id == "|":
sequence += "|"
continue
next_sequence = substitute_rule(next_id, rules, known)
known[next_id] = next_sequence
sequence += next_sequence
return sequence + ")"
input = open('input').read().splitlines()
rules = input[:(index := input.index(''))]
messages = input[index + 1:]
rules = {(r := findall(r"(\d+): (.*)", rule)[0])[0]: r[1].split(" ") for rule in rules}
known = {}
for id, rule in rules.items():
if rule[0][0] == '"':
known[id] = rule[0][1]
rule_zero = substitute_rule("0", rules, known)
result= sum((len((best_match := findall(rule_zero, message))) and message == best_match[0][0] for message in messages))
print(result)
2020 Day 18 Part 02
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
| from re import findall
from functools import reduce
def solve_equation(equation):
while "(" in equation:
index = 0
while equation[index] != ")":
if equation[index] == "(":
opening = index
index += 1
equation = equation[:opening] + solve_equation(equation[opening + 1:index]) + equation[index + 1:]
values = [int(value) for value in findall(r"\d+", equation)]
operators = findall(r"[\+\*]", equation)
while "+" in operators:
index = operators.index("+")
values = values[:index] + [values[index] + values[index + 1]] + values[index + 2:]
operators.remove("+")
return str(reduce(lambda a, b: a * b, [int(value) for value in values]))
input = open('input').read().splitlines()
print(sum((int(solve_equation(equation)) for equation in input))) |
from re import findall
from functools import reduce
def solve_equation(equation):
while "(" in equation:
index = 0
while equation[index] != ")":
if equation[index] == "(":
opening = index
index += 1
equation = equation[:opening] + solve_equation(equation[opening + 1:index]) + equation[index + 1:]
values = [int(value) for value in findall(r"\d+", equation)]
operators = findall(r"[\+\*]", equation)
while "+" in operators:
index = operators.index("+")
values = values[:index] + [values[index] + values[index + 1]] + values[index + 2:]
operators.remove("+")
return str(reduce(lambda a, b: a * b, [int(value) for value in values]))
input = open('input').read().splitlines()
print(sum((int(solve_equation(equation)) for equation in input)))
2020 Day 18 Part 01
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
| from re import findall
def solve_equation(equation):
while "(" in equation:
index = 0
while equation[index] != ")":
if equation[index] == "(":
opening = index
index += 1
equation = equation[:opening] + solve_equation(equation[opening + 1:index]) + equation[index + 1:]
values = [int(value) for value in findall(r"\d+", equation)]
operators = findall(r"[\+\*]", equation)
for index in range(len(operators)):
if operators[index] == "+":
values[0] += values[index + 1]
else:
values[0] *= values[index + 1]
return str(values[0])
input = open('input').read().splitlines()
print(sum((int(solve_equation(equation)) for equation in input))) |
from re import findall
def solve_equation(equation):
while "(" in equation:
index = 0
while equation[index] != ")":
if equation[index] == "(":
opening = index
index += 1
equation = equation[:opening] + solve_equation(equation[opening + 1:index]) + equation[index + 1:]
values = [int(value) for value in findall(r"\d+", equation)]
operators = findall(r"[\+\*]", equation)
for index in range(len(operators)):
if operators[index] == "+":
values[0] += values[index + 1]
else:
values[0] *= values[index + 1]
return str(values[0])
input = open('input').read().splitlines()
print(sum((int(solve_equation(equation)) for equation in input)))
2020 Day 17 Part 02
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
| from collections import defaultdict
def next_state(x, y, z, w, grid):
neighbors = [(x + x_dir, y + y_dir, z + z_dir, w + w_dir)
for x_dir in (-1, 0, 1)
for y_dir in (-1, 0, 1)
for z_dir in (-1, 0, 1)
for w_dir in (-1, 0, 1)
if x_dir or y_dir or z_dir or w_dir]
amount_of_neighors = sum([grid[neighbor] for neighbor in neighbors])
if grid[(x, y, z, w)]:
if (amount_of_neighors == 2 or amount_of_neighors == 3):
return True
return False
if amount_of_neighors == 3:
return True
return False
def cycle(boundary, grid):
for parameter in ("x_max", "y_max", "z_max", "w_max"):
boundary[parameter] += 1
for parameter in ("x_min", "y_min", "z_min", "w_min"):
boundary[parameter] -= 1
return defaultdict(bool, {(x, y, z, w): next_state(x, y, z, w, grid)
for w in range(boundary["w_min"], boundary["w_max"])
for z in range(boundary["z_min"], boundary["z_max"])
for y in range(boundary["y_min"], boundary["y_max"])
for x in range(boundary["x_min"], boundary["x_max"])})
input = open('input').read().splitlines()
boundary = {"x_max": len(input[0]), "y_max": len(input), "z_max": 1, "w_max": 1,
"x_min": 0, "y_min": 0, "z_min": 0, "w_min": 0}
grid = defaultdict(bool, {(x, y, 0, 0): input[y][x] == "#"
for y in range(boundary["y_max"])
for x in range(boundary["x_max"])})
for _ in range(6):
grid = cycle(boundary, grid)
print(sum(grid.values())) |
from collections import defaultdict
def next_state(x, y, z, w, grid):
neighbors = [(x + x_dir, y + y_dir, z + z_dir, w + w_dir)
for x_dir in (-1, 0, 1)
for y_dir in (-1, 0, 1)
for z_dir in (-1, 0, 1)
for w_dir in (-1, 0, 1)
if x_dir or y_dir or z_dir or w_dir]
amount_of_neighors = sum([grid[neighbor] for neighbor in neighbors])
if grid[(x, y, z, w)]:
if (amount_of_neighors == 2 or amount_of_neighors == 3):
return True
return False
if amount_of_neighors == 3:
return True
return False
def cycle(boundary, grid):
for parameter in ("x_max", "y_max", "z_max", "w_max"):
boundary[parameter] += 1
for parameter in ("x_min", "y_min", "z_min", "w_min"):
boundary[parameter] -= 1
return defaultdict(bool, {(x, y, z, w): next_state(x, y, z, w, grid)
for w in range(boundary["w_min"], boundary["w_max"])
for z in range(boundary["z_min"], boundary["z_max"])
for y in range(boundary["y_min"], boundary["y_max"])
for x in range(boundary["x_min"], boundary["x_max"])})
input = open('input').read().splitlines()
boundary = {"x_max": len(input[0]), "y_max": len(input), "z_max": 1, "w_max": 1,
"x_min": 0, "y_min": 0, "z_min": 0, "w_min": 0}
grid = defaultdict(bool, {(x, y, 0, 0): input[y][x] == "#"
for y in range(boundary["y_max"])
for x in range(boundary["x_max"])})
for _ in range(6):
grid = cycle(boundary, grid)
print(sum(grid.values()))
2020 Day 17 Part 01
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
| from collections import defaultdict
def next_state(x, y, z, grid):
neighbors = [(x + x_dir, y + y_dir, z + z_dir)
for x_dir in (-1, 0, 1)
for y_dir in (-1, 0, 1)
for z_dir in (-1, 0, 1)
if x_dir or y_dir or z_dir]
amount_of_neighors = sum([grid[neighbor] for neighbor in neighbors])
if grid[(x, y, z)]:
if (amount_of_neighors == 2 or amount_of_neighors == 3):
return True
return False
if amount_of_neighors == 3:
return True
return False
def cycle(boundary, grid):
for parameter in ("x_max", "y_max", "z_max"):
boundary[parameter] += 1
for parameter in ("x_min", "y_min", "z_min"):
boundary[parameter] -= 1
return defaultdict(bool, {(x, y, z): next_state(x, y, z, grid)
for z in range(boundary["z_min"], boundary["z_max"])
for y in range(boundary["y_min"], boundary["y_max"])
for x in range(boundary["x_min"], boundary["x_max"])})
input = open('input').read().splitlines()
boundary = {"x_max": len(input[0]), "y_max": len(input), "z_max": 1,
"x_min": 0, "y_min": 0, "z_min": 0}
grid = defaultdict(bool, {(x, y, 0): input[y][x] == "#"
for y in range(boundary["y_max"])
for x in range(boundary["x_max"])})
for _ in range(6):
grid = cycle(boundary, grid)
print(sum(grid.values())) |
from collections import defaultdict
def next_state(x, y, z, grid):
neighbors = [(x + x_dir, y + y_dir, z + z_dir)
for x_dir in (-1, 0, 1)
for y_dir in (-1, 0, 1)
for z_dir in (-1, 0, 1)
if x_dir or y_dir or z_dir]
amount_of_neighors = sum([grid[neighbor] for neighbor in neighbors])
if grid[(x, y, z)]:
if (amount_of_neighors == 2 or amount_of_neighors == 3):
return True
return False
if amount_of_neighors == 3:
return True
return False
def cycle(boundary, grid):
for parameter in ("x_max", "y_max", "z_max"):
boundary[parameter] += 1
for parameter in ("x_min", "y_min", "z_min"):
boundary[parameter] -= 1
return defaultdict(bool, {(x, y, z): next_state(x, y, z, grid)
for z in range(boundary["z_min"], boundary["z_max"])
for y in range(boundary["y_min"], boundary["y_max"])
for x in range(boundary["x_min"], boundary["x_max"])})
input = open('input').read().splitlines()
boundary = {"x_max": len(input[0]), "y_max": len(input), "z_max": 1,
"x_min": 0, "y_min": 0, "z_min": 0}
grid = defaultdict(bool, {(x, y, 0): input[y][x] == "#"
for y in range(boundary["y_max"])
for x in range(boundary["x_max"])})
for _ in range(6):
grid = cycle(boundary, grid)
print(sum(grid.values()))
2020 Day 16 Part 02
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
| from re import findall
from functools import reduce
def get_fields_and_tickets():
mode, fields, field_structure, your_ticket, nearby_tickets = 0, set(), {}, [], []
lines = open('input').read().splitlines()
for line in lines:
if not len(line) or "ticket" in line:
mode += 1
continue
if mode == 0:
field = findall(r'(.+): (\d+)-(\d+) or (\d+)-(\d+)', line)[0]
field_structure[field[0]] = [int(num) for num in field[1:]]
fields = fields | \
set(value for value in range(field_structure[field[0]][0], field_structure[field[0]][1] + 1)) | \
set(value for value in range(field_structure[field[0]][2], field_structure[field[0]][3] + 1))
if mode == 2:
your_ticket = [int(value) for value in line.split(",")]
if mode == 4:
values = [int(num) for num in line.split(",")]
if not sum(value not in fields for value in values):
nearby_tickets.append(values)
return field_structure, nearby_tickets, your_ticket
field_structure, nearby_tickets, your_ticket = get_fields_and_tickets()
possible_positions = {field_name: set(range(len(field_structure))) for field_name in field_structure.keys()}
values_in_position = [[value[i] for value in nearby_tickets] for i in range(len(nearby_tickets[0]))]
for field in possible_positions.keys():
for position in range(len(field_structure)):
for value in values_in_position[position]:
if not ((field_structure[field][0] <= value and field_structure[field][1] >= value) or \
(field_structure[field][2] <= value and field_structure[field][3] >= value)):
possible_positions[field].discard(position)
possible_positions = {key: value for key, value in sorted(possible_positions.items(), key=lambda item: item[1])}
found = set()
for field, positions in possible_positions.items():
value = positions.symmetric_difference(found)
found.update(value)
possible_positions[field] = int(list(value)[0])
possible_positions = {key: value for key, value in sorted(possible_positions.items(), key=lambda item: item[1])}
result = reduce(lambda x, y: x*y, [your_ticket[possible_positions[field]] for field, position in possible_positions.items() if "departure" in field])
print(result) |
from re import findall
from functools import reduce
def get_fields_and_tickets():
mode, fields, field_structure, your_ticket, nearby_tickets = 0, set(), {}, [], []
lines = open('input').read().splitlines()
for line in lines:
if not len(line) or "ticket" in line:
mode += 1
continue
if mode == 0:
field = findall(r'(.+): (\d+)-(\d+) or (\d+)-(\d+)', line)[0]
field_structure[field[0]] = [int(num) for num in field[1:]]
fields = fields | \
set(value for value in range(field_structure[field[0]][0], field_structure[field[0]][1] + 1)) | \
set(value for value in range(field_structure[field[0]][2], field_structure[field[0]][3] + 1))
if mode == 2:
your_ticket = [int(value) for value in line.split(",")]
if mode == 4:
values = [int(num) for num in line.split(",")]
if not sum(value not in fields for value in values):
nearby_tickets.append(values)
return field_structure, nearby_tickets, your_ticket
field_structure, nearby_tickets, your_ticket = get_fields_and_tickets()
possible_positions = {field_name: set(range(len(field_structure))) for field_name in field_structure.keys()}
values_in_position = [[value[i] for value in nearby_tickets] for i in range(len(nearby_tickets[0]))]
for field in possible_positions.keys():
for position in range(len(field_structure)):
for value in values_in_position[position]:
if not ((field_structure[field][0] <= value and field_structure[field][1] >= value) or \
(field_structure[field][2] <= value and field_structure[field][3] >= value)):
possible_positions[field].discard(position)
possible_positions = {key: value for key, value in sorted(possible_positions.items(), key=lambda item: item[1])}
found = set()
for field, positions in possible_positions.items():
value = positions.symmetric_difference(found)
found.update(value)
possible_positions[field] = int(list(value)[0])
possible_positions = {key: value for key, value in sorted(possible_positions.items(), key=lambda item: item[1])}
result = reduce(lambda x, y: x*y, [your_ticket[possible_positions[field]] for field, position in possible_positions.items() if "departure" in field])
print(result)
2020 Day 16 Part 01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| from re import findall
mode, result, fields = 0, 0, set()
lines = open('input').read().splitlines()
for line in lines:
if not len(line) or "ticket" in line:
mode += 1
continue
if mode == 0:
field = [int(num) for num in findall(r'\d+', line)]
fields = fields | \
set(value for value in range(field[0], field[1] + 1)) | \
set(value for value in range(field[2], field[3] + 1))
if mode == 4:
result += sum(int(value) for value in line.split(",") if int(value) not in fields)
print(result) |
from re import findall
mode, result, fields = 0, 0, set()
lines = open('input').read().splitlines()
for line in lines:
if not len(line) or "ticket" in line:
mode += 1
continue
if mode == 0:
field = [int(num) for num in findall(r'\d+', line)]
fields = fields | \
set(value for value in range(field[0], field[1] + 1)) | \
set(value for value in range(field[2], field[3] + 1))
if mode == 4:
result += sum(int(value) for value in line.split(",") if int(value) not in fields)
print(result)
2020 Day 15 Part 02
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| from collections import defaultdict
lines = open('input').read().split(",")
numbers = [int(x) for x in lines]
seen = defaultdict(list, {numbers[i]: [i] for i in range(len(numbers))})
counter, current = len(numbers) - 1, numbers[-1]
while (counter := counter + 1) < 30000000:
if len(seen[current]) == 1:
seen[(current := 0)].append(counter)
else:
seen[(current := seen[current][-1] - seen[current][-2])].append(counter)
print(current) |
from collections import defaultdict
lines = open('input').read().split(",")
numbers = [int(x) for x in lines]
seen = defaultdict(list, {numbers[i]: [i] for i in range(len(numbers))})
counter, current = len(numbers) - 1, numbers[-1]
while (counter := counter + 1) < 30000000:
if len(seen[current]) == 1:
seen[(current := 0)].append(counter)
else:
seen[(current := seen[current][-1] - seen[current][-2])].append(counter)
print(current)
2020 Day 15 Part 01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| from collections import defaultdict
lines = open('input').read().split(",")
numbers = [int(x) for x in lines]
seen = defaultdict(list, {numbers[i]: [i] for i in range(len(numbers))})
counter, current = len(numbers) - 1, numbers[-1]
while (counter := counter + 1) < 2020:
if len(seen[current]) == 1:
seen[(current := 0)].append(counter)
else:
seen[(current := seen[current][-1] - seen[current][-2])].append(counter)
print(current) |
from collections import defaultdict
lines = open('input').read().split(",")
numbers = [int(x) for x in lines]
seen = defaultdict(list, {numbers[i]: [i] for i in range(len(numbers))})
counter, current = len(numbers) - 1, numbers[-1]
while (counter := counter + 1) < 2020:
if len(seen[current]) == 1:
seen[(current := 0)].append(counter)
else:
seen[(current := seen[current][-1] - seen[current][-2])].append(counter)
print(current)
2020 Day 14 Part 02
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| from re import match
lines = open('input').read().splitlines()
memory = dict()
for line in lines:
if mask_match := match(r"mask = ([X01]+)", line):
mask = mask_match.group(1)
else:
addresses, value = match(r"mem\[(\d+)\] = (\d+)", line).group(1, 2)
addresses = list(f'{int(addresses):036b}')
addresses = [["1" if mask[i] == "1" else addresses[i] for i in range(36)]]
for i in range(36):
if mask[i] == "X":
addresses = [address[:i] + [bit] + address[i+1:] for bit in ("0", "1") for address in addresses]
for address in addresses:
memory[tuple(address)] = int(value)
print(sum((value for value in memory.values()))) |
from re import match
lines = open('input').read().splitlines()
memory = dict()
for line in lines:
if mask_match := match(r"mask = ([X01]+)", line):
mask = mask_match.group(1)
else:
addresses, value = match(r"mem\[(\d+)\] = (\d+)", line).group(1, 2)
addresses = list(f'{int(addresses):036b}')
addresses = [["1" if mask[i] == "1" else addresses[i] for i in range(36)]]
for i in range(36):
if mask[i] == "X":
addresses = [address[:i] + [bit] + address[i+1:] for bit in ("0", "1") for address in addresses]
for address in addresses:
memory[tuple(address)] = int(value)
print(sum((value for value in memory.values())))
2020 Day 14 Part 01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| from re import match
lines = open('input').read().splitlines()
memory = dict()
for line in lines:
if mask_match := match(r"mask = ([X01]+)", line):
mask = mask_match.group(1)
else:
address, value = match(r"mem\[(\d+)\] = (\d+)", line).group(1, 2)
value = list(f'{int(value):036b}')
value = [value[i] if mask[i] == "X" else mask[i] for i in range(36)]
memory[address] = int("".join(value), 2)
print(sum([value for value in memory.values()])) |
from re import match
lines = open('input').read().splitlines()
memory = dict()
for line in lines:
if mask_match := match(r"mask = ([X01]+)", line):
mask = mask_match.group(1)
else:
address, value = match(r"mem\[(\d+)\] = (\d+)", line).group(1, 2)
value = list(f'{int(value):036b}')
value = [value[i] if mask[i] == "X" else mask[i] for i in range(36)]
memory[address] = int("".join(value), 2)
print(sum([value for value in memory.values()]))
2020 Day 13 Part 02
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
| from functools import reduce
from re import findall
def find_values(offset, increment, ids, pos, index):
result, i = [], 0
while len(result) < 2:
if not (offset + i * increment + pos[index]) % ids[index]:
result.append(offset + i * increment)
i += 1
return result[0], result[1] - result[0]
input = open('input').read().splitlines()
ids = findall(r'\d+', input[1])
all_entries = input[1].split(",")
pos = [all_entries.index(id) for id in ids]
ids = [int(id) for id in ids]
offset, increment = 0, 1
for i in range (len(ids)):
offset, increment = find_values(offset, increment, ids, pos, i)
print(offset) |
from functools import reduce
from re import findall
def find_values(offset, increment, ids, pos, index):
result, i = [], 0
while len(result) < 2:
if not (offset + i * increment + pos[index]) % ids[index]:
result.append(offset + i * increment)
i += 1
return result[0], result[1] - result[0]
input = open('input').read().splitlines()
ids = findall(r'\d+', input[1])
all_entries = input[1].split(",")
pos = [all_entries.index(id) for id in ids]
ids = [int(id) for id in ids]
offset, increment = 0, 1
for i in range (len(ids)):
offset, increment = find_values(offset, increment, ids, pos, i)
print(offset)
2020 Day 13 Part 01
1
2
3
4
5
6
7
8
9
10
11
12
| import re
input = open('input').read().splitlines()
start = int(input[0])
ids = [int(id) for id in re.findall(r'\d+', input[1])]
wait_time = 0
while 0 not in (diff := [(start + wait_time) % id for id in ids]):
wait_time += 1
print(wait_time * ids[diff.index(0)]) |
import re
input = open('input').read().splitlines()
start = int(input[0])
ids = [int(id) for id in re.findall(r'\d+', input[1])]
wait_time = 0
while 0 not in (diff := [(start + wait_time) % id for id in ids]):
wait_time += 1
print(wait_time * ids[diff.index(0)])
2020 Day 12 Part 02
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
| input = open('input').read().splitlines()
x, y, wp_x, wp_y = 0, 0, 10, -1
directions = {"N": (0, -1), "E": (1, 0), "S": (0, 1), "W": (-1, 0)}
rot_r, rot_l = [("R", 90), ("L", 270)], [("L", 90), ("R", 270)]
for instruction in input:
op, value = instruction[0], int("".join(instruction[1:]))
if op == "F":
x, y = x + value * wp_x, y + value * wp_y
elif op in ["R", "L"]:
if value == 180:
wp_x, wp_y = -wp_x, -wp_y
elif (op, value) in rot_r:
wp_x, wp_y = -wp_y, wp_x
elif (op, value) in rot_l:
wp_x, wp_y = wp_y, -wp_x
else:
wp_x, wp_y = wp_x + directions[op][0] * value, wp_y + directions[op][1] * value
print(abs(x) + abs(y)) |
input = open('input').read().splitlines()
x, y, wp_x, wp_y = 0, 0, 10, -1
directions = {"N": (0, -1), "E": (1, 0), "S": (0, 1), "W": (-1, 0)}
rot_r, rot_l = [("R", 90), ("L", 270)], [("L", 90), ("R", 270)]
for instruction in input:
op, value = instruction[0], int("".join(instruction[1:]))
if op == "F":
x, y = x + value * wp_x, y + value * wp_y
elif op in ["R", "L"]:
if value == 180:
wp_x, wp_y = -wp_x, -wp_y
elif (op, value) in rot_r:
wp_x, wp_y = -wp_y, wp_x
elif (op, value) in rot_l:
wp_x, wp_y = wp_y, -wp_x
else:
wp_x, wp_y = wp_x + directions[op][0] * value, wp_y + directions[op][1] * value
print(abs(x) + abs(y))
2020 Day 12 Part 01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| input = open('input').read().splitlines()
x, y, dir = 0, 0, 1
for instruction in input:
op, value = instruction[0], int("".join(instruction[1:]))
if op == "N" or (op == "F" and dir == 0):
y -= value
elif op == "E" or (op == "F" and dir == 1):
x += value
elif op == "S" or (op == "F" and dir == 2):
y += value
elif op == "W" or (op == "F" and dir == 3):
x -= value
elif op == "R":
dir = (dir + value // 90) % 4
elif op == "L":
dir = (dir - value // 90) % 4
print(abs(x) + abs(y)) |
input = open('input').read().splitlines()
x, y, dir = 0, 0, 1
for instruction in input:
op, value = instruction[0], int("".join(instruction[1:]))
if op == "N" or (op == "F" and dir == 0):
y -= value
elif op == "E" or (op == "F" and dir == 1):
x += value
elif op == "S" or (op == "F" and dir == 2):
y += value
elif op == "W" or (op == "F" and dir == 3):
x -= value
elif op == "R":
dir = (dir + value // 90) % 4
elif op == "L":
dir = (dir - value // 90) % 4
print(abs(x) + abs(y))
2020 Day 11 Part 02
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
| from collections import defaultdict
def get_visible_seats(layout):
visible_seats = defaultdict(list)
for x, y in (area := layout.keys()):
for dir in [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]:
x_ray, y_ray = x, y
while ((x_ray := x_ray + dir[0]), (y_ray := y_ray + dir[1])) in area:
if layout[(x_ray, y_ray)] != ".":
visible_seats[(x, y)].append((x_ray, y_ray))
break
return visible_seats
def change_seat(x, y, layout, visible_seats):
if layout[(x, y)] == ".":
return "."
elif layout[(x, y)] == "L":
if not sum([layout[pos] == "#" for pos in visible_seats[(x, y)]]):
return "#"
return "L"
elif layout[(x, y)] == "#":
if sum([layout[pos] == "#" for pos in visible_seats[(x, y)]]) >= 5:
return "L"
return "#"
def next_round(layout, visible_seats):
next_layout = defaultdict(str)
for pos, value in list(layout.items()):
next_layout[pos] = change_seat(*pos, layout, visible_seats)
return next_layout
input = open('input').read().splitlines()
layout = defaultdict(str)
for y in range(len(input)):
for x in range(len(input[0])):
layout[(x, y)] = input[y][x]
visible_seats = get_visible_seats(layout)
last_seen = defaultdict(str)
while (layout := next_round(layout, visible_seats)) != last_seen:
last_seen = layout
print(sum([seat == "#" for seat in layout.values()])) |
from collections import defaultdict
def get_visible_seats(layout):
visible_seats = defaultdict(list)
for x, y in (area := layout.keys()):
for dir in [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]:
x_ray, y_ray = x, y
while ((x_ray := x_ray + dir[0]), (y_ray := y_ray + dir[1])) in area:
if layout[(x_ray, y_ray)] != ".":
visible_seats[(x, y)].append((x_ray, y_ray))
break
return visible_seats
def change_seat(x, y, layout, visible_seats):
if layout[(x, y)] == ".":
return "."
elif layout[(x, y)] == "L":
if not sum([layout[pos] == "#" for pos in visible_seats[(x, y)]]):
return "#"
return "L"
elif layout[(x, y)] == "#":
if sum([layout[pos] == "#" for pos in visible_seats[(x, y)]]) >= 5:
return "L"
return "#"
def next_round(layout, visible_seats):
next_layout = defaultdict(str)
for pos, value in list(layout.items()):
next_layout[pos] = change_seat(*pos, layout, visible_seats)
return next_layout
input = open('input').read().splitlines()
layout = defaultdict(str)
for y in range(len(input)):
for x in range(len(input[0])):
layout[(x, y)] = input[y][x]
visible_seats = get_visible_seats(layout)
last_seen = defaultdict(str)
while (layout := next_round(layout, visible_seats)) != last_seen:
last_seen = layout
print(sum([seat == "#" for seat in layout.values()]))
2020 Day 11 Part 01
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
| from collections import defaultdict
def change_seat(x, y, layout):
if layout[(x, y)] == ".":
return "."
elif layout[(x, y)] == "L":
if not sum([layout[pos] == "#"
for x_offset in [-1, 0, 1]
for y_offset in [-1, 0, 1]
if (pos := (x + x_offset, y + y_offset)) in layout.keys()]):
return "#"
return "L"
elif layout[(x, y)] == "#":
if sum([layout[pos] == "#"
for x_offset in [-1, 0, 1]
for y_offset in [-1, 0, 1]
if (pos := (x + x_offset, y + y_offset)) in layout.keys()]) >= 5:
return "L"
return "#"
def next_round(layout):
next_layout = defaultdict(str)
for pos, value in list(layout.items()):
next_layout[pos] = change_seat(*pos, layout)
return next_layout
input = open('input').read().splitlines()
layout = defaultdict(str)
for y in range(len(input)):
for x in range(len(input[0])):
layout[(x, y)] = input[y][x]
last_seen = defaultdict(str)
while (layout := next_round(layout)) != last_seen:
last_seen = layout
print(sum([seat == "#" for seat in layout.values()])) |
from collections import defaultdict
def change_seat(x, y, layout):
if layout[(x, y)] == ".":
return "."
elif layout[(x, y)] == "L":
if not sum([layout[pos] == "#"
for x_offset in [-1, 0, 1]
for y_offset in [-1, 0, 1]
if (pos := (x + x_offset, y + y_offset)) in layout.keys()]):
return "#"
return "L"
elif layout[(x, y)] == "#":
if sum([layout[pos] == "#"
for x_offset in [-1, 0, 1]
for y_offset in [-1, 0, 1]
if (pos := (x + x_offset, y + y_offset)) in layout.keys()]) >= 5:
return "L"
return "#"
def next_round(layout):
next_layout = defaultdict(str)
for pos, value in list(layout.items()):
next_layout[pos] = change_seat(*pos, layout)
return next_layout
input = open('input').read().splitlines()
layout = defaultdict(str)
for y in range(len(input)):
for x in range(len(input[0])):
layout[(x, y)] = input[y][x]
last_seen = defaultdict(str)
while (layout := next_round(layout)) != last_seen:
last_seen = layout
print(sum([seat == "#" for seat in layout.values()]))
2020 Day 10 Part 02
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| from functools import reduce
def analyze_sequences(adapters):
sequences = [1]
for index in range(len(adapters)-1):
if adapters[index + 1] - adapters[index] == 1:
sequences[-1] += 1
elif adapters[index + 1] - adapters[index] == 3:
sequences.append(1)
return sequences
lines = open('input').read().splitlines()
lines = [int(line) for line in lines]
adapters = sorted(lines)
adapters = [0] + adapters + [adapters[-1] + 3]
print(reduce(lambda a, b: a * b, [[1, 2, 4, 7][max(0, s - 2)] for s in analyze_sequences(adapters)])) |
from functools import reduce
def analyze_sequences(adapters):
sequences = [1]
for index in range(len(adapters)-1):
if adapters[index + 1] - adapters[index] == 1:
sequences[-1] += 1
elif adapters[index + 1] - adapters[index] == 3:
sequences.append(1)
return sequences
lines = open('input').read().splitlines()
lines = [int(line) for line in lines]
adapters = sorted(lines)
adapters = [0] + adapters + [adapters[-1] + 3]
print(reduce(lambda a, b: a * b, [[1, 2, 4, 7][max(0, s - 2)] for s in analyze_sequences(adapters)]))
2020 Day 10 Part 01
1
2
3
4
5
6
7
8
| lines = open('input').read().splitlines()
lines = [int(line) for line in lines]
adapters = sorted(lines)
adapters = [0] + adapters + [adapters[-1] + 3]
diffs=[]
for index in range(len(adapters) - 1):
diffs.append(adapters[index + 1] - adapters[index])
print (diffs.count(1) * diffs.count(3)) |
lines = open('input').read().splitlines()
lines = [int(line) for line in lines]
adapters = sorted(lines)
adapters = [0] + adapters + [adapters[-1] + 3]
diffs=[]
for index in range(len(adapters) - 1):
diffs.append(adapters[index + 1] - adapters[index])
print (diffs.count(1) * diffs.count(3))
2020 Day 09 Part 02
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| def is_valid(preamble, val):
for a in range(25):
for b in range(a+1, len(preamble)):
if preamble[a] + preamble[b] == val:
return True
return False
lines = open('input').read().splitlines()
code = [int(line) for line in lines]
for start in range(25, len(code)):
if not is_valid(code[start-25:start], code[start]):
value = code[start]
break
for start in range(len(code)):
running_sum = 0
for length in range(len(code)-start):
if (running_sum := running_sum + code[start+length]) > value:
break
elif running_sum == value:
print (min(code[start:start+length]) + max(code[start:start+length]))
exit() |
def is_valid(preamble, val):
for a in range(25):
for b in range(a+1, len(preamble)):
if preamble[a] + preamble[b] == val:
return True
return False
lines = open('input').read().splitlines()
code = [int(line) for line in lines]
for start in range(25, len(code)):
if not is_valid(code[start-25:start], code[start]):
value = code[start]
break
for start in range(len(code)):
running_sum = 0
for length in range(len(code)-start):
if (running_sum := running_sum + code[start+length]) > value:
break
elif running_sum == value:
print (min(code[start:start+length]) + max(code[start:start+length]))
exit()
2020 Day 09 Part 01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| def is_valid(preamble, val):
for a in range(25):
for b in range(a+1, len(preamble)):
if preamble[a] + preamble[b] == val:
return True
return False
lines = open('input').read().splitlines()
code = [int(line) for line in lines]
for index in range(25, len(code)):
if not is_valid(code[index-25:index], code[index]):
print(code[index]) |
def is_valid(preamble, val):
for a in range(25):
for b in range(a+1, len(preamble)):
if preamble[a] + preamble[b] == val:
return True
return False
lines = open('input').read().splitlines()
code = [int(line) for line in lines]
for index in range(25, len(code)):
if not is_valid(code[index-25:index], code[index]):
print(code[index])
2020 Day 08 Part 02
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
| lines = open('input').read().splitlines()
mod_pos = -1
seen = set()
while True:
code = [line.split() for line in lines]
mod_pos += 1
if code[mod_pos][0] == "jmp":
code[mod_pos][0] = "nop"
elif code[mod_pos][0] == "nop":
code[mod_pos][0] = "jmp"
else:
continue
accu, pos = 0, 0
while pos not in seen:
seen.add(pos)
if code[pos][0] == "acc":
accu += int(code[pos][1])
elif code[pos][0] == "jmp":
pos += int(code[pos][1]) - 1
pos += 1
if pos == len(code):
print(accu)
exit()
seen.clear() |
lines = open('input').read().splitlines()
mod_pos = -1
seen = set()
while True:
code = [line.split() for line in lines]
mod_pos += 1
if code[mod_pos][0] == "jmp":
code[mod_pos][0] = "nop"
elif code[mod_pos][0] == "nop":
code[mod_pos][0] = "jmp"
else:
continue
accu, pos = 0, 0
while pos not in seen:
seen.add(pos)
if code[pos][0] == "acc":
accu += int(code[pos][1])
elif code[pos][0] == "jmp":
pos += int(code[pos][1]) - 1
pos += 1
if pos == len(code):
print(accu)
exit()
seen.clear()
2020 Day 08 Part 01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| lines = open('input').read().splitlines()
code = [line.split() for line in lines]
accu, pos = 0, 0
seen = set()
while pos not in seen:
seen.add(pos)
if code[pos][0] == "acc":
accu += int(code[pos][1])
elif code[pos][0] == "jmp":
pos += int(code[pos][1]) - 1
pos += 1
print(accu) |
lines = open('input').read().splitlines()
code = [line.split() for line in lines]
accu, pos = 0, 0
seen = set()
while pos not in seen:
seen.add(pos)
if code[pos][0] == "acc":
accu += int(code[pos][1])
elif code[pos][0] == "jmp":
pos += int(code[pos][1]) - 1
pos += 1
print(accu)
2020 Day 07 Part 02
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
| from collections import defaultdict
import re
lines = open('input').read().splitlines()
# Example: light salmon bags contain 5 dark brown bags, 2 dotted coral bags, 5 mirrored turquoise bags.
bags = defaultdict(set)
reg_container = re.compile('^([a-z]+ [a-z]+)')
reg_contains = re.compile('(\d+) ([a-z]+ [a-z]+)')
for line in lines:
container = reg_container.findall(line)[0]
for bag in reg_contains.findall(line):
bags[container].add(bag)
my_bag = "shiny gold"
# print(bags[my_bag])
# {('4', 'clear magenta'), ('2', 'plaid maroon'), ('3', 'mirrored turquoise'), ('5', 'bright crimson')}
def has_num_of_bags(bag, bags):
numbags = []
for b in bags[bag]:
numbags.append ( int(b[0]) * has_num_of_bags(b[1], bags) )
return sum(numbags) + 1
print(has_num_of_bags(my_bag, bags) - 1) |
from collections import defaultdict
import re
lines = open('input').read().splitlines()
# Example: light salmon bags contain 5 dark brown bags, 2 dotted coral bags, 5 mirrored turquoise bags.
bags = defaultdict(set)
reg_container = re.compile('^([a-z]+ [a-z]+)')
reg_contains = re.compile('(\d+) ([a-z]+ [a-z]+)')
for line in lines:
container = reg_container.findall(line)[0]
for bag in reg_contains.findall(line):
bags[container].add(bag)
my_bag = "shiny gold"
# print(bags[my_bag])
# {('4', 'clear magenta'), ('2', 'plaid maroon'), ('3', 'mirrored turquoise'), ('5', 'bright crimson')}
def has_num_of_bags(bag, bags):
numbags = []
for b in bags[bag]:
numbags.append ( int(b[0]) * has_num_of_bags(b[1], bags) )
return sum(numbags) + 1
print(has_num_of_bags(my_bag, bags) - 1)
2020 Day 07 Part 01
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
| from collections import defaultdict
import re
lines = open('input').read().splitlines()
# Example: light salmon bags contain 5 dark brown bags, 2 dotted coral bags, 5 mirrored turquoise bags.
bags = defaultdict(set)
reg_container = re.compile('^([a-z]+ [a-z]+)')
reg_contains = re.compile('\d+ ([a-z]+ [a-z]+)')
for line in lines:
container = reg_container.findall(line)
for bag in reg_contains.findall(line):
bags[bag].update(container)
'''
bags is used as reverse lookup dictionary:
bags['dark brown'] = {'light salmon'}
bags['dotted coral"] = {'light salmon'}
bags['mirrored turquoise'] = {'light salmon'}
After a few iterations:
bags['dark brown'] = {'light salmon'}
bags['dotted coral"] = {'dotted maroon', 'light salmon'}
bags['mirrored turquoise'] = {'light salmon'}
'dotted coral' bag is inside both 'dotted maroon' bag as well as 'light salmon' bag
'''
my_bag = "shiny gold"
def has_my_bag(my_bag, bags):
contains_my_bag = set(bags[my_bag])
# my bag is in {'pale orange', 'dark lime', 'dim fuchsia', 'faded aqua', 'dotted blue', 'drab fuchsia', 'posh gold', 'light lime'}
# for each bag that has my bag (child) find its parent bags.
# repeat recursively until all outermost bags that deep down contain my bag are found.
for b in bags[my_bag]:
contains_my_bag.update(has_my_bag(b, bags))
return contains_my_bag
outer_bags_containing_my_bag = []
outer_bags_containing_my_bag= has_my_bag(my_bag, bags)
print(len(outer_bags_containing_my_bag)) |
from collections import defaultdict
import re
lines = open('input').read().splitlines()
# Example: light salmon bags contain 5 dark brown bags, 2 dotted coral bags, 5 mirrored turquoise bags.
bags = defaultdict(set)
reg_container = re.compile('^([a-z]+ [a-z]+)')
reg_contains = re.compile('\d+ ([a-z]+ [a-z]+)')
for line in lines:
container = reg_container.findall(line)
for bag in reg_contains.findall(line):
bags[bag].update(container)
'''
bags is used as reverse lookup dictionary:
bags['dark brown'] = {'light salmon'}
bags['dotted coral"] = {'light salmon'}
bags['mirrored turquoise'] = {'light salmon'}
After a few iterations:
bags['dark brown'] = {'light salmon'}
bags['dotted coral"] = {'dotted maroon', 'light salmon'}
bags['mirrored turquoise'] = {'light salmon'}
'dotted coral' bag is inside both 'dotted maroon' bag as well as 'light salmon' bag
'''
my_bag = "shiny gold"
def has_my_bag(my_bag, bags):
contains_my_bag = set(bags[my_bag])
# my bag is in {'pale orange', 'dark lime', 'dim fuchsia', 'faded aqua', 'dotted blue', 'drab fuchsia', 'posh gold', 'light lime'}
# for each bag that has my bag (child) find its parent bags.
# repeat recursively until all outermost bags that deep down contain my bag are found.
for b in bags[my_bag]:
contains_my_bag.update(has_my_bag(b, bags))
return contains_my_bag
outer_bags_containing_my_bag = []
outer_bags_containing_my_bag= has_my_bag(my_bag, bags)
print(len(outer_bags_containing_my_bag))
2020 Day 06 Part 02
1
2
3
4
5
6
7
8
9
10
11
| input = open('input').read().strip().split("\n\n")
input = [x.split("\n") for x in input]
count = 0
for group in input:
yes = ''
prev = 'abcdefghijklmnopqrstuvwxyz'
for response_string in group:
yes = ''.join(set(prev).intersection(response_string))
prev = yes
count += len(yes)
print(count) |
input = open('input').read().strip().split("\n\n")
input = [x.split("\n") for x in input]
count = 0
for group in input:
yes = ''
prev = 'abcdefghijklmnopqrstuvwxyz'
for response_string in group:
yes = ''.join(set(prev).intersection(response_string))
prev = yes
count += len(yes)
print(count)
2020 Day 06 Part 01
1
2
3
4
5
6
7
8
9
| input = open('input').read().split("\n\n")
input = [x.split("\n") for x in input]
count = 0
for group in input:
yes = set()
for response_string in group:
yes.update(response_string)
count += len(yes)
print(count) |
input = open('input').read().split("\n\n")
input = [x.split("\n") for x in input]
count = 0
for group in input:
yes = set()
for response_string in group:
yes.update(response_string)
count += len(yes)
print(count)
2020 Day 06 Part 01
1
2
3
4
5
6
7
8
9
10
| input = open('input').read().split("\n\n")
input = [x.split("\n") for x in input]
count = 0
for group in input:
yes = set()
for response_string in group:
for response_char in response_string:
yes.add(response_char)
count += len(yes)
print(count) |
input = open('input').read().split("\n\n")
input = [x.split("\n") for x in input]
count = 0
for group in input:
yes = set()
for response_string in group:
for response_char in response_string:
yes.add(response_char)
count += len(yes)
print(count)
2020 Day 05 Part 02
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
| def calc_seat_id(seat):
row_low, row_high = 0, 127
col_low, col_high = 0, 7
for char in seat[:7]:
if char == "B":
row_low += (row_high - row_low + 1) // 2
else:
row_high -= (row_high - row_low + 1) // 2
for char in seat[7:]:
if char == "R":
col_low += (col_high - col_low + 1) // 2
else:
col_high -= (col_high - col_low + 1) // 2
return row_low * 8 + col_low
lines = open('input').read().splitlines()
seats = sorted(lines, key = lambda s: s[7:])
seats = sorted(seats, key = lambda s: s[:7], reverse = True)
for i in range(len(seats)):
current_id = calc_seat_id(seats[i])
if i and prev_id + 2 == current_id:
print(prev_id + 1)
prev_id = current_id |
def calc_seat_id(seat):
row_low, row_high = 0, 127
col_low, col_high = 0, 7
for char in seat[:7]:
if char == "B":
row_low += (row_high - row_low + 1) // 2
else:
row_high -= (row_high - row_low + 1) // 2
for char in seat[7:]:
if char == "R":
col_low += (col_high - col_low + 1) // 2
else:
col_high -= (col_high - col_low + 1) // 2
return row_low * 8 + col_low
lines = open('input').read().splitlines()
seats = sorted(lines, key = lambda s: s[7:])
seats = sorted(seats, key = lambda s: s[:7], reverse = True)
for i in range(len(seats)):
current_id = calc_seat_id(seats[i])
if i and prev_id + 2 == current_id:
print(prev_id + 1)
prev_id = current_id
2020 Day 05 Part 02
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
| def calc_seat_id(seat):
row_low, row_high = 0, 127
col_low, col_high = 0, 7
for char in seat[:7]:
if char == "B":
row_low += (row_high - row_low + 1) // 2
else:
row_high -= (row_high - row_low + 1) // 2
for char in seat[7:]:
if char == "R":
col_low += (col_high - col_low + 1) // 2
else:
col_high -= (col_high - col_low + 1) // 2
return row_low * 8 + col_low
lines = open('input').read().splitlines()
ids = []
for line in lines:
ids.append(calc_seat_id(line))
ids.sort()
# find the gap in the ascending list of seat ids
for i in range(len(ids)):
if ids[i+1] != ids[i]+1:
print(ids[i]+1)
break |
def calc_seat_id(seat):
row_low, row_high = 0, 127
col_low, col_high = 0, 7
for char in seat[:7]:
if char == "B":
row_low += (row_high - row_low + 1) // 2
else:
row_high -= (row_high - row_low + 1) // 2
for char in seat[7:]:
if char == "R":
col_low += (col_high - col_low + 1) // 2
else:
col_high -= (col_high - col_low + 1) // 2
return row_low * 8 + col_low
lines = open('input').read().splitlines()
ids = []
for line in lines:
ids.append(calc_seat_id(line))
ids.sort()
# find the gap in the ascending list of seat ids
for i in range(len(ids)):
if ids[i+1] != ids[i]+1:
print(ids[i]+1)
break
2020 Day 05 Part 01
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
| def calc_seat_id(seat):
'''
F
|0 1 2 3| 0 |4 5 6 7|
|8 9 etc| 1 |_ _ _ _|
L |_ _ _ _| 2 |_ _ _ _| R
|_ _ _ _|...|_ _ _ _|
|_ _ _ _|127|_ _ _ _|
B
'''
row_low, row_high = 0, 127
col_low, col_high = 0, 7
for char in seat[:7]:
if char == "B":
row_low += (row_high - row_low + 1) // 2
else:
row_high -= (row_high - row_low + 1) // 2
for char in seat[7:]:
if char == "R":
col_low += (col_high - col_low + 1) // 2
else:
col_high -= (col_high - col_low + 1) // 2
return row_low * 8 + col_low
lines = open('input').read().splitlines()
print(max(calc_seat_id(line) for line in lines))
'''
Sort lines in descending order based on last 3 letters
Next, sort lines in ascending order based on first 7 letters
Calculate seat id ONCE, only for seat[0] string.
'''
seats = sorted(lines, key = lambda s: s[7:], reverse = True)
seats = sorted(seats, key = lambda s: s[:7])
print(calc_seat_id(seats[0])) |
def calc_seat_id(seat):
'''
F
|0 1 2 3| 0 |4 5 6 7|
|8 9 etc| 1 |_ _ _ _|
L |_ _ _ _| 2 |_ _ _ _| R
|_ _ _ _|...|_ _ _ _|
|_ _ _ _|127|_ _ _ _|
B
'''
row_low, row_high = 0, 127
col_low, col_high = 0, 7
for char in seat[:7]:
if char == "B":
row_low += (row_high - row_low + 1) // 2
else:
row_high -= (row_high - row_low + 1) // 2
for char in seat[7:]:
if char == "R":
col_low += (col_high - col_low + 1) // 2
else:
col_high -= (col_high - col_low + 1) // 2
return row_low * 8 + col_low
lines = open('input').read().splitlines()
print(max(calc_seat_id(line) for line in lines))
'''
Sort lines in descending order based on last 3 letters
Next, sort lines in ascending order based on first 7 letters
Calculate seat id ONCE, only for seat[0] string.
'''
seats = sorted(lines, key = lambda s: s[7:], reverse = True)
seats = sorted(seats, key = lambda s: s[:7])
print(calc_seat_id(seats[0]))
2020 Day 04 Part 02
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
| def check(passport):
passes = 0
for pair in passport:
code = pair[0]
val = pair[1]
match code:
case "byr":
if 1920 <= int(val) <= 2002:
passes +=1
case "iyr":
if 2010 <= int(val) <= 2020:
passes +=1
case "eyr":
if 2020 <= int(val) <= 2030:
passes +=1
case "hgt":
if val[-2:] == 'cm' and (150 <= int(val[:-2]) <= 193) or \
val[-2:] == 'in' and ( 59 <= int(val[:-2]) <= 76):
passes +=1
case "hcl":
if len(val) == 7 and val[0] == "#" and sum([char in "0123456789abcdef" for char in val[1:]]) == 6:
passes +=1
case "ecl":
if val in ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"]:
passes +=1
case "pid":
if sum([char in "0123456789" for char in val]) == 9:
passes +=1
pidref = val
if passes == 7:
return pidref
lines = open('input').read().strip().split('\n\n')
lines = [line.replace("\n", " ") for line in lines]
valid = []
for line in lines:
# passport check
passport = []
for pair in line.split(" "):
pair = pair.split(":")
passport.append(pair)
result = check(passport)
if result:
valid.append(result)
for v in valid:
print(v)
print("Total:",len(valid)) |
def check(passport):
passes = 0
for pair in passport:
code = pair[0]
val = pair[1]
match code:
case "byr":
if 1920 <= int(val) <= 2002:
passes +=1
case "iyr":
if 2010 <= int(val) <= 2020:
passes +=1
case "eyr":
if 2020 <= int(val) <= 2030:
passes +=1
case "hgt":
if val[-2:] == 'cm' and (150 <= int(val[:-2]) <= 193) or \
val[-2:] == 'in' and ( 59 <= int(val[:-2]) <= 76):
passes +=1
case "hcl":
if len(val) == 7 and val[0] == "#" and sum([char in "0123456789abcdef" for char in val[1:]]) == 6:
passes +=1
case "ecl":
if val in ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"]:
passes +=1
case "pid":
if sum([char in "0123456789" for char in val]) == 9:
passes +=1
pidref = val
if passes == 7:
return pidref
lines = open('input').read().strip().split('\n\n')
lines = [line.replace("\n", " ") for line in lines]
valid = []
for line in lines:
# passport check
passport = []
for pair in line.split(" "):
pair = pair.split(":")
passport.append(pair)
result = check(passport)
if result:
valid.append(result)
for v in valid:
print(v)
print("Total:",len(valid))
2020 Day 04 Part 01
1
2
3
4
5
6
7
8
9
10
11
12
13
| import re
lines = open('input').read().split('\n\n')
valid = 0
for line in lines:
fields = set()
for pair in line.split(" "):
for a in re.findall('(\w*):', pair):
fields.add(a)
fields.discard("cid")
if fields == {'ecl', 'eyr', 'byr', 'iyr', 'hcl', 'hgt', 'pid'}:
valid += 1
print(valid) |
import re
lines = open('input').read().split('\n\n')
valid = 0
for line in lines:
fields = set()
for pair in line.split(" "):
for a in re.findall('(\w*):', pair):
fields.add(a)
fields.discard("cid")
if fields == {'ecl', 'eyr', 'byr', 'iyr', 'hcl', 'hgt', 'pid'}:
valid += 1
print(valid)
2020 Day 03 Part 02
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| lines = open('input').read().splitlines()
def calc (slope):
x = -slope[1]
numtrees = 0
for y in range(0, len(lines), slope[0]):
x = (x + slope[1]) % len(lines[0])
if lines[y][x] == '#':
numtrees += 1
return numtrees
totals = []
for slope in [(1,1), (1,3), (1,5), (1,7), (2,1)]:
totals.append(calc(slope))
product = 1
for total in totals:
product = total * product
print(product) |
lines = open('input').read().splitlines()
def calc (slope):
x = -slope[1]
numtrees = 0
for y in range(0, len(lines), slope[0]):
x = (x + slope[1]) % len(lines[0])
if lines[y][x] == '#':
numtrees += 1
return numtrees
totals = []
for slope in [(1,1), (1,3), (1,5), (1,7), (2,1)]:
totals.append(calc(slope))
product = 1
for total in totals:
product = total * product
print(product)
2020 Day 03 Part 01
1
2
3
4
5
6
7
8
9
| lines = open('input').read().splitlines()
# coordinates are in x,y notation. rows = y values, columns = x values.
x = -3
numtrees = 0
for y,line in enumerate(lines):
x = (x + 3) % len(lines[0]) # 0 3 6 9 etc.
if lines[y][x] == '#':
numtrees += 1
print(numtrees) |
lines = open('input').read().splitlines()
# coordinates are in x,y notation. rows = y values, columns = x values.
x = -3
numtrees = 0
for y,line in enumerate(lines):
x = (x + 3) % len(lines[0]) # 0 3 6 9 etc.
if lines[y][x] == '#':
numtrees += 1
print(numtrees)
2020 Day 02 Part 02
1
2
3
4
5
6
7
8
9
| import re
lines = open('input').read().splitlines()
valid = 0
for line in lines:
for pos1, pos2, char, pwd in re.findall('(\d*)-(\d*) (\w): (\w*)', line):
if (pwd[int(pos1)-1] == char) ^ (pwd[int(pos2)-1] == char): # xor
valid += 1
print(valid) |
import re
lines = open('input').read().splitlines()
valid = 0
for line in lines:
for pos1, pos2, char, pwd in re.findall('(\d*)-(\d*) (\w): (\w*)', line):
if (pwd[int(pos1)-1] == char) ^ (pwd[int(pos2)-1] == char): # xor
valid += 1
print(valid)
2020 Day 02 Part 01
1
2
3
4
5
6
7
8
9
| import re
lines = open('input').read().splitlines()
valid = 0
for line in lines:
for low, high, char, pwd in re.findall('(\d*)-(\d*) (\w): (\w*)', line):
if int(low) <= pwd.count(char) <= int(high):
valid += 1
print(valid) |
import re
lines = open('input').read().splitlines()
valid = 0
for line in lines:
for low, high, char, pwd in re.findall('(\d*)-(\d*) (\w): (\w*)', line):
if int(low) <= pwd.count(char) <= int(high):
valid += 1
print(valid)
2020 Day 01 Part 01 + 02
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| def p1(s):
for e in s:
if 2020-e in s:
return e*(2020-e)
def p2(s):
for i in s:
for j in s:
if 2020-i-j in s:
return i*j*(2020-i-j)
lines = open('input').read().strip().split()
s = set(int(e) for e in lines)
print(p1(s))
print(p2(s)) |
def p1(s):
for e in s:
if 2020-e in s:
return e*(2020-e)
def p2(s):
for i in s:
for j in s:
if 2020-i-j in s:
return i*j*(2020-i-j)
lines = open('input').read().strip().split()
s = set(int(e) for e in lines)
print(p1(s))
print(p2(s))