112 lines
2.2 KiB
Go
112 lines
2.2 KiB
Go
package day07
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"adventofcode2022/utils"
|
|
)
|
|
|
|
type dir struct {
|
|
name string
|
|
files map[string]int
|
|
subdir map[string]*dir
|
|
parent *dir
|
|
size int
|
|
}
|
|
|
|
func Part1(input string) int {
|
|
root := dir{name: "/", files: map[string]int{}, subdir: map[string]*dir{}, parent: nil}
|
|
root.parse(input)
|
|
sum := 0
|
|
find_dirs_part1(&root, 100000, &sum)
|
|
return sum
|
|
}
|
|
|
|
func Part2(input string) int {
|
|
root := dir{name: "/", files: map[string]int{}, subdir: map[string]*dir{}, parent: nil}
|
|
root.parse(input)
|
|
unused := 70000000 - root.size
|
|
need := 30000000 - unused
|
|
dir_size := 0
|
|
find_dirs_part2(&root, need, &dir_size)
|
|
return dir_size
|
|
}
|
|
|
|
func find_dirs_part1(d *dir, size int, sum *int) {
|
|
// recurse into subdir
|
|
for _, subdir := range d.subdir {
|
|
if (subdir.size) <= size {
|
|
*sum += subdir.size
|
|
}
|
|
find_dirs_part1(subdir, size, sum)
|
|
}
|
|
}
|
|
|
|
func find_dirs_part2(d *dir, size int, sum *int) {
|
|
// recurse into subdir
|
|
for _, subdir := range d.subdir {
|
|
if (subdir.size) >= size && (*sum == 0 || (subdir.size) < *sum) {
|
|
*sum = subdir.size
|
|
}
|
|
find_dirs_part2(subdir, size, sum)
|
|
}
|
|
}
|
|
|
|
func (root *dir) parse(input string) {
|
|
c := root
|
|
|
|
for _, line := range strings.Split(input, "\n") {
|
|
pieces := strings.Split(line, " ")
|
|
if pieces[0] == "$" {
|
|
if pieces[1] == "cd" {
|
|
if pieces[2] == ".." {
|
|
c = c.parent
|
|
} else if pieces[2] == "/" {
|
|
c = root
|
|
} else {
|
|
c = c.addDirectoryIfMissing(pieces[2])
|
|
}
|
|
} else if pieces[1] == "ls" {
|
|
// no need to do anything
|
|
} else {
|
|
panic("oops")
|
|
}
|
|
} else if pieces[0] == "dir" {
|
|
c.addDirectoryIfMissing(pieces[1])
|
|
} else {
|
|
c.addFileIfMissing(pieces[1], utils.MustAtoi(pieces[0]))
|
|
}
|
|
}
|
|
}
|
|
|
|
func (d *dir) addDirectoryIfMissing(name string) *dir {
|
|
t, ok := d.subdir[name]
|
|
if !ok {
|
|
t = &dir{
|
|
name: name,
|
|
files: map[string]int{},
|
|
subdir: map[string]*dir{},
|
|
parent: d,
|
|
}
|
|
d.subdir[name] = t
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (d *dir) addFileIfMissing(name string, size int) {
|
|
t, ok := d.files[name]
|
|
if ok {
|
|
if t != size {
|
|
panic("oops")
|
|
}
|
|
} else {
|
|
current := d
|
|
d.files[name] = size
|
|
|
|
for current.name != "/" {
|
|
current.size += size
|
|
current = current.parent
|
|
}
|
|
current.size += size
|
|
}
|
|
} |