#import "Basic";
#import "String";
#import "File";
#import "Math";
solve_day24 :: (test: bool) {
input := read_entire_file("inputs/day24.txt");
string_lines := split(input, "\n");
lines: [..]Line;
lines_f: [..]Line_F;
parse(string_lines, *lines, *lines_f);
part_1 := 0;
for l1: 0..lines_f.count - 2 {
for l2: l1 + 1..lines_f.count - 1 {
pos, success := xy_line_intersect(lines_f[l1], lines_f[l2]);
if success && pos.x >= 200_000_000_000_000 && pos.x <= 400_000_000_000_000
&& pos.y >= 200_000_000_000_000 && pos.y <= 400_000_000_000_000 {
part_1 += 1;
}
if success && pos.x >= 7 && pos.x <= 27
&& pos.y >= 7 && pos.y <= 27 {
part_1 += 1;
}
}
}
print("Part 1: %\n", part_1);
l1 := lines[0];
l2 := lines[1];
l3 := lines[2];
l4 := lines[3];
l2.dir = subtract(l2.dir, l1.dir);
l3.dir = subtract(l3.dir, l1.dir);
l4.dir = subtract(l4.dir, l1.dir);
ll := subtract(l2.point, l1.point);
plane := Plane.{
point = l1.point,
dir = cross(ll, add(ll, l2.dir)),
};
i1, d1 := plane_line_intersect(plane, l3);
i2, d2 := plane_line_intersect(plane, l4);
stone_dir := div(subtract(i1, i2), d2 - d1);
stone_pos := add(mul(stone_dir, d1), i1);
f := stone_pos.x + stone_pos.y + stone_pos.z;
print("Part 2: %\n", f.low);
}
parse :: (input: []string, lines: *[..]Line, lines_f: *[..]Line_F) {
for input {
if it.count == 0 continue;
sections := split(it, " @ ");
coords := split(sections[0], ", ");
dir := split(sections[1], ", ");
xp_f,_ := string_to_float64(coords[0]);
yp_f,_ := string_to_float64(coords[1]);
zp_f,_ := string_to_float64(coords[2]);
xd_f,_ := string_to_float64(dir[0]);
yd_f,_ := string_to_float64(dir[1]);
zd_f,_ := string_to_float64(dir[2]);
xp,_ := string_to_int(coords[0]);
yp,_ := string_to_int(coords[1]);
zp,_ := string_to_int(coords[2]);
xd,_ := string_to_int(dir[0]);
yd,_ := string_to_int(dir[1]);
zd,_ := string_to_int(dir[2]);
array_add(lines_f, .{
point = .{
x = xp_f,
y = yp_f,
z = zp_f,
},
dir = .{
x = xd_f,
y = yd_f,
z = zd_f,
},
});
array_add(lines, .{
point = .{
x = to_s128(xp),
y = to_s128(yp),
z = to_s128(zp),
},
dir = .{
x = to_s128(xd),
y = to_s128(yd),
z = to_s128(zd),
},
});
}
}
Vec3f64 :: struct {
x: float64;
y: float64;
z: float64;
}
Vec3i :: struct {
x: S128;
y: S128;
z: S128;
}
Plane :: struct {
point: Vec3i;
dir: Vec3i;
}
Line_F :: struct {
point: Vec3f64;
dir: Vec3f64;
}
Line :: struct {
point: Vec3i;
dir: Vec3i;
}
dot :: (v1: Vec3i, v2: Vec3i) -> S128 {
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}
cross :: (v1: Vec3i, v2: Vec3i) -> Vec3i {
return .{
x = v1.y * v2.z - v1.z * v2.y,
y = v1.z * v2.x - v1.x * v2.z,
z = v1.x * v2.y - v1.y * v2.x,
};
}
div :: (v: Vec3i, scalar: S128) -> Vec3i {
return .{
x = v.x / scalar,
y = v.y / scalar,
z = v.z / scalar,
};
}
add :: (v1: Vec3i, v2: Vec3i) -> Vec3i {
return .{
x = v1.x + v2.x,
y = v1.y + v2.y,
z = v1.z + v2.z,
};
}
mul :: (v: Vec3i, scalar: S128) -> Vec3i {
return .{
x = v.x * scalar,
y = v.y * scalar,
z = v.z * scalar,
};
}
subtract :: (v1: Vec3i, v2: Vec3i) -> Vec3i {
return .{
x = v1.x - v2.x,
y = v1.y - v2.y,
z = v1.z - v2.z,
};
}
plane_line_intersect :: (plane: Plane, line: Line) -> Vec3i, S128 {
s := dot(subtract(plane.point, line.point), plane.dir) / dot(plane.dir, line.dir);
return add(line.point, mul(line.dir, s)), s;
}
xy_line_intersect :: (l1: Line_F, l2: Line_F) -> (pos: Vec3f64, success: bool) {
det := l2.dir.x * l1.dir.y - l2.dir.y * l1.dir.x;
u := ((l2.point.y - l1.point.y) * l2.dir.x - (l2.point.x - l1.point.x) * l2.dir.y) / det;
v := ((l2.point.y - l1.point.y) * l1.dir.x - (l2.point.x - l1.point.x) * l1.dir.y) / det;
if u < 0 || v < 0 return .{x = 0, y = 0, z = 0}, false;
result := Vec3f64.{
x = l2.point.x + l2.dir.x * v,
y = l2.point.y + l2.dir.y * v,
};
return result, true;
}