code.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. )
  8. func readInput(file *os.File) [][]byte {
  9. scanner := bufio.NewScanner(file)
  10. var platform [][]byte
  11. for scanner.Scan() {
  12. line := scanner.Text()
  13. if line == "" {
  14. break
  15. }
  16. var row []byte
  17. for i := range line {
  18. row = append(row, line[i])
  19. }
  20. platform = append(platform, row)
  21. }
  22. return platform
  23. }
  24. const (
  25. Round = 'O'
  26. Cube = '#'
  27. Empty = '.'
  28. )
  29. func moveO(a *byte, b *byte) {
  30. *a = Empty
  31. *b = Round
  32. }
  33. func tiltNorth(platform [][]byte, y int, x int, height int, width int) {
  34. for {
  35. prevY := y - 1
  36. if prevY < 0 || platform[prevY][x] == Cube || platform[prevY][x] == Round {
  37. break
  38. }
  39. moveO(&platform[y][x], &platform[prevY][x])
  40. y--
  41. }
  42. }
  43. func tiltSouth(platform [][]byte, y int, x int, height int, width int) {
  44. for {
  45. nextY := y + 1
  46. if nextY >= height || platform[nextY][x] == Cube || platform[nextY][x] == Round {
  47. break
  48. }
  49. moveO(&platform[y][x], &platform[nextY][x])
  50. y++
  51. }
  52. }
  53. func tiltEast(platform [][]byte, y int, x int, height int, width int) {
  54. for {
  55. nextX := x + 1
  56. if nextX >= width || platform[y][nextX] == Cube || platform[y][nextX] == Round {
  57. break
  58. }
  59. moveO(&platform[y][x], &platform[y][nextX])
  60. x++
  61. }
  62. }
  63. func tiltWest(platform [][]byte, y int, x int, height int, width int) {
  64. for {
  65. nextX := x - 1
  66. if nextX < 0 || platform[y][nextX] == Cube || platform[y][nextX] == Round {
  67. break
  68. }
  69. moveO(&platform[y][x], &platform[y][nextX])
  70. x--
  71. }
  72. }
  73. func tiltPlatform(platform [][]byte, direction func([][]byte, int, int, int, int), height int, width int) {
  74. for y := range platform {
  75. for x := range platform[y] {
  76. if platform[y][x] == Round {
  77. direction(platform, y, x, height, width)
  78. }
  79. }
  80. }
  81. }
  82. func tiltPlatformFromBottomRight(platform [][]byte, direction func([][]byte, int, int, int, int), height int, width int) {
  83. for y := height - 1; y >= 0; y-- {
  84. for x := width - 1; x >= 0; x-- {
  85. if platform[y][x] == Round {
  86. direction(platform, y, x, height, width)
  87. }
  88. }
  89. }
  90. }
  91. func calculate(platform [][]byte, height int) int {
  92. var result int
  93. for y := range platform {
  94. for x := range platform[y] {
  95. if platform[y][x] == Round {
  96. result += height - y
  97. }
  98. }
  99. }
  100. return result
  101. }
  102. func part1(platform [][]byte) int {
  103. height := len(platform)
  104. width := len(platform[0])
  105. tiltPlatform(platform, tiltNorth, height, width)
  106. return calculate(platform, height)
  107. }
  108. func copyPlatform(platform [][]byte) [][]byte {
  109. var newPlatform [][]byte
  110. for y := range platform {
  111. newPlatform = append(newPlatform, platform[y])
  112. }
  113. return newPlatform
  114. }
  115. func part2(platform [][]byte, cycles int) int {
  116. height := len(platform)
  117. width := len(platform[0])
  118. for i := 0; i < cycles; i++ {
  119. tiltPlatform(platform, tiltNorth, height, width)
  120. tiltPlatform(platform, tiltWest, height, width)
  121. tiltPlatformFromBottomRight(platform, tiltSouth, height, width)
  122. tiltPlatformFromBottomRight(platform, tiltEast, height, width)
  123. }
  124. return calculate(platform, height)
  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. platform := readInput(file)
  136. platformCopy := copyPlatform(platform)
  137. fmt.Println("Part1:", part1(platform))
  138. fmt.Println("Part2:", part2(platformCopy, 1000))
  139. }