Compare commits
	
		
			5 Commits
		
	
	
		
			8cd421a8ef
			...
			fdbbd934a4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | fdbbd934a4 | ||
|   | f87e5ea0af | ||
|   | f9c32f0022 | ||
|   | 2cf47fd7d6 | ||
|   | 647e2fb356 | 
							
								
								
									
										7
									
								
								aoc_2024/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										7
									
								
								aoc_2024/Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -55,6 +55,7 @@ dependencies = [ | |||||||
|  "hashbrown", |  "hashbrown", | ||||||
|  "nom", |  "nom", | ||||||
|  "num", |  "num", | ||||||
|  |  "num-modular", | ||||||
|  "regex", |  "regex", | ||||||
|  "topological-sort", |  "topological-sort", | ||||||
| ] | ] | ||||||
| @ -169,6 +170,12 @@ dependencies = [ | |||||||
|  "num-traits", |  "num-traits", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "num-modular" | ||||||
|  | version = "0.6.1" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f" | ||||||
|  | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "num-rational" | name = "num-rational" | ||||||
| version = "0.4.2" | version = "0.4.2" | ||||||
|  | |||||||
| @ -9,5 +9,6 @@ aoc-runner-derive = "0.3.0" | |||||||
| hashbrown = "0.15.2" | hashbrown = "0.15.2" | ||||||
| nom = "7.1.3" | nom = "7.1.3" | ||||||
| num = "0.4.3" | num = "0.4.3" | ||||||
|  | num-modular = "0.6.1" | ||||||
| regex = "1.11.1" | regex = "1.11.1" | ||||||
| topological-sort = "0.2.2" | topological-sort = "0.2.2" | ||||||
|  | |||||||
							
								
								
									
										147
									
								
								aoc_2024/src/day13.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								aoc_2024/src/day13.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,147 @@ | |||||||
|  | use aoc_runner_derive::{aoc, aoc_generator}; | ||||||
|  | use nom::bytes::complete::tag; | ||||||
|  | use nom::character::complete::i64 as parse_u64; | ||||||
|  | use nom::multi::separated_list0; | ||||||
|  | use nom::IResult; | ||||||
|  | 
 | ||||||
|  | #[derive(Debug, Clone, Copy)] | ||||||
|  | struct Case { | ||||||
|  |     button_a: (i64, i64), | ||||||
|  |     button_b: (i64, i64), | ||||||
|  |     prize: (i64, i64), | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Input = Vec<Case>; | ||||||
|  | 
 | ||||||
|  | #[aoc_generator(day13)] | ||||||
|  | fn parse(input: &str) -> Input { | ||||||
|  |     separated_list0(tag("\n\n"), parse_case)(input).unwrap().1 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn parse_case(input: &str) -> IResult<&str, Case> { | ||||||
|  |     let (input, _) = tag("Button A: X+")(input)?; | ||||||
|  |     let (input, button_a_x) = parse_u64(input)?; | ||||||
|  |     let (input, _) = tag(", Y+")(input)?; | ||||||
|  |     let (input, button_a_y) = parse_u64(input)?; | ||||||
|  |     let (input, _) = tag("\nButton B: X+")(input)?; | ||||||
|  |     let (input, button_b_x) = parse_u64(input)?; | ||||||
|  |     let (input, _) = tag(", Y+")(input)?; | ||||||
|  |     let (input, button_b_y) = parse_u64(input)?; | ||||||
|  |     let (input, _) = tag("\nPrize: X=")(input)?; | ||||||
|  |     let (input, prize_x) = parse_u64(input)?; | ||||||
|  |     let (input, _) = tag(", Y=")(input)?; | ||||||
|  |     let (input, prize_y) = parse_u64(input)?; | ||||||
|  | 
 | ||||||
|  |     Ok(( | ||||||
|  |         input, | ||||||
|  |         Case { | ||||||
|  |             button_a: (button_a_x, button_a_y), | ||||||
|  |             button_b: (button_b_x, button_b_y), | ||||||
|  |             prize: (prize_x, prize_y), | ||||||
|  |         }, | ||||||
|  |     )) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[aoc(day13, part1)] | ||||||
|  | fn part1(input: &Input) -> i64 { | ||||||
|  |     input | ||||||
|  |         .iter() | ||||||
|  |         .copied() | ||||||
|  |         .map(|case| { | ||||||
|  |             let vec_a = case.button_a; | ||||||
|  |             let vec_b = case.button_b; | ||||||
|  |             let vec_p = case.prize; | ||||||
|  | 
 | ||||||
|  |             if (vec_p.0 * vec_b.1 - vec_b.0 * vec_p.1) % (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1) | ||||||
|  |                 == 0 | ||||||
|  |                 && (vec_a.0 * vec_p.1 - vec_p.0 * vec_a.1) % (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1) | ||||||
|  |                     == 0 | ||||||
|  |             { | ||||||
|  |                 let a = (vec_p.0 * vec_b.1 - vec_b.0 * vec_p.1) | ||||||
|  |                     / (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1); | ||||||
|  |                 let b = (vec_a.0 * vec_p.1 - vec_p.0 * vec_a.1) | ||||||
|  |                     / (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1); | ||||||
|  |                 a * 3 + b | ||||||
|  |             } else { | ||||||
|  |                 0 | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  |         .sum() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[aoc(day13, part2)] | ||||||
|  | fn part2(input: &Input) -> i64 { | ||||||
|  |     input | ||||||
|  |         .iter() | ||||||
|  |         .copied() | ||||||
|  |         .map(|case| { | ||||||
|  |             let vec_a = case.button_a; | ||||||
|  |             let vec_b = case.button_b; | ||||||
|  |             let vec_p = case.prize; | ||||||
|  |             let vec_p = (vec_p.0 + 10_000_000_000_000, vec_p.1 + 10_000_000_000_000); | ||||||
|  | 
 | ||||||
|  |             if (vec_p.0 * vec_b.1 - vec_b.0 * vec_p.1) % (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1) | ||||||
|  |                 == 0 | ||||||
|  |                 && (vec_a.0 * vec_p.1 - vec_p.0 * vec_a.1) % (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1) | ||||||
|  |                     == 0 | ||||||
|  |             { | ||||||
|  |                 let a = (vec_p.0 * vec_b.1 - vec_b.0 * vec_p.1) | ||||||
|  |                     / (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1); | ||||||
|  |                 let b = (vec_a.0 * vec_p.1 - vec_p.0 * vec_a.1) | ||||||
|  |                     / (vec_a.0 * vec_b.1 - vec_b.0 * vec_a.1); | ||||||
|  |                 a * 3 + b | ||||||
|  |             } else { | ||||||
|  |                 0 | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  |         .sum() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use super::*; | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn part1_example() { | ||||||
|  |         assert_eq!( | ||||||
|  |             part1(&parse( | ||||||
|  |                 "Button A: X+94, Y+34
 | ||||||
|  | Button B: X+22, Y+67 | ||||||
|  | Prize: X=8400, Y=5400" | ||||||
|  |             )), | ||||||
|  |             280 | ||||||
|  |         ); | ||||||
|  |         assert_eq!( | ||||||
|  |             part1(&parse( | ||||||
|  |                 "Button A: X+94, Y+34
 | ||||||
|  | Button B: X+22, Y+67 | ||||||
|  | Prize: X=8400, Y=5400 | ||||||
|  | 
 | ||||||
|  | Button A: X+26, Y+66 | ||||||
|  | Button B: X+67, Y+21 | ||||||
|  | Prize: X=12748, Y=12176 | ||||||
|  | 
 | ||||||
|  | Button A: X+17, Y+86 | ||||||
|  | Button B: X+84, Y+37 | ||||||
|  | Prize: X=7870, Y=6450 | ||||||
|  | 
 | ||||||
|  | Button A: X+69, Y+23 | ||||||
|  | Button B: X+27, Y+71 | ||||||
|  | Prize: X=18641, Y=10279" | ||||||
|  |             )), | ||||||
|  |             480 | ||||||
|  |         ); | ||||||
|  |         assert_eq!( | ||||||
|  |             part1(&parse(include_str!("../input/2024/day13.txt").trim_end())), | ||||||
|  |             28753 | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn part2_example() { | ||||||
|  |         assert_eq!( | ||||||
|  |             part2(&parse(include_str!("../input/2024/day13.txt").trim_end())), | ||||||
|  |             102718967795500 | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										127
									
								
								aoc_2024/src/day14.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								aoc_2024/src/day14.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,127 @@ | |||||||
|  | use aoc_runner_derive::{aoc, aoc_generator}; | ||||||
|  | 
 | ||||||
|  | use nom::{ | ||||||
|  |     bytes::complete::tag, | ||||||
|  |     character::complete::{i64 as parse_i64, newline, space1}, | ||||||
|  |     error::Error, | ||||||
|  |     multi::separated_list0, | ||||||
|  |     sequence::{preceded, separated_pair}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | use num_modular::ModularPow; | ||||||
|  | 
 | ||||||
|  | type Input = Vec<((i64, i64), (i64, i64))>; | ||||||
|  | 
 | ||||||
|  | #[aoc_generator(day14)] | ||||||
|  | fn parse(input: &str) -> Input { | ||||||
|  |     separated_list0( | ||||||
|  |         newline::<&str, Error<&str>>, | ||||||
|  |         separated_pair( | ||||||
|  |             preceded(tag("p="), separated_pair(parse_i64, tag(","), parse_i64)), | ||||||
|  |             space1, | ||||||
|  |             preceded(tag("v="), separated_pair(parse_i64, tag(","), parse_i64)), | ||||||
|  |         ), | ||||||
|  |     )(input) | ||||||
|  |     .unwrap() | ||||||
|  |     .1 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[aoc(day14, part1)] | ||||||
|  | fn part1(input: &Input) -> i64 { | ||||||
|  |     #[cfg(test)] | ||||||
|  |     let (w, h) = (7, 11); | ||||||
|  |     #[cfg(not(test))] | ||||||
|  |     let (w, h) = (101, 103); | ||||||
|  | 
 | ||||||
|  |     let mut quadrants = [0, 0, 0, 0]; | ||||||
|  | 
 | ||||||
|  |     input.iter().copied().for_each(|(p, v)| { | ||||||
|  |         let (px, py) = (p.0, p.1); | ||||||
|  |         let (vx, vy) = (v.0 + w, v.1 + h); | ||||||
|  |         let (ex, ey) = ((px + vx * 100) % w, (py + vy * 100) % h); | ||||||
|  |         if ex < w / 2 && ey < h / 2 { | ||||||
|  |             quadrants[0] += 1; | ||||||
|  |         } else if ex > (w - 1) / 2 && ey < h / 2 { | ||||||
|  |             quadrants[1] += 1; | ||||||
|  |         } else if ex < w / 2 && ey > (h - 1) / 2 { | ||||||
|  |             quadrants[2] += 1; | ||||||
|  |         } else if ex > (w - 1) / 2 && ey > (h - 1) / 2 { | ||||||
|  |             quadrants[3] += 1; | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     quadrants.iter().product() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[aoc(day14, part2)] | ||||||
|  | fn part2(input: &Input) -> i64 { | ||||||
|  |     let (w, h) = (101, 103); | ||||||
|  | 
 | ||||||
|  |     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 < min_var { | ||||||
|  |             min_var = variance; | ||||||
|  |             offset_x = t; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     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)] | ||||||
|  | mod tests { | ||||||
|  |     use super::*; | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn part1_example() { | ||||||
|  |         assert_eq!( | ||||||
|  |             part1(&parse( | ||||||
|  |                 "p=0,4 v=3,-3
 | ||||||
|  | p=6,3 v=-1,-3 | ||||||
|  | p=10,3 v=-1,2 | ||||||
|  | p=2,0 v=2,-1 | ||||||
|  | p=0,0 v=1,3 | ||||||
|  | p=3,0 v=-2,-2 | ||||||
|  | p=7,6 v=-1,-3 | ||||||
|  | p=3,0 v=-1,-2 | ||||||
|  | p=9,3 v=2,3 | ||||||
|  | p=7,3 v=-1,2 | ||||||
|  | p=2,4 v=2,-3 | ||||||
|  | p=9,5 v=-3,-3" | ||||||
|  |             )), | ||||||
|  |             12 | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn part2_example() { | ||||||
|  |         assert_eq!( | ||||||
|  |             part2(&parse(include_str!("../input/2024/day14.txt").trim_end())), | ||||||
|  |             6398 | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -2,6 +2,8 @@ mod day1; | |||||||
| mod day10; | mod day10; | ||||||
| mod day11; | mod day11; | ||||||
| mod day12; | mod day12; | ||||||
|  | mod day13; | ||||||
|  | mod day14; | ||||||
| mod day2; | mod day2; | ||||||
| mod day3; | mod day3; | ||||||
| mod day4; | mod day4; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user