From bea82cb54827d3be094b3b468c77faf233f85b19 Mon Sep 17 00:00:00 2001 From: efim Date: Sun, 24 Dec 2023 09:01:27 +0000 Subject: [PATCH] day24: why slope&shift work, while points dont? --- day24/lines.go | 60 +++++++++++++++++++++++++++++++++++++-------- day24/lines_test.go | 13 ++++++++++ day24/notes.org | 2 ++ 3 files changed, 65 insertions(+), 10 deletions(-) diff --git a/day24/lines.go b/day24/lines.go index 3189512..4125797 100644 --- a/day24/lines.go +++ b/day24/lines.go @@ -22,13 +22,12 @@ type HailParam struct { p0, p1 Point Dx, Dy, Dz int line string - // for 2d : ay + bx + c = 0 + // for 2d : ay + bx = 0 a, b, c int + // for 2d : y = slope*x + shift + slope, shift float64 } -func (h HailParam) String() string { - return "(" + h.line + ")" -} func CheckPairwiseIntersections(hails []HailParam) (totalIntersections int) { for i, hail := range hails { @@ -47,9 +46,11 @@ func CheckTaskIntersection(h1, h2 HailParam) (doIntersect bool) { log.Printf("intersecting %+v and %+v\n", h1, h2) // x, y, intersectAtAll := IntersectByLineEquasions(h1, h2) // x, y, intersectAtAll := IntersectByTwoPoints(h1, h2) - x, y, intersectAtAll := IntersectByTwoPointsAttempt2(h1, h2) + // x, y, intersectAtAll := IntersectByTwoPointsAttempt2(h1, h2) + // x, y, intersectAtAll := IntersectByTwoPointsAttempt3(h1, h2) + x, y, intersectAtAll := IntersectBySlopeAndShift(h1, h2) if !intersectAtAll { - log.Printf("no intersection at all\n") + log.Println("no intersection at all\n", x, y) return false } isH1Future := h1.FloatPointInFuture(x, y) @@ -71,7 +72,7 @@ func CheckTaskIntersection(h1, h2 HailParam) (doIntersect bool) { return false // outside of area } - log.Println("> intersect inside of the area!") + log.Println("> intersect inside of the area! ", x, y) return true } @@ -130,6 +131,38 @@ func IntersectByTwoPointsAttempt2(h1, h2 HailParam) (intersectionX, intersection return } +func determinant(a, b Point) int { + return a.x * b.y - a.y * b.x +} +func IntersectByTwoPointsAttempt3(h1, h2 HailParam) (intersectionX, intersectionY float64, isIntersecting bool) { + xdiff := Point{ h1.p0.x - h1.p1.x, h2.p0.x - h2.p1.x, 0 } + ydiff := Point { h1.p0.y - h1.p1.y, h2.p0.y - h2.p1.y , 0 } + + div := determinant(xdiff, ydiff) + if div == 0 { + return + } + d := Point { determinant(h1.p0, h1.p1), determinant(h2.p0, h2.p1), 0} + x := float64(determinant(d, xdiff)) / float64(div) + y := float64(determinant(d, ydiff)) / float64(div) + + return x, y, true +} + +func IntersectBySlopeAndShift(h1, h2 HailParam) (intersectionX, intersectionY float64, isIntersecting bool) { + if h1.slope == h2.slope { + return + } + // y = slope * x + shift + // slope1 * x + shift1 = slope2 * x + shift2 + // x = ( shift2 - shift1 ) / (slope1 - slope2) + + x := (h2.shift - h1.shift) / (h1.slope - h2.slope) + y := h1.slope * x + h1.shift + + return x, y, true +} + func (h HailParam) PointInFuture(p Point) bool { xPositiveSteps := (p.x-h.p0.x)*h.Dx >= 0 yPositiveSteps := (p.y-h.p0.y)*h.Dy >= 0 @@ -157,14 +190,21 @@ func ReadHailLine(line string) (h HailParam) { h.Dy = AtoIOrPanic(fields[4]) h.Dz = AtoIOrPanic(fields[5]) - h.p1.x = h.p0.x + h.Dx - h.p1.y = h.p0.y + h.Dy - h.p1.Z = h.p0.Z + h.Dz + countP1AfterMillis := 1 + + h.p1.x = h.p0.x + countP1AfterMillis * h.Dx + h.p1.y = h.p0.y + countP1AfterMillis * h.Dy + h.p1.Z = h.p0.Z + countP1AfterMillis * h.Dz h.a = h.p0.y - h.p1.y h.b = h.p1.x - h.p0.x h.c = -(h.p0.x*h.p1.y - h.p1.x*h.p0.y) + h.slope = float64(h.Dy) / float64(h.Dx) + // y = slope * x + shift + // shift = y - slope * x // for some point + h.shift = float64(h.p0.y) - h.slope * float64(h.p0.x) + return } diff --git a/day24/lines_test.go b/day24/lines_test.go index cf0de5c..c957e1d 100644 --- a/day24/lines_test.go +++ b/day24/lines_test.go @@ -19,6 +19,19 @@ func TestReadLine(t *testing.T) { } +func TestReadLineInput(t *testing.T) { + lines := `147847636573416, 190826994408605, 140130741291716 @ 185, 49, 219 +287509258905812, 207449079739538, 280539021150559 @ -26, 31, 8 +390970075767404, 535711685410735, 404166182422876 @ -147, -453, -149 +306391780523937, 382508967958270, 264612201472049 @ -24, -274, 28 +278063616684570, 510959526404728, 288141792965603 @ -18, -441, -6` + for _, line := range strings.Split(lines, "\n") { + hail := ReadHailLine(line) + t.Logf("%+v\n", hail) + } + +} + func TestSecondPointIsInFuture(t *testing.T) { lines := `19, 13, 30 @ -2, 1, -2 18, 19, 22 @ -1, -1, -2 diff --git a/day24/notes.org b/day24/notes.org index b6b878b..37037a4 100644 --- a/day24/notes.org +++ b/day24/notes.org @@ -31,3 +31,5 @@ should be easy day24 result: 8406 * another formula gives day24 result: 8406 +* another formula +12938