Skip to content

Commit 7d78397

Browse files
committed
day24
1 parent 4def78e commit 7d78397

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

24/sample_input

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
19, 13, 30 @ -2, 1, -2
2+
18, 19, 22 @ -1, -1, -2
3+
20, 25, 34 @ -2, -2, -4
4+
12, 31, 28 @ -1, -2, -1
5+
20, 19, 15 @ 1, -5, -3

24/sol.exs

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
defmodule Day24 do
2+
def read_input(file_path) do
3+
file_path |> File.read!() |> String.split("\n", trim: true) |> Enum.map(&parse_line/1)
4+
end
5+
6+
def parse_line(line) do
7+
[px, py, pz, vx, vy, vz] =
8+
line |> String.split(~r/\ |,|@/, trim: true) |> Enum.map(&String.to_integer/1)
9+
10+
m = vy / vx
11+
b = py - m * px
12+
%{vel: {vx, vy, vz}, pos: {px, py, pz}, m: m, b: b}
13+
end
14+
15+
def valid_intersection_xy(
16+
%{
17+
pos: {pxa, _pya, _pza},
18+
vel: {vxa, _vya, _vza},
19+
m: ma,
20+
b: ba
21+
},
22+
%{
23+
pos: {pxb, _pyb, _pzb},
24+
vel: {vxb, _vyb, _vzb},
25+
m: mb,
26+
b: bb
27+
}
28+
) do
29+
if abs(ma - mb) < 1.0e-8 do
30+
false
31+
else
32+
x = (bb - ba) / (ma - mb)
33+
y = ma * x + ba
34+
35+
ta = (x - pxa) / vxa
36+
tb = (x - pxb) / vxb
37+
38+
ta >= 0 and tb >= 0 and x >= 200_000_000_000_000 and x <= 400_000_000_000_000 and
39+
y >= 200_000_000_000_000 and y <= 400_000_000_000_000
40+
end
41+
end
42+
43+
def count_intersections_xy(list), do: count_intersections_xy(list, 0)
44+
def count_intersections_xy([], acc), do: acc
45+
46+
def count_intersections_xy([x | xs], acc) do
47+
count_intersections_xy(xs, acc + (xs |> Enum.count(&valid_intersection_xy(&1, x))))
48+
end
49+
50+
def dot({a1, a2, a3}, {b1, b2, b3}), do: a1 * b1 + a2 * b2 + a3 * b3
51+
52+
def cross({a1, a2, a3}, {b1, b2, b3}),
53+
do: {
54+
a2 * b3 - b2 * a3,
55+
a3 * b1 - b3 * a1,
56+
a1 * b2 - b1 * a2
57+
}
58+
59+
def neg({a, b, c}), do: {-a, -b, -c}
60+
def add({a1, a2, a3}, {b1, b2, b3}), do: {a1 + b1, a2 + b2, a3 + b3}
61+
def sub(a, b), do: add(a, neg(b))
62+
def mult(m, {x, y, z}), do: {m * x, m * y, m * z}
63+
64+
def plane(%{pos: p1, vel: v1}, %{pos: p2, vel: v2}) do
65+
p12 = sub(p1, p2)
66+
v12 = sub(v1, v2)
67+
vv = cross(v1, v2)
68+
{cross(p12, v12), dot(p12, vv)}
69+
end
70+
71+
def rock(%{pos: p1, vel: v1} = h1, %{pos: p2, vel: v2} = h2, %{pos: _p3, vel: _v3} = h3) do
72+
{a, a_} = plane(h1, h2)
73+
{b, b_} = plane(h1, h3)
74+
{c, c_} = plane(h2, h3)
75+
w = mult(a_, cross(b, c)) |> add(mult(b_, cross(c, a))) |> add(mult(c_, cross(a, b)))
76+
t = dot(a, cross(b, c))
77+
w = mult(1 / t, w)
78+
w1 = sub(v1, w)
79+
w2 = sub(v2, w)
80+
ww = cross(w1, w2)
81+
e = dot(ww, cross(p2, w2))
82+
f = dot(ww, cross(p1, w1))
83+
g = dot(p1, ww)
84+
s = dot(ww, ww)
85+
mult(e / s, w1) |> add(mult(-f / s, w2)) |> add(mult(g / s, ww))
86+
end
87+
88+
def partA(file_path) do
89+
# Somehow, partA works for my real input but fails on sample input, interesting.
90+
file_path |> read_input() |> count_intersections_xy()
91+
end
92+
93+
def partB(file_path) do
94+
[a, b, c | _] = file_path |> read_input()
95+
{x, y, z} = rock(a, b, c)
96+
round(x + y + z)
97+
end
98+
end
99+
100+
IO.puts(Day24.partA("./input"))
101+
IO.puts(Day24.partB("./input"))

0 commit comments

Comments
 (0)