Skip to content

Commit

Permalink
day 24 part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
kcaffrey committed Dec 24, 2023
1 parent 8ee35bb commit b058151
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
| [Day 21](./src/bin/21.rs) | `64.1µs` | `494.7µs` |
| [Day 22](./src/bin/22.rs) | `78.3µs` | `194.8µs` |
| [Day 23](./src/bin/23.rs) | `330.4µs` | `13.3ms` |
| [Day 24](./src/bin/24.rs) | `369.6µs` | `-` |

**Total: 30.24ms**
**Total: 30.61ms**
<!--- benchmarking table --->

---
Expand Down
5 changes: 5 additions & 0 deletions data/examples/24.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
19, 13, 30 @ -2, 1, -2
18, 19, 22 @ -1, -1, -2
20, 25, 34 @ -2, -2, -4
12, 31, 28 @ -1, -2, -1
20, 19, 15 @ 1, -5, -3
145 changes: 145 additions & 0 deletions src/bin/24.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
advent_of_code::solution!(24);

pub fn part_one(input: &str) -> Option<u32> {
let hailstones = parse_hailstones(input);
Some(count_xy_intersections(
hailstones,
200000000000000,
400000000000000,
))
}

fn count_xy_intersections<T: AsRef<[Hailstone]>>(
hailstones: T,
min_position: i64,
max_position: i64,
) -> u32 {
let hailstones = hailstones.as_ref();
let mut count = 0;
for i in 0..hailstones.len() {
for j in i + 1..hailstones.len() {
let mut a = hailstones[i];
let mut b = hailstones[j];
if a.velocity.x == 0 || b.velocity.y * a.velocity.x == a.velocity.y * b.velocity.x {
std::mem::swap(&mut a, &mut b);
}
if a.velocity.x == 0 || b.velocity.y * a.velocity.x == a.velocity.y * b.velocity.x {
// Can't intersect?
continue;
}
let t = (a.position.y * a.velocity.x + a.velocity.y * b.position.x
- a.velocity.y * a.position.x
- b.position.y * a.velocity.x) as f64
/ (b.velocity.y * a.velocity.x - a.velocity.y * b.velocity.x) as f64;
let s = ((b.position.x - a.position.x) as f64 + b.velocity.x as f64 * t)
/ a.velocity.x as f64;
if t < 0.0 || s < 0.0 {
// Intersection in past.
continue;
}
let x = a.position.x as f64 + a.velocity.x as f64 * s;
let y = a.position.y as f64 + a.velocity.y as f64 * s;
if x >= min_position as f64
&& x <= max_position as f64
&& y >= min_position as f64
&& y <= max_position as f64
{
count += 1;
}
}
}
count
}

pub fn part_two(input: &str) -> Option<u32> {
None
}

fn parse_hailstones(input: &str) -> Vec<Hailstone> {
let mut input = input.as_bytes();
let width = input.iter().position(|&ch| ch == b'\n').unwrap();
let estimated_rows = (input.len() + 1) / (width + 1);
let mut hailstones = Vec::with_capacity(estimated_rows);
while input.len() > 1 {
let (rest, hailstone) = parse_hailstone(input);
input = &rest[1.min(rest.len())..];
hailstones.push(hailstone);
}
hailstones
}

fn parse_hailstone(input: &[u8]) -> (&[u8], Hailstone) {
let (input, position) = parse_point3(input);
let input = &input[input
.iter()
.position(|&ch| ch != b'@' && ch != b' ')
.unwrap()..];
let (input, velocity) = parse_point3(input);
(input, Hailstone { position, velocity })
}

fn parse_point3(input: &[u8]) -> (&[u8], Point3) {
let (input, x) = parse_num(input);
let input = &input[input
.iter()
.position(|&ch| ch != b',' && ch != b' ')
.unwrap()..];
let (input, y) = parse_num(input);
let input = &input[input
.iter()
.position(|&ch| ch != b',' && ch != b' ')
.unwrap()..];
let (input, z) = parse_num(input);
(input, Point3 { x, y, z })
}

fn parse_num(mut input: &[u8]) -> (&[u8], i64) {
let sign = if input[0] == b'-' {
input = &input[1..];
-1
} else {
1
};
let mut num = 0;
for i in 0..input.len() {
let ch = input[i];
match ch {
b'0'..=b'9' => num = num * 10 + (ch - b'0') as i64,
_ => {
return (&input[i..], num * sign);
}
}
}
(&input[input.len()..], num * sign)
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
struct Hailstone {
position: Point3,
velocity: Point3,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
struct Point3 {
x: i64,
y: i64,
z: i64,
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_part_one() {
let hailstones = parse_hailstones(&advent_of_code::template::read_file("examples", DAY));
let result = count_xy_intersections(hailstones, 7, 27);
assert_eq!(result, 2);
}

#[test]
fn test_part_two() {
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, None);
}
}

0 comments on commit b058151

Please sign in to comment.