Skip to content

Commit bd6ec98

Browse files
committed
Solution for 2023, day 24 + vendor
1 parent bac48cc commit bd6ec98

File tree

336 files changed

+75949
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

336 files changed

+75949
-1
lines changed

2023/24/Makefile

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
main1:
2+
go build -o main1 main1.go common.go
3+
4+
main2:
5+
go build -o main2 main2.go common.go
6+
7+
.PHONY: run1 run2 clean
8+
9+
run1: main1
10+
./main1 <input
11+
12+
run2: main2
13+
./main2 <input
14+
15+
clean:
16+
rm -f main1 main2
17+

2023/24/common.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"os"
7+
)
8+
9+
type P struct{ x, y, z float64 }
10+
11+
type HailStone struct{ Pos, Vel P }
12+
13+
func parse() []HailStone {
14+
hail := []HailStone{}
15+
scanner := bufio.NewScanner(os.Stdin)
16+
for scanner.Scan() {
17+
ice := HailStone{}
18+
_, _ = fmt.Sscanf(
19+
scanner.Text(),
20+
"%f, %f, %f @ %f, %f, %f",
21+
&ice.Pos.x,
22+
&ice.Pos.y,
23+
&ice.Pos.z,
24+
&ice.Vel.x,
25+
&ice.Vel.y,
26+
&ice.Vel.z,
27+
)
28+
hail = append(hail, ice)
29+
}
30+
return hail
31+
}

2023/24/main1.go

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package main
2+
3+
import "fmt"
4+
5+
const (
6+
Min = 200000000000000
7+
Max = 400000000000000
8+
)
9+
10+
func main() {
11+
hail := parse()
12+
13+
count := 0
14+
for i := 0; i < len(hail)-1; i++ {
15+
for j := i + 1; j < len(hail); j++ {
16+
p, intersect := findIntersection(hail[i], hail[j])
17+
18+
if intersect {
19+
if p.x >= Min && p.x <= Max && p.y >= Min && p.y <= Max {
20+
count++
21+
}
22+
}
23+
}
24+
}
25+
26+
fmt.Println(count)
27+
}
28+
29+
func findIntersection(h1, h2 HailStone) (P, bool) {
30+
// (1) xf = x0 + vx*t ==> t = (xf-x0)/vx
31+
// (2) yf = y0 + vy*t
32+
//
33+
// Combining (1) and (2)
34+
// yf = y0 + vy * (xf-x0)/vx
35+
// yf = y0 + (vy/vx)(xf-x0)
36+
// yf = (vy/vx) * xf + [ y0 - (vy/vx)*x0 ]
37+
// y = m * x + q
38+
//
39+
// m = vy/vx
40+
// q = y0 - m*x0
41+
42+
m1 := h1.Vel.y / h1.Vel.x
43+
m2 := h2.Vel.y / h2.Vel.x
44+
45+
if m1 == m2 {
46+
// parallel lines
47+
return P{}, false
48+
}
49+
50+
q1 := h1.Pos.y - m1*h1.Pos.x
51+
q2 := h2.Pos.y - m2*h2.Pos.x
52+
53+
xf := (q2 - q1) / (m1 - m2)
54+
yf := m1*xf + q1
55+
56+
// they meet in (xf,yf)
57+
// need to check if this was in the past
58+
59+
// From (1)
60+
t1 := (xf - h1.Pos.x) / h1.Vel.x
61+
if t1 < 0 {
62+
// past
63+
return P{}, false
64+
}
65+
66+
// From (1)
67+
t2 := (yf - h2.Pos.y) / h2.Vel.y
68+
if t2 < 0 {
69+
// past
70+
return P{}, false
71+
}
72+
73+
return P{xf, yf, 0}, true
74+
}

