add part 2 of day 13

This commit is contained in:
2024-12-14 12:14:48 +01:00
parent e5a179ab5a
commit 19b8711a83

142
day13/hugeclawmachine.go Normal file
View File

@@ -0,0 +1,142 @@
package main
import (
"fmt"
"os"
"math"
"errors"
"strings"
"regexp"
"strconv"
)
// data types
type Vec struct {
x float64
y float64
}
func (v Vec) Add(other Vec) Vec {
return Vec{x: v.x + other.x, y: v.y + other.y}
}
func (v Vec) Sub(other Vec) Vec {
return Vec{x: v.x - other.x, y: v.y - other.y}
}
func (v Vec) Mul(skalar float64) Vec {
return Vec{x: v.x * skalar, y: v.y *skalar}
}
func (v Vec) VecDiv(other Vec) (float64, error) {
/* Returns an error if v and other do not lie on a staight line.
* It holds: v.VecDiv(other).Abs() = v.Abs() / other.Abs()
*/
cx := float64(v.x) / float64(other.x)
cy := float64(v.y) / float64(other.y)
if abs(cx - cy) > 10e-5 { return 0, errors.New("vectors do not lie in a straight line") }
return cx, nil
}
func (v Vec) Abs() float64 {
return math.Sqrt(float64(v.x * v.x + v.y * v.y))
}
func (v Vec) IsNatural() bool {
intX := int(v.x + 10e-5)
intY := int(v.y + 10e-5)
return abs(float64(intX) - v.x) < 10e-5 && abs(float64(intY) - v.y) < 10e-5
}
type Matrix struct {
c0 Vec // left column
c1 Vec // right column
}
func (m Matrix) LinearTransform(v Vec) Vec {
return m.c0.Mul(v.x).Add( m.c1.Mul(v.y) )
}
func (m Matrix) Inverse() (Matrix, error) {
det := m.c0.x * m.c1.y - m.c0.y * m.c1.x
if det == 0 {
return Matrix{}, errors.New("Matrix is not invertable")
}
invDet := 1 / det
invMatrix := Matrix{
Vec{ m.c1.y, -m.c0.y}.Mul(invDet),
Vec{-m.c1.x, m.c0.x}.Mul(invDet),
}
return invMatrix, nil
}
type ClawMachine struct {
buttonA Vec
buttonB Vec
price Vec
}
func (cm ClawMachine) GetTransform() (Matrix, error) {
return Matrix{cm.buttonA, cm.buttonB}.Inverse()
}
// general util
func check(e error) {
if e != nil { panic(e) }
}
func abs(n float64) float64 {
if n < 0 { return -n }
return n
}
// main loop
func main() {
// read in file
dat, err := os.ReadFile("data.txt")
check(err)
dat_str := strings.TrimSpace(string(dat))
cms := make([]ClawMachine, 0)
pattern := regexp.MustCompile(`\d+`)
numbers := [6]float64{}
for _, machine_str := range strings.Split(dat_str, "\n\n") {
// collect numbers as ints
for i, match := range pattern.FindAllString(machine_str, -1) {
numInt, err := strconv.Atoi(match)
check(err)
numbers[i] = float64(numInt)
}
// construct ClawMachines
cms = append(cms, ClawMachine{
Vec{numbers[0], numbers[1]},
Vec{numbers[2], numbers[3]},
Vec{numbers[4] + 10000000000000, numbers[5] + 10000000000000},
})
}
// calculate cost
cost := 0
for _, cm := range cms {
inv, err := cm.GetTransform()
check(err)
price_trans := inv.LinearTransform(cm.price)
if price_trans.IsNatural() {
cost += int(price_trans.x + 10e-5) * 3 + int(price_trans.y + 10e-5)
}
}
fmt.Println(cost)
}