Skip to content

Commit

Permalink
Part 1, Day 24
Browse files Browse the repository at this point in the history
  • Loading branch information
bozdoz committed Jan 14, 2024
1 parent 7a8773a commit ad78218
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 22 deletions.
12 changes: 12 additions & 0 deletions BLOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# What Am I Learning Each Day?

### Day 24

**Difficulty: 5/10 ★★★★★★☆☆☆☆☆**

**Time: ~3 hrs**

**Run Time: ~8ms**

Part One seemed alright. I had a hard time with floats, and understanding that the hailstones intersect in the past (because they're not just straight lines).

I have no idea how to do Part Two and will have to find out what other people did.

### Day 23

**Difficulty: 9/10 ★★★★★★★★★★☆**
Expand Down
5 changes: 5 additions & 0 deletions day-24/src/example.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
152 changes: 130 additions & 22 deletions day-24/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
use std::{ time::Instant, fs, str::FromStr, io::Error, vec };
use std::{
time::Instant,
fs,
str::FromStr,
io::Error,
vec,
};
use lib::get_part;

struct Vec3d(isize, isize, isize);
Expand All @@ -9,7 +15,15 @@ impl FromStr for Vec3d {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let pos = s
.split(", ")
.map(|x| x.parse::<isize>().unwrap())
.map(|x| {
let num = x.trim().parse::<isize>();

if num.is_err() {
panic!("what is this? {}", x);
}

num.unwrap()
})
.collect::<Vec<isize>>();

Result::Ok(Self(pos[0], pos[1], pos[2]))
Expand All @@ -19,36 +33,66 @@ impl FromStr for Vec3d {
struct Hailstone {
position: Vec3d,
velocity: Vec3d,
slope: isize,
intercept: isize,
// dang
slope: f64,
intercept: f64,
}

impl Hailstone {
fn new(position: Vec3d, velocity: Vec3d) -> Self {
let (x1, y1, z1) = (position.0, position.1, position.2);
let (x2, y2, z2) = (x1 + velocity.0, y1 + velocity.1, z1 + velocity.2);
let (x2, y2, _z2) = (x1 + velocity.0, y1 + velocity.1, z1 + velocity.2);

// TODO: this is 2d
let slope = (y2 - y1) / (x2 - x1);
let slope = ((y2 - y1) as f64) / ((x2 - x1) as f64);

// TODO: this is 2d
let intercept = y1 - slope * x1;
let intercept = (y1 as f64) - slope * (x1 as f64);

Self {
position,
velocity,
slope,
intercept
intercept,
}
}

fn intersects(&self, b: Hailstone) -> Vec3d {
// TODO: 2d
// and wow f64
fn intersects(&self, b: &Hailstone) -> Result<(f64, f64, f64), &str> {
// x0​= (b2​−b1) / (a1​−a2)
// ​​y0​= a1*(b2​−b1​​)/(​a1​−a2​)+b1​
// ​​y0​= a1*x0+b1​
let div: f64 = (self.slope - b.slope) as f64;

if div == (0 as f64) {
return Err("divide by zero");
}

if b.slope == self.slope {
return Err("parallel");
}

let x = ((b.intercept - self.intercept) as f64) / div;
let y = (self.slope as f64) * x + (self.intercept as f64);

return Ok((x, y, 0 as f64));
}

fn is_past(&self, point: (f64, f64, f64)) -> bool {
let (x, y) = (self.position.0 as f64, self.position.1 as f64);
let (vx, vy) = (self.velocity.0 as f64, self.velocity.1 as f64);

#[allow(unused_parens)]
return (
(vx < 0.0 && point.0 > x) ||
(vx > 0.0 && point.0 < x) ||
(vy < 0.0 && point.1 > y) ||
(vy > 0.0 && point.1 < y)
);
}
}

fn parseHailstones(contents: &str) -> Vec<Hailstone> {
fn parse_hailstones(contents: &str) -> Vec<Hailstone> {
let mut hailstones = vec![];
let lines = contents.lines();

Expand All @@ -58,17 +102,60 @@ fn parseHailstones(contents: &str) -> Vec<Hailstone> {
let position = pos.parse().expect("position");
let velocity = vel.parse().expect("velocity");

hailstones.push(Hailstone::new(
position,
velocity,
));
hailstones.push(Hailstone::new(position, velocity));
}

return hailstones;
}

fn part_one() -> usize {
0
fn get_intersecting_count(
hailstones: &Vec<Hailstone>,
boundary: (f64, f64)
) -> usize {
let mut count = 0;
let r = boundary.0..boundary.1;

for (i, h1) in hailstones.iter().enumerate() {
for (j, h2) in hailstones.iter().enumerate() {
if j <= i {
// already seen this hailstone
continue;
}
let intersection = h1.intersects(h2);

if let Ok(intersection) = intersection {
if r.contains(&intersection.0) && r.contains(&intersection.1) {
if !h1.is_past(intersection) && !h2.is_past(intersection) {
count += 1;
// println!("Yes: {}, {}, {:?}", i, j, (
// intersection.0,
// intersection.1,
// ));
} else {
// println!("No (past): {}, {}, {:?}", i, j, (
// intersection.0,
// intersection.1,
// ));
}
} else {
// println!("No (contains): {}, {}, {:?}", i, j, (
// intersection.0,
// intersection.1,
// ));
}
} else {
// println!("No: {}, {}, {}", i, j, intersection.unwrap_err());
}
}
}

count
}

fn part_one(hailstones: &Vec<Hailstone>) -> usize {
let boundary = (200000000000000., 400000000000000.);

get_intersecting_count(hailstones, boundary)
}

fn part_two() -> usize {
Expand All @@ -79,10 +166,11 @@ fn main() {
let (one, two) = get_part();
let start = Instant::now();
let contents = fs::read_to_string("./src/input.txt").unwrap();
let hailstones = parse_hailstones(&contents);

if one {
let now = Instant::now();
let ans = part_one();
let ans = part_one(&hailstones);
println!("Part one: {:?} {:?}", ans, now.elapsed());
}

Expand All @@ -102,10 +190,30 @@ mod tests {
const EXAMPLE: &str = include_str!("./example.txt");

#[test]
fn test_part_one() {
let ans = part_one();
fn test_intersects() {
let a = Hailstone {
intercept: 2.0,
slope: 3.0,
position: Vec3d(0, 0, 0),
velocity: Vec3d(0, 0, 0),
};
let b = Hailstone {
intercept: -9.0,
slope: 4.0,
position: Vec3d(0, 0, 0),
velocity: Vec3d(0, 0, 0),
};

assert_eq!(a.intersects(&b).unwrap(), (11.0, 35.0, 0.0));
}

assert_eq!(ans, 0);
#[test]
fn test_intersections() {
let hailstones: Vec<Hailstone> = parse_hailstones(EXAMPLE);

let count = get_intersecting_count(&hailstones, (7.0, 27.0));

assert_eq!(count, 2);
}

#[test]
Expand Down

0 comments on commit ad78218

Please sign in to comment.