🌅
This commit is contained in:
159
solutions/day7/day7.go
Normal file
159
solutions/day7/day7.go
Normal file
@@ -0,0 +1,159 @@
|
||||
package day7
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type FileSystem struct {
|
||||
name string
|
||||
parent *FileSystem
|
||||
subdirectories []*FileSystem
|
||||
files []FileInfo
|
||||
}
|
||||
|
||||
func newFileSystem(name string, parent *FileSystem) *FileSystem {
|
||||
return &FileSystem{name, parent, []*FileSystem{}, []FileInfo{}}
|
||||
}
|
||||
|
||||
func printFileTree(tree *FileSystem, prefix string) {
|
||||
fmt.Println(prefix, "-", tree.name, fmt.Sprintf("(dir size=%d)", totalSize(tree)))
|
||||
|
||||
for _, file := range tree.files {
|
||||
fmt.Println(prefix, " ", "-", file.name, fmt.Sprintf("(file, size=%d)", file.size))
|
||||
}
|
||||
|
||||
for _, dir := range tree.subdirectories {
|
||||
printFileTree(dir, prefix+" ")
|
||||
}
|
||||
}
|
||||
|
||||
func totalSize(tree *FileSystem) int {
|
||||
total := 0
|
||||
|
||||
for _, file := range tree.files {
|
||||
total += file.size
|
||||
}
|
||||
|
||||
for _, dir := range tree.subdirectories {
|
||||
total += totalSize(dir)
|
||||
}
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
func computePart1(tree *FileSystem) int {
|
||||
result := 0
|
||||
|
||||
for _, dir := range tree.subdirectories {
|
||||
result += computePart1(dir)
|
||||
}
|
||||
|
||||
currentSize := totalSize(tree)
|
||||
if currentSize <= 100000 {
|
||||
result += currentSize
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func computePart2(tree *FileSystem, size int) int {
|
||||
result := 70000000
|
||||
|
||||
for _, dir := range tree.subdirectories {
|
||||
subResult := computePart2(dir, size)
|
||||
if subResult < result {
|
||||
result = subResult
|
||||
}
|
||||
}
|
||||
|
||||
currentSize := totalSize(tree)
|
||||
if currentSize > size && currentSize < result {
|
||||
result = currentSize
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
type FileInfo struct {
|
||||
name string
|
||||
size int
|
||||
}
|
||||
|
||||
func parseFileInfo(line string) (result FileInfo, err error) {
|
||||
splits := strings.Split(line, " ")
|
||||
if len(splits) != 2 {
|
||||
err = errors.New("too many values from file info split")
|
||||
return
|
||||
}
|
||||
|
||||
size, err := strconv.Atoi(splits[0])
|
||||
if err != nil {
|
||||
err = errors.New(fmt.Sprintf("could not parse file size: '%s'", splits[0]))
|
||||
return
|
||||
}
|
||||
|
||||
result = FileInfo{splits[1], size}
|
||||
return
|
||||
}
|
||||
|
||||
func Run(filename string) {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
fmt.Println("Error opening file:", err)
|
||||
return
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
|
||||
root := newFileSystem("/", nil)
|
||||
current := root
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
fmt.Println("line", line)
|
||||
if strings.HasPrefix(line, "$ cd /") {
|
||||
current = root
|
||||
} else if strings.HasPrefix(line, "$ cd ..") {
|
||||
current = current.parent
|
||||
} else if strings.HasPrefix(line, "$ cd ") {
|
||||
for _, subdir := range current.subdirectories {
|
||||
if subdir.name == line[5:] {
|
||||
current = subdir
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else if strings.HasPrefix(line, "$ ls") {
|
||||
// don't do anything
|
||||
} else if strings.HasPrefix(line, "dir ") {
|
||||
newTree := newFileSystem(line[4:], current)
|
||||
current.subdirectories = append(current.subdirectories, newTree)
|
||||
} else {
|
||||
fileInfo, err := parseFileInfo(line)
|
||||
if err != nil {
|
||||
fmt.Println("PANIC:", err)
|
||||
return
|
||||
}
|
||||
|
||||
current.files = append((*current).files, fileInfo)
|
||||
}
|
||||
}
|
||||
|
||||
file.Close()
|
||||
|
||||
printFileTree(root, "")
|
||||
fmt.Println("example first part", computePart1(root))
|
||||
|
||||
unusedSpace := 70000000 - totalSize(root)
|
||||
fmt.Println("unused space is currently", unusedSpace)
|
||||
needToGet := 30000000 - unusedSpace
|
||||
fmt.Println("need to find a directory at least", needToGet, "bytes big")
|
||||
fmt.Println("that directory has size", computePart2(root, needToGet))
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user