code.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. )
  8. type move struct {
  9. quantity int
  10. from int
  11. to int
  12. }
  13. func parseBoxes(line string, boxes [][]byte) [][]byte {
  14. counter := 0
  15. index := 0
  16. readLetter := false
  17. for i := range line {
  18. if line[i] == '\n' {
  19. break
  20. }
  21. counter++
  22. if counter > 3 {
  23. index++
  24. counter = 0
  25. }
  26. if line[i] == '[' {
  27. readLetter = true
  28. continue
  29. }
  30. if line[i] == ']' {
  31. readLetter = false
  32. continue
  33. }
  34. if readLetter {
  35. edge := len(boxes) - 1
  36. if index > edge {
  37. for i := 0; i < index-edge; i++ {
  38. boxes = append(boxes, []byte{})
  39. }
  40. }
  41. boxes[index] = append(boxes[index], line[i])
  42. }
  43. }
  44. return boxes
  45. }
  46. func reverseBoxes(boxes [][]byte) [][]byte {
  47. for x := range boxes {
  48. for i, j := 0, len(boxes[x])-1; i < j; i, j = i+1, j-1 {
  49. boxes[x][i], boxes[x][j] = boxes[x][j], boxes[x][i]
  50. }
  51. }
  52. return boxes
  53. }
  54. func parseMove(line string) move {
  55. var current move
  56. n, err := fmt.Sscanf(line, "move %d from %d to %d", &current.quantity, &current.from, &current.to)
  57. if n != 3 || err != nil {
  58. log.Fatal("Can't parse move!", err)
  59. }
  60. current.from--
  61. current.to--
  62. return current
  63. }
  64. func readInput(file *os.File) ([][]byte, []move) {
  65. scanner := bufio.NewScanner(file)
  66. var moves []move
  67. var boxes [][]byte
  68. readBoxes := true
  69. for scanner.Scan() {
  70. line := scanner.Text()
  71. if line == "" {
  72. readBoxes = false
  73. continue
  74. }
  75. if readBoxes {
  76. boxes = parseBoxes(line, boxes)
  77. continue
  78. }
  79. moves = append(moves, parseMove(line))
  80. }
  81. return reverseBoxes(boxes), moves
  82. }
  83. func moveBox(boxes [][]byte, action move) [][]byte {
  84. last := len(boxes[action.from]) - 1
  85. letter := boxes[action.from][last]
  86. boxes[action.from] = boxes[action.from][:last]
  87. boxes[action.to] = append(boxes[action.to], letter)
  88. return boxes
  89. }
  90. func part1(boxes [][]byte, moves []move) string {
  91. for i := range moves {
  92. for j := 0; j < moves[i].quantity; j++ {
  93. moveBox(boxes, moves[i])
  94. }
  95. }
  96. var word []byte
  97. for i := range boxes {
  98. word = append(word, boxes[i][len(boxes[i])-1])
  99. }
  100. return string(word)
  101. }
  102. func moveBoxes(boxes [][]byte, action move) [][]byte {
  103. toTake := len(boxes[action.from]) - action.quantity
  104. boxes[action.to] = append(boxes[action.to], boxes[action.from][toTake:]...)
  105. boxes[action.from] = boxes[action.from][:toTake]
  106. return boxes
  107. }
  108. func part2(boxes [][]byte, moves []move) string {
  109. for i := range moves {
  110. moveBoxes(boxes, moves[i])
  111. }
  112. var word []byte
  113. for i := range boxes {
  114. word = append(word, boxes[i][len(boxes[i])-1])
  115. }
  116. return string(word)
  117. }
  118. func copyBoxes(boxes [][]byte) [][]byte {
  119. var copied [][]byte
  120. for i := range boxes {
  121. copied = append(copied, make([]byte, len(boxes[i])))
  122. copy(copied[i], boxes[i])
  123. }
  124. return copied
  125. }
  126. func main() {
  127. if len(os.Args) < 2 {
  128. log.Fatal("You need to specify a file!")
  129. }
  130. filePath := os.Args[1]
  131. file, err := os.Open(filePath)
  132. if err != nil {
  133. log.Fatalf("Failed to open %s!\n", filePath)
  134. }
  135. boxes, moves := readInput(file)
  136. originalBoxes := copyBoxes(boxes)
  137. fmt.Println("Part1:", part1(boxes, moves))
  138. fmt.Println("Part2:", part2(originalBoxes, moves))
  139. }