From 19b8711a83a7d180d67cbec2b12837c7579e605e Mon Sep 17 00:00:00 2001 From: Elias Kohout Date: Sat, 14 Dec 2024 12:14:48 +0100 Subject: [PATCH] add part 2 of day 13 --- day13/hugeclawmachine.go | 142 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 day13/hugeclawmachine.go diff --git a/day13/hugeclawmachine.go b/day13/hugeclawmachine.go new file mode 100644 index 0000000..3180300 --- /dev/null +++ b/day13/hugeclawmachine.go @@ -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) +}