day 23. also, long term nuclear warning messages in day 21.
This commit is contained in:
		
							parent
							
								
									926fc4f6a8
								
							
						
					
					
						commit
						28f5eb17b0
					
				| @ -4,3 +4,4 @@ version = "0.1.0" | ||||
| edition = "2021" | ||||
| 
 | ||||
| [dependencies] | ||||
| memoize = "0.4.2" | ||||
|  | ||||
| @ -1,7 +1,22 @@ | ||||
| /* | ||||
| THIS PLACE IS NOT A PLACE OF HONOR... | ||||
| NO HIGHLY ESTEEMED DEED IS COMMEMORATED HERE... | ||||
| NOTHING VALUED IS HERE. | ||||
| 
 | ||||
| THE DANGER IS PRESENT IN YOUR TIME AS IT WAS IN OURS. | ||||
| 
 | ||||
| THE DANGER IS UNLEASHED ONLY IF YOU SUBSTANTIALLY DISTURB THIS FILE... | ||||
| THIS FILE IS BEST LEFT SHUNNED AND UNINHABITED. | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| use std::collections::HashSet; | ||||
| use std::collections::HashMap; | ||||
| use std::env; | ||||
| use std::fs; | ||||
| 
 | ||||
| use memoize::memoize; | ||||
| 
 | ||||
| use crate::Dir::{North, South, East, West, Stay }; | ||||
| 
 | ||||
| 
 | ||||
| @ -118,7 +133,6 @@ fn main() { | ||||
|             &keypad_door, 
 | ||||
|             &door_code, 
 | ||||
|             'A'); | ||||
|         println!("{options_door:?}"); | ||||
|         for arrow_code_1 in sequences(options_door, &door_map, keypad_door[&'A']) { | ||||
|             print_code(&arrow_code_1); | ||||
| 
 | ||||
| @ -146,7 +160,518 @@ fn main() { | ||||
|     } | ||||
| 
 | ||||
|     println!("the sum of the complexity scores is {}", sum); | ||||
| 
 | ||||
|     println!("okay let's play around"); | ||||
|     let code_0 = "029A"; | ||||
|     println!("starting sequence is {code_0}"); | ||||
|     let mut seed = 0; | ||||
|     let code_1 = &expand( | ||||
|         &code_0.chars().collect(), 
 | ||||
|         &door_map, | ||||
|         &keypad_door, | ||||
|         'A', | ||||
|         &mut seed); | ||||
|     print_code(code_1); | ||||
|     let code_2 = &expand( | ||||
|         &code_1, | ||||
|         &keypad_map, | ||||
|         &keypad_arrows, | ||||
|         Stay, | ||||
|         &mut seed); | ||||
|     print_code(code_2); | ||||
|     let code_3 = &expand( | ||||
|         &code_2, | ||||
|         &keypad_map, | ||||
|         &keypad_arrows, | ||||
|         Stay, | ||||
|         &mut seed); | ||||
|     print_code(code_3); | ||||
|     let code_4 = &expand( | ||||
|         &code_3, | ||||
|         &keypad_map, | ||||
|         &keypad_arrows, | ||||
|         Stay, | ||||
|         &mut seed); | ||||
|     print_code(code_4); | ||||
|     seed = 0b11111111111111111111111; | ||||
|     let code_1 = &expand( | ||||
|         &code_0.chars().collect(), 
 | ||||
|         &door_map, | ||||
|         &keypad_door, | ||||
|         'A', | ||||
|         &mut seed); | ||||
|     print_code(code_1); | ||||
|     let code_2 = &expand( | ||||
|         &code_1, | ||||
|         &keypad_map, | ||||
|         &keypad_arrows, | ||||
|         Stay, | ||||
|         &mut seed); | ||||
|     print_code(code_2); | ||||
|     let code_3 = &expand( | ||||
|         &code_2, | ||||
|         &keypad_map, | ||||
|         &keypad_arrows, | ||||
|         Stay, | ||||
|         &mut seed); | ||||
|     print_code(code_3); | ||||
|     let code_4 = &expand( | ||||
|         &code_3, | ||||
|         &keypad_map, | ||||
|         &keypad_arrows, | ||||
|         Stay, | ||||
|         &mut seed); | ||||
|     print_code(code_4); | ||||
| 
 | ||||
|     println!("\n\n\nokay, i think i got it. now let's do the memoized solution."); | ||||
| 
 | ||||
| 
 | ||||
|     let mut bests: HashMap<(Dir, Dir), Vec<Dir>> = HashMap::new(); | ||||
|     for prev in [Stay, East, West, North, South] { | ||||
|         for next in [Stay, East, West, North, South] { | ||||
|             let four_deep = shortest_seq( | ||||
|                 keypad_arrows[&prev], 
 | ||||
|                 keypad_arrows[&next], 
 | ||||
|                 7, | ||||
|                 vec![(0,3)]); | ||||
|             let mut result = four_deep; | ||||
|             for _ in 0..6 { | ||||
|                 result = execute_code(&result, &keypad_map, keypad_arrows[&Stay]); | ||||
|             } | ||||
|             bests.insert((prev, next), result); | ||||
|         } | ||||
|     } | ||||
|     for (key, value) in &bests { | ||||
|         print!("{key:?}:"); | ||||
|         print_code(&value); | ||||
|     } | ||||
| 
 | ||||
|     let mut sum = 0; | ||||
|     for line in file.lines() { | ||||
|         let num: i32 = line[..line.len()-1].parse().expect("failed to parse door code as number"); | ||||
|         
 | ||||
|         println!("looking at code {line}, generating:"); | ||||
|         print_code(&thru_keypads(line, 2)); | ||||
|         print_code(&thru_keypads(line, 3)); | ||||
|         print_code(&thru_keypads(line, 4)); | ||||
| 
 | ||||
|         let extra = 25; | ||||
|         let mut length = 0; | ||||
|         let mut prev = 'A'; | ||||
|         for d in line.chars() { | ||||
|             length += length_calc_numpad(prev, d, 1+extra); | ||||
|             prev = d; | ||||
|         } | ||||
|         println!("length should be {length}"); | ||||
| 
 | ||||
|         sum += length * (num as i64); | ||||
|     } | ||||
| 
 | ||||
|     println!("the answer is {sum}"); | ||||
| } | ||||
| 
 | ||||
| fn length_calc_numpad(prev: char, next: char, depth: i32) -> i64 { | ||||
|     let optimals: HashMap<(char, char), Vec<Dir>> = HashMap::from([ | ||||
|         (('A', 'A'), vec![Stay]), | ||||
|         (('A', '0'), vec![West, Stay]), 
 | ||||
|         (('A', '1'), vec![North, West, West, Stay]), | ||||
|         (('A', '2'), vec![West, North, Stay]), | ||||
|         (('A', '3'), vec![North, Stay]), | ||||
|         (('A', '4'), vec![North, North, West, West, Stay]), | ||||
|         (('A', '5'), vec![West, North, North, Stay]), | ||||
|         (('A', '6'), vec![North, North, Stay]), | ||||
|         (('A', '7'), vec![North, North, North, West, West, Stay]), | ||||
|         (('A', '8'), vec![West, North, North, North, Stay]), | ||||
|         (('A', '9'), vec![North, North, North, Stay]), | ||||
| 
 | ||||
|         (('0', 'A'), vec![East, Stay]), | ||||
|         (('0', '0'), vec![Stay]), 
 | ||||
|         (('0', '1'), vec![North, West, Stay]), | ||||
|         (('0', '2'), vec![North, Stay]), | ||||
|         (('0', '3'), vec![North, East, Stay]), | ||||
|         (('0', '4'), vec![North, North, West, Stay]), | ||||
|         (('0', '5'), vec![North, North, Stay]), | ||||
|         (('0', '6'), vec![North, North, East, Stay]), | ||||
|         (('0', '7'), vec![North, North, North, West, Stay]), | ||||
|         (('0', '8'), vec![North, North, North, Stay]), | ||||
|         (('0', '9'), vec![North, North, North, East, Stay]), | ||||
| 
 | ||||
|         (('1', 'A'), vec![East, East, South, Stay]), | ||||
|         (('1', '0'), vec![East, South, Stay]), 
 | ||||
|         (('1', '1'), vec![Stay]), | ||||
|         (('1', '2'), vec![East, Stay]), | ||||
|         (('1', '3'), vec![East, East, Stay]), | ||||
|         (('1', '4'), vec![North, Stay]), | ||||
|         (('1', '5'), vec![North, East, Stay]), | ||||
|         (('1', '6'), vec![North, East, East, Stay]), | ||||
|         (('1', '7'), vec![North, North, Stay]), | ||||
|         (('1', '8'), vec![North, North, East, Stay]), | ||||
|         (('1', '9'), vec![North, North, East, East, Stay]), | ||||
|         
 | ||||
|         (('2', 'A'), vec![South, East, Stay]), | ||||
|         (('2', '0'), vec![South, Stay]), 
 | ||||
|         (('2', '1'), vec![West, Stay]), | ||||
|         (('2', '2'), vec![Stay]), | ||||
|         (('2', '3'), vec![East, Stay]), | ||||
|         (('2', '4'), vec![West, North, Stay]), | ||||
|         (('2', '5'), vec![North, Stay]), | ||||
|         (('2', '6'), vec![East, North, Stay]), | ||||
|         (('2', '7'), vec![West, North, North, Stay]), | ||||
|         (('2', '8'), vec![North, North, Stay]), | ||||
|         (('2', '9'), vec![East, North, North, Stay]), | ||||
| 
 | ||||
|         (('3', 'A'), vec![South, Stay]), | ||||
|         (('3', '0'), vec![West, South, Stay]), 
 | ||||
|         (('3', '1'), vec![West, West, Stay]), | ||||
|         (('3', '2'), vec![West, Stay]), | ||||
|         (('3', '3'), vec![Stay]), | ||||
|         (('3', '4'), vec![West, West, North, Stay]), | ||||
|         (('3', '5'), vec![West, North, Stay]), | ||||
|         (('3', '6'), vec![North, Stay]), | ||||
|         (('3', '7'), vec![West, West, North, North, Stay]), | ||||
|         (('3', '8'), vec![West, North, Stay]), | ||||
|         (('3', '9'), vec![North, North, Stay]), | ||||
| 
 | ||||
|         (('4', 'A'), vec![East, East, South, South, Stay]), | ||||
|         (('4', '0'), vec![East, South, South, Stay]), 
 | ||||
|         (('4', '1'), vec![South, Stay]), | ||||
|         (('4', '2'), vec![South, East, Stay]), | ||||
|         (('4', '3'), vec![South, East, East, Stay]), | ||||
|         (('4', '4'), vec![Stay]), | ||||
|         (('4', '5'), vec![East, Stay]), | ||||
|         (('4', '6'), vec![East, East, Stay]), | ||||
|         (('4', '7'), vec![North, Stay]), | ||||
|         (('4', '8'), vec![North, East, Stay]), | ||||
|         (('4', '9'), vec![North, East, East, Stay]), | ||||
|         
 | ||||
|         (('5', 'A'), vec![South, South, East, Stay]), | ||||
|         (('5', '0'), vec![South, South, Stay]), 
 | ||||
|         (('5', '1'), vec![West, South, Stay]), | ||||
|         (('5', '2'), vec![South, Stay]), | ||||
|         (('5', '3'), vec![South, East, Stay]), | ||||
|         (('5', '4'), vec![West, Stay]), | ||||
|         (('5', '5'), vec![Stay]), | ||||
|         (('5', '6'), vec![East, Stay]), | ||||
|         (('5', '7'), vec![West, North, Stay]), | ||||
|         (('5', '8'), vec![North, Stay]), | ||||
|         (('5', '9'), vec![North, East, Stay]), | ||||
| 
 | ||||
|         (('6', 'A'), vec![South, South, Stay]), | ||||
|         (('6', '0'), vec![West, South, South, Stay]), 
 | ||||
|         (('6', '1'), vec![West, West, South, Stay]), | ||||
|         (('6', '2'), vec![West, South, Stay]), | ||||
|         (('6', '3'), vec![South, Stay]), | ||||
|         (('6', '4'), vec![West, West, Stay]), | ||||
|         (('6', '5'), vec![West, Stay]), | ||||
|         (('6', '6'), vec![Stay]), | ||||
|         (('6', '7'), vec![West, West, North, Stay]), | ||||
|         (('6', '8'), vec![West, North, Stay]), | ||||
|         (('6', '9'), vec![North, Stay]), | ||||
| 
 | ||||
|         (('7', 'A'), vec![East, East, South, South, South, Stay]), | ||||
|         (('7', '0'), vec![East, South, South, South, Stay]), 
 | ||||
|         (('7', '1'), vec![South, South, Stay]), | ||||
|         (('7', '2'), vec![South, South, East, Stay]), | ||||
|         (('7', '3'), vec![South, South, East, East, Stay]), | ||||
|         (('7', '4'), vec![South, Stay]), | ||||
|         (('7', '5'), vec![South, East, Stay]), | ||||
|         (('7', '6'), vec![South, East, East, Stay]), | ||||
|         (('7', '7'), vec![Stay]), | ||||
|         (('7', '8'), vec![East, Stay]), | ||||
|         (('7', '9'), vec![East, East, Stay]), | ||||
|         
 | ||||
|         (('8', 'A'), vec![South, South, South, East, Stay]), | ||||
|         (('8', '0'), vec![South, South, South, Stay]), 
 | ||||
|         (('8', '1'), vec![West, South, South, Stay]), | ||||
|         (('8', '2'), vec![South, South, Stay]), | ||||
|         (('8', '3'), vec![South, South, East, Stay]), | ||||
|         (('8', '4'), vec![West, South, Stay]), | ||||
|         (('8', '5'), vec![South, Stay]), | ||||
|         (('8', '6'), vec![South, East, Stay]), | ||||
|         (('8', '7'), vec![West, West, Stay]), | ||||
|         (('8', '8'), vec![Stay]), | ||||
|         (('8', '9'), vec![East, Stay]), | ||||
| 
 | ||||
|         (('9', 'A'), vec![South, South, South, Stay]), | ||||
|         (('9', '0'), vec![West, South, South, South, Stay]), 
 | ||||
|         (('9', '1'), vec![West, West, South, South, Stay]), | ||||
|         (('9', '2'), vec![West, South, South, Stay]), | ||||
|         (('9', '3'), vec![South, South, Stay]), | ||||
|         (('9', '4'), vec![West, West, South, Stay]), | ||||
|         (('9', '5'), vec![West, South, Stay]), | ||||
|         (('9', '6'), vec![South, Stay]), | ||||
|         (('9', '7'), vec![West, West, Stay]), | ||||
|         (('9', '8'), vec![West, Stay]), | ||||
|         (('9', '9'), vec![Stay]), | ||||
|         ]); | ||||
| 
 | ||||
|     if depth == 0 { 
 | ||||
|         return 1; | ||||
|     } else { | ||||
|         let mut p = Stay; | ||||
|         let mut len = 0; | ||||
|         for d in &optimals[&(prev, next)] { | ||||
|             len += length_calc(p, *d, depth - 1); | ||||
|             p = *d; | ||||
|         } | ||||
|         return len; | ||||
|     } | ||||
| } | ||||
| #[memoize] | ||||
| fn length_calc(prev: Dir, next: Dir, depth: i32) -> i64 { | ||||
|     let optimals: HashMap<(Dir, Dir), Vec<Dir>> = HashMap::from([ | ||||
|         ((Stay, Stay), vec![Stay]), 
 | ||||
|         ((Stay, North), vec![West, Stay]), 
 | ||||
|         ((Stay, East), vec![South, Stay]), 
 | ||||
|         ((Stay, South), vec![West, South, Stay]), | ||||
|         ((Stay, West), vec![South, West, West, Stay]), | ||||
| 
 | ||||
|         ((North, Stay), vec![East, Stay]), 
 | ||||
|         ((North, North), vec![Stay]), 
 | ||||
|         ((North, South), vec![South, Stay]), | ||||
|         ((North, East), vec![South, East, Stay]), | ||||
|         ((North, West), vec![South, West, Stay]), | ||||
| 
 | ||||
|         ((South, Stay), vec![North, East, Stay]), | ||||
|         ((South, North), vec![North, Stay]), | ||||
|         ((South, South), vec![Stay]), | ||||
|         ((South, East), vec![East, Stay]), | ||||
|         ((South, West), vec![West, Stay]), | ||||
| 
 | ||||
|         ((East, Stay), vec![North, Stay]), | ||||
|         ((East, North), vec![West, North, Stay]), | ||||
|         ((East, South), vec![West, Stay]), | ||||
|         ((East, East), vec![Stay]), | ||||
|         ((East, West), vec![West, West, Stay]), | ||||
| 
 | ||||
|         ((West, Stay), vec![East, East, North, Stay]), | ||||
|         ((West, North), vec![East, North, Stay]), | ||||
|         ((West, South), vec![East, Stay]), | ||||
|         ((West, East), vec![East, East, Stay]), | ||||
|         ((West, West), vec![Stay]), | ||||
|         ]); | ||||
| 
 | ||||
|     if depth == 0 { 
 | ||||
|         return 1; | ||||
|     } else { | ||||
|         let mut p = Stay; | ||||
|         let mut len = 0; | ||||
|         for d in &optimals[&(prev, next)] { | ||||
|             len += length_calc(p, *d, depth - 1); | ||||
|             p = *d; | ||||
|         } | ||||
|         return len; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| fn expandaband(sequence: Vec<Dir>, optimals: &HashMap<(Dir, Dir), Vec<Dir>>) -> Vec<Dir> { | ||||
|     let mut output = vec![]; | ||||
|     let mut prev = Stay; | ||||
|     for dir in sequence { | ||||
|         output.extend(optimals.get(&(prev, dir)).unwrap()); | ||||
|         prev = dir; | ||||
|     } | ||||
|     return output; | ||||
| } | ||||
| fn thru_keypads(code: &str, keypads: i32) -> Vec<Dir> { | ||||
|     let keypad_door: HashMap<char, Coord> = HashMap::from([ | ||||
|         ('7', (0,0)), ('8', (1,0)), ('9', (2,0)), | ||||
|         ('4', (0,1)), ('5', (1,1)), ('6', (2,1)), | ||||
|         ('1', (0,2)), ('2', (1,2)), ('3', (2,2)), | ||||
|         ('0', (1,3)), ('A', (2,3)), | ||||
|         ]); | ||||
|     let mut prev = 'A'; | ||||
|     let mut output = vec![]; | ||||
|     for c in code.chars() { | ||||
|         //println!("navigating from {prev} to {c}");
 | ||||
|         let shortest = shortest_seq( | ||||
|             keypad_door[&prev], 
 | ||||
|             keypad_door[&c], 
 | ||||
|             keypads-1, 
 | ||||
|             vec![(0,3)]); | ||||
|         output.extend(shortest); | ||||
|         prev = c; | ||||
|     } | ||||
|     return output; | ||||
| } | ||||
| 
 | ||||
| #[memoize] | ||||
| fn shortest_seq( | ||||
|     start: Coord, 
 | ||||
|     end: Coord, 
 | ||||
|     keypads: i32, 
 | ||||
|     blacklist: Vec<Coord>, 
 | ||||
| ) -> Vec<Dir> { | ||||
|     // starting at start what is the shortest sequence to navigate to and press end, 
 | ||||
|     // through many keypads?
 | ||||
|     let keypad: HashMap<Dir, Coord> = HashMap::from([ | ||||
|                        (North, (1,0)), (Stay, (2,0)), | ||||
|         (West, (0,1)), (South, (1,1)), (East, (2,1)), | ||||
|         ]); | ||||
|     
 | ||||
|     let paths: Vec<_> = all_paths(start, end) | ||||
|         .into_iter() | ||||
|         .filter(|p| traversal_avoids(start, p, &blacklist)) | ||||
|         .collect(); | ||||
|     //println!("with {keypads} left");
 | ||||
| 
 | ||||
|     if keypads == 1 { | ||||
|         let mut output = vec![]; | ||||
|         output.extend(paths[0].clone()); | ||||
|         output.push(Stay); | ||||
|         return output; | ||||
|     } else { | ||||
|         let mut next_keypad_paths = vec![]; | ||||
|         for path in paths { | ||||
|             let mut longer = vec![]; | ||||
|             let mut prev = keypad[&Stay]; | ||||
|             for dir in path { | ||||
|                 longer.extend( | ||||
|                     shortest_seq( | ||||
|                         prev, 
 | ||||
|                         keypad[&dir], 
 | ||||
|                         keypads-1, 
 | ||||
|                         vec![(0,0)] | ||||
|                         ) | ||||
|                     ); | ||||
|                 prev = keypad[&dir]; | ||||
|             } | ||||
|             longer.extend( | ||||
|                 shortest_seq( | ||||
|                     prev, | ||||
|                     keypad[&Stay], | ||||
|                     keypads-1, | ||||
|                     vec![(0,0)] | ||||
|                     ) | ||||
|                 ); | ||||
|             next_keypad_paths.push(longer); | ||||
|         } | ||||
|         let mut shortest = &next_keypad_paths[0]; | ||||
|         for path in &next_keypad_paths { | ||||
|             if path.len() < shortest.len() { | ||||
|                 shortest = path; | ||||
|             } | ||||
|         } | ||||
|         return shortest.to_vec(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fn traversal_avoids(start: Coord, path: &Vec<Dir>, blacklist: &Vec<Coord>) -> bool { | ||||
|     let mut here = start; | ||||
|     let mut hit = blacklist.contains(&here); | ||||
|     for d in path { | ||||
|         here = step(&here, *d, 1); | ||||
|         hit = hit || blacklist.contains(&here); | ||||
|     } | ||||
|     return !hit; | ||||
| } | ||||
| 
 | ||||
| fn all_paths(prev: Coord, next: Coord) -> Vec<Vec<Dir>> { | ||||
|     let mut out = vec![]; | ||||
| 
 | ||||
|     match (next.0-prev.0, next.1-prev.1) { | ||||
|         (0, 0) => out.push(vec![]), | ||||
|         (mut x, 0) => { | ||||
|             let mut horizontal = vec![]; | ||||
|             while x > 0 { horizontal.push(East); x-=1; } | ||||
|             while x < 0 { horizontal.push(West); x+=1; } | ||||
|             out.push(horizontal); | ||||
|         }, | ||||
|         (0, mut y) => { | ||||
|             let mut vertical = vec![]; | ||||
|             while y > 0 { vertical.push(South); y-=1; } | ||||
|             while y < 0 { vertical.push(North); y+=1; } | ||||
|             out.push(vertical); | ||||
|         }, | ||||
|         (_x, _y) => { | ||||
|             for p1 in all_paths(prev, (next.0, prev.1)) { | ||||
|                 for p2 in all_paths((next.0, prev.1), next) { | ||||
|                     let mut p12 = vec![]; | ||||
|                     p12.extend(p1.clone()); | ||||
|                     p12.extend(p2); | ||||
|                     out.push(p12); | ||||
|                 } | ||||
|             } | ||||
|             for p1 in all_paths(prev, (prev.0, next.1)) { | ||||
|                 for p2 in all_paths((prev.0, next.1), next) { | ||||
|                     let mut p12 = vec![]; | ||||
|                     p12.extend(p1.clone()); | ||||
|                     p12.extend(p2); | ||||
|                     out.push(p12); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return out; | ||||
| } | ||||
| 
 | ||||
| fn expand<T: std::cmp::Eq + std::hash::Hash>( | ||||
|     sequence: &Vec<T>, 
 | ||||
|     map: &HashMap<Coord, T>, 
 | ||||
|     keypad: &HashMap<T, Coord>, 
 | ||||
|     start: T, 
 | ||||
|     seed: &mut u128 | ||||
| ) -> Vec<Dir> { | ||||
|     let mut here = keypad[&start]; | ||||
|     let mut output = Vec::new(); | ||||
|     for t in sequence { | ||||
|         let there = keypad[&t]; | ||||
|         let diff = (there.0 - here.0, there.1 - here.1); | ||||
|         
 | ||||
|         output.extend(build_path(diff, seed)); | ||||
| 
 | ||||
|         here = there; | ||||
|     } | ||||
|     return output; | ||||
| } | ||||
| 
 | ||||
| fn build_path(diff: Coord, seed: &mut u128) -> Vec<Dir> { | ||||
|     let mut output = vec![]; | ||||
|     match diff { | ||||
|         (0, 0) => output.push(Stay), | ||||
|         (x, 0) => { 
 | ||||
|             for _ in 0..x.abs() { 
 | ||||
|                 if x < 0 { output.push(West); } | ||||
|                 if x > 0 { output.push(East); } | ||||
|             } | ||||
|             output.push(Stay); | ||||
|         }, | ||||
|         (0, y) => { | ||||
|             for _ in 0..y.abs() { | ||||
|                 if y < 0 { output.push(North); } | ||||
|                 if y > 0 { output.push(South); } | ||||
|             } | ||||
|             output.push(Stay); | ||||
|         }, | ||||
|         (x, y) => { | ||||
|             if *seed & 1 == 0 { | ||||
|                 for _ in 0..y.abs() { | ||||
|                     if y < 0 { output.push(North); } | ||||
|                     if y > 0 { output.push(South); } | ||||
|                 } | ||||
|                 for _ in 0..x.abs() { 
 | ||||
|                     if x < 0 { output.push(West); } | ||||
|                     if x > 0 { output.push(East); } | ||||
|                 } | ||||
|             } else { | ||||
|                 for _ in 0..x.abs() { 
 | ||||
|                     if x < 0 { output.push(West); } | ||||
|                     if x > 0 { output.push(East); } | ||||
|                 } | ||||
|                 for _ in 0..y.abs() { | ||||
|                     if y < 0 { output.push(North); } | ||||
|                     if y > 0 { output.push(South); } | ||||
|                 } | ||||
|             } | ||||
|             output.push(Stay); | ||||
|             *seed = *seed >> 1; | ||||
|         } | ||||
|     } | ||||
|     return output; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| fn sequences<T>(options: Vec<Vec<(Dir, i32)>>, map: &HashMap<Coord, T>, start: Coord) -> Vec<Vec<Dir>> { | ||||
|     let mut out: Vec<(Vec<Dir>, Coord, Dir)> = vec![(vec![], start, Stay)]; | ||||
| @ -279,7 +804,3 @@ fn execute_code<T: Clone + Copy>( | ||||
|     return out; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										6
									
								
								day23/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								day23/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| [package] | ||||
| name = "day23" | ||||
| version = "0.1.0" | ||||
| edition = "2021" | ||||
| 
 | ||||
| [dependencies] | ||||
							
								
								
									
										124
									
								
								day23/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								day23/src/main.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,124 @@ | ||||
| use std::collections::HashSet; | ||||
| use std::collections::HashMap; | ||||
| 
 | ||||
| use std::env; | ||||
| use std::fs; | ||||
| 
 | ||||
| fn main() { | ||||
|     println!("Hello, AoC day 23!"); | ||||
| 
 | ||||
|     let args: Vec<String> = env::args().collect(); | ||||
|     if args.len() != 2 { | ||||
|         println!("wrong number of arguments!"); | ||||
|         std::process::exit(1); | ||||
|     } | ||||
| 
 | ||||
|     let file_path = &args[1]; | ||||
| 
 | ||||
|     let file = fs::read_to_string(file_path) | ||||
|         .expect("should be able to read the file"); | ||||
| 
 | ||||
|     println!("building adjacency matrix"); | ||||
|     let mut adjacency = HashMap::new(); | ||||
|     let mut edges = HashSet::new(); | ||||
|     for line in file.lines() { | ||||
|         let (a, b) = line.split_once("-").expect("badly formatted line"); | ||||
| 
 | ||||
|         let a_edges = adjacency.entry(a).or_insert(vec![]); | ||||
|         a_edges.push(b); | ||||
|         let b_edges = adjacency.entry(b).or_insert(vec![]); | ||||
|         b_edges.push(a); | ||||
| 
 | ||||
|         edges.insert((a,b)); | ||||
|         edges.insert((b,a)); | ||||
|     } | ||||
| 
 | ||||
|     println!("sorting edges"); | ||||
|     for (_, edges) in adjacency.iter_mut() { | ||||
|        edges.sort(); 
 | ||||
|     } | ||||
| 
 | ||||
|     // part a
 | ||||
| 
 | ||||
|     println!("looking for 3-cliques"); | ||||
|     let mut cliques = HashSet::new(); | ||||
|     for (&a, a_connections) in &adjacency { | ||||
|         for &b in a_connections { | ||||
|              for &c in adjacency.get(b).unwrap() { | ||||
|                 if edges.contains(&(a,c)) { | ||||
|                     let mut clique = vec![a, b, c]; | ||||
|                     clique.sort(); | ||||
|                     cliques.insert(clique); | ||||
|                 } | ||||
|              } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     let mut sorted_cliques = cliques.iter().collect::<Vec<_>>(); | ||||
|     sorted_cliques.sort(); | ||||
|     let mut count_t = 0; | ||||
|     for c in sorted_cliques { | ||||
|         //println!("{},{},{}", c[0], c[1], c[2]);
 | ||||
|         let mut found = false; | ||||
|         for computer in c { | ||||
|             if computer.starts_with("t") { | ||||
|                 found = true; | ||||
|             } | ||||
|         } | ||||
|         if found { | ||||
|             count_t += 1; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     println!("found {count_t} cliques with a computer with t in the name"); | ||||
| 
 | ||||
|     // part b
 | ||||
|     let mut done = false; | ||||
|     while !done { | ||||
|         done = true; | ||||
|         let mut new_cliques = HashSet::new(); | ||||
| 
 | ||||
|         for old_clique in cliques.iter() { | ||||
|             let mut computers = old_clique.clone(); | ||||
|             let me = computers[0]; | ||||
|             for you in adjacency.get(me).unwrap() { | ||||
|                 if computers.contains(you) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 let mut accepted = true; | ||||
|                 for them in &computers { | ||||
|                     if *them == me { | ||||
|                         continue; | ||||
|                     } else if !edges.contains(&(you, *them)) { | ||||
|                         accepted = false; | ||||
|                     } | ||||
|                 } | ||||
|                 // grow the clique iff 'you' is connected to all the members of the clique
 | ||||
|                 if accepted { | ||||
|                     done = false; | ||||
|                     computers.push(you); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             computers.sort(); | ||||
|             new_cliques.insert(computers); | ||||
|         } | ||||
| 
 | ||||
|         cliques = new_cliques; | ||||
|     } | ||||
| 
 | ||||
|     let mut clique_size = 0; | ||||
|     for clique in &cliques { | ||||
|         // for comp in clique { print!("{comp},"); }
 | ||||
|         // print!("\n");
 | ||||
|         clique_size = clique_size.max(clique.len()); | ||||
|     } | ||||
|     println!("the largest clique is {clique_size} computers"); | ||||
| 
 | ||||
|     for clique in &cliques { | ||||
|         if clique.len() == clique_size { | ||||
|             for comp in clique { print!("{comp},"); } | ||||
|             print!("\n"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user