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

1
 

2018 Day 25 Part 01

1
 

2018 Day 24 Part 02

1
 

2018 Day 24 Part 01

1
 

2018 Day 23 Part 02

1
 

2018 Day 23 Part 01

1
 

2018 Day 22 Part 02

1
 

2018 Day 22 Part 01

1
 

2018 Day 21 Part 02

1
 

2018 Day 21 Part 01

1
 

2018 Day 20 Part 02

1
 

2018 Day 20 Part 01

1
 

2018 Day 19 Part 02

1
 

2018 Day 19 Part 01

1
 

2018 Day 18 Part 02

1
 

2018 Day 18 Part 01

1
 

2018 Day 17 Part 02

1
 

2018 Day 17 Part 01

1
 

2018 Day 16 Part 02

1
 

2018 Day 16 Part 01

1
 

2018 Day 15 Part 02

1
 

2018 Day 15 Part 01

1
 

2018 Day 14 Part 02

1
 

2018 Day 14 Part 01

1
 

2018 Day 13 Part 02

1
 

2018 Day 13 Part 01

1
 

2018 Day 12 Part 02

1
 

2018 Day 12 Part 01

1
 

2018 Day 11 Part 02

1
 

2018 Day 11 Part 01

1
 

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

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))

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())

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)

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)

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)

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))

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)

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)

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))

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)

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)

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)