day24: problem 1 solution
This commit is contained in:
parent
c1eb7761e3
commit
881d0b08ad
134
24/Cargo.lock
generated
Normal file
134
24/Cargo.lock
generated
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "day24"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"itertools",
|
||||||
|
"lazy-regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy-regex"
|
||||||
|
version = "3.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d12be4595afdf58bd19e4a9f4e24187da2a66700786ff660a418e9059937a4c"
|
||||||
|
dependencies = [
|
||||||
|
"lazy-regex-proc_macros",
|
||||||
|
"once_cell",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy-regex-proc_macros"
|
||||||
|
version = "3.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44bcd58e6c97a7fcbaffcdc95728b393b8d98933bfadad49ed4097845b57ef0b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"regex",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.71"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.42"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
10
24/Cargo.toml
Normal file
10
24/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "day24"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
itertools = "0.12.0"
|
||||||
|
lazy-regex = "3.1.0"
|
205
24/src/main.rs
Normal file
205
24/src/main.rs
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
use itertools::Itertools;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{BufRead, BufReader, Lines};
|
||||||
|
use std::ops::Index;
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
// BOILERPLATE
|
||||||
|
type InputIter = Lines<BufReader<File>>;
|
||||||
|
|
||||||
|
fn get_input() -> InputIter {
|
||||||
|
let f = File::open("input").unwrap();
|
||||||
|
let br = BufReader::new(f);
|
||||||
|
br.lines()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let start = Instant::now();
|
||||||
|
let ans1 = problem1(get_input());
|
||||||
|
let duration = start.elapsed();
|
||||||
|
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
|
||||||
|
|
||||||
|
let start = Instant::now();
|
||||||
|
let ans2 = problem2(get_input());
|
||||||
|
let duration = start.elapsed();
|
||||||
|
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
struct Vec3 {
|
||||||
|
x: f64,
|
||||||
|
y: f64,
|
||||||
|
z: f64,
|
||||||
|
}
|
||||||
|
impl Debug for Vec3 {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}, {}, {}", self.x, self.y, self.z)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
struct Vec2 {
|
||||||
|
x: f64,
|
||||||
|
y: f64,
|
||||||
|
}
|
||||||
|
impl Debug for Vec2 {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}, {}", self.x, self.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
|
||||||
|
struct Hailstone {
|
||||||
|
pos: Vec3,
|
||||||
|
vel: Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hailstone {
|
||||||
|
fn xy_vel_angle(&self) -> f64 {
|
||||||
|
(self.vel.y / self.vel.x).atan()
|
||||||
|
}
|
||||||
|
fn xy_vel_abs(&self) -> f64 {
|
||||||
|
(self.vel.x.powi(2) + self.vel.y.powi(2)).sqrt()
|
||||||
|
}
|
||||||
|
fn xy_slope(&self) -> f64 {
|
||||||
|
self.vel.y / self.vel.x
|
||||||
|
}
|
||||||
|
fn y_crossing(&self) -> f64 {
|
||||||
|
self.pos.y - self.xy_slope() * self.pos.x
|
||||||
|
}
|
||||||
|
fn xy_poi(&self, other: &Hailstone) -> Option<Vec2> {
|
||||||
|
let our_slope = self.xy_slope();
|
||||||
|
let other_slope = other.xy_slope();
|
||||||
|
if our_slope == other_slope || our_slope * other_slope == -1. {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let our_yint = self.y_crossing();
|
||||||
|
let other_yint = other.y_crossing();
|
||||||
|
let ratio = (other_yint - our_yint) / (our_slope - other_slope);
|
||||||
|
Some(Vec2 {
|
||||||
|
x: ratio,
|
||||||
|
y: our_slope * ratio + our_yint,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn xy_point_future(&self, point: &Vec2) -> bool {
|
||||||
|
// a point will be in the past if the difference between its 'new' position and its 'start' position has a
|
||||||
|
// different sign than the velocity for any component
|
||||||
|
let diffs = [point.x - self.pos.x, point.y - self.pos.y];
|
||||||
|
// for (diff, vel) in diffs.iter().zip([self.vel.x, self.vel.y].iter()) {
|
||||||
|
// println!(" diff: {:?} vel: {:?} mul: {:?}", diff, vel, diff * vel > 0.);
|
||||||
|
// }
|
||||||
|
diffs.iter().zip([self.vel.x, self.vel.y].iter()).any(|(diff, vel)| diff * vel > 0.)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for Hailstone {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
let (pos, vel) = value.split_once("@").unwrap();
|
||||||
|
let [px, py, pz] = pos.split(",").map(|s| s.trim().parse::<f64>().unwrap()).collect_vec()[..] else {
|
||||||
|
panic!()
|
||||||
|
};
|
||||||
|
let [vx, vy, vz] = vel.split(",").map(|s| s.trim().parse::<f64>().unwrap()).collect_vec()[..] else {
|
||||||
|
panic!()
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
pos: Vec3 { x: px, y: py, z: pz },
|
||||||
|
vel: Vec3 { x: vx, y: vy, z: vz },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Hailstone {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{:?} @ {:?}", self.pos, self.vel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Hailstones {
|
||||||
|
stones: Vec<Hailstone>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hailstones {
|
||||||
|
fn count_xy_pois(&self, bounds: (f64, f64)) -> u64 {
|
||||||
|
assert!(bounds.0 < bounds.1);
|
||||||
|
let mut stones = self.stones.clone();
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
while let Some(stone) = &stones.pop() {
|
||||||
|
for other in &stones {
|
||||||
|
let Some(poi) = stone.xy_poi(other) else { continue };
|
||||||
|
// println!("intersection: {:?} / {:?} @ {:?}", stone, other, poi);
|
||||||
|
if poi.x >= bounds.0 && poi.x <= bounds.1 && poi.y >= bounds.0 && poi.y <= bounds.1 && stone.xy_point_future(&poi) && other.xy_point_future(&poi) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Index<usize> for Hailstones {
|
||||||
|
type Output = Hailstone;
|
||||||
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
|
&self.stones[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: BufRead> From<Lines<T>> for Hailstones {
|
||||||
|
fn from(value: Lines<T>) -> Self {
|
||||||
|
let mut stones = Vec::new();
|
||||||
|
for line in value {
|
||||||
|
stones.push(Hailstone::from(line.unwrap().as_str()));
|
||||||
|
}
|
||||||
|
Hailstones { stones }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PROBLEM 1 solution
|
||||||
|
|
||||||
|
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
|
||||||
|
problem1_impl(input, (200000000000000., 400000000000000.))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn problem1_impl<T: BufRead>(input: Lines<T>, bounds: (f64, f64)) -> u64 {
|
||||||
|
let stones = Hailstones::from(input);
|
||||||
|
|
||||||
|
stones.count_xy_pois(bounds)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PROBLEM 2 solution
|
||||||
|
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::*;
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
const EXAMPLE: &str = &"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";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn problem1_example() {
|
||||||
|
let c = Cursor::new(EXAMPLE);
|
||||||
|
assert_eq!(problem1_impl(c.lines(), (7., 27.)), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn problem2_example() {
|
||||||
|
let c = Cursor::new(EXAMPLE);
|
||||||
|
assert_eq!(problem2(c.lines()), 0);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user