2018 Advent of Code (Python)
By telleropnul, December 31, 2018
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: adventofcode2018inputs.zip [To be uploaded still…]
2018 Day 25 Part 02
2018 Day 25 Part 01
2018 Day 24 Part 02
2018 Day 24 Part 01
2018 Day 23 Part 02
2018 Day 23 Part 01
2018 Day 22 Part 02
2018 Day 22 Part 01
2018 Day 21 Part 02
2018 Day 21 Part 01
2018 Day 20 Part 02
2018 Day 20 Part 01
2018 Day 19 Part 02
2018 Day 19 Part 01
2018 Day 18 Part 02
2018 Day 18 Part 01
2018 Day 17 Part 02
2018 Day 17 Part 01
2018 Day 16 Part 02
2018 Day 16 Part 01
2018 Day 15 Part 02
2018 Day 15 Part 01
2018 Day 14 Part 02
2018 Day 14 Part 01
2018 Day 13 Part 02
2018 Day 13 Part 01
2018 Day 12 Part 02
2018 Day 12 Part 01
2018 Day 11 Part 02
2018 Day 11 Part 01
2018 Day 10 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
31
32
33
34
35
36
37
38
39
40
41
| import re
from itertools import count
lines = open('input').read().splitlines()
lines = [re.findall(r'-?\d+', line) for line in lines]
lines = [list(map(int, line)) for line in lines]
stars = lines
min_width = 10000000000000000000000
for i in count():
new_stars = []
for px, py, vx, vy in stars:
px += vx
py += vy
new_stars.append((px, py, vx, vy))
max_y = max(k[1] for k in new_stars)
min_y = min(k[1] for k in new_stars)
width = max_y - min_y
if width < min_width:
min_width = width
if width > min_width:
max_x = max(k[0] for k in stars)
min_x = min(k[0] for k in stars)
max_y = max(k[1] for k in stars)
min_y = min(k[1] for k in stars)
star_map = set((px, py) for px, py, *_ in stars)
for y in range(min_y, max_y + 1):
row = []
for x in range(min_x, max_x + 1):
if (x, y) in star_map:
row.append('#')
else:
row.append(' ')
print(''.join(row))
print(i)
break
stars = new_stars |
import re
from itertools import count
lines = open('input').read().splitlines()
lines = [re.findall(r'-?\d+', line) for line in lines]
lines = [list(map(int, line)) for line in lines]
stars = lines
min_width = 10000000000000000000000
for i in count():
new_stars = []
for px, py, vx, vy in stars:
px += vx
py += vy
new_stars.append((px, py, vx, vy))
max_y = max(k[1] for k in new_stars)
min_y = min(k[1] for k in new_stars)
width = max_y - min_y
if width < min_width:
min_width = width
if width > min_width:
max_x = max(k[0] for k in stars)
min_x = min(k[0] for k in stars)
max_y = max(k[1] for k in stars)
min_y = min(k[1] for k in stars)
star_map = set((px, py) for px, py, *_ in stars)
for y in range(min_y, max_y + 1):
row = []
for x in range(min_x, max_x + 1):
if (x, y) in star_map:
row.append('#')
else:
row.append(' ')
print(''.join(row))
print(i)
break
stars = new_stars
2018 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
| from collections import deque
def play(players, marbles):
circle = deque()
circle.append(0)
scores = [0] * players
for marble in range(1, marbles+1):
if marble % 23 == 0:
circle.rotate(-7)
scores[marble % players] += marble + circle.pop()
else:
circle.rotate(2)
circle.append(marble)
return max(scores)
data = open('input').read().split()
players = int(data[0])
value = int(data[6])
print(play(players, value))
print(play(players, value * 100)) |
from collections import deque
def play(players, marbles):
circle = deque()
circle.append(0)
scores = [0] * players
for marble in range(1, marbles+1):
if marble % 23 == 0:
circle.rotate(-7)
scores[marble % players] += marble + circle.pop()
else:
circle.rotate(2)
circle.append(marble)
return max(scores)
data = open('input').read().split()
players = int(data[0])
value = int(data[6])
print(play(players, value))
print(play(players, value * 100))
2018 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
31
32
33
34
35
| import itertools
class Node(object):
def __init__(self, children, metadata):
self.children = children
self.metadata = metadata
def __repr__(self):
return '[%s %s]' % (self.metadata, self.children)
def all_meta(self):
return self.metadata + [x for c in self.children for x in c.all_meta()]
def value(self):
if not self.children:
return sum(self.metadata)
return sum(
self.children[m-1].value()
for m in self.metadata
if m >= 1 and m <= len(self.children))
def parse(it):
nc = next(it)
nm = next(it)
children = [parse(it) for c in range(nc)]
metadata = list(itertools.islice(it, nm))
return Node(children, metadata)
def parse_file(filename):
ins = map(int, open(filename).read().split())
return parse(ins)
tree = parse_file('input')
print(sum(tree.all_meta()))
print(tree.value()) |
import itertools
class Node(object):
def __init__(self, children, metadata):
self.children = children
self.metadata = metadata
def __repr__(self):
return '[%s %s]' % (self.metadata, self.children)
def all_meta(self):
return self.metadata + [x for c in self.children for x in c.all_meta()]
def value(self):
if not self.children:
return sum(self.metadata)
return sum(
self.children[m-1].value()
for m in self.metadata
if m >= 1 and m <= len(self.children))
def parse(it):
nc = next(it)
nm = next(it)
children = [parse(it) for c in range(nc)]
metadata = list(itertools.islice(it, nm))
return Node(children, metadata)
def parse_file(filename):
ins = map(int, open(filename).read().split())
return parse(ins)
tree = parse_file('input')
print(sum(tree.all_meta()))
print(tree.value())
2018 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
26
27
28
29
30
31
32
| import re
def cost(c):
return ord(c)-ord('A')+61
data = open('input').read().splitlines()
data = [re.findall(' ([A-Z]) ', line) for line in data]
t = 0
max_workers = 5
work = []
started = set()
remain = set(a for p in data for a in p)
while remain:
done = set(c for c, td in work if t == td)
if done:
remain -= done
data = [(a, b) for a, b in data if a not in done]
work = [(c, td) for c, td in work if c not in done]
ready = set(remain) - set(b for _, b in data) - started
idle = max_workers - len(work)
for _, start in zip(range(idle), ready):
started.update(start)
work.append((start, t + cost(start)))
if remain:
t += 1
print(t) |
import re
def cost(c):
return ord(c)-ord('A')+61
data = open('input').read().splitlines()
data = [re.findall(' ([A-Z]) ', line) for line in data]
t = 0
max_workers = 5
work = []
started = set()
remain = set(a for p in data for a in p)
while remain:
done = set(c for c, td in work if t == td)
if done:
remain -= done
data = [(a, b) for a, b in data if a not in done]
work = [(c, td) for c, td in work if c not in done]
ready = set(remain) - set(b for _, b in data) - started
idle = max_workers - len(work)
for _, start in zip(range(idle), ready):
started.update(start)
work.append((start, t + cost(start)))
if remain:
t += 1
print(t)
2018 Day 07 Part 01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| import re
data = open('input').read().splitlines()
data = [re.findall(' ([A-Z]) ', line) for line in data]
remain = set(a for p in data for a in p)
order = ''
while remain:
ready = set(remain) - set(b for _, b in data)
now = sorted(ready)[0]
order += now
remain.remove(now)
data = [(a, b) for a, b in data if a != now]
print(order) |
import re
data = open('input').read().splitlines()
data = [re.findall(' ([A-Z]) ', line) for line in data]
remain = set(a for p in data for a in p)
order = ''
while remain:
ready = set(remain) - set(b for _, b in data)
now = sorted(ready)[0]
order += now
remain.remove(now)
data = [(a, b) for a, b in data if a != now]
print(order)
2018 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
30
31
32
33
34
35
36
37
38
| from collections import defaultdict
data = open('input').read().splitlines()
data = [list(map(int, x.split(", "))) for x in data]
x0 = min(x for x, y in data)
x1 = max(x for x, y in data)
y0 = min(y for x, y in data)
y1 = max(y for x, y in data)
def dist(a, b):
return abs(a[0] - b[0]) + abs(a[1] - b[1])
def closest(pad=0):
r = defaultdict(int)
for x in range(x0 - pad, x1 + pad):
for y in range(y0 - pad, y1 + pad):
d = [dist([x, y], p) for p in data]
m = min(d)
if d.count(m) == 1:
i = d.index(min(d))
r[i] += 1
return r
a = closest()
b = closest(1)
stable = [k for k in a.keys() if a[k] == b[k]]
print(max(a[k] for k in stable))
count = 0
for x in range(x0, x1):
for y in range(y0, y1):
if sum(dist([x, y], p) for p in data) < 10000:
count += 1
print(count) |
from collections import defaultdict
data = open('input').read().splitlines()
data = [list(map(int, x.split(", "))) for x in data]
x0 = min(x for x, y in data)
x1 = max(x for x, y in data)
y0 = min(y for x, y in data)
y1 = max(y for x, y in data)
def dist(a, b):
return abs(a[0] - b[0]) + abs(a[1] - b[1])
def closest(pad=0):
r = defaultdict(int)
for x in range(x0 - pad, x1 + pad):
for y in range(y0 - pad, y1 + pad):
d = [dist([x, y], p) for p in data]
m = min(d)
if d.count(m) == 1:
i = d.index(min(d))
r[i] += 1
return r
a = closest()
b = closest(1)
stable = [k for k in a.keys() if a[k] == b[k]]
print(max(a[k] for k in stable))
count = 0
for x in range(x0, x1):
for y in range(y0, y1):
if sum(dist([x, y], p) for p in data) < 10000:
count += 1
print(count)
2018 Day 05 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
| import re
from string import ascii_lowercase as lc
from string import ascii_uppercase as uc
polymer = open('input').read().rstrip()
def react(polymer):
pairs = list(zip(lc, uc)) + list(zip(uc, lc))
patterns = ["".join(x) for x in pairs]
l2 = len(polymer)
l1 = l2 + 1
while l1 != l2:
l1 = l2
for p in patterns:
polymer = re.sub(p, "", polymer)
l2 = len(polymer)
return polymer
print(len(react(polymer)))
def fix_and_react(polymer, l):
fixed = re.sub(l, "", polymer, flags=re.IGNORECASE)
return react(fixed)
print(min(len(fix_and_react(polymer, l)) for l in lc)) |
import re
from string import ascii_lowercase as lc
from string import ascii_uppercase as uc
polymer = open('input').read().rstrip()
def react(polymer):
pairs = list(zip(lc, uc)) + list(zip(uc, lc))
patterns = ["".join(x) for x in pairs]
l2 = len(polymer)
l1 = l2 + 1
while l1 != l2:
l1 = l2
for p in patterns:
polymer = re.sub(p, "", polymer)
l2 = len(polymer)
return polymer
print(len(react(polymer)))
def fix_and_react(polymer, l):
fixed = re.sub(l, "", polymer, flags=re.IGNORECASE)
return react(fixed)
print(min(len(fix_and_react(polymer, l)) for l in lc))
2018 Day 04 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
31
32
33
34
35
36
37
38
39
| from collections import defaultdict, Counter
lines = open('input').read().splitlines()
lines.sort()
sleep=[]
for line in lines:
words = line.split()
minute = int(words[1][3:5])
if words[2] == 'falls':
start = minute
elif words[2] == 'wakes':
end = minute
sleep.append([guard, start, end])
else:
guard = int(words[3][1:])
#print(sleep)
total_sleep = Counter()
by_minute = defaultdict(Counter)
for guard_id, fell_asleep, wake_up in sleep:
total_sleep[guard_id] += wake_up - fell_asleep
by_minute[guard_id].update(range(fell_asleep, wake_up))
sleepiest, _ = total_sleep.most_common(1)[0]
best_minute = by_minute[sleepiest].most_common(1)[0][0]
print(sleepiest * best_minute)
guard_minute = Counter()
for guard_id, fell_asleep, wake_up in sleep:
guard_minute.update((guard_id, m) for m in range(fell_asleep, wake_up))
a, b = guard_minute.most_common(1)[0][0]
print(a * b) |
from collections import defaultdict, Counter
lines = open('input').read().splitlines()
lines.sort()
sleep=[]
for line in lines:
words = line.split()
minute = int(words[1][3:5])
if words[2] == 'falls':
start = minute
elif words[2] == 'wakes':
end = minute
sleep.append([guard, start, end])
else:
guard = int(words[3][1:])
#print(sleep)
total_sleep = Counter()
by_minute = defaultdict(Counter)
for guard_id, fell_asleep, wake_up in sleep:
total_sleep[guard_id] += wake_up - fell_asleep
by_minute[guard_id].update(range(fell_asleep, wake_up))
sleepiest, _ = total_sleep.most_common(1)[0]
best_minute = by_minute[sleepiest].most_common(1)[0][0]
print(sleepiest * best_minute)
guard_minute = Counter()
for guard_id, fell_asleep, wake_up in sleep:
guard_minute.update((guard_id, m) for m in range(fell_asleep, wake_up))
a, b = guard_minute.most_common(1)[0][0]
print(a * b)
2018 Day 03 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
| import re
from collections import defaultdict
claims = []
lines = open('input').read().splitlines()
for line in lines:
claims.append (re.findall(r'\d+',line))
claims = [list(map(int, c)) for c in claims]
fabric = defaultdict(list)
for id_, dx, dy, x, y in claims:
for i in range(dx, dx + x):
for j in range(dy, dy + y):
fabric[(i, j)].append(id_)
print(len([i for i in fabric.values() if len(i) > 1]))
ids_all = set(map(lambda x: x[0], claims))
ids_overlapped = set(id_ for ids in fabric.values() if len(ids) > 1
for id_ in ids)
print(ids_all - ids_overlapped) |
import re
from collections import defaultdict
claims = []
lines = open('input').read().splitlines()
for line in lines:
claims.append (re.findall(r'\d+',line))
claims = [list(map(int, c)) for c in claims]
fabric = defaultdict(list)
for id_, dx, dy, x, y in claims:
for i in range(dx, dx + x):
for j in range(dy, dy + y):
fabric[(i, j)].append(id_)
print(len([i for i in fabric.values() if len(i) > 1]))
ids_all = set(map(lambda x: x[0], claims))
ids_overlapped = set(id_ for ids in fabric.values() if len(ids) > 1
for id_ in ids)
print(ids_all - ids_overlapped)
2018 Day 02 Part 01 + 02
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| from collections import Counter
from itertools import combinations
c2 = 0
c3 = 0
lines = open('input').read().splitlines()
for line in lines:
c = Counter(line)
if 2 in c.values():
c2 += 1
if 3 in c.values():
c3 += 1
print(c2 * c3)
for a, b in combinations(lines, 2):
count_diff = sum(i != j for i, j in zip(a, b))
if count_diff == 1:
print(''.join(i for i, j in zip(a, b) if i == j)) |
from collections import Counter
from itertools import combinations
c2 = 0
c3 = 0
lines = open('input').read().splitlines()
for line in lines:
c = Counter(line)
if 2 in c.values():
c2 += 1
if 3 in c.values():
c3 += 1
print(c2 * c3)
for a, b in combinations(lines, 2):
count_diff = sum(i != j for i, j in zip(a, b))
if count_diff == 1:
print(''.join(i for i, j in zip(a, b) if i == j))
2018 Day 02 Part 01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| def countDups(string):
c2 = 0 # 'doubles' (count_2)
c3 = 0 # 'triples' (count_3)
for c in string:
n = string.count(c)
if not c2 and n == 2:
c2 = 1
if not c3 and n == 3:
c3 = 1
if c2 and c3:
break
return c2, c3
c2 = 0
c3 = 0
lines = open('input').read().splitlines()
for line in lines:
c = countDups(line)
c2 += c[0]
c3 += c[1]
print(c2 * c3) |
def countDups(string):
c2 = 0 # 'doubles' (count_2)
c3 = 0 # 'triples' (count_3)
for c in string:
n = string.count(c)
if not c2 and n == 2:
c2 = 1
if not c3 and n == 3:
c3 = 1
if c2 and c3:
break
return c2, c3
c2 = 0
c3 = 0
lines = open('input').read().splitlines()
for line in lines:
c = countDups(line)
c2 += c[0]
c3 += c[1]
print(c2 * c3)
2018 Day 01 Part 02
1
2
3
4
5
6
7
8
9
10
11
12
| lines = open('input').read().splitlines()
f = 0
prev = set()
while True:
for line in lines:
f += (int(line))
if f in prev:
print(f)
exit()
else:
prev.add(f) |
lines = open('input').read().splitlines()
f = 0
prev = set()
while True:
for line in lines:
f += (int(line))
if f in prev:
print(f)
exit()
else:
prev.add(f)
2018 Day 01 Part 01
1
2
3
4
5
| lines = open('input').read().splitlines()
f = 0
for line in lines:
f += (int(line))
print(f) |
lines = open('input').read().splitlines()
f = 0
for line in lines:
f += (int(line))
print(f)