code.go 2.2 KB

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