package main import ( "bufio" "errors" "fmt" "io" "log" "os" "strconv" "strings" ) func trim(s string) string { if len(s) > 0 && s[len(s)-1] == '\n' { return s[:len(s)-1] } return s } func main() { r := bufio.NewReader(os.Stdin) calibration := 0 for { line, err := r.ReadString('\n') if errors.Is(err, io.EOF) { break } if err != nil { log.Fatalf("While reading input: %v", err) } line = trim(line) parts := strings.SplitN(line, ":", 2) test64, err := strconv.ParseInt(parts[0], 10, 32) if err != nil { log.Fatalf("Unable to parse test value %#v: %v", parts[0], err) } test := int(test64) fs := strings.Fields(parts[1]) operands := make([]int, 0, 8) for _, f := range fs { o, err := strconv.ParseInt(f, 10, 32) if err != nil { log.Fatalf("Unable to parse operand %#v: %v", f, err) } operands = append(operands, int(o)) } if bruteForce(test, operands) { calibration += test } } fmt.Printf("%d\n", calibration) } func bruteForce(test int, vars []int) bool { if len(vars) > 64 { log.Fatalf("Maximum expected operands exceeded: %#v", vars) } var ops uint64 for ops < uint64(len(vars)) { candidate := vars[0] for i := 0; i < len(vars)-1; i++ { switch (ops & (uint64(1) << i)) >> i { case 0: candidate += vars[i+1] case 1: candidate *= vars[i+1] default: log.Fatal("BUG: unexpected bit value: neither 0 nor 1!") } if candidate > test { break } } if candidate == test { return true } ops++ } return false }