Skip to content

Commit 18e93c5

Browse files
committed
day24pt2: done
This solution makes multiple assumptions that only apply to the real Advent of Code 2023 Day 24 input; this won't even work on the sample input. 1. A solution exists at all. 2. The dx/dy/dz of the thrown rock ranges between 0 and 1000; there's no reason to assume this, except that all the velocities of the hailstones follow this rule. 3. On each of the x/y/z axes, there is exactly one common divisor for the differences between positions of all pairs of hailstones that have the same velocity component along that axis, e.g. if two hailstones have the same dx, the difference of rock's dx and that of the hailstones must be a divisor of the difference in the x positions of those hailstones, and this divisor must exist for all such pairs. 4. The rock's dx, dy and dz are all positive, otherwise there would be eight possible thrown rock vectors to check. For fairly-involved puzzles like these, Advent of Code likes to keep solutions simple once you've found out the gimmick hidden in the input, and checking multiple negative rock velocity axes seems like too much effort from this perspective.
1 parent 7824848 commit 18e93c5

File tree

4 files changed

+143
-0
lines changed

4 files changed

+143
-0
lines changed

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ members = [
4747
"day23",
4848
"day23pt2",
4949
"day24",
50+
"day24pt2",
5051
]
5152

5253
[profile.dev]

day24pt2/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "day24pt2"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]

day24pt2/src/main.rs

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#[derive(Debug)]
2+
struct Line {
3+
x: i64,
4+
y: i64,
5+
z: i64,
6+
dx: i16,
7+
dy: i16,
8+
dz: i16,
9+
}
10+
11+
impl From<&str> for Line {
12+
fn from(s: &str) -> Self {
13+
let (x, s) = s
14+
.split_once(", ")
15+
.map(|(n, s)| (n.parse::<i64>().expect("x i64"), s))
16+
.expect("comma");
17+
let (y, s) = s
18+
.split_once(", ")
19+
.map(|(n, s)| (n.parse::<i64>().expect("y i64"), s))
20+
.expect("comma");
21+
let (z, s) = s
22+
.split_once(" @ ")
23+
.map(|(n, s)| (n.parse::<i64>().expect("z i64"), s))
24+
.expect("at sign");
25+
let (dx, s) = s
26+
.split_once(", ")
27+
.map(|(n, s)| (n.parse::<i16>().expect("dx i16"), s))
28+
.expect("comma");
29+
let (dy, s) = s
30+
.split_once(", ")
31+
.map(|(n, s)| (n.parse::<i16>().expect("dy i16"), s))
32+
.expect("comma");
33+
let dz = s.parse::<i16>().expect("dz i16");
34+
Self {
35+
x,
36+
y,
37+
z,
38+
dx,
39+
dy,
40+
dz,
41+
}
42+
}
43+
}
44+
45+
fn line_intersection(
46+
ax: i64,
47+
ay: i64,
48+
adx: i16,
49+
ady: i16,
50+
bx: i64,
51+
by: i64,
52+
bdx: i16,
53+
bdy: i16,
54+
) -> Option<(i64, i64)> {
55+
let adx = adx as i64;
56+
let ady = ady as i64;
57+
let bdx = bdx as i64;
58+
let bdy = bdy as i64;
59+
let denom = bdy * adx - bdx * ady;
60+
if denom == 0 {
61+
return None;
62+
}
63+
let ua = (bdx * (ay - by) - bdy * (ax - bx)) / denom;
64+
//let ub = (adx * (ay - by) - ady * (ax - bx)) / denom;
65+
let x = ax + ua * adx;
66+
let y = ay + ua * ady;
67+
return Some((x, y));
68+
}
69+
70+
fn main() {
71+
let lines = std::io::stdin()
72+
.lines()
73+
.map(Result::unwrap)
74+
.map(|line| Line::from(&line[..]))
75+
.collect::<Vec<_>>();
76+
let mut x_divisors: Vec<i64> = (0..1000).collect::<Vec<_>>();
77+
let mut y_divisors: Vec<i64> = (0..1000).collect::<Vec<_>>();
78+
let mut z_divisors: Vec<i64> = (0..1000).collect::<Vec<_>>();
79+
for a in 0..lines.len() - 1 {
80+
for b in a + 1..lines.len() {
81+
if lines[a].dx == lines[b].dx {
82+
let dx = lines[a].dx as i64;
83+
let x_diff = lines[a].x.abs_diff(lines[b].x) as i64;
84+
x_divisors.retain(|&x_div| dx == x_div || x_diff % (x_div - dx) == 0);
85+
}
86+
if lines[a].dy == lines[b].dy {
87+
let dy = lines[a].dy as i64;
88+
let y_diff = lines[a].y.abs_diff(lines[b].y) as i64;
89+
y_divisors.retain(|&y_div| dy == y_div || y_diff % (y_div - dy) == 0);
90+
}
91+
if lines[a].dz == lines[b].dz {
92+
let dz = lines[a].dz as i64;
93+
let z_diff = lines[a].z.abs_diff(lines[b].z) as i64;
94+
z_divisors.retain(|&z_div| dz == z_div || z_diff % (z_div - dz) == 0);
95+
}
96+
}
97+
}
98+
println!("{x_divisors:?} {y_divisors:?} {z_divisors:?}");
99+
assert_eq!(1, x_divisors.len());
100+
assert_eq!(1, y_divisors.len());
101+
assert_eq!(1, z_divisors.len());
102+
let rock_dx = x_divisors[0] as i16;
103+
let rock_dy = y_divisors[0] as i16;
104+
let rock_dz = z_divisors[0] as i16;
105+
let (rock_x1, rock_y) = line_intersection(
106+
lines[0].x,
107+
lines[0].y,
108+
lines[0].dx - rock_dx,
109+
lines[0].dy - rock_dy,
110+
lines[1].x,
111+
lines[1].y,
112+
lines[1].dx - rock_dx,
113+
lines[1].dy - rock_dy,
114+
)
115+
.expect("xy intersection");
116+
let (rock_x2, rock_z) = line_intersection(
117+
lines[0].x,
118+
lines[0].z,
119+
lines[0].dx - rock_dx,
120+
lines[0].dz - rock_dz,
121+
lines[1].x,
122+
lines[1].z,
123+
lines[1].dx - rock_dx,
124+
lines[1].dz - rock_dz,
125+
)
126+
.expect("xz intersection");
127+
assert_eq!(rock_x1, rock_x2);
128+
println!("{rock_x1} {rock_y} {rock_z}");
129+
println!("{}", rock_x1 + rock_y + rock_z);
130+
}

0 commit comments

Comments
 (0)