code.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "os"
  6. "strconv"
  7. "strings"
  8. )
  9. func readInput(path string) []string {
  10. data, err := os.ReadFile(path)
  11. if err != nil {
  12. log.Fatal(err)
  13. }
  14. parts := strings.Split(string(data), ",")
  15. if len(parts) == 0 {
  16. log.Fatal("Bad input!")
  17. }
  18. for i := range parts {
  19. parts[i] = strings.TrimRight(parts[i], "\n")
  20. }
  21. return parts
  22. }
  23. const (
  24. Max = 256
  25. )
  26. func hash(text string) int {
  27. var current int
  28. for i := range text {
  29. current += int(text[i])
  30. current = current * 17 % Max
  31. }
  32. return current
  33. }
  34. func part1(steps []string) int {
  35. var result int
  36. for i := range steps {
  37. result += hash(steps[i])
  38. }
  39. return result
  40. }
  41. type Lens struct {
  42. label string
  43. power int
  44. }
  45. func lensFromString(text string) Lens {
  46. parts := strings.Split(text, "=")
  47. if len(parts) != 2 {
  48. log.Fatalf("Problem reading step %s", text)
  49. }
  50. lens := Lens{label: parts[0]}
  51. n, err := strconv.Atoi(parts[1])
  52. if err != nil {
  53. log.Fatalf("Problem converting number %s: %s", parts[1], err)
  54. }
  55. lens.power = n
  56. return lens
  57. }
  58. func addLens(box []Lens, lens Lens) []Lens {
  59. found := false
  60. for i := range box {
  61. if box[i].label == lens.label {
  62. box[i] = lens
  63. found = true
  64. break
  65. }
  66. }
  67. if !found {
  68. box = append(box, lens)
  69. }
  70. return box
  71. }
  72. func getBoxes(steps []string) [][]Lens {
  73. lenses := make([][]Lens, 256)
  74. for i := range steps {
  75. if strings.Contains(steps[i], "=") {
  76. lens := lensFromString(steps[i])
  77. boxIndex := hash(lens.label)
  78. lenses[boxIndex] = addLens(lenses[boxIndex], lens)
  79. } else {
  80. label := strings.TrimRight(steps[i], "-")
  81. boxIndex := hash(label)
  82. for i := range lenses[boxIndex] {
  83. if lenses[boxIndex][i].label == label {
  84. lenses[boxIndex] = append(lenses[boxIndex][:i], lenses[boxIndex][i+1:]...)
  85. break
  86. }
  87. }
  88. }
  89. }
  90. return lenses
  91. }
  92. func part2(steps []string) int {
  93. var result int
  94. lenses := getBoxes(steps)
  95. for i := range lenses {
  96. for j := range lenses[i] {
  97. result += (i + 1) * (j + 1) * lenses[i][j].power
  98. }
  99. }
  100. return result
  101. }
  102. func main() {
  103. if len(os.Args) < 2 {
  104. log.Fatal("You need to specify a file!")
  105. }
  106. steps := readInput(os.Args[1])
  107. fmt.Println("Part1:", part1(steps))
  108. fmt.Println("Part2:", part2(steps))
  109. }