2022 Day 7 Complete!
This commit is contained in:
parent
235801201f
commit
e7892906d6
1091
2022/day07/input
Normal file
1091
2022/day07/input
Normal file
File diff suppressed because it is too large
Load Diff
212
2022/day07/main.go
Normal file
212
2022/day07/main.go
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
inp := h.StdinToStringSlice()
|
||||||
|
part1(inp)
|
||||||
|
fmt.Println("")
|
||||||
|
part2(inp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildFileSystem(inp []string) *dir {
|
||||||
|
root := NewDir(nil, []string{}, "/")
|
||||||
|
cwd := root
|
||||||
|
for i := range inp {
|
||||||
|
if i == 0 {
|
||||||
|
// We've already done this
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pts := strings.Fields(inp[i])
|
||||||
|
switch pts[0] {
|
||||||
|
case "$":
|
||||||
|
if pts[1] == "cd" {
|
||||||
|
if pts[2] == ".." {
|
||||||
|
cwd = cwd.Parent()
|
||||||
|
} else {
|
||||||
|
ch, err := cwd.ChangeDir(pts[2])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to change directories: %s/%s, %s", strings.Join(cwd.Path(), "/"), pts[2], err.Error())
|
||||||
|
}
|
||||||
|
cwd = ch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "dir":
|
||||||
|
cwd.AddDir(pts[1])
|
||||||
|
default:
|
||||||
|
cwd.AddFile(pts[1], h.Atoi(pts[0]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return root
|
||||||
|
}
|
||||||
|
|
||||||
|
func part1(inp []string) {
|
||||||
|
fmt.Println("# Part 1")
|
||||||
|
root := buildFileSystem(inp)
|
||||||
|
smallDirs := root.FindDirectoriesMaxSize(100000)
|
||||||
|
var sum int
|
||||||
|
for i := range smallDirs {
|
||||||
|
sum += smallDirs[i].Size()
|
||||||
|
}
|
||||||
|
fmt.Printf("Naive Size of Small Dirs: %d\n", sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
func part2(inp []string) {
|
||||||
|
fmt.Println("# Part 2")
|
||||||
|
root := buildFileSystem(inp)
|
||||||
|
total := 70000000
|
||||||
|
required := 30000000
|
||||||
|
used := root.Size()
|
||||||
|
needed := required - (total - used)
|
||||||
|
dir := root.FindSmallestDirectoryAtLeast(needed)
|
||||||
|
if dir == nil {
|
||||||
|
log.Fatal("No suitable directories found")
|
||||||
|
}
|
||||||
|
fmt.Printf("Disk Space %d / %d. Need %d more for update.\n", (total - used), total, needed)
|
||||||
|
fmt.Println("Auto-deleting smallest directory that will permit update... Don't panic.")
|
||||||
|
fmt.Printf("Freed space by deleting %s: %d\n", dir.FullPath(), dir.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TpFile = iota
|
||||||
|
TpDir
|
||||||
|
)
|
||||||
|
|
||||||
|
type node interface {
|
||||||
|
Parent() *dir
|
||||||
|
Path() []string
|
||||||
|
Name() string
|
||||||
|
Type() int
|
||||||
|
Size() int
|
||||||
|
FullPath() []string
|
||||||
|
Print(depth int)
|
||||||
|
}
|
||||||
|
|
||||||
|
type file struct {
|
||||||
|
parent *dir
|
||||||
|
path []string
|
||||||
|
name string
|
||||||
|
size int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFile(parent *dir, path []string, nm string, size int) *file {
|
||||||
|
return &file{
|
||||||
|
parent: parent,
|
||||||
|
path: path,
|
||||||
|
name: nm,
|
||||||
|
size: size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (f file) Parent() *dir { return f.parent }
|
||||||
|
func (f file) Path() []string { return f.path }
|
||||||
|
func (f file) Name() string { return f.name }
|
||||||
|
func (f file) Type() int { return TpFile }
|
||||||
|
func (f file) Size() int { return f.size }
|
||||||
|
func (f file) FullPath() []string { return append(f.path, f.name) }
|
||||||
|
func (f file) Print(depth int) {
|
||||||
|
fmt.Printf("%s- %s (file, size=%d)\n", strings.Repeat(" ", depth), f.Name(), f.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
type dir struct {
|
||||||
|
parent *dir
|
||||||
|
path []string
|
||||||
|
name string
|
||||||
|
contents map[string]node
|
||||||
|
contentsList []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDir(parent *dir, path []string, name string) *dir {
|
||||||
|
return &dir{
|
||||||
|
parent: parent,
|
||||||
|
path: path,
|
||||||
|
name: name,
|
||||||
|
contents: make(map[string]node),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (d dir) Parent() *dir { return d.parent }
|
||||||
|
func (d dir) Path() []string { return d.path }
|
||||||
|
func (d dir) Name() string { return d.name }
|
||||||
|
func (d dir) Type() int { return TpDir }
|
||||||
|
func (d dir) Size() int {
|
||||||
|
var size int
|
||||||
|
for i := range d.contents {
|
||||||
|
size += d.contents[i].Size()
|
||||||
|
}
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
func (d dir) FullPath() []string { return append(d.path, d.name) }
|
||||||
|
func (d *dir) ChangeDir(to string) (*dir, error) {
|
||||||
|
if v, ok := d.contents[to]; !ok {
|
||||||
|
return nil, errors.New("Directory not found")
|
||||||
|
} else {
|
||||||
|
switch d := v.(type) {
|
||||||
|
case *dir:
|
||||||
|
return d, nil
|
||||||
|
default:
|
||||||
|
return nil, errors.New("Not a directory")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (d *dir) AddFile(nm string, size int) {
|
||||||
|
d.contents[nm] = NewFile(d, d.FullPath(), nm, size)
|
||||||
|
d.contentsList = append(d.contentsList, nm)
|
||||||
|
sort.Strings(d.contentsList)
|
||||||
|
}
|
||||||
|
func (d *dir) AddDir(nm string) {
|
||||||
|
d.contents[nm] = NewDir(d, d.FullPath(), nm)
|
||||||
|
d.contentsList = append(d.contentsList, nm)
|
||||||
|
sort.Strings(d.contentsList)
|
||||||
|
}
|
||||||
|
func (d dir) Print(depth int) {
|
||||||
|
fmt.Printf("%s- %s (dir)\n", strings.Repeat(" ", depth), d.Name())
|
||||||
|
for _, nm := range d.contentsList {
|
||||||
|
n, ok := d.contents[nm]
|
||||||
|
if !ok {
|
||||||
|
log.Fatalf("Error printing directory %s: %s not found.", d.FullPath(), nm)
|
||||||
|
}
|
||||||
|
n.Print(depth + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (d *dir) FreeSpace(driveSize int) int { return driveSize - d.Size() }
|
||||||
|
|
||||||
|
func (d *dir) FindDirectoriesMaxSize(size int) []*dir {
|
||||||
|
var ret []*dir
|
||||||
|
for _, node := range d.contents {
|
||||||
|
switch child := node.(type) {
|
||||||
|
case *dir:
|
||||||
|
if child.Size() <= size {
|
||||||
|
ret = append(ret, child)
|
||||||
|
}
|
||||||
|
ret = append(ret, child.FindDirectoriesMaxSize(size)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
func (d *dir) FindSmallestDirectoryAtLeast(needed int) *dir {
|
||||||
|
var ret *dir
|
||||||
|
retSize := d.Size()
|
||||||
|
for _, node := range d.contents {
|
||||||
|
switch child := node.(type) {
|
||||||
|
case *dir:
|
||||||
|
sz := child.Size()
|
||||||
|
if sz >= needed && sz < retSize {
|
||||||
|
ret = child
|
||||||
|
retSize = sz
|
||||||
|
rec := child.FindSmallestDirectoryAtLeast(needed)
|
||||||
|
if rec != nil {
|
||||||
|
ret = rec
|
||||||
|
retSize = rec.Size()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
151
2022/day07/problem
Normal file
151
2022/day07/problem
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
Advent of Code
|
||||||
|
br0xen (AoC++) 14*
|
||||||
|
|
||||||
|
--- 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?
|
||||||
|
|
||||||
|
Your puzzle answer was 1642503.
|
||||||
|
|
||||||
|
--- 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?
|
||||||
|
|
||||||
|
Your puzzle answer was 6999588.
|
||||||
|
|
||||||
|
Both parts of this puzzle are complete! They provide two gold stars: **
|
||||||
|
|
||||||
|
References
|
||||||
|
|
||||||
|
Visible links
|
||||||
|
. https://adventofcode.com/
|
||||||
|
. https://adventofcode.com/2022/about
|
||||||
|
. https://adventofcode.com/2022/events
|
||||||
|
. https://adventofcode.com/2022/settings
|
||||||
|
. https://adventofcode.com/2022/auth/logout
|
||||||
|
. Advent of Code Supporter
|
||||||
|
https://adventofcode.com/2022/support
|
||||||
|
. https://adventofcode.com/2022
|
||||||
|
. https://adventofcode.com/2022
|
||||||
|
. https://adventofcode.com/2022/support
|
||||||
|
. https://adventofcode.com/2022/sponsors
|
||||||
|
. https://adventofcode.com/2022/leaderboard
|
||||||
|
. https://adventofcode.com/2022/stats
|
||||||
|
. https://adventofcode.com/2022/sponsors
|
||||||
|
. https://adventofcode.com/2022
|
||||||
|
. https://adventofcode.com/2022/day/7/input
|
23
2022/day07/testinput
Normal file
23
2022/day07/testinput
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
|
Loading…
Reference in New Issue
Block a user