Added AOC 2022 day 07
This commit is contained in:
parent
0f7ba091be
commit
bde2750e23
@ -1,4 +1,19 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
|
<component name="MessDetectorOptionsConfiguration">
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PHPCSFixerOptionsConfiguration">
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PHPCodeSnifferOptionsConfiguration">
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
<component name="PhpProjectSharedConfiguration" php_language_level="8.1" />
|
<component name="PhpProjectSharedConfiguration" php_language_level="8.1" />
|
||||||
|
<component name="PhpStanOptionsConfiguration">
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
|
<component name="PsalmOptionsConfiguration">
|
||||||
|
<option name="transferred" value="true" />
|
||||||
|
</component>
|
||||||
</project>
|
</project>
|
99
www/statics/aoc/2022/07_challenge.txt
Normal file
99
www/statics/aoc/2022/07_challenge.txt
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
--- Day 7: No Space Left On Device ---
|
||||||
|
|
||||||
|
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 Two ---
|
||||||
|
|
||||||
|
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?
|
1045
www/statics/aoc/2022/07_input.txt
Normal file
1045
www/statics/aoc/2022/07_input.txt
Normal file
File diff suppressed because it is too large
Load Diff
85
www/statics/aoc/2022/07_solution-1.nim
Normal file
85
www/statics/aoc/2022/07_solution-1.nim
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
import std/strutils
|
||||||
|
import std/sequtils
|
||||||
|
import std/re
|
||||||
|
|
||||||
|
type
|
||||||
|
DirEntry = ref object
|
||||||
|
parent: DirEntry
|
||||||
|
name: string
|
||||||
|
dirs: seq[DirEntry]
|
||||||
|
files: seq[FileEntry]
|
||||||
|
FileEntry = ref object
|
||||||
|
name: string
|
||||||
|
size: int
|
||||||
|
|
||||||
|
|
||||||
|
proc mkcd(a: DirEntry, name: string): DirEntry =
|
||||||
|
for i in 0.. (a.dirs.len() - 1):
|
||||||
|
if a.dirs[i].name == name:
|
||||||
|
return a.dirs[i]
|
||||||
|
a.dirs.add(DirEntry(parent: a, name: name, dirs: @[], files: @[]))
|
||||||
|
return a.dirs[len(a.dirs)-1]
|
||||||
|
|
||||||
|
proc recursive_size(a: DirEntry): int =
|
||||||
|
var sz = 0
|
||||||
|
for d in a.dirs:
|
||||||
|
sz += d.recursive_size()
|
||||||
|
for f in a.files:
|
||||||
|
sz += f.size
|
||||||
|
return sz
|
||||||
|
|
||||||
|
proc sum_size_sub(a: DirEntry, max: int): int =
|
||||||
|
let sz = a.recursive_size()
|
||||||
|
var res = 0
|
||||||
|
if sz < max:
|
||||||
|
res += sz
|
||||||
|
for d in a.dirs:
|
||||||
|
res += d.sum_size_sub(max)
|
||||||
|
return res
|
||||||
|
|
||||||
|
proc print(a: DirEntry, indent: int) =
|
||||||
|
echo ' '.repeat(indent*2), a.name, " (sz = ", a.recursive_size(), " )"
|
||||||
|
echo ' '.repeat(indent*2), "{"
|
||||||
|
for f in a.files:
|
||||||
|
echo ' '.repeat(indent*2+2), "[F] ", f.name, " (sz = ", f.size, " )"
|
||||||
|
for d in a.dirs:
|
||||||
|
d.print(indent+1)
|
||||||
|
echo ' '.repeat(indent*2), "}"
|
||||||
|
|
||||||
|
|
||||||
|
proc run07_1(): string =
|
||||||
|
const input = staticRead"../input/day07.txt"
|
||||||
|
|
||||||
|
let lines = splitLines(input).filter(proc(p: string): bool = p != "")
|
||||||
|
|
||||||
|
var root = DirEntry(parent: nil, name: "/", dirs: @[], files: @[])
|
||||||
|
|
||||||
|
var curr = root
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
if line == "$ cd ..":
|
||||||
|
curr = curr.parent
|
||||||
|
elif line.startsWith("$ cd "):
|
||||||
|
curr = curr.mkcd(line.substr(5))
|
||||||
|
elif line == "$ ls":
|
||||||
|
continue
|
||||||
|
elif line.startsWith("dir "):
|
||||||
|
discard curr.mkcd(line.substr(4))
|
||||||
|
elif line.match(re"^[0-9].*"):
|
||||||
|
let split = line.split(" ")
|
||||||
|
curr.files.add(FileEntry(name: split[1], size: parseInt(split[0])))
|
||||||
|
else:
|
||||||
|
echo "UNKNOWN LINE: " & line
|
||||||
|
|
||||||
|
|
||||||
|
# echo root.recursive_size()
|
||||||
|
# root.print(0)
|
||||||
|
|
||||||
|
return intToStr(root.sum_size_sub(100000))
|
||||||
|
|
||||||
|
|
||||||
|
when not defined(js):
|
||||||
|
echo run07_1()
|
||||||
|
else:
|
||||||
|
proc js_run07_1(): cstring {.exportc.} =
|
||||||
|
return cstring(run07_1())
|
110
www/statics/aoc/2022/07_solution-2.nim
Normal file
110
www/statics/aoc/2022/07_solution-2.nim
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import std/strutils
|
||||||
|
import std/sequtils
|
||||||
|
import std/algorithm
|
||||||
|
import std/re
|
||||||
|
|
||||||
|
type
|
||||||
|
DirEntry = ref object
|
||||||
|
parent: DirEntry
|
||||||
|
name: string
|
||||||
|
dirs: seq[DirEntry]
|
||||||
|
files: seq[FileEntry]
|
||||||
|
FileEntry = ref object
|
||||||
|
name: string
|
||||||
|
size: int
|
||||||
|
|
||||||
|
|
||||||
|
proc mkcd(a: DirEntry, name: string): DirEntry =
|
||||||
|
for i in 0.. (a.dirs.len() - 1):
|
||||||
|
if a.dirs[i].name == name:
|
||||||
|
return a.dirs[i]
|
||||||
|
a.dirs.add(DirEntry(parent: a, name: name, dirs: @[], files: @[]))
|
||||||
|
return a.dirs[len(a.dirs)-1]
|
||||||
|
|
||||||
|
proc recursive_size(a: DirEntry): int =
|
||||||
|
var sz = 0
|
||||||
|
for d in a.dirs:
|
||||||
|
sz += d.recursive_size()
|
||||||
|
for f in a.files:
|
||||||
|
sz += f.size
|
||||||
|
return sz
|
||||||
|
|
||||||
|
proc sum_size_sub(a: DirEntry, max: int): int =
|
||||||
|
let sz = a.recursive_size()
|
||||||
|
var res = 0
|
||||||
|
if sz < max:
|
||||||
|
res += sz
|
||||||
|
for d in a.dirs:
|
||||||
|
res += d.sum_size_sub(max)
|
||||||
|
return res
|
||||||
|
|
||||||
|
proc print(a: DirEntry, indent: int) =
|
||||||
|
echo ' '.repeat(indent*2), a.name, " (sz = ", a.recursive_size(), " )"
|
||||||
|
echo ' '.repeat(indent*2), "{"
|
||||||
|
for f in a.files:
|
||||||
|
echo ' '.repeat(indent*2+2), "[F] ", f.name, " (sz = ", f.size, " )"
|
||||||
|
for d in a.dirs:
|
||||||
|
d.print(indent+1)
|
||||||
|
echo ' '.repeat(indent*2), "}"
|
||||||
|
|
||||||
|
proc collect_dirs(a: DirEntry, coll: var seq[DirEntry]) =
|
||||||
|
coll.add(a)
|
||||||
|
for d in a.dirs:
|
||||||
|
coll.add(d)
|
||||||
|
d.collect_dirs(coll)
|
||||||
|
|
||||||
|
|
||||||
|
proc run07_2(): string =
|
||||||
|
const input = staticRead"../input/day07.txt"
|
||||||
|
|
||||||
|
let lines = splitLines(input).filter(proc(p: string): bool = p != "")
|
||||||
|
|
||||||
|
var root = DirEntry(parent: nil, name: "/", dirs: @[], files: @[])
|
||||||
|
|
||||||
|
var curr = root
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
if line == "$ cd ..":
|
||||||
|
curr = curr.parent
|
||||||
|
elif line.startsWith("$ cd "):
|
||||||
|
curr = curr.mkcd(line.substr(5))
|
||||||
|
elif line == "$ ls":
|
||||||
|
continue
|
||||||
|
elif line.startsWith("dir "):
|
||||||
|
discard curr.mkcd(line.substr(4))
|
||||||
|
elif line.match(re"^[0-9].*"):
|
||||||
|
let split = line.split(" ")
|
||||||
|
curr.files.add(FileEntry(name: split[1], size: parseInt(split[0])))
|
||||||
|
else:
|
||||||
|
echo "UNKNOWN LINE: " & line
|
||||||
|
|
||||||
|
|
||||||
|
# echo root.recursive_size()
|
||||||
|
|
||||||
|
# root.print(0)
|
||||||
|
|
||||||
|
var dirs: seq[DirEntry] = @[]
|
||||||
|
root.collect_dirs(dirs)
|
||||||
|
|
||||||
|
proc scmp(a, b: DirEntry): int =
|
||||||
|
if a.recursive_size() < b.recursive_size(): -1
|
||||||
|
else: 1
|
||||||
|
|
||||||
|
dirs.sort(scmp)
|
||||||
|
|
||||||
|
let min_size = -(70000000 - 30000000 - root.recursive_size())
|
||||||
|
|
||||||
|
# echo min_size
|
||||||
|
|
||||||
|
for d in dirs:
|
||||||
|
if d.recursive_size() > min_size:
|
||||||
|
return intToStr(d.recursive_size())
|
||||||
|
|
||||||
|
return "ERR"
|
||||||
|
|
||||||
|
|
||||||
|
when not defined(js):
|
||||||
|
echo run07_2()
|
||||||
|
else:
|
||||||
|
proc js_run07_2(): cstring {.exportc.} =
|
||||||
|
return cstring(run07_2())
|
@ -113,5 +113,6 @@ return
|
|||||||
['day' => 4, 'parts' => 2, 'title' => 'Camp Cleanup', 'language' => 'nim', 'solutions' => ['550', '931'] ],
|
['day' => 4, 'parts' => 2, 'title' => 'Camp Cleanup', 'language' => 'nim', 'solutions' => ['550', '931'] ],
|
||||||
['day' => 5, 'parts' => 2, 'title' => 'Supply Stacks', 'language' => 'nim', 'solutions' => ['HBTMTBSDC', 'PQTJRSHWS'] ],
|
['day' => 5, 'parts' => 2, 'title' => 'Supply Stacks', 'language' => 'nim', 'solutions' => ['HBTMTBSDC', 'PQTJRSHWS'] ],
|
||||||
['day' => 6, 'parts' => 2, 'title' => 'Tuning Trouble', 'language' => 'nim', 'solutions' => ['1042', '2980'] ],
|
['day' => 6, 'parts' => 2, 'title' => 'Tuning Trouble', 'language' => 'nim', 'solutions' => ['1042', '2980'] ],
|
||||||
|
['day' => 7, 'parts' => 2, 'title' => 'No Space Left On Device', 'language' => 'nim', 'solutions' => ['1243729', '4443914'] ],
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
Loading…
Reference in New Issue
Block a user