Day 12
This commit is contained in:
		
							
								
								
									
										7
									
								
								day12/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								day12/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| # This file is automatically @generated by Cargo. | ||||
| # It is not intended for manual editing. | ||||
| version = 3 | ||||
|  | ||||
| [[package]] | ||||
| name = "day12" | ||||
| version = "0.1.0" | ||||
							
								
								
									
										41
									
								
								day12/input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								day12/input.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| abcccccccccccccccccccccccccccccccccccccaaaaaaacccccccaaaaaaaaaaaccccccccccccccccccccaaacaaaaaaaacccccccccccccccccccccccccccccccccccaaaaa | ||||
| abccccccccccccccccccaaccaacccccccccccccaaaaaaaccccccccaaaaaaaaaaacccccccaaaaccccccccaaaaaaaaaaaaacccccccccccccccccccccccccccccccccaaaaaa | ||||
| abccccccccccccccccccaaaaaaccccccccccaaaccaaaaaacccccccaaaaaaaaaaccccccccaaaaccccccaaaaaaaaaaaaaaacccccccccccccccccccaaacccccccccccaaaaaa | ||||
| abcccccccccccccccccccaaaaacccccccccccaaccaacaaaccccccaaaaaaaaaaaccccccccaaaacccccaaaaaaaaacaaaaaaacccccccccccccccccaaaacccccccccccaaacaa | ||||
| abccccccccccccccccccaaaaaaccccccccaacaaaaaacccccccccaaaaaaaaaaaaacaaaccccaaccccccaaaaaaaaacaacccccccccccccccccaaaccaaaacccccccccccccccaa | ||||
| abcccccccccccccccccaaaaaaaacccccccaaaaaaaaccccccaaaaaaaacaaaacaaaaaaacccccccccaaccccaaaaaacaaacccccccccccccccaaaakkkaaccccccccccccccccaa | ||||
| abcccccccccccccccccaaaaaaaaccccccccaaaaaccccaacccaaaaaaaaaaaacaaaaaaccccccccccaacccaaaaaaaaaaaacccccccccccccccakkkkkklcccccccccccccccccc | ||||
| abaaacccccccccccaaccccaaccccccccccccaaaaaccaaacccaaaaaaaaaaaaaaaaaaaaccccccaaaaaaaacaacccaaaaaaccccccccccccccckkkkkkkllcccccccaaaccccccc | ||||
| abaaaacccccccaacaaccccaacccccccccccaaacaaaaaaaccccaaaaaaaaaaaaaaaaaaaacccccaaaaaaaaaaaccccaaaaacccccccccccccckkkksssllllccccccaaaaaacccc | ||||
| abaaaacccccccaaaaacccccccccccaaaccccaacaaaaaaccccaaaaaacaaaaaaaaaaaaaacccccccaaaaccccccccaaaaacccccccccccccckkkksssssllllcccccaaaaaacccc | ||||
| abaaacccccccccaaaaaaccccccccaaaaccccccccaaaaaaaacaaaaaaaaaaaaacaaacaaacccccccaaaaacccccccaaaaacccccccccccccjkkkrssssssllllccccccaaaccccc | ||||
| abccccccccccaaaaaaaaccccccccaaaacccccccaaaaaaaaacaacaaaaaaaaaacaaaccccccccccaaacaaccccccccccccccccccccccccjjkkrrsuuussslllllcccccaaccccc | ||||
| abccaaacccccaaaaacccccccccccaaaaccccccaaaaaaaaaacccccaaaaaaaaaacaaccccccccccaacccacccccccccccccccccccccjjjjjjrrrsuuuussslllllmcccddacccc | ||||
| abcccaaaccaccacaaaccccccccccccccccccccaaaaaaaccccccccccaaaaaaaaccccccaacccccccccccaaaaacccccccccccccccjjjjjjrrrruuuuuusssllmmmmmddddcccc | ||||
| abccaaaaaaaacccaaaccccccccccccccccaaacccccaaaccccccccccccaaacccccccccaacccccccccccaaaaacccccccccccccjjjjjrrrrrruuuxuuussqqqqmmmmmdddcccc | ||||
| abcaaaaaaaacccaaaaaacaaaaaccccccaaaaaaccccaaacccaaccccccccaaccccccaaaaaaaaccaaacccaaaaaaccccccccccccjjjjrrrrrruuuxxxuuuqqqqqqqmmmdddcccc | ||||
| abaaaaaaaaaccccaaaaacaaaaaccccccaaaaaaaaccccccaaaaaaccccccccccccccaaaaaaaaccaaacaaaaaaaacccccccccccjjjjrrrtttuuuuxxxyvvvvvqqqqmmmdddcccc | ||||
| abaaaaaaaaaccaaaaaaacaaaaaaccccccaaaaaaaacccccaaaaaaccccccccccccccccaaaaccaaaaaaaaaaaaaacccccccccaaiijqqqrttttuuuxxyyvvvvvvvqqmmmdddcccc | ||||
| abcaaaaaaaaccaaaaaaaaaaaaaacccccaaaaaaaacccccccaaaacccccaaaaccccccccaaaaacaaaaaaaaccaaccccccccccaaaiiiqqqttttxxxxxxyyyyyyvvvqqmmmdddcccc | ||||
| abcccaaaaaaacaaaaaaaaaaaaaacccccaaaaaaaaaaaccccaaaaccccaaaaacccccccaaaaaacaaaaaaacccccccccccccccaaaiiiqqqtttxxxxxxxyyyyyyvvqqqmmmdddcccc | ||||
| SbcccaacccaccccaaacacccaaacccccccccaaaaaaaaacccaccaccccaaaaaaccccccaaccaacccaaaaaccccccccccccccccaaiiiiqqtttxxxxEzzzyyyyvvvqqqmmmddccccc | ||||
| abccaaaccccccccaaccccccccccccccccccaaaaaaaaccccccccccccaaaaaaccccccccccccccaaacaaaccaacccccccccccccciiiqqqttttxxxyyyyyvvvvqqqmmmdddccccc | ||||
| abccccccccccccccccccccccccccccccccaaaaaaaccccccccccccccaaaaaacccccccccccccccaacccccaaaaaaaccccccccccciiiqqqttttxxyyyyyvvvrrrnnneeecccccc | ||||
| abcaaaaccccccccccccccccccccccccccaaaaaaaaccccccccccccccccaacccccccccccccccccccccccccaaaaacccccccccccciiiqqqqttxxyyyyyyyvvrrnnnneeecccccc | ||||
| abcaaaaacccccccccccccccccccccccccaaaacaaacccaccaaacccccccccccccccccccccccccaaaccccaaaaaaaccccccccccccciiiqqqttwwyywwyyywwrrnnneeeccccccc | ||||
| abaaaaaacccaccaccccccccccccccccccaaaaccaacccaaaaaaccccccccccccccccaaaccccaaaaaacccaaaaaaaacccccccccccciiiqqqtswwwwwwwwwwwrrnnneeeccccccc | ||||
| abaaaaaacccaaaaccccccccaaaacccccccaaacccccccaaaaaacccccccccccccccaaaaaaccaaaaaacccaaaaaaaacaaccccccaaciiiqppsswwwwsswwwwwrrrnneeeccccccc | ||||
| abcaaaaacccaaaaacccccccaaaacccccccccccccccccaaaaaaaccccccccccccccaaaaaaccaaaaaacccccaaaaaaaaaccccccaaaahhpppssswwsssswwwwrrrnneeeacccccc | ||||
| abcaaaccccaaaaaacccccccaaaaccccccccccccccccaaaaaaaaccccccccccccccaaaaacccaaaaaccccccaacaaaaaaaaccaaaaaahhpppsssssssssrrrrrrnnneeeacccccc | ||||
| abccccccccaaaaaaccccccccaacccccccccccccccccaaaaaaaaccccaacccccccccaaaaaccaaaaacccccccccaaaaaaaaccaaaaachhpppssssssoosrrrrrrnnneeeaaacccc | ||||
| abccccccccccaaccccccccccccccccaaaaaccccccaacccaaacccaaaaacccccccccaacaacccccccccccccccccaaaaaaacccaaaaahhhppppssppooooorroonnffeaaaacccc | ||||
| abaaccccccccccccccccccccccccccaaaaaccccccaacccaaaccccaaaaacccccccccccccccccccccccccccaacaaaaacccccaacaahhhppppppppoooooooooonfffaaaacccc | ||||
| abaccccccccccccccccccccccccccaaaaaacccaaaaaaaacccccccaaaaaccccccccccccccccccccccccaaaaaaaaaaaccccccccccchhhpppppppgggoooooooffffaacccccc | ||||
| abaccccccccccccccccccccccccccaaaaaacccaaaaaaaaccccccaaaaaccccccacccaacccccccccccccaaaaaccccaaccccccccccchhhhhhggggggggfffffffffaaacccccc | ||||
| abaacccccccccccccccccccccccccaaaaaacccccaaaacccccccccaaaacccaacaacaaacccccccccccccaaaaaaacccccccccccccccchhhhgggggggggffffffffccaacccccc | ||||
| abcccccccaacccccccccccccccccccaaaccccccaaaaaccccccccaaaaccaaaacaaaaacccccccccccccaaaaaaaaccccccccccccccccchhhggggaaaagffffffcccccccccccc | ||||
| abcccccccaacccccccccccccaacccccccccccccaaaaaaccaaccccaaaaaaaaacaaaaaacccccccaaaacaaaaaaaacccccccccccaacccccccaaaacaaaacccccccccccccccccc | ||||
| abccccaaaaaaaacccccccaacaaaccccccccccccaaccaacaaaacccaaaaaaaacaaaaaaaaccccccaaaaccacaaaccaaaccccaaaaaacccccccaacccaaaacccccccccccccaaaaa | ||||
| abccccaaaaaaaacccccccaaaaaccccccccccccccccccccaaaaccccaaaaaaacaaaaaaaaccccccaaaaccccaaaccaaaaaccaaaaaaaacccccccccccaaaccccccccccccccaaaa | ||||
| abccccccaaaaccccccccccaaaaaaccccccccccccccccccaaaacccaaaaaaaaaaccaaccccccccccaacccccccccaaaaacccaaaaaaaacccccccccccaaaccccccccccccccaaaa | ||||
| abcccccaaaaaacccccccaaaaaaaacccccccccccccccccccccccaaaaaaaaaaaaaaaacccccccccccccccccccccaaaaaacccaaaaaaaccccccccccccccccccccccccccaaaaaa | ||||
| @@ -1,3 +1,178 @@ | ||||
| fn main() { | ||||
|     println!("Hello, world!"); | ||||
| use std::{collections::HashSet, fs::read_to_string}; | ||||
|  | ||||
| #[derive(Debug, PartialEq, Eq, Clone, Copy)] | ||||
| enum Tile { | ||||
|     Start, | ||||
|     End, | ||||
|     Hight(u8), | ||||
| } | ||||
|  | ||||
| impl From<char> for Tile { | ||||
|     fn from(input: char) -> Self { | ||||
|         match input { | ||||
|             'S' => Self::Start, | ||||
|             'E' => Self::End, | ||||
|             h => Self::Hight(('a'..='z').position(|c| c == h).unwrap() as u8), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Tile { | ||||
|     fn can_move_to(self, other: Tile) -> bool { | ||||
|         if let Self::Hight(h1) = self { | ||||
|             if let Self::Hight(h2) = other { | ||||
|                 return h1 + 1 >= h2; | ||||
|             } | ||||
|         } | ||||
|         if self == Self::Start { | ||||
|             return other == Self::Hight(0) || other == Self::Hight(1); | ||||
|         } | ||||
|         if other == Self::End { | ||||
|             return self == Self::Hight(('a'..='z').position(|c| c == 'z').unwrap() as u8); | ||||
|         } | ||||
|         false | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Debug, PartialEq, Eq, Clone)] | ||||
| struct Map<T> { | ||||
|     map: Vec<T>, | ||||
|     width: usize, | ||||
|     height: usize, | ||||
| } | ||||
|  | ||||
| impl From<&str> for Map<Tile> { | ||||
|     fn from(input: &str) -> Self { | ||||
|         let width = input.lines().map(|line| line.len()).next().unwrap(); | ||||
|         let height = input.lines().count(); | ||||
|         let map = input | ||||
|             .lines() | ||||
|             .flat_map(|line| line.chars().map(Tile::from).collect::<Vec<_>>()) | ||||
|             .collect::<Vec<_>>(); | ||||
|         Self { map, width, height } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T> Map<T> { | ||||
|     fn at(&self, point: (usize, usize)) -> &T { | ||||
|         let (x, y) = point; | ||||
|         let index = x + y * self.width; | ||||
|         &self.map[index] | ||||
|     } | ||||
|  | ||||
|     fn at_mut(&mut self, point: (usize, usize)) -> &mut T { | ||||
|         let (x, y) = point; | ||||
|         let index = x + y * self.width; | ||||
|         &mut self.map[index] | ||||
|     } | ||||
| } | ||||
|  | ||||
| fn update( | ||||
|     from: (usize, usize), | ||||
|     to: (usize, usize), | ||||
|     path: &mut Map<Option<u32>>, | ||||
|     map: &Map<Tile>, | ||||
|     changed: &mut bool, | ||||
| ) { | ||||
|     if !map.at(from).can_move_to(*map.at(to)) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     let Some(c) = path.at(from) else {return}; | ||||
|     let cost = path.at(to); | ||||
|     let cost = cost.unwrap_or(u32::MAX); | ||||
|     if cost <= c + 1 { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     *path.at_mut(to) = Some(c + 1); | ||||
|     *changed = true; | ||||
| } | ||||
|  | ||||
| fn find_shortest_path(map: &Map<Tile>) -> Option<u32> { | ||||
|     let mut path = Map { | ||||
|         map: vec![None; map.width * map.height], | ||||
|         width: map.width, | ||||
|         height: map.height, | ||||
|     }; | ||||
|     let mut start = (0, 0); | ||||
|     let mut end = (0, 0); | ||||
|     for x in 0..map.width { | ||||
|         for y in 0..map.height { | ||||
|             match map.at((x, y)) { | ||||
|                 Tile::Start => start = (x, y), | ||||
|                 Tile::End => end = (x, y), | ||||
|                 _ => (), | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     *path.at_mut(start) = Some(0); | ||||
|  | ||||
|     let mut changing = true; | ||||
|     while changing { | ||||
|         changing = false; | ||||
|         for x in 0..map.width { | ||||
|             for y in 0..map.height { | ||||
|                 let point = (x, y); | ||||
|                 if x != 0 { | ||||
|                     update((x - 1, y), point, &mut path, map, &mut changing); | ||||
|                 } | ||||
|                 if y != 0 { | ||||
|                     update((x, y - 1), point, &mut path, map, &mut changing); | ||||
|                 } | ||||
|                 if x != map.width - 1 { | ||||
|                     update((x + 1, y), point, &mut path, map, &mut changing); | ||||
|                 } | ||||
|                 if y != map.height - 1 { | ||||
|                     update((x, y + 1), point, &mut path, map, &mut changing); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     *path.at(end) | ||||
| } | ||||
|  | ||||
| fn find_best_start(map: &Map<Tile>) -> u32 { | ||||
|     let mut start = (0, 0); | ||||
|     let mut possible_starts = HashSet::new(); | ||||
|     for x in 0..map.width { | ||||
|         for y in 0..map.height { | ||||
|             match map.at((x, y)) { | ||||
|                 Tile::Start => { | ||||
|                     possible_starts.insert((x, y)); | ||||
|                     start = (x, y); | ||||
|                 } | ||||
|                 Tile::Hight(0) => { | ||||
|                     possible_starts.insert((x, y)); | ||||
|                 } | ||||
|                 _ => (), | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     let mut map = map.clone(); | ||||
|     *map.at_mut(start) = Tile::Hight(0); | ||||
|  | ||||
|     possible_starts | ||||
|         .iter() | ||||
|         .flat_map(|&start| { | ||||
|             let mut map = map.clone(); | ||||
|             *map.at_mut(start) = Tile::Start; | ||||
|             find_shortest_path(&map) | ||||
|         }) | ||||
|         .min() | ||||
|         .unwrap() | ||||
| } | ||||
|  | ||||
| fn main() { | ||||
|     let input = "Sabqponm | ||||
| abcryxxl | ||||
| accszExk | ||||
| acctuvwj | ||||
| abdefghi"; | ||||
|     let input = read_to_string("input.txt").unwrap_or_else(|_| input.to_owned()); | ||||
|     let map: Map<_> = (&*input).into(); | ||||
|     let cost = find_shortest_path(&map); | ||||
|     println!("{cost:?}"); | ||||
|     let cost = find_best_start(&map); | ||||
|     println!("{cost}"); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user