code.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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 trees [][]byte
  11. for scanner.Scan() {
  12. line := scanner.Text()
  13. if line == "" {
  14. continue
  15. }
  16. trees = append(trees, []byte(line))
  17. }
  18. return trees
  19. }
  20. func visibleFromLeft(x int, y int, trees [][]byte) bool {
  21. visible := true
  22. for i := 0; i < x; i++ {
  23. if trees[y][i] >= trees[y][x] {
  24. visible = false
  25. break
  26. }
  27. }
  28. return visible
  29. }
  30. func visibleFromRight(x int, y int, trees [][]byte, limit int) bool {
  31. visible := true
  32. for i := x + 1; i < limit; i++ {
  33. if trees[y][i] >= trees[y][x] {
  34. visible = false
  35. break
  36. }
  37. }
  38. return visible
  39. }
  40. func visibleFromTop(x int, y int, trees [][]byte) bool {
  41. visible := true
  42. for i := 0; i < y; i++ {
  43. if trees[i][x] >= trees[y][x] {
  44. visible = false
  45. break
  46. }
  47. }
  48. return visible
  49. }
  50. func visibleFromBottom(x int, y int, trees [][]byte, limit int) bool {
  51. visible := true
  52. for i := y + 1; i < limit; i++ {
  53. if trees[i][x] >= trees[y][x] {
  54. visible = false
  55. break
  56. }
  57. }
  58. return visible
  59. }
  60. func isVisible(x int, y int, trees [][]byte, width int, height int) bool {
  61. if visibleFromLeft(x, y, trees) {
  62. return true
  63. }
  64. if visibleFromRight(x, y, trees, width) {
  65. return true
  66. }
  67. if visibleFromTop(x, y, trees) {
  68. return true
  69. }
  70. if visibleFromBottom(x, y, trees, height) {
  71. return true
  72. }
  73. return false
  74. }
  75. func part1(trees [][]byte) int {
  76. width := len(trees[0])
  77. height := len(trees)
  78. visible := 2*height + (width-2)*2
  79. for y := 1; y < height-1; y++ {
  80. for x := 1; x < width-1; x++ {
  81. if isVisible(x, y, trees, width, height) {
  82. visible++
  83. }
  84. }
  85. }
  86. return visible
  87. }
  88. func numberFromLeft(x int, y int, trees [][]byte) int {
  89. count := 0
  90. for i := x - 1; i >= 0; i-- {
  91. count++
  92. if trees[y][i] >= trees[y][x] {
  93. break
  94. }
  95. }
  96. return count
  97. }
  98. func numberFromRight(x int, y int, trees [][]byte, limit int) int {
  99. count := 0
  100. for i := x + 1; i < limit; i++ {
  101. count++
  102. if trees[y][i] >= trees[y][x] {
  103. break
  104. }
  105. }
  106. return count
  107. }
  108. func numberFromTop(x int, y int, trees [][]byte) int {
  109. count := 0
  110. for i := y - 1; i >= 0; i-- {
  111. count++
  112. if trees[i][x] >= trees[y][x] {
  113. break
  114. }
  115. }
  116. return count
  117. }
  118. func numberFromBottom(x int, y int, trees [][]byte, limit int) int {
  119. count := 0
  120. for i := y + 1; i < limit; i++ {
  121. count++
  122. if trees[i][x] >= trees[y][x] {
  123. break
  124. }
  125. }
  126. return count
  127. }
  128. func numberVisible(x int, y int, trees [][]byte, width int, height int) int {
  129. count := 1
  130. count *= numberFromLeft(x, y, trees)
  131. count *= numberFromRight(x, y, trees, width)
  132. count *= numberFromTop(x, y, trees)
  133. count *= numberFromBottom(x, y, trees, height)
  134. return count
  135. }
  136. func part2(trees [][]byte) int {
  137. width := len(trees[0])
  138. height := len(trees)
  139. max := 0
  140. for y := 0; y < height; y++ {
  141. for x := 0; x < width; x++ {
  142. count := numberVisible(x, y, trees, width, height)
  143. if count > max {
  144. max = count
  145. }
  146. }
  147. }
  148. return max
  149. }
  150. func main() {
  151. if len(os.Args) < 2 {
  152. log.Fatal("You need to specify a file!")
  153. }
  154. filePath := os.Args[1]
  155. file, err := os.Open(filePath)
  156. if err != nil {
  157. log.Fatalf("Failed to open %s!\n", filePath)
  158. }
  159. trees := readInput(file)
  160. fmt.Println("Part1:", part1(trees))
  161. fmt.Println("Part2:", part2(trees))
  162. }