Compare commits
No commits in common. "047a183f60596570e55a5384ef41e9718e0d719c" and "a6491289a762a2d73aad7c84883b9111838c4593" have entirely different histories.
047a183f60
...
a6491289a7
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1 @@
|
||||||
day*.txt
|
day*.txt
|
||||||
venv/
|
|
||||||
|
|
30
2018/day2.py
30
2018/day2.py
|
@ -1,30 +0,0 @@
|
||||||
def main():
|
|
||||||
with open("day2.txt", "rt") as f:
|
|
||||||
lines = [line.rstrip() for line in f.readlines()]
|
|
||||||
|
|
||||||
n2 = 0
|
|
||||||
n3 = 0
|
|
||||||
for line in lines:
|
|
||||||
occurences = [line.count(letter) for letter in line]
|
|
||||||
if 2 in occurences:
|
|
||||||
n2 += 1
|
|
||||||
if 3 in occurences:
|
|
||||||
n3 += 1
|
|
||||||
print(n2 * n3)
|
|
||||||
|
|
||||||
for line in lines:
|
|
||||||
for other in lines:
|
|
||||||
diffs = 0
|
|
||||||
common = ""
|
|
||||||
for c1, c2 in zip(line, other):
|
|
||||||
if c1 == c2:
|
|
||||||
common += c1
|
|
||||||
else:
|
|
||||||
diffs += 1
|
|
||||||
if diffs == 1:
|
|
||||||
print(common)
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
59
2018/day3.py
59
2018/day3.py
|
@ -1,59 +0,0 @@
|
||||||
import re
|
|
||||||
|
|
||||||
from grid import Grid
|
|
||||||
|
|
||||||
|
|
||||||
EX = [
|
|
||||||
"#1 @ 1,3: 4x4",
|
|
||||||
"#2 @ 3,1: 4x4",
|
|
||||||
"#3 @ 5,5: 2x2",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
with open("day3.txt", "rt") as f:
|
|
||||||
lines = [line.rstrip() for line in f.readlines()]
|
|
||||||
|
|
||||||
# Part 1
|
|
||||||
g = Grid()
|
|
||||||
for line in lines:
|
|
||||||
ident, left, top, width, height = parse_line(line)
|
|
||||||
for i in range(int(width)):
|
|
||||||
for j in range(int(height)):
|
|
||||||
x = int(left) + i
|
|
||||||
y = int(top) + j
|
|
||||||
g.setv(x, y, g.getv(x, y) + 1)
|
|
||||||
n = get_overlaps(g)
|
|
||||||
print(n)
|
|
||||||
|
|
||||||
# Part 2
|
|
||||||
g = Grid()
|
|
||||||
over = []
|
|
||||||
for line in lines:
|
|
||||||
ident, left, top, width, height = parse_line(line)
|
|
||||||
for i in range(int(width)):
|
|
||||||
for j in range(int(height)):
|
|
||||||
x = int(left) + i
|
|
||||||
y = int(top) + j
|
|
||||||
current_v = g.getv(x, y)
|
|
||||||
if current_v == None:
|
|
||||||
over.append(int(ident))
|
|
||||||
continue
|
|
||||||
elif current_v == 0:
|
|
||||||
g.setv(x, y, int(ident))
|
|
||||||
else:
|
|
||||||
over += [int(ident), current_v]
|
|
||||||
g.setv(x, y, None)
|
|
||||||
print(set(v for _, _, v in g.values_gen()).difference(set(over)))
|
|
||||||
|
|
||||||
LINE_RE = re.compile(r"#(\d+) @ (\d+),(\d+): (\d+)x(\d+)")
|
|
||||||
|
|
||||||
def parse_line(line):
|
|
||||||
match = LINE_RE.match(line)
|
|
||||||
return match.groups()
|
|
||||||
|
|
||||||
def get_overlaps(grid):
|
|
||||||
return sum([v > 1 for _, _, v in grid.values_gen()])
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
58
2018/day4.py
58
2018/day4.py
|
@ -1,58 +0,0 @@
|
||||||
import re
|
|
||||||
from collections import defaultdict
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
with open("day4.txt", "rt") as f:
|
|
||||||
lines = [line.rstrip() for line in f.readlines()]
|
|
||||||
entries = [parse_entry(line) for line in lines]
|
|
||||||
entries = sorted(entries, key=lambda e: e[0])
|
|
||||||
|
|
||||||
sleepz = defaultdict(int)
|
|
||||||
noight = defaultdict(lambda: [0] * 60)
|
|
||||||
for t, v in entries:
|
|
||||||
if not isinstance(v, bool):
|
|
||||||
guard = v
|
|
||||||
elif v == False:
|
|
||||||
sleep_t = t
|
|
||||||
elif v == True:
|
|
||||||
sleep_d = t - sleep_t
|
|
||||||
sleep_minutes = sleep_d.seconds // 60
|
|
||||||
sleepz[guard] += sleep_minutes
|
|
||||||
for i in range(sleep_minutes):
|
|
||||||
noight[guard][sleep_t.minute + i] += 1
|
|
||||||
lazy_g = max(sleepz, key=lambda k: sleepz[k])
|
|
||||||
print("Laziest guard:", lazy_g)
|
|
||||||
sleepiest_min = max(range(60), key=lambda m: noight[lazy_g][m])
|
|
||||||
print("Sleepiest minute:", sleepiest_min)
|
|
||||||
print("Part 1:", lazy_g * sleepiest_min)
|
|
||||||
|
|
||||||
reliable_v = -1
|
|
||||||
for g in noight:
|
|
||||||
sleepiest_min = max(range(60), key=lambda m: noight[g][m])
|
|
||||||
sleepiest_v = noight[g][sleepiest_min]
|
|
||||||
if sleepiest_v > reliable_v:
|
|
||||||
reliable_g = g
|
|
||||||
reliable_m = sleepiest_min
|
|
||||||
reliable_v = sleepiest_v
|
|
||||||
print("Part 2:", reliable_g * reliable_m)
|
|
||||||
|
|
||||||
|
|
||||||
LINE_RE = re.compile(r"^\[([^\]]+)\] (.+)$")
|
|
||||||
|
|
||||||
def parse_entry(line):
|
|
||||||
match = LINE_RE.match(line)
|
|
||||||
ts, content = match.groups()
|
|
||||||
dt = datetime.fromisoformat(ts)
|
|
||||||
if content.startswith("Guard"):
|
|
||||||
v = int(content.split()[1][1:])
|
|
||||||
elif content.startswith("w"):
|
|
||||||
v = True
|
|
||||||
elif content.startswith("f"):
|
|
||||||
v = False
|
|
||||||
return (dt, v)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
55
2018/grid.py
55
2018/grid.py
|
@ -1,55 +0,0 @@
|
||||||
"""Generic 2D grid with a few helpers."""
|
|
||||||
|
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
|
|
||||||
class Grid:
|
|
||||||
|
|
||||||
def __init__(self, value_factory=int, lines=None):
|
|
||||||
self.g = defaultdict(lambda: defaultdict(value_factory))
|
|
||||||
if lines:
|
|
||||||
self.load(lines)
|
|
||||||
|
|
||||||
def getv(self, x, y):
|
|
||||||
return self.g[y][x]
|
|
||||||
|
|
||||||
def setv(self, x, y, value):
|
|
||||||
self.g[y][x] = value
|
|
||||||
|
|
||||||
def load(self, lines, f=lambda v: v):
|
|
||||||
for y, line in enumerate(lines):
|
|
||||||
for x, c in enumerate(line.rstrip()):
|
|
||||||
self.g[y][x] = f(c)
|
|
||||||
|
|
||||||
def values_gen(self):
|
|
||||||
for y, row in self.g.items():
|
|
||||||
for x, v in row.items():
|
|
||||||
yield (x, y, v)
|
|
||||||
|
|
||||||
def near_objects(self, p):
|
|
||||||
"""Return a dict of neighbor positions to values (U, L, D, R)."""
|
|
||||||
return {q: self.g[q[1]][q[0]] for q in Grid.near(p)}
|
|
||||||
|
|
||||||
def dumb_print(self, f=lambda v: v):
|
|
||||||
for row in self.g.values():
|
|
||||||
for x in row.values():
|
|
||||||
print(f(x), end="")
|
|
||||||
print()
|
|
||||||
|
|
||||||
def print_near(self, p, view_size=2):
|
|
||||||
"""Print near values in an area of view_size. Works iff keys support addition."""
|
|
||||||
for dy in range(-view_size, view_size + 1):
|
|
||||||
print("".join([
|
|
||||||
self.g[p[1] + dy][p[0] + dx]
|
|
||||||
for dx in range(-view_size, view_size + 1)
|
|
||||||
]))
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def near(p):
|
|
||||||
"""Return a tuple of neighbor positions (up, left, down, right)."""
|
|
||||||
return (
|
|
||||||
(p[0] , p[1] - 1),
|
|
||||||
(p[0] + 1, p[1] ),
|
|
||||||
(p[0] , p[1] + 1),
|
|
||||||
(p[0] - 1, p[1] ),
|
|
||||||
)
|
|
|
@ -1,7 +0,0 @@
|
||||||
def main():
|
|
||||||
with open("", "rt") as f:
|
|
||||||
lines = [line.rstrip() for line in f.readlines()]
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -12,7 +12,7 @@ class Grid:
|
||||||
|
|
||||||
def getv(self, x, y):
|
def getv(self, x, y):
|
||||||
return self.g[y][x]
|
return self.g[y][x]
|
||||||
|
|
||||||
def setv(self, x, y, value):
|
def setv(self, x, y, value):
|
||||||
self.g[y][x] = value
|
self.g[y][x] = value
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue