code.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. "strings"
  8. )
  9. type item struct {
  10. name string
  11. size int
  12. }
  13. type dir struct {
  14. name string
  15. parent *dir
  16. dirs []*dir
  17. files []*item
  18. }
  19. func parentHasDir(parent *dir, name string) *dir {
  20. for i := range parent.dirs {
  21. if parent.dirs[i].name == name {
  22. return parent.dirs[i]
  23. }
  24. }
  25. return nil
  26. }
  27. func cd(line string, current *dir, root *dir) *dir {
  28. var name string
  29. n, err := fmt.Sscanf(line, "$ cd %s", &name)
  30. if n != 1 || err != nil {
  31. log.Fatal("Can't parse cd:", err)
  32. }
  33. if name == "/" {
  34. current = root
  35. } else if name == ".." {
  36. current = current.parent
  37. } else {
  38. parent := current
  39. current = parentHasDir(parent, name)
  40. if current == nil {
  41. newDir := dir{name: name, parent: parent}
  42. parent.dirs = append(parent.dirs, &newDir)
  43. current = &newDir
  44. }
  45. }
  46. return current
  47. }
  48. func readInput(file *os.File) dir {
  49. scanner := bufio.NewScanner(file)
  50. root := dir{name: "/"}
  51. var current *dir
  52. read := false
  53. for scanner.Scan() {
  54. line := scanner.Text()
  55. if line == "" {
  56. continue
  57. }
  58. if strings.HasPrefix(line, "$ cd") {
  59. read = false
  60. current = cd(line, current, &root)
  61. } else if strings.HasPrefix(line, "$ ls") {
  62. read = true
  63. continue
  64. }
  65. if read {
  66. if strings.HasPrefix(line, "dir ") {
  67. continue
  68. } else {
  69. var newFile item
  70. n, err := fmt.Sscanf(line, "%d %s", &newFile.size, &newFile.name)
  71. if n != 2 || err != nil {
  72. log.Fatal("Can't parse cd:", err)
  73. }
  74. current.files = append(current.files, &newFile)
  75. }
  76. }
  77. }
  78. return root
  79. }
  80. func getSizes(root dir, sizes []int) (int, []int) {
  81. size := 0
  82. for i := range root.files {
  83. size += root.files[i].size
  84. }
  85. for i := range root.dirs {
  86. var c int
  87. c, sizes = getSizes(*root.dirs[i], sizes)
  88. size += c
  89. }
  90. sizes = append(sizes, size)
  91. return size, sizes
  92. }
  93. func part1(root dir) int {
  94. _, sizes := getSizes(root, []int{})
  95. sum := 0
  96. for i := range sizes {
  97. if sizes[i] < 100000 {
  98. sum += sizes[i]
  99. }
  100. }
  101. return sum
  102. }
  103. func main() {
  104. if len(os.Args) < 2 {
  105. log.Fatal("You need to specify a file!")
  106. }
  107. filePath := os.Args[1]
  108. file, err := os.Open(filePath)
  109. if err != nil {
  110. log.Fatalf("Failed to open %s!\n", filePath)
  111. }
  112. root := readInput(file)
  113. fmt.Println("Part1:", part1(root))
  114. }