2023/24/main2.go

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
6+
"gonum.org/v1/gonum/mat"
7+
)
8+
9+
// Given:
10+
// (1) p¹ = p₀¹ + v¹⋅t
11+
// (2) p² = p₀² + v²⋅t
12+
// (3) p³ = p₀³ + v³⋅t
13+
// ...
14+
//
15+
// Find:
16+
// p = p₀ + v⋅t
17+
//
18+
// such as:
19+
// p¹=p when t¹=t
20+
// p²=p when t²=t
21+
// p³=p when t³=t
22+
// ...
23+
//
24+
// where
25+
// pⁿ = [pₓⁿ, pᵧⁿ, pₛⁿ]
26+
// p₀ⁿ = [pₓ₀ⁿ, pᵧⁿ, pₛ₀ⁿ]
27+
// vⁿ = [vₓⁿ, vᵧⁿ, vₛⁿ]
28+
29+
// p¹ + v¹⋅t = p + v⋅t
30+
// p² + v²⋅t = p + v⋅t
31+
// p³ + v³⋅t = p + v⋅t
32+
// pⁿ + vⁿ⋅t = p + v⋅t
33+
//
34+
// (p - p¹) = (v¹ - v)t¹
35+
// (p - p²) = (v² - v)t²
36+
// (p - p³) = (v³ - v)t³
37+
// (p - pⁿ) = (vⁿ - v)tⁿ
38+
// and so:
39+
// (p - pⁿ) ⋅ (v-vⁿ) = 0
40+
func main() {
41+
hail := parse()
42+
43+
// Ax = b
44+
//
45+
// A = [ 0, -v⁰ₛ +v¹ₛ, v⁰ᵧ - v¹ᵧ, 0, -p¹ₛ +p⁰ₛ, p¹ᵧ -p⁰ᵧ
46+
// v⁰ₛ -v¹ₛ, 0, -v⁰ₓ + v¹ₓ, p¹ₛ -p⁰ₛ, 0, -p¹ₓ +p⁰ₓ
47+
// -v⁰ᵧ +v¹ᵧ, v⁰ₓ -v¹ₓ, 0, -p¹ᵧ +p⁰ᵧ, p¹ₓ -p⁰ₓ, 0
48+
// 0, -v⁰ₛ +v²ₛ, v⁰ᵧ - v²ᵧ, 0, -p²ₛ +p⁰ₛ, p²ᵧ -p⁰ᵧ
49+
// v⁰ₛ -v²ₛ, 0, -v⁰ₓ + v²ₓ, p²ₛ -p⁰ₛ, 0, -p²ₓ +p⁰ₓ
50+
// -v⁰ᵧ +v²ᵧ, v⁰ₓ -v²ₓ, 0, -p²ᵧ +p⁰ᵧ, p²ₓ -p⁰ₓ, 0 ]
51+
//
52+
// x = [ pₓ
53+
// pᵧ
54+
// pₛ
55+
// vₓ
56+
// vᵧ
57+
// vₛ ]
58+
//
59+
// b = [ p¹ᵧ⋅v¹ₛ -p¹ₛ⋅v¹ᵧ -p⁰ᵧ⋅v⁰ₛ +p⁰ₛ⋅v⁰ᵧ,
60+
// p¹ₛ⋅v¹ₓ -p¹ₓ⋅v¹ₛ -p⁰ₛ⋅v⁰ₓ +p⁰ₓ⋅v⁰ₛ,
61+
// p¹ₓ⋅v¹ᵧ -p¹ᵧ⋅v¹ₓ -p⁰ₓ⋅v⁰ᵧ +p⁰ᵧ⋅v⁰ₓ,
62+
// p²ᵧ⋅v²ₛ -p²ₛ⋅v²ᵧ -p⁰ᵧ⋅v⁰ₛ +p⁰ₛ⋅v⁰ᵧ,
63+
// p²ₛ⋅v²ₓ -p²ₓ⋅v²ₛ -p⁰ₛ⋅v⁰ₓ +p⁰ₓ⋅v⁰ₛ,
64+
// p²ₓ⋅v²ᵧ -p²ᵧ⋅v²ₓ -p⁰ₓ⋅v⁰ᵧ +p⁰ᵧ⋅v⁰ₓ ]
65+
//
66+
67+
// hail[0] with hail[1]
68+
// (p0 - p[1]) x (v0 - v[1]) == 0
69+
A00 := diff(crossMatrix(hail[0].Vel), crossMatrix(hail[1].Vel))
70+
A03 := diff(crossMatrix(hail[1].Pos), crossMatrix(hail[0].Pos))
71+
72+
// hail[0] with hail[2]
73+
// (p0 - p[2]) x (v0 - v[2]) == 0
74+
A30 := diff(crossMatrix(hail[0].Vel), crossMatrix(hail[2].Vel))
75+
A33 := diff(crossMatrix(hail[2].Pos), crossMatrix(hail[0].Pos))
76+
77+
A := mat.NewDense(6, 6, []float64{
78+
A00[0], A00[1], A00[2], A03[0], A03[1], A03[2],
79+
A00[3], A00[4], A00[5], A03[3], A03[4], A03[5],
80+
A00[6], A00[7], A00[8], A03[6], A03[7], A03[8],
81+
A30[0], A30[1], A30[2], A33[0], A33[1], A33[2],
82+
A30[3], A30[4], A30[5], A33[3], A33[4], A33[5],
83+
A30[6], A30[7], A30[8], A33[6], A33[7], A33[8],
84+
})
85+
86+
b0 := diff(hail[1].Pos.cross(hail[1].Vel).toF(), hail[0].Pos.cross(hail[0].Vel).toF())
87+
b3 := diff(hail[2].Pos.cross(hail[2].Vel).toF(), hail[0].Pos.cross(hail[0].Vel).toF())
88+
89+
b := mat.NewVecDense(6, []float64{b0[0], b0[1], b0[2], b3[0], b3[1], b3[2]})
90+
91+
var x mat.VecDense
92+
_ = x.SolveVec(A, b)
93+
94+
rock := HailStone{
95+
Pos: P{x.At(0, 0), x.At(1, 0), x.At(2, 0)},
96+
Vel: P{x.At(3, 0), x.At(4, 0), x.At(5, 0)},
97+
}
98+
99+
fmt.Printf("%.0f\n", rock.Pos.x+rock.Pos.y+rock.Pos.z)
100+
}
101+
102+
func crossMatrix(p P) []float64 {
103+
return []float64{
104+
0, -p.z, p.y,
105+
p.z, 0, -p.x,
106+
-p.y, p.x, 0,
107+
}
108+
}
109+
110+
func diff(a, b []float64) []float64 {
111+
res := make([]float64, len(a))
112+
for i := 0; i < len(a); i++ {
113+
res[i] = a[i] - b[i]
114+
}
115+
return res
116+
}
117+
118+
// https://wikimedia.org/api/rest_v1/media/math/render/svg/3242bd71d63c393d02302c7dbe517cd0ec352d31
119+
// https://en.wikipedia.org/wiki/Cross_product#Coordinate_notation
120+
func (p P) cross(p2 P) P {
121+
return P{
122+
p.y*p2.z - p.z*p2.y,
123+
p.z*p2.x - p.x*p2.z,
124+
p.x*p2.y - p.y*p2.x,
125+
}
126+
}
127+
128+
func (p P) toF() []float64 {
129+
return []float64{p.x, p.y, p.z}
130+
}

go.mod

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ module github.com/lucianoq/adventofcode
22

33
go 1.23.4
44

5-
require github.com/lucianoq/container/set v0.0.0-20220318183130-8a364c4afb3e
5+
require (
6+
github.com/lucianoq/container/set v0.0.0-20220318183130-8a364c4afb3e
7+
gonum.org/v1/gonum v0.15.1
8+
)

go.sum

+4
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
github.com/lucianoq/container/set v0.0.0-20220318183130-8a364c4afb3e h1:22MyLR3FQpLZGoCTyvD05lbVOptCgY4U+uAGVdPf3OQ=
22
github.com/lucianoq/container/set v0.0.0-20220318183130-8a364c4afb3e/go.mod h1:MQlqJvLUYtP+m6YG0x7FteiDO0QQCN0i0d1KqFtxO/c=
3+
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
4+
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
5+
gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0=
6+
gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o=

0 commit comments

Comments
 (0)