Compare commits

...

2 Commits

Author SHA1 Message Date
fc35818fd4 Add day 8 solution 2022-12-10 19:21:07 +01:00
786be99a7a Add day 7 solution 2022-12-10 18:09:57 +01:00
4 changed files with 219 additions and 0 deletions

23
07/example Normal file
View File

@ -0,0 +1,23 @@
$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k

77
07/parser.py Normal file
View File

@ -0,0 +1,77 @@
import fileinput
from typing import Iterable, Optional
class Directory():
def __init__(self, parent = None):
self.dirs = {}
self.files = {}
self.parent = parent
def get_size(self) -> int:
return sum(self.files.values()) + sum([d.get_size() for d in self.dirs.values()])
def print_tree(self, depth = 0):
if depth == 0:
print("/")
for d, v in self.dirs.items():
print(" "*(depth+1) + d)
v.print_tree(depth+1)
for f, size in self.files.items():
print(" "*(depth+1) + f + " " + str(size))
def walk(self):
output = [self]
for d in self.dirs.values():
output += d.walk()
return output
def parse(lines: Iterable[str]) -> Directory:
root = None
cwd = None
for line in map(lambda x: x.strip(), lines):
if line.startswith("$ "): # command
if line == "$ cd /":
root = Directory()
cwd = root
elif line == "$ cd ..":
cwd = cwd.parent
elif line.startswith("$ cd"):
cwd = cwd.dirs[line.split(" ")[2]]
elif line.startswith("$ ls"):
pass
elif line.startswith("dir "): # dir
name = line.split(' ')[1]
cwd.dirs[name] = Directory(cwd)
else: # file
size, name = line.split(' ')
cwd.files[name] = int(size)
return root
def solve(lines: Iterable[str]) -> int:
root = parse(lines)
output = 0
for d in root.walk():
size = d.get_size()
if size <= 100000:
output += size
return output
def solveb(lines: Iterable[str]) -> int:
TOTAL = 70000000
GOAL = 30000000
root = parse(lines)
current = root.get_size()
free = TOTAL - current
to_free = GOAL - free
print(f"Current: {current}")
print(f"To free: {to_free}")
candidates = [d for d in root.walk() if d.get_size() >= to_free]
return min(map(lambda x: x.get_size(), candidates))
if __name__ == "__main__":
parse(fileinput.input()).print_tree()
print(solve(fileinput.input()))
print(solveb(fileinput.input()))

6
08/example Normal file
View File

@ -0,0 +1,6 @@
30373
25512
65332
33549
35390

113
08/trees.py Normal file
View File

@ -0,0 +1,113 @@
import fileinput
def get_row(m, idx):
return m[idx]
def get_col(m, idx):
return list(map(lambda x: x[idx], m))
class Forest:
def __init__(self, width, height):
self.visible = []
self.heightmap = []
self.score = []
self.width = width
for _ in range(height):
self.visible.append([False] * width)
self.heightmap.append([0] * width)
self.score.append([0] * width)
def print(self):
print("Heightmap:")
for r in self.heightmap:
print(''.join(map(lambda x: str(x), r)))
print("Visibility:")
for r in self.visible:
print(''.join(map(lambda x: "X" if x else "O", r)))
def solve_visibility(self):
# TOP-DOWN
limit = [-1] * self.width
for rowidx in range(self.width):
for colidx in range(self.width):
if limit[colidx] < self.heightmap[rowidx][colidx]:
self.visible[rowidx][colidx] = True
limit[colidx] = self.heightmap[rowidx][colidx]
# BOT-UP
limit = [-1] * self.width
for rowidx in range(self.width):
for colidx in range(self.width):
if limit[colidx] < self.heightmap[-rowidx-1][colidx]:
self.visible[-rowidx-1][colidx] = True
limit[colidx] = self.heightmap[-rowidx-1][colidx]
# LEFT-RIGHT
limit = [-1] * self.width
for colidx in range(self.width):
for rowidx in range(self.width):
if limit[rowidx] < self.heightmap[rowidx][colidx]:
self.visible[rowidx][colidx] = True
limit[rowidx] = self.heightmap[rowidx][colidx]
# RIGHT-LEFT
limit = [-1] * self.width
for colidx in range(self.width):
for rowidx in range(self.width):
if limit[rowidx] < self.heightmap[rowidx][-colidx-1]:
self.visible[rowidx][-colidx-1] = True
limit[rowidx] = self.heightmap[rowidx][-colidx-1]
def solve_score(self):
for rowidx in range(self.width):
for colidx in range(self.width):
current = self.heightmap[rowidx][colidx]
lscore = 0
rscore = 0
uscore = 0
dscore = 0
for idx in range(colidx): # left
lscore += 1
if self.heightmap[rowidx][colidx-idx-1] >= current:
break
for idx in range(self.width - colidx - 1): # right
rscore += 1
if self.heightmap[rowidx][colidx+idx+1] >= current:
break
for idx in range(rowidx): # up
uscore += 1
if self.heightmap[rowidx-idx-1][colidx] >= current:
break
for idx in range(self.width - rowidx - 1): # down
dscore += 1
if self.heightmap[rowidx+idx+1][colidx] >= current:
break
self.score[rowidx][colidx] = lscore*rscore*uscore*dscore
@classmethod
def parse(cls, lines):
output = None
idx = 0
for line in map(lambda x: x.strip(), lines):
if line != "":
if output is None:
output = cls(len(line), len(line))
output.heightmap[idx] = list(map(lambda x: int(x), list(line)))
idx += 1
return output
def visible_count(self):
output = 0
for r in self.visible:
output += sum(r)
return output
if __name__ == "__main__":
forest = Forest.parse(fileinput.input())
forest.solve_visibility()
forest.solve_score()
forest.print()
print(f"Visible: {forest.visible_count()}")
print(f"Score: {max([max(row) for row in forest.score])}")