2017 Advent of Code (Python)
By telleropnul, April 8, 2023
Advent of Code 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: adventofcode2017inputs.zip [To be uploaded still…]
2017 Day 25 Part 02
2017 Day 25 Part 01
2017 Day 24 Part 02
2017 Day 24 Part 01
2017 Day 23 Part 02
2017 Day 23 Part 01
2017 Day 22 Part 02
2017 Day 22 Part 01
2017 Day 21 Part 02
2017 Day 21 Part 01
2017 Day 20 Part 02
2017 Day 20 Part 01
2017 Day 19 Part 02
2017 Day 19 Part 01
2017 Day 18 Part 02
2017 Day 18 Part 01
2017 Day 17 Part 02
2017 Day 17 Part 01
2017 Day 16 Part 02
2017 Day 16 Part 01
2017 Day 15 Part 02
2017 Day 15 Part 01
2017 Day 14 Part 02
2017 Day 14 Part 01
2017 Day 13 Part 02
2017 Day 13 Part 01
2017 Day 12 Part 02
2017 Day 12 Part 01
2017 Day 11 Part 02
2017 Day 11 Part 01
2017 Day 10 Part 02
2017 Day 10 Part 01
2017 Day 09 Part 01 + 02
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| data = open('input').read().strip()
garbage_cleaned = 0
nesting_level = 0
score = 0
i = 0
while i < len(data):
if data[i] == '<':
i += 1
while data[i] != '>':
if data[i] == '!':
i += 1
else:
garbage_cleaned += 1
i += 1
elif data[i] == '{':
nesting_level += 1
elif data[i] == '}':
score += nesting_level
nesting_level -= 1
i += 1
print(score)
print(garbage_cleaned) |
data = open('input').read().strip()
garbage_cleaned = 0
nesting_level = 0
score = 0
i = 0
while i < len(data):
if data[i] == '<':
i += 1
while data[i] != '>':
if data[i] == '!':
i += 1
else:
garbage_cleaned += 1
i += 1
elif data[i] == '{':
nesting_level += 1
elif data[i] == '}':
score += nesting_level
nesting_level -= 1
i += 1
print(score)
print(garbage_cleaned)
2017 Day 08 Part 01 + 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
| # dict and defaultdict are almost the same except for the fact that defaultdict never raises a KeyError.
# defaultdict provides a default value for keys that do not exist.
# even when just calling a key in an empty defaultdict, the key will be added and a default value is generated.
# when the int class is passed as the default_factory argument, a defaultdict is created with default value as zero.
from collections import defaultdict
from operator import lt, gt, eq, ne, le, ge
data = open('input').read().splitlines()
registers = defaultdict(int)
operators = {
'<': lt,
'>': gt,
'==': eq,
'!=': ne,
'<=': le,
'>=': ge,
}
maximum = 0
for line in data:
register, instruction, amount, _, cond_reg, operator, value = line.split()
directon = 1 if instruction == 'inc' else -1
if operators[operator](registers[cond_reg], int(value)): # example: if gt(hx,-10):
registers[register] += directon * int(amount)
maximum = max(registers[register], maximum)
print(max(registers.values()))
print(maximum) |
# dict and defaultdict are almost the same except for the fact that defaultdict never raises a KeyError.
# defaultdict provides a default value for keys that do not exist.
# even when just calling a key in an empty defaultdict, the key will be added and a default value is generated.
# when the int class is passed as the default_factory argument, a defaultdict is created with default value as zero.
from collections import defaultdict
from operator import lt, gt, eq, ne, le, ge
data = open('input').read().splitlines()
registers = defaultdict(int)
operators = {
'<': lt,
'>': gt,
'==': eq,
'!=': ne,
'<=': le,
'>=': ge,
}
maximum = 0
for line in data:
register, instruction, amount, _, cond_reg, operator, value = line.split()
directon = 1 if instruction == 'inc' else -1
if operators[operator](registers[cond_reg], int(value)): # example: if gt(hx,-10):
registers[register] += directon * int(amount)
maximum = max(registers[register], maximum)
print(max(registers.values()))
print(maximum)
2017 Day 07 Part 01 + 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
| from collections import Counter
import re
data = open('input').read().splitlines()
weights = {}
children = {}
for line in data:
node, weight, *kids = re.findall(r"(\w+)", line)
weights[node] = int(weight)
children[node] = kids
#print(weights)
#print(children)
all_nodes = set(weights)
all_kids = {kid for kids in children.values() for kid in kids}
root = (all_nodes - all_kids).pop()
print(root)
def find_offsprings_weights(node):
kids_weights = [find_offsprings_weights(kid) for kid in children[node]]
unique_weights = Counter(kids_weights).most_common()
if len(unique_weights) == 2:
(correct_total, _), (wrong_total, _) = unique_weights
difference = correct_total - wrong_total
wrong_node = children[node][kids_weights.index(wrong_total)]
wrong_weight = weights[wrong_node]
print(wrong_weight + difference)
return weights[node] + sum(kids_weights) + difference
return weights[node] + sum(kids_weights)
find_offsprings_weights(root) |
from collections import Counter
import re
data = open('input').read().splitlines()
weights = {}
children = {}
for line in data:
node, weight, *kids = re.findall(r"(\w+)", line)
weights[node] = int(weight)
children[node] = kids
#print(weights)
#print(children)
all_nodes = set(weights)
all_kids = {kid for kids in children.values() for kid in kids}
root = (all_nodes - all_kids).pop()
print(root)
def find_offsprings_weights(node):
kids_weights = [find_offsprings_weights(kid) for kid in children[node]]
unique_weights = Counter(kids_weights).most_common()
if len(unique_weights) == 2:
(correct_total, _), (wrong_total, _) = unique_weights
difference = correct_total - wrong_total
wrong_node = children[node][kids_weights.index(wrong_total)]
wrong_weight = weights[wrong_node]
print(wrong_weight + difference)
return weights[node] + sum(kids_weights) + difference
return weights[node] + sum(kids_weights)
find_offsprings_weights(root)
2017 Day 06 Part 01 + 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
| from collections import OrderedDict
data = open('input').read().split()
data = list(map(int, data))
size = len(data) # = 16 registers
seen = OrderedDict()
# A tuple is a collection which is ordered (not to be confused with sorted) and unchangeable.
# A set is a collection which is sorted (order is not preserved) and contains only unique elements.
# Does Python have an ordered set?
# No, but you can use collections.OrderedDict with just keys (and values as None)
# Using while ... not in ... we can check if/when a collection pattern reoccurs.
while tuple(data) not in seen:
seen[tuple(data)] = None
max_value = max(data)
max_index = data.index(max_value)
data[max_index] = 0
to_every, to_some = divmod(max_value, size)
data = [d + to_every for d in data]
for i in range(to_some):
data[(max_index + i+1) % size] += 1
print(len(seen))
# Lookup in the OrderedDict keys, the index of when we first encountered the duplicate value.
loop_start = list(seen.keys()).index(tuple(data))
print(len(seen) - loop_start) |
from collections import OrderedDict
data = open('input').read().split()
data = list(map(int, data))
size = len(data) # = 16 registers
seen = OrderedDict()
# A tuple is a collection which is ordered (not to be confused with sorted) and unchangeable.
# A set is a collection which is sorted (order is not preserved) and contains only unique elements.
# Does Python have an ordered set?
# No, but you can use collections.OrderedDict with just keys (and values as None)
# Using while ... not in ... we can check if/when a collection pattern reoccurs.
while tuple(data) not in seen:
seen[tuple(data)] = None
max_value = max(data)
max_index = data.index(max_value)
data[max_index] = 0
to_every, to_some = divmod(max_value, size)
data = [d + to_every for d in data]
for i in range(to_some):
data[(max_index + i+1) % size] += 1
print(len(seen))
# Lookup in the OrderedDict keys, the index of when we first encountered the duplicate value.
loop_start = list(seen.keys()).index(tuple(data))
print(len(seen) - loop_start)
2017 Day 05 Part 02
1
2
3
4
5
6
7
8
9
10
11
12
13
| data = open('input').read().splitlines()
data = list(map(int, data))
ptr = 0
steps = 0
while ptr < len(data):
offset = data[ptr]
if offset >= 3:
data[ptr] -= 1
else:
data[ptr] += 1
ptr += offset
steps += 1
print(steps) |
data = open('input').read().splitlines()
data = list(map(int, data))
ptr = 0
steps = 0
while ptr < len(data):
offset = data[ptr]
if offset >= 3:
data[ptr] -= 1
else:
data[ptr] += 1
ptr += offset
steps += 1
print(steps)
2017 Day 05 Part 01
1
2
3
4
5
6
7
8
9
10
| data = open('input').read().splitlines()
data = list(map(int, data))
ptr = 0
steps = 0
while ptr < len(data):
offset = data[ptr]
data[ptr] += 1
ptr += offset
steps += 1
print(steps) |
data = open('input').read().splitlines()
data = list(map(int, data))
ptr = 0
steps = 0
while ptr < len(data):
offset = data[ptr]
data[ptr] += 1
ptr += offset
steps += 1
print(steps)
2017 Day 04 Part 02
1
2
3
4
5
6
7
8
9
10
| data = open('input').read().splitlines()
valid = 0
words = []
for d in data:
words = d.split()
words = [''.join(sorted(word)) for word in words]
uniq = set(words)
if len(words) == len(uniq):
valid+=1
print(valid) |
data = open('input').read().splitlines()
valid = 0
words = []
for d in data:
words = d.split()
words = [''.join(sorted(word)) for word in words]
uniq = set(words)
if len(words) == len(uniq):
valid+=1
print(valid)
2017 Day 04 Part 01
1
2
3
4
5
6
7
8
9
| data = open('input').read().splitlines()
valid = 0
words = []
for d in data:
words = d.split()
uniq = set(words)
if len(words) == len(uniq):
valid+=1
print(valid) |
data = open('input').read().splitlines()
valid = 0
words = []
for d in data:
words = d.split()
uniq = set(words)
if len(words) == len(uniq):
valid+=1
print(valid)
2017 Day 03 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
| data = open('input').read().split()
number = int(data[0])
grid = {(0, 0): 1}
neighbours = lambda x, y: [(x+1, y), (x, y+1), (x+1, y+1), (x-1, y-1),
(x-1, y), (x, y-1), (x+1, y-1), (x-1, y+1)]
def set_value(point):
grid[point] = sum(grid.get(neighbour, 0) for neighbour in neighbours(*point))
return grid[point]
def iterate_through_spiral(ring=0):
while True:
ring += 1
for y in range(-ring + 1, ring): yield set_value((ring, y))
for x in range(ring, -ring, -1): yield set_value((x, ring))
for y in range(ring, -ring, -1): yield set_value((-ring, y))
for x in range(-ring, ring + 1): yield set_value((x, -ring))
for value in iterate_through_spiral():
if value > number:
print(value)
break |
data = open('input').read().split()
number = int(data[0])
grid = {(0, 0): 1}
neighbours = lambda x, y: [(x+1, y), (x, y+1), (x+1, y+1), (x-1, y-1),
(x-1, y), (x, y-1), (x+1, y-1), (x-1, y+1)]
def set_value(point):
grid[point] = sum(grid.get(neighbour, 0) for neighbour in neighbours(*point))
return grid[point]
def iterate_through_spiral(ring=0):
while True:
ring += 1
for y in range(-ring + 1, ring): yield set_value((ring, y))
for x in range(ring, -ring, -1): yield set_value((x, ring))
for y in range(ring, -ring, -1): yield set_value((-ring, y))
for x in range(-ring, ring + 1): yield set_value((x, -ring))
for value in iterate_through_spiral():
if value > number:
print(value)
break
2017 Day 03 Part 01
1
2
3
4
5
6
7
8
9
10
| data = open('input').read().split()
number = int(data[0])
# double-asterisks (**) in Python is a
# 'to the power of' exponentiation operator
# example: 2 ** 6 = 64
spiral_corner = int(number ** 0.5)
remaining_steps = number % spiral_corner ** 2
side_length = spiral_corner + 1
towards_middle = remaining_steps % (side_length // 2)
print(side_length - towards_middle) |
data = open('input').read().split()
number = int(data[0])
# double-asterisks (**) in Python is a
# 'to the power of' exponentiation operator
# example: 2 ** 6 = 64
spiral_corner = int(number ** 0.5)
remaining_steps = number % spiral_corner ** 2
side_length = spiral_corner + 1
towards_middle = remaining_steps % (side_length // 2)
print(side_length - towards_middle)
2017 Day 02 Part 02
1
2
3
4
5
6
7
8
9
10
11
| data = open('input').read().splitlines()
delta = 0
nums = []
for line in data:
nums = line.split('\t')
nums = list(map(int, nums))
for a in nums:
for b in nums:
if a % b == 0 and a != b:
delta += a // b
print(delta) |
data = open('input').read().splitlines()
delta = 0
nums = []
for line in data:
nums = line.split('\t')
nums = list(map(int, nums))
for a in nums:
for b in nums:
if a % b == 0 and a != b:
delta += a // b
print(delta)
2017 Day 02 Part 01
1
2
3
4
5
6
7
8
| data = open('input').read().splitlines()
delta = 0
nums = []
for line in data:
nums = line.split('\t')
nums = list(map(int, nums))
delta += max(nums) - min(nums)
print(delta) |
data = open('input').read().splitlines()
delta = 0
nums = []
for line in data:
nums = line.split('\t')
nums = list(map(int, nums))
delta += max(nums) - min(nums)
print(delta)
2017 Day 01 Part 01 + 02 v2
1
2
3
4
5
6
7
8
9
| data = open('input').read().strip()
data = list(map(int, data))
def solve(digits, second_part=False):
jump = 1 if not second_part else len(digits)//2
return sum(n for i, n in enumerate(digits) if n == digits[i-jump])
print(solve(data))
print(solve(data, 'part 2')) |
data = open('input').read().strip()
data = list(map(int, data))
def solve(digits, second_part=False):
jump = 1 if not second_part else len(digits)//2
return sum(n for i, n in enumerate(digits) if n == digits[i-jump])
print(solve(data))
print(solve(data, 'part 2'))
2017 Day 01 Part 02
1
2
3
4
5
6
7
8
9
10
11
| data = open('input').read().strip()
data = list(map(int, data))
count = 0
offset = len(data)//2
for i, n in enumerate(data):
if n == data[i - offset]:
count += data[i]
print(count)
# Single slash(/) in python is used to perform classic division
# whereas double slash in python (//) is used to perform floor division.
# Floor division means rounding down to the nearest whole number. |
data = open('input').read().strip()
data = list(map(int, data))
count = 0
offset = len(data)//2
for i, n in enumerate(data):
if n == data[i - offset]:
count += data[i]
print(count)
# Single slash(/) in python is used to perform classic division
# whereas double slash in python (//) is used to perform floor division.
# Floor division means rounding down to the nearest whole number.
2017 Day 01 Part 01
1
2
3
4
5
6
7
| data = open('input').read().strip()
data = list(map(int, data))
count = 0
for i, n in enumerate(data):
if n == data[i-1]:
count += data[i]
print(count) |
data = open('input').read().strip()
data = list(map(int, data))
count = 0
for i, n in enumerate(data):
if n == data[i-1]:
count += data[i]
print(count)