day18.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. "strconv"
  8. "strings"
  9. )
  10. func getTokens(line string) ([]rune, error) {
  11. scanner := bufio.NewScanner(strings.NewReader(line))
  12. scanner.Split(bufio.ScanWords)
  13. var tokens []rune
  14. for scanner.Scan() {
  15. newTokens := []rune(scanner.Text())
  16. tokens = append(tokens, newTokens...)
  17. }
  18. if err := scanner.Err(); err != nil {
  19. return tokens, fmt.Errorf("Scanner error: %s", err)
  20. }
  21. return tokens, nil
  22. }
  23. func getExpression(tokens []rune) []interface{} {
  24. var expression []interface{}
  25. for _, token := range tokens {
  26. stringToken := string(token)
  27. value, err := strconv.Atoi(stringToken)
  28. if err != nil {
  29. expression = append(expression, stringToken)
  30. continue
  31. }
  32. expression = append(expression, value)
  33. }
  34. return expression
  35. }
  36. func readFile(file *os.File) [][]interface{} {
  37. var expressions [][]interface{}
  38. scanner := bufio.NewScanner(file)
  39. for scanner.Scan() {
  40. line := scanner.Text()
  41. if line == "" {
  42. continue
  43. }
  44. tokens, err := getTokens(line)
  45. if err != nil {
  46. log.Fatalf("Error scanning %s: %s", line, err)
  47. }
  48. expressions = append(expressions, getExpression(tokens))
  49. }
  50. if err := scanner.Err(); err != nil {
  51. log.Fatalf("Scanner error: %s", err)
  52. }
  53. return expressions
  54. }
  55. var precedence map[string]int
  56. func init() {
  57. precedence = make(map[string]int)
  58. precedence["+"] = 1
  59. precedence["*"] = 0
  60. }
  61. func getRPNFromExpression(expression []interface{}, withPrecedence bool) []interface{} {
  62. var rpn []interface{}
  63. var operators []string
  64. for _, token := range expression {
  65. switch token := token.(type) {
  66. case int:
  67. rpn = append(rpn, token)
  68. case string:
  69. switch token {
  70. case "(":
  71. operators = append(operators, token)
  72. case ")":
  73. for len(operators) > 0 {
  74. oper := operators[len(operators)-1]
  75. operators = operators[:len(operators)-1]
  76. if oper == "(" {
  77. break
  78. }
  79. rpn = append(rpn, oper)
  80. }
  81. default:
  82. priority := precedence[token]
  83. for len(operators) > 0 {
  84. top := operators[len(operators)-1]
  85. if top == "(" {
  86. break
  87. }
  88. prevPriority := precedence[top]
  89. if withPrecedence {
  90. if priority < prevPriority {
  91. operators = operators[:len(operators)-1]
  92. rpn = append(rpn, top)
  93. } else {
  94. break
  95. }
  96. } else {
  97. operators = operators[:len(operators)-1]
  98. rpn = append(rpn, top)
  99. }
  100. }
  101. operators = append(operators, token)
  102. }
  103. }
  104. }
  105. for len(operators) > 0 {
  106. oper := operators[len(operators)-1]
  107. operators = operators[:len(operators)-1]
  108. rpn = append(rpn, oper)
  109. }
  110. return rpn
  111. }
  112. func doMath(operator string, arg1, arg2 int) int {
  113. switch operator {
  114. case "+":
  115. return arg1 + arg2
  116. case "*":
  117. return arg1 * arg2
  118. }
  119. return -1
  120. }
  121. func evaluateRPN(rpn []interface{}) int {
  122. var stack []int
  123. for _, token := range rpn {
  124. switch token := token.(type) {
  125. case int:
  126. stack = append(stack, token)
  127. case string:
  128. if len(stack) < 2 {
  129. log.Fatalf("Invalid expresion token %s in %s!", token, rpn)
  130. }
  131. arg1, arg2 := stack[len(stack)-2], stack[len(stack)-1]
  132. stack = stack[:len(stack)-2]
  133. value := doMath(token, arg1, arg2)
  134. stack = append(stack, value)
  135. }
  136. }
  137. if len(stack) != 1 {
  138. log.Fatal("Bad stack!")
  139. }
  140. return stack[len(stack)-1]
  141. }
  142. func part1(expressions [][]interface{}) int {
  143. sum := 0
  144. for _, expression := range expressions {
  145. rpn := getRPNFromExpression(expression, false)
  146. sum += evaluateRPN(rpn)
  147. }
  148. return sum
  149. }
  150. func part2(expressions [][]interface{}) int {
  151. sum := 0
  152. for _, expression := range expressions {
  153. rpn := getRPNFromExpression(expression, true)
  154. sum += evaluateRPN(rpn)
  155. }
  156. return sum
  157. }
  158. func main() {
  159. if len(os.Args) < 2 {
  160. log.Fatal("You need to specify a file!")
  161. }
  162. filePath := os.Args[1]
  163. file, err := os.Open(filePath)
  164. if err != nil {
  165. log.Fatalf("Failed to open %s!\n", filePath)
  166. }
  167. expressions := readFile(file)
  168. if err := file.Close(); err != nil {
  169. log.Fatalf("Failed to close file: %s", err)
  170. }
  171. fmt.Println("Part1:", part1(expressions))
  172. fmt.Println("Part2:", part2(expressions))
  173. }