2022 Day 07
This commit is contained in:
parent
8879b7c1c8
commit
64a31b5a05
109
2022/07/README.md
Normal file
109
2022/07/README.md
Normal file
@ -0,0 +1,109 @@
|
||||
# 2022 Day 07: No Space Left On Device
|
||||
Copyright (c) Eric Wastl
|
||||
#### [Direct Link](https://adventofcode.com/2022/day/7)
|
||||
|
||||
## Part 1
|
||||
|
||||
You can hear birds chirping and raindrops hitting leaves as the expedition proceeds. Occasionally, you can even hear much louder sounds in the distance; how big do the animals get out here, anyway?
|
||||
|
||||
The device the Elves gave you has problems with more than just its communication system. You try to run a system update:
|
||||
|
||||
```
|
||||
$ system-update --please --pretty-please-with-sugar-on-top
|
||||
Error: No space left on device
|
||||
```
|
||||
|
||||
Perhaps you can delete some files to make space for the update?
|
||||
|
||||
You browse around the filesystem to assess the situation and save the resulting terminal output (your puzzle input). For example:
|
||||
|
||||
```
|
||||
$ 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
|
||||
```
|
||||
|
||||
The filesystem consists of a tree of files (plain data) and directories (which can contain other directories or files). The outermost directory is called `/`. You can navigate around the filesystem, moving into or out of directories and listing the contents of the directory you're currently in.
|
||||
|
||||
Within the terminal output, lines that begin with `$` are **commands you executed**, very much like some modern computers:
|
||||
|
||||
- `cd` means **change directory**. This changes which directory is the current directory, but the specific result depends on the argument:
|
||||
- `cd x` moves **in** one level: it looks in the current directory for the directory named `x` and makes it the current directory.
|
||||
- `cd ..` moves **out** one level: it finds the directory that contains the current directory, then makes that directory the current directory.
|
||||
- `cd /` switches the current directory to the outermost directory, `/`.
|
||||
- `ls` means **list**. It prints out all of the files and directories immediately contained by the current directory:
|
||||
- `123 abc` means that the current directory contains a file named `abc` with size `123`.
|
||||
- `dir xyz` means that the current directory contains a directory named `xyz`.
|
||||
|
||||
Given the commands and output in the example above, you can determine that the filesystem looks visually like this:
|
||||
|
||||
```
|
||||
- / (dir)
|
||||
- a (dir)
|
||||
- e (dir)
|
||||
- i (file, size=584)
|
||||
- f (file, size=29116)
|
||||
- g (file, size=2557)
|
||||
- h.lst (file, size=62596)
|
||||
- b.txt (file, size=14848514)
|
||||
- c.dat (file, size=8504156)
|
||||
- d (dir)
|
||||
- j (file, size=4060174)
|
||||
- d.log (file, size=8033020)
|
||||
- d.ext (file, size=5626152)
|
||||
- k (file, size=7214296)
|
||||
```
|
||||
|
||||
Here, there are four directories: `/` (the outermost directory), `a` and `d` (which are in `/`), and `e` (which is in `a`). These directories also contain files of various sizes.
|
||||
|
||||
Since the disk is full, your first step should probably be to find directories that are good candidates for deletion. To do this, you need to determine the **total size** of each directory. The total size of a directory is the sum of the sizes of the files it contains, directly or indirectly. (Directories themselves do not count as having any intrinsic size.)
|
||||
|
||||
The total sizes of the directories above can be found as follows:
|
||||
|
||||
- The total size of directory `e` is **584** because it contains a single file `i` of size 584 and no other directories.
|
||||
- The directory `a` has total size **94853** because it contains files `f` (size 29116), `g` (size 2557), and `h.lst` (size 62596), plus file `i` indirectly (`a` contains `e` which contains `i`).
|
||||
- Directory `d` has total size **24933642**.
|
||||
- As the outermost directory, `/` contains every file. Its total size is **48381165**, the sum of the size of every file.
|
||||
|
||||
To begin, find all of the directories with a total size of **at most 100000**, then calculate the sum of their total sizes. In the example above, these directories are `a` and `e`; the sum of their total sizes is **`95437`** (94853 + 584). (As in this example, this process can count files more than once!)
|
||||
|
||||
Find all of the directories with a total size of at most 100000. **What is the sum of the total sizes of those directories?**
|
||||
|
||||
## Part 2
|
||||
|
||||
Now, you're ready to choose a directory to delete.
|
||||
|
||||
The total disk space available to the filesystem is **`70000000`**. To run the update, you need unused space of at least **`30000000`**. You need to find a directory you can delete that will **free up enough space** to run the update.
|
||||
|
||||
In the example above, the total size of the outermost directory (and thus the total amount of used space) is `48381165`; this means that the size of the **unused** space must currently be `21618835`, which isn't quite the `30000000` required by the update. Therefore, the update still requires a directory with total size of at least `8381165` to be deleted before it can run.
|
||||
|
||||
To achieve this, you have the following options:
|
||||
|
||||
- Delete directory `e`, which would increase unused space by `584`.
|
||||
- Delete directory `a`, which would increase unused space by `94853`.
|
||||
- Delete directory `d`, which would increase unused space by `24933642`.
|
||||
- Delete directory `/`, which would increase unused space by `48381165`.
|
||||
|
||||
Directories `e` and `a` are both too small; deleting them would not free up enough space. However, directories `d` and `/` are both big enough! Between these, choose the **smallest**: d, increasing unused space by **`24933642`**.
|
||||
|
||||
Find the smallest directory that, if deleted, would free up enough space on the filesystem to run the update. **What is the total size of that directory?**
|
71
2022/07/code.py
Normal file
71
2022/07/code.py
Normal file
@ -0,0 +1,71 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2022 Akumatic
|
||||
#
|
||||
# https://adventofcode.com/2022/day/7
|
||||
|
||||
class Node:
|
||||
def __init__(self, name, parent = None, size = None) -> None:
|
||||
self.name = name
|
||||
self.parent = parent
|
||||
if parent:
|
||||
parent.children[name] = self
|
||||
self.size = size
|
||||
self.children = dict()
|
||||
|
||||
def get_size(self) -> int:
|
||||
if self.size:
|
||||
return self.size
|
||||
return sum(self.children[child].get_size() for child in self.children)
|
||||
|
||||
def build_dir_tree(terminal_output: list) -> Node:
|
||||
root = Node("/")
|
||||
cur_dir = root
|
||||
for line in terminal_output:
|
||||
if line.startswith("$ ls"):
|
||||
continue # 'else' will deal with output
|
||||
elif line.startswith("$ cd"):
|
||||
dir = line[5:]
|
||||
match dir:
|
||||
case "/":
|
||||
cur_dir = root
|
||||
case "..":
|
||||
cur_dir = cur_dir.parent
|
||||
case _:
|
||||
cur_dir = cur_dir.children[dir]
|
||||
else: # line not starting with "$" => output of ls
|
||||
type, name = line.split(" ")
|
||||
match type:
|
||||
case "dir":
|
||||
new_node = Node(name=name, parent=cur_dir)
|
||||
case _:
|
||||
new_node = Node(name=name, parent=cur_dir, size=int(type))
|
||||
return root
|
||||
|
||||
def read_file(filename: str = "input.txt") -> Node:
|
||||
with open(f"{__file__.rstrip('code.py')}{filename}", "r") as f:
|
||||
lines = [line.strip() for line in f.readlines()]
|
||||
return build_dir_tree(lines)
|
||||
|
||||
def get_possible_folder_sizes(node: Node, target_size: int, size_up_to: bool, sizes: list) -> None:
|
||||
if len(node.children) == 0:
|
||||
return
|
||||
size = node.get_size()
|
||||
if not size_up_to and size >= target_size or size_up_to and size <= target_size:
|
||||
sizes.append(size)
|
||||
for child in node.children:
|
||||
get_possible_folder_sizes(node.children[child], target_size, size_up_to, sizes)
|
||||
|
||||
def part1(node: Node) -> int:
|
||||
sizes = []
|
||||
get_possible_folder_sizes(node, 100000, True, sizes)
|
||||
return sum(sizes)
|
||||
|
||||
def part2(node: Node) -> int:
|
||||
sizes = []
|
||||
get_possible_folder_sizes(node, node.get_size() - 40000000, False, sizes)
|
||||
return min(sizes)
|
||||
|
||||
if __name__ == "__main__":
|
||||
vals = read_file()
|
||||
print(f"Part 1: {part1(vals)}")
|
||||
print(f"Part 2: {part2(vals)}")
|
1105
2022/07/input.txt
Normal file
1105
2022/07/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
2
2022/07/solution.txt
Normal file
2
2022/07/solution.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Part 1: 1348005
|
||||
Part 2: 12785886
|
19
2022/07/test_code.py
Normal file
19
2022/07/test_code.py
Normal file
@ -0,0 +1,19 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright (c) 2022 Akumatic
|
||||
|
||||
from code import read_file, part1, part2
|
||||
|
||||
def test():
|
||||
root = read_file("test_input.txt")
|
||||
assert root.get_size() == 48381165
|
||||
assert root.children["d"].get_size() == 24933642
|
||||
assert root.children["a"].get_size() == 94853
|
||||
assert root.children["a"].children["e"].get_size() == 584
|
||||
print("Passed Tree Bulding")
|
||||
assert part1(root) == 95437
|
||||
print("Passed Part 1")
|
||||
assert part2(root) == 24933642
|
||||
print("Passed Part 2")
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
23
2022/07/test_input.txt
Normal file
23
2022/07/test_input.txt
Normal 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
|
@ -21,7 +21,7 @@ Collect stars by solving puzzles. Two puzzles will be made available on each day
|
||||
| 04 | :white_check_mark: | :white_check_mark: | [Solution](04/code.py) | [Day 04](https://adventofcode.com/2022/day/4) |
|
||||
| 05 | :white_check_mark: | :white_check_mark: | [Solution](05/code.py) | [Day 05](https://adventofcode.com/2022/day/5) |
|
||||
| 06 | :white_check_mark: | :white_check_mark: | [Solution](06/code.py) | [Day 06](https://adventofcode.com/2022/day/6) |
|
||||
| 07 | | | | [Day 07](https://adventofcode.com/2022/day/7) |
|
||||
| 07 | :white_check_mark: | :white_check_mark: | [Solution](07/code.py) | [Day 07](https://adventofcode.com/2022/day/7) |
|
||||
| 08 | | | | [Day 08](https://adventofcode.com/2022/day/8) |
|
||||
| 09 | | | | [Day 09](https://adventofcode.com/2022/day/9) |
|
||||
| 10 | | | | [Day 10](https://adventofcode.com/2022/day/10) |
|
||||
|
Loading…
x
Reference in New Issue
Block a user