Compare commits

...

3 Commits

Author SHA1 Message Date
c9d83911ac Removed toy_input files 2024-12-01 20:03:39 +01:00
6cbcfec987 toy_input are now ignored 2024-12-01 19:57:32 +01:00
8ed21157a0 Days 7 and 8 completed 2024-12-01 19:53:34 +01:00
10 changed files with 202 additions and 21 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ cookies.txt
**/input
__pycache__
.venv
toy_input

View File

@ -1,6 +0,0 @@
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw

View File

@ -1,6 +0,0 @@
2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8

View File

@ -1,9 +0,0 @@
[D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2

71
day7/common.py Normal file
View File

@ -0,0 +1,71 @@
from __future__ import annotations
import re
from dataclasses import dataclass
@dataclass
class File:
name: str
size: int
def __equals__(self, other):
return self.name == other.name and self.size == other.size
@dataclass
class Folder:
name: str
parent: Folder | None
children: list[Folder | File]
def __equals__(self, other):
return self.name == other.name and self.parent == other.parent
@property
def full_name(self):
if self.parent is None:
return "/"
else:
return self.parent.full_name + f"/{self.name}"
@property
def size(self):
return sum(map(lambda x: x.size, self.children))
def __lt__(self, other):
return self.size < other.size
def pretty_print(folder: Folder, depth: int = 0) -> None:
print("".join([" " for i in range(depth + 1)]), end="- ")
print(f"{folder.name} (dir)")
for object in folder.children:
if type(object) is Folder:
pretty_print(object, depth + 1)
else:
print("".join([" " for i in range(depth + 2)]), end="- ")
print(f"{object.name} (file, size={object.size})")
def parse(filename: str) -> Folder:
filesystem = Folder(name="/", parent=None, children=[])
with open(filename) as f:
f.readline()
current = filesystem
while line := f.readline()[:-1]:
if line[0] == "$":
if match := re.match(r"\$ cd (.+)", line):
folder_name = match.group(1)
if folder_name != "..":
current = filter(lambda x: x.name == folder_name, current.children).__next__()
else:
current = current.parent
else:
if match := re.match(r"(\d+) ((?:\w|.)+)", line):
fichier = File(name=match.group(2), size=int(match.group(1)))
current.children.append(fichier)
elif match := re.match(r"dir (\w+)", line):
folder = Folder(name=match.group(1), parent=current, children=[])
current.children.append(folder)
return filesystem

18
day7/part1.py Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env python
from common import Folder, parse
def solve(folder: Folder) -> int:
childrens_sizes = sum(map(lambda x: solve(x), filter(lambda y: type(y) is Folder, folder.children)))
if folder.size >= 100000:
return childrens_sizes
else:
return folder.size + childrens_sizes
def main():
print(solve(parse("input")))
if __name__ == "__main__":
main()

25
day7/part2.py Executable file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env python
from common import Folder, parse
def folders_big_enough(folder: Folder, threshold: int) -> list[Folder]:
if folder.size < threshold:
return []
else:
folder_list = [folder]
for child in filter(lambda x: type(x) is Folder, folder.children):
folder_list += folders_big_enough(child, threshold)
return folder_list
def solve(folder: Folder) -> int:
threshold = 30000000 - (70000000 - folder.size)
return min(sorted(folders_big_enough(folder, threshold))).size
def main():
print(solve(parse("input")))
if __name__ == "__main__":
main()

3
day8/common.py Normal file
View File

@ -0,0 +1,3 @@
def parse(filename: str) -> list[list[int]]:
with open(filename) as f:
return [[int(i) for i in line.strip("\n")] for line in f.readlines()]

27
day8/part1.py Executable file
View File

@ -0,0 +1,27 @@
#!/usr/bin/env python
from common import parse
def is_visible(forest: list[list[int]], x: int, y: int) -> bool:
height = forest[y][x]
west = forest[y][0:x]
east = forest[y][x + 1 :]
north = [forest[i][x] for i in range(y)]
south = [forest[i][x] for i in range(y + 1, len(forest))]
return any(map(lambda x: x == [] or max(x) < height, (west, east, north, south)))
def solve(input: list[list[int]]) -> int:
count = 0
for y, line in enumerate(input):
for x, tree in enumerate(line):
count += 1 if is_visible(input, x, y) else 0
return count
def main():
print(solve(parse("input")))
if __name__ == "__main__":
main()

57
day8/part2.py Executable file
View File

@ -0,0 +1,57 @@
#!/usr/bin/env python
from common import parse
def scenic_score(forest: list[list[int]], x: int, y: int) -> int:
height = forest[y][x]
sw = se = sn = ss = 0
west = reversed(forest[y][0:x])
for w in west:
if w < height:
sw += 1
continue
elif w == height:
sw += 1
break
east = forest[y][x + 1 :]
for e in east:
if e < height:
se += 1
continue
elif e == height:
se += 1
break
north = reversed([forest[i][x] for i in range(y)])
for n in north:
if n < height:
sn += 1
continue
elif n == height:
sn += 1
break
south = [forest[i][x] for i in range(y + 1, len(forest))]
for s in south:
if s < height:
ss += 1
continue
elif s == height:
ss += 1
break
return sw * se * sn * ss
def solve(input: list[list[int]]) -> int:
maxi = 0
for y, line in enumerate(input):
for x, tree in enumerate(input):
maxi = max(maxi, scenic_score(input, x, y))
return maxi
def main():
print(solve(parse("input")))
if __name__ == "__main__":
main()