day24: adding python z3, example
This commit is contained in:
parent
bea82cb548
commit
5b03b8f156
|
@ -0,0 +1,73 @@
|
||||||
|
package day24
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// most inner loop
|
||||||
|
// assumint stone hits h1 at t1, and h2 at t2
|
||||||
|
// return the line. so 'HailParam' for my stone trajectory
|
||||||
|
func AssumeHails(h1, h2 HailParam, t1, t2 int) (stoneTrajectory HailParam, isInt bool) {
|
||||||
|
Dx, isXInt := AssumedDelta(h1.p0.x, h2.p0.x, h1.Dx, h2.Dx, t1, t2)
|
||||||
|
Dy, isYInt := AssumedDelta(h1.p0.y, h2.p0.y, h1.Dy, h2.Dy, t1, t2)
|
||||||
|
Dz, isZInt := AssumedDelta(h1.p0.z, h2.p0.z, h1.Dz, h2.Dz, t1, t2)
|
||||||
|
|
||||||
|
isInt = isXInt && isYInt && isZInt
|
||||||
|
|
||||||
|
x := AssumedStartFromDelta(h1.p0.x, h1.Dx, t1, Dx)
|
||||||
|
y := AssumedStartFromDelta(h1.p0.y, h1.Dy, t1, Dy)
|
||||||
|
z := AssumedStartFromDelta(h1.p0.z, h1.Dz, t1, Dz)
|
||||||
|
|
||||||
|
stoneTrajectoryLine := fmt.Sprintf("%d, %d, %d @ %d, %d, %d", x, y, z, Dx, Dy, Dz)
|
||||||
|
stoneTrajectory = ReadHailLine(stoneTrajectoryLine)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func HailMaryLoop(hails []HailParam) {
|
||||||
|
// for t1, t2 from [1, 100]
|
||||||
|
// try to fit stoneTrajectory on every pair of hails.
|
||||||
|
// and hope for integer fit
|
||||||
|
for t1 := 1; t1 <= 100; t1++ {
|
||||||
|
for t2 := t1+1 ; t2 <= 100; t2++ {
|
||||||
|
for i, hail := range hails {
|
||||||
|
innerHail:
|
||||||
|
for j, otherHail := range hails {
|
||||||
|
if i == j {
|
||||||
|
continue innerHail
|
||||||
|
}
|
||||||
|
_, isInt := AssumeHails(hail, otherHail, t1, t2)
|
||||||
|
if !isInt {
|
||||||
|
continue innerHail // TODO first hope to loose
|
||||||
|
}
|
||||||
|
// if isInt {
|
||||||
|
// log.Printf("hail mary int fit between %s (%d) and %s (%d)",
|
||||||
|
// hail.SomeString(), t1, otherHail.SomeString(), t2)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO check for inner loop : when get assumed stoneTrajectory
|
||||||
|
// for all hail params, check that they intercept
|
||||||
|
// func CheckAssumedTrajectory(assumedStone HailParam, hails []HailParam) bool {
|
||||||
|
// for _, hail := range hails {
|
||||||
|
// // i guess i could try to do what?
|
||||||
|
// // assume oh, no. there can be t whatever
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
func AssumedDelta(c1, c2 int, Dc1, Dc2 int, t1, t2 int) (delta int, isInt bool) {
|
||||||
|
divisor := t1 - t2
|
||||||
|
divisible := c1 - c2 + (t1 * Dc1) - (t2 * Dc2)
|
||||||
|
|
||||||
|
isInt = divisible % divisor == 0
|
||||||
|
delta = divisible / divisor
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func AssumedStartFromDelta(c1 int, Dc1 int, t1, Dc int) (c int) {
|
||||||
|
return c1 + t1 * Dc1 - t1 * Dc
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package day24
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestHailMaryOnExamle(t *testing.T) {
|
||||||
|
filename := "input"
|
||||||
|
hails := ReadHailFile(filename)
|
||||||
|
HailMaryLoop(hails)
|
||||||
|
}
|
117
day24/lines.go
117
day24/lines.go
|
@ -15,7 +15,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Point struct {
|
type Point struct {
|
||||||
x, y, Z int
|
x, y, z int
|
||||||
}
|
}
|
||||||
|
|
||||||
type HailParam struct {
|
type HailParam struct {
|
||||||
|
@ -28,6 +28,39 @@ type HailParam struct {
|
||||||
slope, shift float64
|
slope, shift float64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *HailParam) SomeString() string {
|
||||||
|
return h.line
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HailParam) GetCoord(name string) (result int) {
|
||||||
|
switch name {
|
||||||
|
case "x":
|
||||||
|
result = h.p0.x
|
||||||
|
case "y":
|
||||||
|
result = h.p0.y
|
||||||
|
case "z":
|
||||||
|
result = h.p0.z
|
||||||
|
default:
|
||||||
|
panic("unknown param")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HailParam) GetSpeedOf(name string) (result int) {
|
||||||
|
switch name {
|
||||||
|
case "x":
|
||||||
|
result = h.Dx
|
||||||
|
case "y":
|
||||||
|
result = h.Dy
|
||||||
|
case "z":
|
||||||
|
result = h.Dz
|
||||||
|
default:
|
||||||
|
panic("unknown param")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func CheckPairwiseIntersections(hails []HailParam) (totalIntersections int) {
|
func CheckPairwiseIntersections(hails []HailParam) (totalIntersections int) {
|
||||||
for i, hail := range hails {
|
for i, hail := range hails {
|
||||||
|
@ -44,10 +77,7 @@ func CheckPairwiseIntersections(hails []HailParam) (totalIntersections int) {
|
||||||
|
|
||||||
func CheckTaskIntersection(h1, h2 HailParam) (doIntersect bool) {
|
func CheckTaskIntersection(h1, h2 HailParam) (doIntersect bool) {
|
||||||
log.Printf("intersecting %+v and %+v\n", h1, h2)
|
log.Printf("intersecting %+v and %+v\n", h1, h2)
|
||||||
// x, y, intersectAtAll := IntersectByLineEquasions(h1, h2)
|
|
||||||
// x, y, intersectAtAll := IntersectByTwoPoints(h1, h2)
|
// x, y, intersectAtAll := IntersectByTwoPoints(h1, h2)
|
||||||
// x, y, intersectAtAll := IntersectByTwoPointsAttempt2(h1, h2)
|
|
||||||
// x, y, intersectAtAll := IntersectByTwoPointsAttempt3(h1, h2)
|
|
||||||
x, y, intersectAtAll := IntersectBySlopeAndShift(h1, h2)
|
x, y, intersectAtAll := IntersectBySlopeAndShift(h1, h2)
|
||||||
if !intersectAtAll {
|
if !intersectAtAll {
|
||||||
log.Println("no intersection at all\n", x, y)
|
log.Println("no intersection at all\n", x, y)
|
||||||
|
@ -76,79 +106,12 @@ func CheckTaskIntersection(h1, h2 HailParam) (doIntersect bool) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// WRONG
|
func IntersectInTheeDimentions(h1, h2 HailParam) (interX, interY, interZ float64,
|
||||||
func IntersectByLineEquasions(h1, h2 HailParam) (intersectionX, intersectionY float64, isIntersecting bool) {
|
interT float64, isIntersecting bool) {
|
||||||
D := h1.a*h2.b - h1.b*h2.a
|
|
||||||
if D == 0 {
|
|
||||||
return 0, 0, false
|
|
||||||
}
|
|
||||||
Dx := h1.c*h2.b - h1.b*h2.c
|
|
||||||
Dy := h1.a*h2.c - h1.b*h2.a
|
|
||||||
intersectionX = float64(Dx) / float64(D)
|
|
||||||
intersectionY = float64(Dy) / float64(D)
|
|
||||||
isIntersecting = true
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// WRONG
|
|
||||||
// in 2d only
|
|
||||||
func IntersectByTwoPoints(h1, h2 HailParam) (intersectionX, intersectoinY float64, isIntersecting bool) {
|
|
||||||
p1 := h1.p0
|
|
||||||
p2 := h1.p1
|
|
||||||
p3 := h2.p0
|
|
||||||
p4 := h2.p1
|
|
||||||
|
|
||||||
denominator := (p1.x-p2.x)*(p3.y-p4.y) - (p1.y-p2.y)*(p3.x-p4.x)
|
|
||||||
if denominator == 0 {
|
|
||||||
return 0, 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
divisibleX := (p1.x*p2.y-p1.y*p2.x)*(p3.x-p4.x) - (p1.x-p2.x)*(p3.x*p4.y-p3.y*p4.x)
|
|
||||||
divisibleY := (p1.x*p2.y-p1.y*p2.x)*(p3.y-p4.y) - (p1.y-p2.y)*(p3.x*p4.y-p3.y*p4.x)
|
|
||||||
|
|
||||||
x := float64(divisibleX) / float64(denominator)
|
|
||||||
y := float64(divisibleY) / float64(denominator)
|
|
||||||
|
|
||||||
return x, y, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func IntersectByTwoPointsAttempt2(h1, h2 HailParam) (intersectionX, intersectionY float64, isIntersecting bool) {
|
|
||||||
x1 := h1.p0.x
|
|
||||||
y1 := h1.p0.y
|
|
||||||
x2 := h1.p1.x
|
|
||||||
y2 := h1.p1.y
|
|
||||||
x3 := h2.p0.x
|
|
||||||
y3 := h2.p0.y
|
|
||||||
x4 := h2.p1.x
|
|
||||||
y4 := h2.p1.y
|
|
||||||
divisor := (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)
|
|
||||||
if divisor == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
intersectionX = float64((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4)) / float64(divisor)
|
|
||||||
intersectionY = float64((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4)) / float64(divisor)
|
|
||||||
isIntersecting = true
|
|
||||||
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) {
|
func IntersectBySlopeAndShift(h1, h2 HailParam) (intersectionX, intersectionY float64, isIntersecting bool) {
|
||||||
if h1.slope == h2.slope {
|
if h1.slope == h2.slope {
|
||||||
return
|
return
|
||||||
|
@ -166,7 +129,7 @@ func IntersectBySlopeAndShift(h1, h2 HailParam) (intersectionX, intersectionY fl
|
||||||
func (h HailParam) PointInFuture(p Point) bool {
|
func (h HailParam) PointInFuture(p Point) bool {
|
||||||
xPositiveSteps := (p.x-h.p0.x)*h.Dx >= 0
|
xPositiveSteps := (p.x-h.p0.x)*h.Dx >= 0
|
||||||
yPositiveSteps := (p.y-h.p0.y)*h.Dy >= 0
|
yPositiveSteps := (p.y-h.p0.y)*h.Dy >= 0
|
||||||
zPositiveSteps := (p.Z-h.p0.Z)*h.Dz >= 0
|
zPositiveSteps := (p.z-h.p0.z)*h.Dz >= 0
|
||||||
return xPositiveSteps && yPositiveSteps && zPositiveSteps
|
return xPositiveSteps && yPositiveSteps && zPositiveSteps
|
||||||
}
|
}
|
||||||
func (h HailParam) FloatPointInFuture(x, y float64) bool {
|
func (h HailParam) FloatPointInFuture(x, y float64) bool {
|
||||||
|
@ -185,7 +148,7 @@ func ReadHailLine(line string) (h HailParam) {
|
||||||
|
|
||||||
h.p0.x = AtoIOrPanic(fields[0])
|
h.p0.x = AtoIOrPanic(fields[0])
|
||||||
h.p0.y = AtoIOrPanic(fields[1])
|
h.p0.y = AtoIOrPanic(fields[1])
|
||||||
h.p0.Z = AtoIOrPanic(fields[2])
|
h.p0.z = AtoIOrPanic(fields[2])
|
||||||
h.Dx = AtoIOrPanic(fields[3])
|
h.Dx = AtoIOrPanic(fields[3])
|
||||||
h.Dy = AtoIOrPanic(fields[4])
|
h.Dy = AtoIOrPanic(fields[4])
|
||||||
h.Dz = AtoIOrPanic(fields[5])
|
h.Dz = AtoIOrPanic(fields[5])
|
||||||
|
@ -194,7 +157,7 @@ func ReadHailLine(line string) (h HailParam) {
|
||||||
|
|
||||||
h.p1.x = h.p0.x + countP1AfterMillis*h.Dx
|
h.p1.x = h.p0.x + countP1AfterMillis*h.Dx
|
||||||
h.p1.y = h.p0.y + countP1AfterMillis*h.Dy
|
h.p1.y = h.p0.y + countP1AfterMillis*h.Dy
|
||||||
h.p1.Z = h.p0.Z + countP1AfterMillis * h.Dz
|
h.p1.z = h.p0.z + countP1AfterMillis*h.Dz
|
||||||
|
|
||||||
h.a = h.p0.y - h.p1.y
|
h.a = h.p0.y - h.p1.y
|
||||||
h.b = h.p1.x - h.p0.x
|
h.b = h.p1.x - h.p0.x
|
||||||
|
|
|
@ -55,7 +55,7 @@ func TestIntersectExampleOne(t *testing.T) {
|
||||||
hA := ReadHailLine("19, 13, 30 @ -2, 1, -2")
|
hA := ReadHailLine("19, 13, 30 @ -2, 1, -2")
|
||||||
hB := ReadHailLine("18, 19, 22 @ -1, -1, -2")
|
hB := ReadHailLine("18, 19, 22 @ -1, -1, -2")
|
||||||
|
|
||||||
x, y, check := IntersectByTwoPoints(hA, hB)
|
x, y, check := IntersectBySlopeAndShift(hA, hB)
|
||||||
if !check {
|
if !check {
|
||||||
panic("should intersect")
|
panic("should intersect")
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ func TestIntersectExampleTwo(t *testing.T) {
|
||||||
hA := ReadHailLine("18, 19, 22 @ -1, -1, -2")
|
hA := ReadHailLine("18, 19, 22 @ -1, -1, -2")
|
||||||
hB := ReadHailLine("20, 25, 34 @ -2, -2, -4")
|
hB := ReadHailLine("20, 25, 34 @ -2, -2, -4")
|
||||||
|
|
||||||
x, y, check := IntersectByTwoPoints(hA, hB)
|
x, y, check := IntersectBySlopeAndShift(hA, hB)
|
||||||
if check {
|
if check {
|
||||||
panic("should not intersect")
|
panic("should not intersect")
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,9 @@ func TestIntersectExampleTwo(t *testing.T) {
|
||||||
func TestExamplePairwiseChecks(t *testing.T) {
|
func TestExamplePairwiseChecks(t *testing.T) {
|
||||||
filename := "example"
|
filename := "example"
|
||||||
hails := ReadHailFile(filename)
|
hails := ReadHailFile(filename)
|
||||||
|
for _, hail := range hails {
|
||||||
|
t.Log(hail)
|
||||||
|
}
|
||||||
|
|
||||||
intersections := CheckPairwiseIntersections(hails)
|
intersections := CheckPairwiseIntersections(hails)
|
||||||
t.Log("counted intersections ", intersections)
|
t.Log("counted intersections ", intersections)
|
||||||
|
|
|
@ -20,16 +20,86 @@ so, what do i do? to get the ends of the lines?
|
||||||
i try to calcluate with both x & y in 2 min\max. then if the other is ok, than that's the ends?
|
i try to calcluate with both x & y in 2 min\max. then if the other is ok, than that's the ends?
|
||||||
wait, what happens when i do x = 7, and x = 27 and y is outside? it means no intesections, i guess
|
wait, what happens when i do x = 7, and x = 27 and y is outside? it means no intesections, i guess
|
||||||
or it could be outside from different sides, so not all x are ok, but there's still line there
|
or it could be outside from different sides, so not all x are ok, but there's still line there
|
||||||
* Using homogeneous coordinates
|
** Using homogeneous coordinates
|
||||||
https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
|
https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
|
||||||
no, i don't understant that
|
no, i don't understant that
|
||||||
* https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
|
** https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
|
||||||
with 2 points. i guess
|
with 2 points. i guess
|
||||||
but also - check if the point in future of the hail, by comparing with speeds?
|
but also - check if the point in future of the hail, by comparing with speeds?
|
||||||
should be easy
|
should be easy
|
||||||
* and i got wrong result
|
** and i got wrong result
|
||||||
day24 result: 8406
|
day24 result: 8406
|
||||||
* another formula gives
|
** another formula gives
|
||||||
day24 result: 8406
|
day24 result: 8406
|
||||||
* another formula
|
** another formula
|
||||||
12938
|
12938
|
||||||
|
*
|
||||||
|
* ok, part 2.
|
||||||
|
what if.
|
||||||
|
i start checking t = 0, 1, etc.
|
||||||
|
for each t, i need two points of the two hail lines.
|
||||||
|
|
||||||
|
it would constitute the trajectory.
|
||||||
|
then condition for the solution that all other hail lines will intersect it at some t.
|
||||||
|
so check for intersection (maybe not necessarily in the field?)
|
||||||
|
|
||||||
|
go though lines, if any fail to intersect - continue with t
|
||||||
|
|
||||||
|
if all intersect, find where the rock has to be in time 0
|
||||||
|
|
||||||
|
oh. no.
|
||||||
|
it's not just intersect. it's that the movement of the rock with t would be there at correct time? yuck?
|
||||||
|
|
||||||
|
would there really be more than i line that intersects all of the hail lines?
|
||||||
|
|
||||||
|
i'll just need to also figure out t=0 from other coords.
|
||||||
|
|
||||||
|
i don't like this at all.
|
||||||
|
|
||||||
|
And intersections have to be over (X, Y, Z)
|
||||||
|
** so 'hail mary' approach would be
|
||||||
|
scan first 1k nanoseconds. so already 1M calculations
|
||||||
|
( this is first part of desperation, that at least 2 hails will intercept in first 1k ticks )
|
||||||
|
|
||||||
|
for collision 1, assume HailA is on path.
|
||||||
|
then iterate for all other assumint they are intercepted on t 2 etc ?
|
||||||
|
|
||||||
|
no. the intersections could be on non-integer times?
|
||||||
|
( this would be second part of the 'hail mary' )
|
||||||
|
|
||||||
|
from that i should be able to construct the 'trajectory' line.
|
||||||
|
and then check with all other points - do the intersect?
|
||||||
|
( and check of intersection in future would be nice )
|
||||||
|
|
||||||
|
then if line confirmed, will need to calc for t = 0, t = 1, and get speeds
|
||||||
|
*** not hoping for all integer intersections
|
||||||
|
or what if i will hope for that?
|
||||||
|
let's try?
|
||||||
|
* ok, what if i could do system of equasions?
|
||||||
|
#+begin_src
|
||||||
|
yuck_test.go:12:
|
||||||
|
x + Dx * t0 == 19 + -2 * t0
|
||||||
|
y + Dy * t0 == 13 + 1 * t0
|
||||||
|
z + Dz * t0 == 19 + -2 * t0
|
||||||
|
x + Dx * t1 == 18 + -1 * t1
|
||||||
|
y + Dy * t1 == 19 + -1 * t1
|
||||||
|
z + Dz * t1 == 18 + -2 * t1
|
||||||
|
x + Dx * t2 == 20 + -2 * t2
|
||||||
|
y + Dy * t2 == 25 + -2 * t2
|
||||||
|
z + Dz * t2 == 20 + -4 * t2
|
||||||
|
solve for x, y, z, Dx, Dy, Dz, t1, t2, t3. ti > 0
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
yuck_test.go:18:
|
||||||
|
x + Dx * t0 == 147847636573416 + 185 * t0
|
||||||
|
y + Dy * t0 == 190826994408605 + 49 * t0
|
||||||
|
z + Dz * t0 == 147847636573416 + 219 * t0
|
||||||
|
x + Dx * t1 == 287509258905812 + -26 * t1
|
||||||
|
y + Dy * t1 == 207449079739538 + 31 * t1
|
||||||
|
z + Dz * t1 == 287509258905812 + 8 * t1
|
||||||
|
x + Dx * t2 == 390970075767404 + -147 * t2
|
||||||
|
y + Dy * t2 == 535711685410735 + -453 * t2
|
||||||
|
z + Dz * t2 == 390970075767404 + -149 * t2
|
||||||
|
solve for x, y, z, Dx, Dy, Dz, t1, t2, t3. ti > 0
|
||||||
|
#+end_src
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from z3 import *
|
||||||
|
|
||||||
|
s = Solver()
|
||||||
|
|
||||||
|
x = Real('x')
|
||||||
|
Dx = Real('Dx')
|
||||||
|
y = Real('y')
|
||||||
|
Dy = Real('Dy')
|
||||||
|
z = Real('z')
|
||||||
|
Dz = Real('Dz')
|
||||||
|
t0 = Real('t0')
|
||||||
|
eqT0 = t0 >= 0
|
||||||
|
eq0x = x + Dx * t0 == (-2 * t0) + 19
|
||||||
|
eq0y = y + Dy * t0 == (1 * t0) + 13
|
||||||
|
eq0z = z + Dz * t0 == (-2 * t0) + 30
|
||||||
|
t1 = Real('t1')
|
||||||
|
eqT1 = t1 >= 0
|
||||||
|
eq1x = x + Dx * t1 == (-1 * t1) + 18
|
||||||
|
eq1y = y + Dy * t1 == (-1 * t1) + 19
|
||||||
|
eq1z = z + Dz * t1 == (-2 * t1) + 22
|
||||||
|
t2 = Real('t2')
|
||||||
|
eqT2 = t2 >= 0
|
||||||
|
eq2x = x + Dx * t2 == (-2 * t2) + 20
|
||||||
|
eq2y = y + Dy * t2 == (-2 * t2) + 25
|
||||||
|
eq2z = z + Dz * t2 == (-4 * t2) + 34
|
||||||
|
#solve for x, y, z, Dx, Dy, Dz, t1, t2, t3.
|
||||||
|
|
||||||
|
|
||||||
|
s.add(eqT0,
|
||||||
|
eq0x,
|
||||||
|
eq0y,
|
||||||
|
eq0z,
|
||||||
|
eqT1,
|
||||||
|
eq1x,
|
||||||
|
eq1y,
|
||||||
|
eq1z,
|
||||||
|
eqT2,
|
||||||
|
eq2x,
|
||||||
|
eq2y,
|
||||||
|
eq2z)
|
||||||
|
|
||||||
|
if s.check() == sat:
|
||||||
|
print("Solution:", s.model())
|
||||||
|
else:
|
||||||
|
print("No solution found")
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from z3 import *
|
||||||
|
|
||||||
|
x = Real('x')
|
||||||
|
y = Real('y')
|
||||||
|
|
||||||
|
eq1 = x + y == 5
|
||||||
|
eq2 = x - y == 3
|
||||||
|
|
||||||
|
s = Solver()
|
||||||
|
s.add(eq1, eq2)
|
||||||
|
|
||||||
|
if s.check() == sat:
|
||||||
|
print("Solution:", s.model())
|
||||||
|
else:
|
||||||
|
print("No solution found")
|
|
@ -0,0 +1,78 @@
|
||||||
|
package day24
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SystemsWithSymbols() (result string) {
|
||||||
|
result += "\n"
|
||||||
|
coords := []string{"x", "y", "z"}
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
for _, coord := range coords {
|
||||||
|
result += fmt.Sprintf("%s + D%s * t%d == %s%d + D%s%d * t%d\n",
|
||||||
|
coord, coord, i, coord, i, coord, i, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result += "solve for x, y, z, Dx, Dy, Dz, t1, t2, t3. ti > 0"
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SystemFromThreeHailstones(hails []HailParam) (result string) {
|
||||||
|
result += "\n"
|
||||||
|
coords := []string{"x", "y", "z"}
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
result += fmt.Sprintf("t%d >= 0\n", i)
|
||||||
|
hailIter := hails[i]
|
||||||
|
for _, coord := range coords {
|
||||||
|
result += fmt.Sprintf("%s + D%s * t%d == %d + %d * t%d\n",
|
||||||
|
coord, coord, i,
|
||||||
|
hailIter.GetCoord(coord), hailIter.GetSpeedOf(coord), i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result += "solve for x, y, z, Dx, Dy, Dz, t1, t2, t3."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SystemFromThreeHailstonesToTheLeft(hails []HailParam) (result string) {
|
||||||
|
result += "\n"
|
||||||
|
coords := []string{"x", "y", "z"}
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
result += fmt.Sprintf("t%d >= 0\n", i)
|
||||||
|
hailIter := hails[i]
|
||||||
|
for _, coord := range coords {
|
||||||
|
result += fmt.Sprintf("%s + D%s * t%d - (%d * t%d) == %d \n",
|
||||||
|
coord, coord, i,
|
||||||
|
hailIter.GetSpeedOf(coord), i, hailIter.GetCoord(coord))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result += "solve for x, y, z, Dx, Dy, Dz, t1, t2, t3."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SystemAsPythonInit(hails []HailParam) (result string) {
|
||||||
|
result += "\n"
|
||||||
|
coords := []string{"x", "y", "z"}
|
||||||
|
for _, coord := range coords {
|
||||||
|
result += fmt.Sprintf("%s = Real('%s')\n", coord, coord)
|
||||||
|
result += fmt.Sprintf("D%s = Real('D%s')\n", coord, coord)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
result += fmt.Sprintf("t%d = Real('t%d')\n", i, i)
|
||||||
|
result += fmt.Sprintf("eqT%d = t%d >= 0\n", i, i)
|
||||||
|
hailIter := hails[i]
|
||||||
|
for _, coord := range coords {
|
||||||
|
result += fmt.Sprintf("eq%d%s = %s + D%s * t%d == (%d * t%d) + %d \n",
|
||||||
|
i, coord,
|
||||||
|
coord, coord, i,
|
||||||
|
hailIter.GetSpeedOf(coord), i, hailIter.GetCoord(coord))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result += "//solve for x, y, z, Dx, Dy, Dz, t1, t2, t3."
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package day24
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestPrintJustSymbol(t *testing.T) {
|
||||||
|
t.Log(SystemsWithSymbols())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrintSystemExample(t *testing.T) {
|
||||||
|
filename := "example"
|
||||||
|
hails := ReadHailFile(filename)
|
||||||
|
t.Log(SystemAsPythonInit(hails))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrintSystemInput(t *testing.T) {
|
||||||
|
filename := "input"
|
||||||
|
hails := ReadHailFile(filename)
|
||||||
|
t.Log(SystemAsPythonInit(hails))
|
||||||
|
}
|
12
flake.lock
12
flake.lock
|
@ -5,11 +5,11 @@
|
||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1694529238,
|
"lastModified": 1701680307,
|
||||||
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -20,11 +20,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1701253981,
|
"lastModified": 1703255338,
|
||||||
"narHash": "sha256-ztaDIyZ7HrTAfEEUt9AtTDNoCYxUdSd6NrRHaYOIxtk=",
|
"narHash": "sha256-Z6wfYJQKmDN9xciTwU3cOiOk+NElxdZwy/FiHctCzjU=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "e92039b55bcd58469325ded85d4f58dd5a4eaf58",
|
"rev": "6df37dc6a77654682fe9f071c62b4242b5342e04",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
Loading…
Reference in New Issue