Files
adventofcode/2022/go/day07/day07.go
2023-11-16 10:48:53 +00:00

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
}
}