python: Submit Python solutions

This commit is contained in:
Sijmen 2020-12-16 03:21:17 +01:00
parent 9e01e0dd90
commit 87fdcce197
Signed by: vijfhoek
GPG key ID: DAF7821E067D9C48
7 changed files with 351 additions and 0 deletions

48
python/day07.py Normal file
View file

@ -0,0 +1,48 @@
import fileinput
import re
from collections import defaultdict
network = {}
reverse = defaultdict(list)
for line in fileinput.input():
parent, children = line.strip().split(" contain ")
parent = parent[:-5]
children = children.rstrip(".").split(", ")
children = [
child.rstrip("s")[:-4].split(" ", 1)
for child in children
if "no other" not in child
]
children = [(int(n), c) for n, c in children]
network[parent] = children
for n, child in children:
reverse[child].append((n, parent))
reverse = dict(reverse)
shiny_gold_bags = set()
stack = ["shiny gold"]
while stack:
color = stack.pop()
if color not in reverse:
continue
for _, parent in reverse[color]:
stack.append(parent)
shiny_gold_bags.add(parent)
print("part 1:", len(shiny_gold_bags))
part2 = 0
stack = [(1, "shiny gold")]
while stack:
n, color = stack.pop()
part2 += n
children = network[color]
for m, child in children:
stack.append((n * m, child))
part2 -= 1
print("part 2:", part2)

22
python/day09-a.py Normal file
View file

@ -0,0 +1,22 @@
import fileinput
import itertools
N = 25
numbers = []
for line in fileinput.input():
numbers.append(int(line))
for i in range(N, len(numbers)):
found = False
for j in numbers[i - N:i]:
for k in numbers[i - N:i]:
if j == k:
continue
if j + k == numbers[i]:
found = True
if not found:
print(numbers[i])
break

22
python/day09-b.py Normal file
View file

@ -0,0 +1,22 @@
import fileinput
import itertools
import sys
N = 25
numbers = []
for line in fileinput.input():
numbers.append(int(line))
for i in range(N, len(numbers)):
target = 25918798
#target=127
for j in range(i - N,i):
for k in range(j+ 1, i):
nn = numbers[j:k]
if sum(nn) == target:
print(max(nn) + min(nn))
sys.exit(0)

38
python/day10.py Normal file
View file

@ -0,0 +1,38 @@
import fileinput
import itertools
from collections import deque
adapters = [0]
for line in fileinput.input():
adapters.append(int(line))
adapters.sort()
adapters.append(adapters[-1] + 3)
one = 0
three = 0
for (fr, to) in zip(adapters[:-1], adapters[1:]):
if to - fr == 1:
one += 1
elif to - fr == 3:
three += 1
print(fr, to)
print(one, three, one * three)
paths = [0] * len(adapters)
paths[0] = 1
ways = 1
for i, value in enumerate(adapters[:-1]):
try:
if adapters[i + 1] <= value + 3:
paths[i + 1] += paths[i]
if adapters[i + 2] <= value + 3:
paths[i + 2] += paths[i]
if adapters[i + 3] <= value + 3:
paths[i + 3] += paths[i]
except IndexError:
pass
print(paths)
print(paths[-1])

118
python/day11.py Normal file
View file

