Rewrote part 2 using Chinese Remainder theorem
This commit is contained in:
		
							parent
							
								
									f87e5ea0af
								
							
						
					
					
						commit
						fdbbd934a4
					
				
							
								
								
									
										7
									
								
								aoc_2024/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										7
									
								
								aoc_2024/Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -55,6 +55,7 @@ dependencies = [ | ||||
|  "hashbrown", | ||||
|  "nom", | ||||
|  "num", | ||||
|  "num-modular", | ||||
|  "regex", | ||||
|  "topological-sort", | ||||
| ] | ||||
| @ -169,6 +170,12 @@ dependencies = [ | ||||
|  "num-traits", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "num-modular" | ||||
| version = "0.6.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "num-rational" | ||||
| version = "0.4.2" | ||||
|  | ||||
| @ -9,5 +9,6 @@ aoc-runner-derive = "0.3.0" | ||||
| hashbrown = "0.15.2" | ||||
| nom = "7.1.3" | ||||
| num = "0.4.3" | ||||
| num-modular = "0.6.1" | ||||
| regex = "1.11.1" | ||||
| topological-sort = "0.2.2" | ||||
|  | ||||
| @ -1,5 +1,3 @@ | ||||
| use std::sync::OnceLock; | ||||
| 
 | ||||
| use aoc_runner_derive::{aoc, aoc_generator}; | ||||
| 
 | ||||
| use nom::{ | ||||
| @ -10,6 +8,8 @@ use nom::{ | ||||
|     sequence::{preceded, separated_pair}, | ||||
| }; | ||||
| 
 | ||||
| use num_modular::ModularPow; | ||||
| 
 | ||||
| type Input = Vec<((i64, i64), (i64, i64))>; | ||||
| 
 | ||||
| #[aoc_generator(day14)] | ||||
| @ -54,43 +54,42 @@ fn part1(input: &Input) -> i64 { | ||||
| } | ||||
| 
 | ||||
| #[aoc(day14, part2)] | ||||
| fn part2(input: &Input) -> usize { | ||||
| fn part2(input: &Input) -> i64 { | ||||
|     let (w, h) = (101, 103); | ||||
| 
 | ||||
|     let mut input = input.clone(); | ||||
| 
 | ||||
|     let mut iter = 0; | ||||
| 
 | ||||
|     loop { | ||||
|         iter += 1; | ||||
| 
 | ||||
|         let mut total = (0f64, 0f64); | ||||
|         input = input | ||||
|             .into_iter() | ||||
|             .map(|((px, py), (vx, vy))| { | ||||
|                 let (px, py) = ((px + vx + w) % w, (py + vy + h) % h); | ||||
|                 total.0 += px as f64; | ||||
|                 total.1 += py as f64; | ||||
|                 ((px, py), (vx, vy)) | ||||
|             }) | ||||
|             .collect(); | ||||
|         let mean = (total.0 / input.len() as f64, total.1 / input.len() as f64); | ||||
|         let variance = input | ||||
|             .iter() | ||||
|             .map(|((px, py), _)| { | ||||
|                 let dx = *px as f64 - mean.0; | ||||
|                 let dy = *py as f64 - mean.1; | ||||
|                 dx * dx + dy * dy | ||||
|             }) | ||||
|     let mut offset_x = 0; | ||||
|     let mut min_var = f64::INFINITY; | ||||
|     for t in 0..w { | ||||
|         let values = input.iter().map(|((p, _), (v, _))| (p + t * (v + w)) % w); | ||||
|         let mean = values.clone().sum::<i64>() as f64 / input.len() as f64; | ||||
|         let variance = values | ||||
|             .map(|v| (v as f64 - mean) * (v as f64 - mean)) | ||||
|             .sum::<f64>() | ||||
|             / input.len() as f64; | ||||
| 
 | ||||
|         if variance < 1000.0 { | ||||
|             break; | ||||
|         if variance < min_var { | ||||
|             min_var = variance; | ||||
|             offset_x = t; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     iter | ||||
|     let mut offset_y = 0; | ||||
|     let mut min_var = f64::INFINITY; | ||||
|     for t in 0..h { | ||||
|         let values = input.iter().map(|((_, p), (_, v))| (p + t * (v + h)) % h); | ||||
|         let mean = values.clone().sum::<i64>() as f64 / input.len() as f64; | ||||
|         let variance = values | ||||
|             .map(|v| (v as f64 - mean) * (v as f64 - mean)) | ||||
|             .sum::<f64>() | ||||
|             / input.len() as f64; | ||||
|         if variance < min_var { | ||||
|             min_var = variance; | ||||
|             offset_y = t; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     let invmod_x = (w as u64).powm((h - 2) as u64, &(h as u64)) as i64; | ||||
|     let invmod_y = (h as u64).powm((w - 2) as u64, &(w as u64)) as i64; | ||||
|     (offset_x * h * invmod_x + offset_y * w * invmod_y) % (w * h) | ||||
| } | ||||
| 
 | ||||
| #[cfg(test)] | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Jan-Bulthuis
						Jan-Bulthuis