code.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "log"
  6. "os"
  7. "strconv"
  8. "strings"
  9. )
  10. type point struct {
  11. x, y int
  12. }
  13. type fold struct {
  14. val int
  15. cat string
  16. }
  17. func readInput(file string) ([]point, []fold) {
  18. content, err := ioutil.ReadFile(file)
  19. if err != nil {
  20. log.Fatal(err)
  21. }
  22. lines := strings.Split(string(content), "\n")
  23. var input []point
  24. var folds []fold
  25. readingPoints := true
  26. for _, line := range lines {
  27. if line == "" {
  28. readingPoints = false
  29. continue
  30. }
  31. if readingPoints {
  32. parts := strings.Split(line, ",")
  33. if len(parts) != 2 {
  34. log.Fatal("Invalid input")
  35. }
  36. x, err := strconv.Atoi(parts[0])
  37. if err != nil {
  38. log.Fatal(err)
  39. }
  40. y, err := strconv.Atoi(parts[1])
  41. if err != nil {
  42. log.Fatal(err)
  43. }
  44. input = append(input, point{x, y})
  45. } else {
  46. parts := strings.Split(line, "=")
  47. if len(parts) != 2 {
  48. log.Fatal("Invalid input")
  49. }
  50. val, err := strconv.Atoi(parts[1])
  51. if err != nil {
  52. log.Fatal(err)
  53. }
  54. if parts[0] == "fold along x" {
  55. folds = append(folds, fold{val, "x"})
  56. } else if parts[0] == "fold along y" {
  57. folds = append(folds, fold{val, "y"})
  58. } else {
  59. log.Fatal("Invalid input")
  60. }
  61. }
  62. }
  63. return input, folds
  64. }
  65. func foldByY(input []point, foldY int) {
  66. for i, p := range input {
  67. if p.y < foldY {
  68. continue
  69. }
  70. newY := p.y % foldY
  71. if newY > 0 {
  72. newY = foldY - newY
  73. }
  74. input[i].y = newY
  75. }
  76. }
  77. func foldByX(input []point, foldX int) {
  78. for i, p := range input {
  79. if p.x > foldX {
  80. input[i].x = p.x - foldX - 1
  81. continue
  82. }
  83. input[i].x = foldX - p.x - 1
  84. }
  85. }
  86. func countPoints(input []point) int {
  87. counted := make(map[point]bool)
  88. count := 0
  89. for _, p := range input {
  90. if counted[p] {
  91. continue
  92. }
  93. counted[p] = true
  94. count++
  95. }
  96. return count
  97. }
  98. func part1(input []point, folds []fold) int {
  99. firstFold := folds[0]
  100. if firstFold.cat == "x" {
  101. foldByX(input, firstFold.val)
  102. } else {
  103. foldByY(input, firstFold.val)
  104. }
  105. return countPoints(input)
  106. }
  107. func largest(input []point) (int, int) {
  108. largestX := input[0].x
  109. largestY := input[0].y
  110. for _, i := range input {
  111. if i.x > largestX {
  112. largestX = i.x
  113. }
  114. if i.y > largestY {
  115. largestY = i.y
  116. }
  117. }
  118. return largestX, largestY
  119. }
  120. func createBoard(input []point) [][]string {
  121. largestX, largestY := largest(input)
  122. board := make([][]string, largestY+1)
  123. for i, _ := range board {
  124. board[i] = make([]string, largestX+1)
  125. }
  126. for _, p := range input {
  127. if p.x < 0 || p.y < 0 {
  128. continue
  129. }
  130. board[p.y][p.x] = "#"
  131. }
  132. return board
  133. }
  134. func printBoard(input []point) {
  135. board := createBoard(input)
  136. for _, line := range board {
  137. for _, c := range line {
  138. if c == "" {
  139. fmt.Print(" ")
  140. } else {
  141. fmt.Print(c)
  142. }
  143. }
  144. fmt.Println()
  145. }
  146. }
  147. func part2(input []point, folds []fold) {
  148. for _, fold := range folds[1:] {
  149. if fold.cat == "x" {
  150. foldByX(input, fold.val)
  151. } else {
  152. foldByY(input, fold.val)
  153. }
  154. }
  155. printBoard(input)
  156. }
  157. func main() {
  158. if len(os.Args) < 2 {
  159. log.Fatal("Please provide a file name as argument")
  160. }
  161. input, folds := readInput(os.Args[1])
  162. fmt.Println("Part1:", part1(input, folds))
  163. fmt.Println("Part2:")
  164. part2(input, folds)
  165. }