code.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. )
  8. type Point struct {
  9. y, x int
  10. }
  11. type Pattern struct {
  12. note [][]byte
  13. mirror Point
  14. }
  15. func readInput(file *os.File) []Pattern {
  16. scanner := bufio.NewScanner(file)
  17. var patterns []Pattern
  18. var current Pattern
  19. for scanner.Scan() {
  20. line := scanner.Text()
  21. if line == "" {
  22. patterns = append(patterns, current)
  23. current = Pattern{}
  24. continue
  25. }
  26. var row []byte
  27. for i := range line {
  28. row = append(row, line[i])
  29. }
  30. current.note = append(current.note, row)
  31. }
  32. patterns = append(patterns, current)
  33. return patterns
  34. }
  35. func checkVertical(index int, note [][]byte, width int, canMissOne bool) bool {
  36. left := 0
  37. prev := index - 1
  38. right := index + prev
  39. if right >= width {
  40. right = width - 1
  41. }
  42. for {
  43. if prev < left || index > right {
  44. break
  45. }
  46. for i := range note {
  47. if note[i][prev] != note[i][index] {
  48. if canMissOne {
  49. canMissOne = false
  50. continue
  51. }
  52. return false
  53. }
  54. }
  55. prev--
  56. index++
  57. }
  58. return true
  59. }
  60. func checkHorizontal(index int, note [][]byte, height int, width int, canMissOne bool) bool {
  61. up := 0
  62. prev := index - 1
  63. down := index + prev
  64. if down >= height {
  65. down = height - 1
  66. }
  67. for {
  68. if prev < up || index > down {
  69. break
  70. }
  71. for i := range note[index] {
  72. if note[index][i] != note[prev][i] {
  73. if canMissOne {
  74. canMissOne = false
  75. continue
  76. }
  77. return false
  78. }
  79. }
  80. prev--
  81. index++
  82. }
  83. return true
  84. }
  85. func part1(patterns []Pattern) int {
  86. var result int
  87. for i := range patterns {
  88. width := len(patterns[i].note[0])
  89. height := len(patterns[i].note)
  90. gotVertical := false
  91. for index := 1; index < width; index++ {
  92. if checkVertical(index, patterns[i].note, width, false) {
  93. result += index
  94. gotVertical = true
  95. break
  96. }
  97. }
  98. if gotVertical {
  99. continue
  100. }
  101. for index := 1; index < height; index++ {
  102. if checkHorizontal(index, patterns[i].note, height, width, false) {
  103. result += index * 100
  104. break
  105. }
  106. }
  107. }
  108. return result
  109. }
  110. func part2(patterns []Pattern) int {
  111. var result int
  112. for i := range patterns {
  113. width := len(patterns[i].note[0])
  114. height := len(patterns[i].note)
  115. vertical := 0
  116. for index := 1; index < width; index++ {
  117. if checkVertical(index, patterns[i].note, width, true) {
  118. vertical = index
  119. break
  120. }
  121. }
  122. horizontal := 0
  123. for index := 1; index < height; index++ {
  124. if checkHorizontal(index, patterns[i].note, height, width, true) {
  125. horizontal = index
  126. break
  127. }
  128. }
  129. if horizontal > 0 {
  130. result += horizontal * 100
  131. } else if vertical > 0 {
  132. result += vertical
  133. }
  134. }
  135. return result
  136. }
  137. func main() {
  138. if len(os.Args) < 2 {
  139. log.Fatal("You need to specify a file!")
  140. }
  141. filePath := os.Args[1]
  142. file, err := os.Open(filePath)
  143. if err != nil {
  144. log.Fatalf("Failed to open %s!\n", filePath)
  145. }
  146. patterns := readInput(file)
  147. fmt.Println("Part1:", part1(patterns))
  148. fmt.Println("Part2:", part2(patterns))
  149. }