Compare commits
	
		
			2 Commits
		
	
	
		
			c1eb7761e3
			...
			342f4c1883
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 342f4c1883 | |||
| 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); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										266
									
								
								25/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										266
									
								
								25/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,266 @@ | ||||
| # This file is automatically @generated by Cargo. | ||||
| # It is not intended for manual editing. | ||||
| version = 3 | ||||
|  | ||||
| [[package]] | ||||
| name = "autocfg" | ||||
| version = "1.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" | ||||
|  | ||||
| [[package]] | ||||
| name = "cfg-if" | ||||
| version = "1.0.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | ||||
|  | ||||
| [[package]] | ||||
| name = "console" | ||||
| version = "0.15.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" | ||||
| dependencies = [ | ||||
|  "encode_unicode", | ||||
|  "lazy_static", | ||||
|  "libc", | ||||
|  "unicode-width", | ||||
|  "windows-sys", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "crossbeam-deque" | ||||
| version = "0.8.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
|  "crossbeam-epoch", | ||||
|  "crossbeam-utils", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "crossbeam-epoch" | ||||
| version = "0.9.17" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d" | ||||
| dependencies = [ | ||||
|  "autocfg", | ||||
|  "cfg-if", | ||||
|  "crossbeam-utils", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "crossbeam-utils" | ||||
| version = "0.8.18" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "day25" | ||||
| version = "0.1.0" | ||||
| dependencies = [ | ||||
|  "indicatif", | ||||
|  "itertools", | ||||
|  "petgraph", | ||||
|  "rayon", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "either" | ||||
| version = "1.9.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" | ||||
|  | ||||
| [[package]] | ||||
| name = "encode_unicode" | ||||
| version = "0.3.6" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" | ||||
|  | ||||
| [[package]] | ||||
| name = "equivalent" | ||||
| version = "1.0.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" | ||||
|  | ||||
| [[package]] | ||||
| name = "fixedbitset" | ||||
| version = "0.4.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" | ||||
|  | ||||
| [[package]] | ||||
| name = "hashbrown" | ||||
| version = "0.14.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" | ||||
|  | ||||
| [[package]] | ||||
| name = "indexmap" | ||||
| version = "2.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" | ||||
| dependencies = [ | ||||
|  "equivalent", | ||||
|  "hashbrown", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "indicatif" | ||||
| version = "0.17.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25" | ||||
| dependencies = [ | ||||
|  "console", | ||||
|  "instant", | ||||
|  "number_prefix", | ||||
|  "portable-atomic", | ||||
|  "unicode-width", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "instant" | ||||
| version = "0.1.12" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" | ||||
| dependencies = [ | ||||
|  "cfg-if", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "itertools" | ||||
| version = "0.12.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" | ||||
| dependencies = [ | ||||
|  "either", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "lazy_static" | ||||
| version = "1.4.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | ||||
|  | ||||
| [[package]] | ||||
| name = "libc" | ||||
| version = "0.2.151" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" | ||||
|  | ||||
| [[package]] | ||||
| name = "number_prefix" | ||||
| version = "0.4.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" | ||||
|  | ||||
| [[package]] | ||||
| name = "petgraph" | ||||
| version = "0.6.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" | ||||
| dependencies = [ | ||||
|  "fixedbitset", | ||||
|  "indexmap", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "portable-atomic" | ||||
| version = "1.6.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" | ||||
|  | ||||
| [[package]] | ||||
| name = "rayon" | ||||
| version = "1.8.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" | ||||
| dependencies = [ | ||||
|  "either", | ||||
|  "rayon-core", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "rayon-core" | ||||
| version = "1.12.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" | ||||
| dependencies = [ | ||||
|  "crossbeam-deque", | ||||
|  "crossbeam-utils", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "unicode-width" | ||||
| version = "0.1.11" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" | ||||
|  | ||||
| [[package]] | ||||
| name = "windows-sys" | ||||
| version = "0.45.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" | ||||
| dependencies = [ | ||||
|  "windows-targets", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "windows-targets" | ||||
| version = "0.42.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" | ||||
| dependencies = [ | ||||
|  "windows_aarch64_gnullvm", | ||||
|  "windows_aarch64_msvc", | ||||
|  "windows_i686_gnu", | ||||
|  "windows_i686_msvc", | ||||
|  "windows_x86_64_gnu", | ||||
|  "windows_x86_64_gnullvm", | ||||
|  "windows_x86_64_msvc", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "windows_aarch64_gnullvm" | ||||
| version = "0.42.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" | ||||
|  | ||||
| [[package]] | ||||
| name = "windows_aarch64_msvc" | ||||
| version = "0.42.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" | ||||
|  | ||||
| [[package]] | ||||
| name = "windows_i686_gnu" | ||||
| version = "0.42.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" | ||||
|  | ||||
| [[package]] | ||||
| name = "windows_i686_msvc" | ||||
| version = "0.42.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" | ||||
|  | ||||
| [[package]] | ||||
| name = "windows_x86_64_gnu" | ||||
| version = "0.42.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" | ||||
|  | ||||
| [[package]] | ||||
| name = "windows_x86_64_gnullvm" | ||||
| version = "0.42.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" | ||||
|  | ||||
| [[package]] | ||||
| name = "windows_x86_64_msvc" | ||||
| version = "0.42.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" | ||||
							
								
								
									
										12
									
								
								25/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								25/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| [package] | ||||
| name = "day25" | ||||
| version = "0.1.0" | ||||
| edition = "2021" | ||||
|  | ||||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||
|  | ||||
| [dependencies] | ||||
| indicatif = "0.17.7" | ||||
| itertools = "0.12.0" | ||||
| petgraph = "0.6.4" | ||||
| rayon = "1.8.0" | ||||
							
								
								
									
										171
									
								
								25/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								25/src/main.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,171 @@ | ||||
| use indicatif::{ProgressBar, ProgressIterator, ProgressStyle}; | ||||
| use itertools::Itertools; | ||||
| use petgraph::algo::connected_components; | ||||
| use petgraph::dot::Dot; | ||||
| use petgraph::prelude::*; | ||||
| use petgraph::visit::{depth_first_search, DfsEvent, IntoEdgeReferences, IntoNodeIdentifiers, IntoNodeReferences}; | ||||
| use rayon::prelude::*; | ||||
| use std::collections::HashMap; | ||||
| use std::fs::File; | ||||
| use std::io::{BufRead, BufReader, Lines}; | ||||
| 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 | ||||
|  | ||||
| struct Circuit { | ||||
|     graph: UnGraph<String, String>, | ||||
|     nodes: HashMap<String, Node>, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Clone)] | ||||
| struct Node { | ||||
|     targets: Vec<String>, | ||||
|     index: Option<NodeIndex>, | ||||
| } | ||||
|  | ||||
| impl Node { | ||||
|     fn with_index(mut self, index: NodeIndex) -> Self { | ||||
|         self.index = Some(index); | ||||
|         self | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T: BufRead> From<Lines<T>> for Circuit { | ||||
|     fn from(lines: Lines<T>) -> Self { | ||||
|         let mut graph = UnGraph::default(); | ||||
|         let mut nodes = HashMap::new(); | ||||
|         for line in lines.map(|v| v.unwrap()) { | ||||
|             let (source, targets_s) = line.split_once(": ").unwrap(); | ||||
|             let targets = targets_s.split_whitespace().map(|s| s.to_string()).collect_vec(); | ||||
|             nodes.insert( | ||||
|                 source.to_string(), | ||||
|                 Node { | ||||
|                     targets, | ||||
|                     index: Some(graph.add_node(source.to_string())), | ||||
|                 }, | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         for (name, node) in nodes.iter_mut() { | ||||
|             for target in &node.targets { | ||||
|                 let target_idx = match graph.node_references().find(|n| n.1 == target).map(|n| n.0) { | ||||
|                     Some(target) => target, | ||||
|                     None => graph.add_node(target.to_string()), | ||||
|                 }; | ||||
|                 graph.add_edge(node.index.unwrap(), target_idx, format!("{}-{}", name, target)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Self { graph, nodes } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Circuit { | ||||
|     // returns the set of nodes on each side | ||||
|     fn find_critical_edges(&self, removals: usize) -> (Vec<String>, Vec<String>) { | ||||
|         let bar = ProgressBar::new(self.graph.edge_references().combinations(removals).try_len().unwrap() as u64) | ||||
|             .with_style( | ||||
|                 ProgressStyle::with_template( | ||||
|                     "[{elapsed_precise}/{eta_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {per_sec}", | ||||
|                 ) | ||||
|                 .unwrap(), | ||||
|             ); | ||||
|         // for set in self.graph.edge_references().combinations(removals).progress_with(bar) { | ||||
|          | ||||
|         let set = [("zcp", "zjm"), ("rsg", "nsk"), ("jks", "rfg")] | ||||
|             .iter() | ||||
|             .flat_map(|(src, dst)| { | ||||
|                 self.graph.edge_references().filter(|e| self.graph[e.source()] == *src && self.graph[e.target()] == *dst || self.graph[e.target()] == *src && self.graph[e.source()] == *dst) | ||||
|             }).collect_vec(); | ||||
|         let mut local_graph: StableUnGraph<_, _> = self.graph.clone().into(); | ||||
|         for wire in &set { | ||||
|             local_graph.remove_edge(wire.id()); | ||||
|         } | ||||
|         let local_graph = UnGraph::from(local_graph); | ||||
|         if connected_components(&local_graph) == 2 { | ||||
|             // each edge will have one leg in each component, so return the set of connected nodes | ||||
|             let mut left = Vec::new(); | ||||
|             depth_first_search(&local_graph, Some(set[0].source()), |event| { | ||||
|                 if let DfsEvent::Discover(n, t) = event { | ||||
|                     left.push(local_graph[n].to_string()); | ||||
|                 } | ||||
|             }); | ||||
|             let mut right = Vec::new(); | ||||
|             depth_first_search(&local_graph, Some(set[0].target()), |event| { | ||||
|                 if let DfsEvent::Discover(n, t) = event { | ||||
|                     right.push(local_graph[n].to_string()); | ||||
|                 } | ||||
|             }); | ||||
|             return (left, right); | ||||
|         } | ||||
|         // } | ||||
|         panic!("no cutline found"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // PROBLEM 1 solution | ||||
|  | ||||
| fn problem1<T: BufRead>(input: Lines<T>) -> u64 { | ||||
|     let circuit = Circuit::from(input); | ||||
|     println!("{:?}", Dot::new(&circuit.graph)); | ||||
|     let (left, right) = circuit.find_critical_edges(3); | ||||
|     (left.len() * right.len()) as u64 | ||||
| } | ||||
|  | ||||
| // 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 = &"jqt: rhn xhk nvd | ||||
| rsh: frs pzl lsr | ||||
| xhk: hfx | ||||
| cmg: qnr nvd lhk bvb | ||||
| rhn: xhk bvb hfx | ||||
| bvb: xhk hfx | ||||
| pzl: lsr hfx nvd | ||||
| qnr: nvd | ||||
| ntq: jqt hfx bvb xhk | ||||
| nvd: lhk | ||||
| lsr: lhk | ||||
| rzs: qnr cmg lsr rsh | ||||
| frs: qnr lhk lsr"; | ||||
|  | ||||
|     #[test] | ||||
|     fn problem1_example() { | ||||
|         let c = Cursor::new(EXAMPLE); | ||||
|         assert_eq!(problem1(c.lines()), 54); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn problem2_example() { | ||||
|         let c = Cursor::new(EXAMPLE); | ||||
|         assert_eq!(problem2(c.lines()), 0); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user