@ -0,0 +1,118 @@
import fileinput
from pprint import pprint
from copy import deepcopy
layout = []
for line in fileinput.input():
if line.strip():
layout.append(list(line.strip()))
part1 = -1
old_layout = deepcopy(layout)
row_length = len(old_layout[0])
while True:
new_layout = [[None] * len(row) for row in old_layout]
for y in range(len(old_layout)):
for x in range(len(old_layout[0])):
if old_layout[y][x] == ".":
new_layout[y][x] = old_layout[y][x]
continue
count = sum(
(
x >= 1 and old_layout[y][x - 1] == "#",
x < row_length - 1 and old_layout[y][x + 1] == "#",
)
)
if y >= 1:
count += sum(
(
x >= 1 and old_layout[y - 1][x - 1] == "#",
old_layout[y - 1][x] == "#",
x < row_length - 1 and old_layout[y - 1][x + 1] == "#",
)
)
if y < len(layout) - 1:
count += sum(
(
x >= 1 and old_layout[y + 1][x - 1] == "#",
old_layout[y + 1][x] == "#",
x < row_length - 1 and old_layout[y + 1][x + 1] == "#",
)
)
if count == 0:
new_layout[y][x] = "#"
elif count >= 4:
new_layout[y][x] = "L"
else:
new_layout[y][x] = old_layout[y][x]
new_part1 = sum(sum(s == "#" for s in row) for row in new_layout)
if part1 == new_part1:
break
part1 = new_part1
old_layout = new_layout
print(part1)
part2 = -1
old_layout = deepcopy(layout)
def get(x, y, dx, dy):
try:
x += dx
y += dy
while old_layout[y][x] == ".":
if x < 0 or y < 0:
raise IndexError
x += dx
y += dy
except:
return "."
return old_layout[y][x]
while True:
new_layout = [[None] * len(row) for row in old_layout]
for y in range(1, len(old_layout) - 1):
for x in range(1, len(old_layout[0]) - 1):
if old_layout[y][x] == ".":
new_layout[y][x] = old_layout[y][x]
continue
count = sum(
(
get(x, y, -1, -1) == "#",
get(x, y, -1, 0) == "#",
get(x, y, -1, 1) == "#",
get(x, y, 0, -1) == "#",
get(x, y, 0, 1) == "#",
get(x, y, 1, -1) == "#",
get(x, y, 1, 0) == "#",
get(x, y, 1, 1) == "#",
)
)
if count == 0:
new_layout[y][x] = "#"
elif count >= 5:
new_layout[y][x] = "L"
else:
new_layout[y][x] = old_layout[y][x]
new_part2 = sum(sum(s == "#" for s in row) for row in new_layout)
if part2 == new_part2:
break
part2 = new_part2
old_layout = new_layout
print(part2)

48
python/day13.py Normal file
View file

@ -0,0 +1,48 @@
import fileinput
input = fileinput.input()
arrival = int(next(input))
buses = [None if bus == "x" else int(bus) for bus in next(input).split(",")]
print(arrival, buses)
remainders = [-(arrival % (-bus)) if bus else float("inf") for bus in buses]
print(remainders)
print(
"Part 1:",
min(enumerate(buses), key=lambda x: remainders[x[0]])[1] * min(remainders),
)
def combine(a_period, a_offset, b_period, b_offset):
gcd, s, _ = egcd(a_period, b_period)
diff = a_offset - b_offset
diff_quot, dif_rem = divmod(diff, gcd)
assert(dif_rem == 0)
combined_period = a_period // gcd * b_period
combined_offset = (a_offset - s * diff_quot * a_period) % combined_period
return combined_period, combined_offset
def egcd(a, b):
r_, r = a, b
s_, s = 1, 0
t_, t = 0, 1
while r:
quot, rem = divmod(r_, r)
r_, r = r, rem
s_, s = s, (s_ - quot * s)
t_, t = t, (t_ - quot * t)
return r_, s_, t_
period = 1
offset = 0
for i, bus in enumerate(buses):
if bus is None:
continue
period, offset = combine(period, offset, bus, i)
print(i, bus, period, offset)
print(-offset % period)

55
python/day14.py Normal file
View file

@ -0,0 +1,55 @@
import fileinput
from pprint import pprint
from typing import List
mem = {}
for line in fileinput.input():
l, r = line.strip().split(" = ")
if l == "mask":
and_mask = int(r.replace("X", "1"), base=2)
or_mask = int(r.replace("X", "0"), base=2)
else:
value = int(r)
value &= and_mask
value |= or_mask
mem[int(l[4:-1])] = value
print(sum(mem.values()))
def recurse(s: str) -> List[str]:
x = s.find("X")
if x == -1:
return [s]
s0 = s[:x] + '0' + s[x + 1:]
s1 = s[:x] + '1' + s[x + 1:]
return [*recurse(s0), *recurse(s1)]
mem = {}
for line in fileinput.input():
l, r = line.strip().split(" = ")
if l == "mask":
mask = r
or_mask = int(r.replace("X", "0"), base=2)
floatings = recurse(r.replace("0", "_").replace("1", "_"))
and_masks = [int(v.replace("_", "1"), 2) for v in floatings]
or_masks = [int(v.replace("_", "0"), 2) for v in floatings]
assert(len(and_masks) == 2 ** r.count("X"))
assert(len(or_masks) == 2 ** r.count("X"))
else:
orig_address = int(l[4:-1])
orig_address |= or_mask
for (and_, or_) in zip(and_masks, or_masks):
address = orig_address
address &= and_
address |= or_
mem[address] = int(r)
assert(address >= 0)
assert(not [k for k in mem.keys() if k < 0])
print(sum(mem.values()))