code.go 3.1 KB

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