main.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package main
  2. import (
  3. "bufio"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "log"
  8. "os"
  9. "strconv"
  10. "strings"
  11. )
  12. func trim(s string) string {
  13. if len(s) > 0 && s[len(s)-1] == '\n' {
  14. return s[:len(s)-1]
  15. }
  16. return s
  17. }
  18. func main() {
  19. r := bufio.NewReader(os.Stdin)
  20. calibration := 0
  21. for {
  22. line, err := r.ReadString('\n')
  23. if errors.Is(err, io.EOF) {
  24. break
  25. }
  26. if err != nil {
  27. log.Fatalf("While reading input: %v", err)
  28. }
  29. line = trim(line)
  30. parts := strings.SplitN(line, ":", 2)
  31. test64, err := strconv.ParseInt(parts[0], 10, 32)
  32. if err != nil {
  33. log.Fatalf("Unable to parse test value %#v: %v", parts[0], err)
  34. }
  35. test := int(test64)
  36. fs := strings.Fields(parts[1])
  37. operands := make([]int, 0, 8)
  38. for _, f := range fs {
  39. o, err := strconv.ParseInt(f, 10, 32)
  40. if err != nil {
  41. log.Fatalf("Unable to parse operand %#v: %v", f, err)
  42. }
  43. operands = append(operands, int(o))
  44. }
  45. if bruteForce(test, operands) {
  46. calibration += test
  47. }
  48. }
  49. fmt.Printf("%d\n", calibration)
  50. }
  51. func bruteForce(test int, vars []int) bool {
  52. if len(vars) > 64 {
  53. log.Fatalf("Maximum expected operands exceeded: %#v", vars)
  54. }
  55. var ops uint64
  56. for ops < uint64(len(vars)) {
  57. candidate := vars[0]
  58. for i := 0; i < len(vars)-1; i++ {
  59. switch (ops & (uint64(1) << i)) >> i {
  60. case 0:
  61. candidate += vars[i+1]
  62. case 1:
  63. candidate *= vars[i+1]
  64. default:
  65. log.Fatal("BUG: unexpected bit value: neither 0 nor 1!")
  66. }
  67. if candidate > test {
  68. break
  69. }
  70. }
  71. if candidate == test {
  72. return true
  73. }
  74. ops++
  75. }
  76. return false
  77. }