112 lines
2.5 KiB
Go
112 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"fmt"
|
|
"strings"
|
|
"strconv"
|
|
"math"
|
|
)
|
|
|
|
// data types
|
|
type Equation struct {
|
|
result int
|
|
params []int
|
|
}
|
|
|
|
// general util
|
|
func check(e error) {
|
|
if e != nil { panic(e) }
|
|
}
|
|
|
|
func newEquations(data string) []*Equation {
|
|
/* Reads the puzzle input, return a list of Equation structs.
|
|
*/
|
|
lines := strings.Split(data, "\n")
|
|
equations := make([]*Equation, 0, len(lines))
|
|
|
|
for _, line := range lines {
|
|
split_line := strings.Split(line, ":")
|
|
|
|
// get result/ number before the colon
|
|
result, err := strconv.Atoi(split_line[0])
|
|
check(err)
|
|
|
|
// parse paramter/ numbers after the colon
|
|
str_params := strings.Split(strings.TrimSpace(split_line[1]), " ")
|
|
params := make([]int, 0, len(str_params))
|
|
for _, num := range str_params {
|
|
param, err := strconv.Atoi(num)
|
|
check(err)
|
|
|
|
params = append(params, param)
|
|
}
|
|
|
|
equations = append(equations, &Equation{ result: result, params: params })
|
|
}
|
|
|
|
return equations
|
|
}
|
|
|
|
func incr(arr []int) []int {
|
|
/* least significant bit first increment, base 3 */
|
|
over := 1
|
|
for i := range arr {
|
|
if over == 0 { break }
|
|
arr[i] += over
|
|
over = arr[i] / 3
|
|
arr[i] = arr[i] % 3
|
|
}
|
|
return arr
|
|
}
|
|
|
|
func isValid(eq *Equation) bool {
|
|
/* Checks whether the equation could be right by combining the paramters in
|
|
* all possible ways and comparing to the result.
|
|
*/
|
|
|
|
operators := make([]int, len(eq.params) - 1)
|
|
|
|
for range int(math.Pow(3.0, float64(len(operators)))) {
|
|
|
|
// calc possible result
|
|
acc := eq.params[0]
|
|
for i, op := range operators {
|
|
if op == 0 {
|
|
acc += eq.params[i + 1]
|
|
} else if op == 1 {
|
|
acc *= eq.params[i + 1]
|
|
} else if op == 2 {
|
|
num, err := strconv.Atoi(strconv.Itoa(acc) + strconv.Itoa(eq.params[i + 1]))
|
|
check(err)
|
|
acc = num
|
|
}
|
|
}
|
|
|
|
// compare to actual result
|
|
if acc == eq.result { return true }
|
|
|
|
operators = incr(operators)
|
|
}
|
|
return false
|
|
}
|
|
|
|
// main loop
|
|
func main() {
|
|
|
|
// read in file
|
|
dat, err := os.ReadFile("data.txt")
|
|
check(err)
|
|
dat_str := strings.TrimSpace(string(dat))
|
|
|
|
|
|
equations := newEquations(dat_str)
|
|
|
|
result := 0
|
|
for _, eq := range equations {
|
|
if isValid(eq) { result += eq.result }
|
|
}
|
|
|
|
fmt.Println(result)
|
|
}
|