code.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. "strconv"
  8. "strings"
  9. )
  10. func readInput(file *os.File) ([]string, []string) {
  11. scanner := bufio.NewScanner(file)
  12. var numberLines []string
  13. var symbols []string
  14. for scanner.Scan() {
  15. line := scanner.Text()
  16. if line == "" {
  17. continue
  18. }
  19. if line[0] == '+' || line[0] == '*' {
  20. var symbol []byte
  21. for i := range line {
  22. if i > 0 && line[i] == '+' || line[i] == '*' {
  23. symbols = append(symbols, string(symbol))
  24. symbol = []byte{}
  25. }
  26. symbol = append(symbol, line[i])
  27. }
  28. symbols = append(symbols, string(symbol))
  29. } else {
  30. numberLines = append(numberLines, line)
  31. }
  32. }
  33. return numberLines, symbols
  34. }
  35. func parseNumbers(numberLines, symbols []string) [][]string {
  36. var numbers [][]string
  37. for _, line := range numberLines {
  38. var start, end int
  39. var lineNumbers []string
  40. for _, symbol := range symbols {
  41. end += len(symbol)
  42. var number string
  43. for i := start; i < end; i++ {
  44. number += string(line[i])
  45. }
  46. lineNumbers = append(lineNumbers, number)
  47. start = end
  48. }
  49. numbers = append(numbers, lineNumbers)
  50. }
  51. return numbers
  52. }
  53. func part1(numbers [][]string, symbols []string) int {
  54. var sum int
  55. for i, symbol := range symbols {
  56. var result int
  57. for row := range numbers {
  58. if numbers[row][i] == "" {
  59. continue
  60. }
  61. number, err := strconv.Atoi(strings.Trim(numbers[row][i], " "))
  62. if err != nil {
  63. log.Fatalf("Failed to convert %s to int (row: %d, col: %d)!\n", numbers[row][i], row, i)
  64. }
  65. if symbol[0] == '+' {
  66. result += number
  67. } else if symbol[0] == '*' {
  68. if result == 0 {
  69. result = 1
  70. }
  71. result *= number
  72. }
  73. }
  74. sum += result
  75. }
  76. return sum
  77. }
  78. func part2(numbers [][]string, symbols []string) int {
  79. var sum int
  80. for i, symbol := range symbols {
  81. var result int
  82. for j := len(symbol) - 1; j >= 0; j-- {
  83. var digits []byte
  84. for row := range numbers {
  85. if numbers[row][i] == "" {
  86. continue
  87. }
  88. if numbers[row][i][j] >= '0' && numbers[row][i][j] <= '9' {
  89. digits = append(digits, numbers[row][i][j])
  90. }
  91. }
  92. numberString := string(digits)
  93. if numberString == "" {
  94. continue
  95. }
  96. number, err := strconv.Atoi(numberString)
  97. if err != nil {
  98. log.Fatalf("Failed to convert %s to int!\n", numberString)
  99. }
  100. if symbol[0] == '+' {
  101. result += number
  102. } else if symbol[0] == '*' {
  103. if result == 0 {
  104. result = 1
  105. }
  106. result *= number
  107. }
  108. }
  109. sum += result
  110. }
  111. return sum
  112. }
  113. func main() {
  114. if len(os.Args) < 2 {
  115. log.Fatal("You need to specify a file!")
  116. }
  117. filePath := os.Args[1]
  118. file, err := os.Open(filePath)
  119. if err != nil {
  120. log.Fatalf("Failed to open %s!\n", filePath)
  121. }
  122. numberLines, symbols := readInput(file)
  123. numbers := parseNumbers(numberLines, symbols)
  124. fmt.Println("Part1:", part1(numbers, symbols))
  125. fmt.Println("Part2:", part2(numbers, symbols))
  126. }