advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git

main.rs (5700B)

    1 use std::collections::{HashMap, HashSet, VecDeque};
    2 
    3 #[derive(Debug, Copy, Clone)]
    4 enum CaveSize {
    5     Big,
    6     Small,
    7 }
    8 
    9 impl CaveSize {
   10     fn check(s: &str) -> CaveSize {
   11         if s.chars().all(char::is_lowercase) {
   12             CaveSize::Small
   13         } else {
   14             CaveSize::Big
   15         }
   16     }
   17 }
   18 
   19 #[derive(Debug, Clone)]
   20 struct CaveSystem {
   21     map: HashMap<String, HashSet<String>>,
   22     cave_size: HashMap<String, CaveSize>,
   23 }
   24 
   25 impl CaveSystem {
   26     fn new(input: &Vec<String>) -> Self {
   27         let mut map = HashMap::<String, HashSet<String>>::new();
   28         let mut cave_size = HashMap::<String, CaveSize>::new();
   29         for s in input {
   30             let mut tmp = s.split('-');
   31             let a = tmp.next().unwrap().to_string();
   32             let b = tmp.next().unwrap().to_string();
   33             if let Some(connected) = map.get_mut(&a) {
   34                 connected.insert(b.clone());
   35             } else {
   36                 map.insert(a.clone(), {
   37                     let mut tmp = HashSet::new();
   38                     tmp.insert(b.clone());
   39                     tmp
   40                 });
   41             }
   42             if !cave_size.contains_key(&a) {
   43                 cave_size.insert(a.clone(), CaveSize::check(&a));
   44             }
   45             if let Some(connected) = map.get_mut(&b) {
   46                 connected.insert(a.clone());
   47             } else {
   48                 map.insert(b.clone(), {
   49                     let mut tmp = HashSet::new();
   50                     tmp.insert(a.clone());
   51                     tmp
   52                 });
   53             }
   54             if !cave_size.contains_key(&b) {
   55                 cave_size.insert(b.clone(), CaveSize::check(&b));
   56             }
   57         }
   58         CaveSystem { map, cave_size }
   59     }
   60 }
   61 
   62 fn main() {
   63     let input = std::fs::read_to_string("input.txt")
   64         .unwrap()
   65         .trim()
   66         .split('\n')
   67         .map(|s| s.to_string())
   68         .collect::<Vec<_>>();
   69     let cave_system = CaveSystem::new(&input);
   70     // 5076
   71     println!("Part 1: {}", part_1(&cave_system));
   72     // 145643
   73     println!("Part 2: {}", part_2(&cave_system));
   74 }
   75 
   76 fn part_1(cave_system: &CaveSystem) -> i32 {
   77     let cave_system = cave_system.clone();
   78     let mut queue = VecDeque::<(VecDeque<String>, HashSet<String>)>::new();
   79     queue.push_back({
   80         let mut path = VecDeque::<String>::new();
   81         path.push_back("start".to_string());
   82         (path, HashSet::<String>::new())
   83     });
   84     let mut path_count = 0;
   85     while let Some((path, mut visited)) = queue.pop_front() {
   86         if let Some(last_step) = path.back() {
   87             visited.insert(last_step.clone());
   88             if last_step == "end" {
   89                 path_count += 1;
   90             } else {
   91                 for next_step in cave_system.map[last_step].iter() {
   92                     match (
   93                         cave_system.cave_size[next_step],
   94                         visited.contains(next_step),
   95                     ) {
   96                         (CaveSize::Big, _) | (CaveSize::Small, false) => {
   97                             queue.push_back((
   98                                 {
   99                                     let mut tmp = path.clone();
  100                                     tmp.push_back(next_step.clone());
  101                                     tmp
  102                                 },
  103                                 visited.clone(),
  104                             ));
  105                         }
  106                         _ => (),
  107                     }
  108                 }
  109             }
  110         }
  111     }
  112     path_count
  113 }
  114 
  115 fn part_2(cave_system: &CaveSystem) -> i32 {
  116     let cave_system = cave_system.clone();
  117     let mut queue = VecDeque::<(VecDeque<String>, HashSet<String>, Option<String>)>::new();
  118     queue.push_back({
  119         let mut path = VecDeque::<String>::new();
  120         path.push_back("start".to_string());
  121         (path, HashSet::<String>::new(), None)
  122     });
  123     let mut path_count = 0;
  124     while let Some((path, mut visited, twice)) = queue.pop_front() {
  125         if let Some(last_step) = path.back() {
  126             visited.insert(last_step.clone());
  127             if last_step == "end" {
  128                 path_count += 1;
  129             } else {
  130                 for next_step in cave_system.map[last_step].iter() {
  131                     match (
  132                         cave_system.cave_size[next_step],
  133                         visited.contains(next_step),
  134                         twice.clone(),
  135                     ) {
  136                         (CaveSize::Big, _, twice) | (CaveSize::Small, false, twice) => {
  137                             queue.push_back((
  138                                 {
  139                                     let mut tmp = path.clone();
  140                                     tmp.push_back(next_step.clone());
  141                                     tmp
  142                                 },
  143                                 visited.clone(),
  144                                 twice,
  145                             ));
  146                         }
  147                         (CaveSize::Small, true, None) => {
  148                             if next_step != "start" {
  149                                 queue.push_back((
  150                                     {
  151                                         let mut tmp = path.clone();
  152                                         tmp.push_back(next_step.clone());
  153                                         tmp
  154                                     },
  155                                     visited.clone(),
  156                                     Some(next_step.clone()),
  157                                 ));
  158                             }
  159                         }
  160                         _ => (),
  161                     }
  162                 }
  163             }
  164         }
  165     }
  166     path_count
  167 }