code.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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 lines [][]byte
  11. for scanner.Scan() {
  12. line := scanner.Text()
  13. if line == "" {
  14. break
  15. }
  16. items := make([]byte, len(line))
  17. for i := range line {
  18. items[i] = line[i]
  19. }
  20. lines = append(lines, items)
  21. }
  22. return lines
  23. }
  24. type point struct {
  25. x int
  26. y int
  27. }
  28. func howManyNeighbors(lines [][]byte, x, y int) int {
  29. var count int
  30. for row := y - 1; row <= y+1; row++ {
  31. if row < 0 || row >= len(lines) {
  32. continue
  33. }
  34. for col := x - 1; col <= x+1; col++ {
  35. if col < 0 || col >= len(lines[row]) {
  36. continue
  37. }
  38. if row == y && col == x {
  39. continue
  40. }
  41. if lines[row][col] == '@' {
  42. count++
  43. }
  44. }
  45. }
  46. return count
  47. }
  48. func removeRolls(lines [][]byte) int {
  49. var count int
  50. var toRemove []point
  51. for y := range lines {
  52. for x := range lines[y] {
  53. if lines[y][x] != '@' {
  54. continue
  55. }
  56. neighbors := howManyNeighbors(lines, x, y)
  57. if neighbors < 4 {
  58. toRemove = append(toRemove, point{x: x, y: y})
  59. count++
  60. }
  61. }
  62. }
  63. for _, p := range toRemove {
  64. lines[p.y][p.x] = '.'
  65. }
  66. return count
  67. }
  68. func main() {
  69. if len(os.Args) < 2 {
  70. log.Fatal("You need to specify a file!")
  71. }
  72. filePath := os.Args[1]
  73. file, err := os.Open(filePath)
  74. if err != nil {
  75. log.Fatalf("Failed to open %s!\n", filePath)
  76. }
  77. lines := readInput(file)
  78. part1 := removeRolls(lines)
  79. fmt.Println("Part1:", part1)
  80. part2 := part1
  81. for {
  82. removed := removeRolls(lines)
  83. if removed == 0 {
  84. break
  85. }
  86. part2 += removed
  87. }
  88. fmt.Println("Part2:", part2)
  89. }