advent-of-code

Perserverance, or the lack thereof

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

main.rs (3424B)

    1 use std::cmp::Ordering;
    2 use std::collections::HashMap;
    3 
    4 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
    5 struct Coord(i32, i32);
    6 
    7 impl Coord {
    8     fn from_str(s: &str) -> Self {
    9         let tmp = s
   10             .split(',')
   11             .map(|x| x.parse::<i32>().unwrap())
   12             .collect::<Vec<i32>>();
   13         Self(tmp[0], tmp[1])
   14     }
   15 }
   16 
   17 #[derive(Debug, Clone, Copy)]
   18 enum Terrain {
   19     Sand,
   20     Rock,
   21 }
   22 
   23 fn sign(a: i32) -> i32 {
   24     match a.cmp(&0) {
   25         Ordering::Less => -1,
   26         Ordering::Equal => 0,
   27         Ordering::Greater => 1,
   28     }
   29 }
   30 
   31 fn main() {
   32     let input = {
   33         let mut tmp = HashMap::new();
   34         for l in std::fs::read_to_string("input.txt")
   35             .unwrap()
   36             .trim()
   37             .split('\n')
   38         {
   39             let points = l
   40                 .split(" -> ")
   41                 .map(|s| Coord::from_str(s))
   42                 .collect::<Vec<Coord>>();
   43             let mut curr = points[0];
   44             tmp.insert(curr, Terrain::Rock);
   45             for next in &points[1..] {
   46                 while curr != *next {
   47                     curr = Coord(
   48                         curr.0 + sign(next.0 - curr.0),
   49                         curr.1 + sign(next.1 - curr.1),
   50                     );
   51                     tmp.insert(curr, Terrain::Rock);
   52                 }
   53             }
   54         }
   55         tmp
   56     };
   57     let source = Coord(500, 0);
   58     // 1072
   59     println!("Part 1: {}", part_1(&input, source));
   60     // 24659
   61     println!("Part 2: {}", part_2(&input, source, 2));
   62 }
   63 
   64 fn part_1(input: &HashMap<Coord, Terrain>, source: Coord) -> usize {
   65     let y_max = input.keys().map(|c| c.1).max().unwrap();
   66     let mut sim: HashMap<Coord, Terrain> = input.clone();
   67     'outer: loop {
   68         let mut sand_curr = source;
   69         while sand_curr.1 < y_max {
   70             let mut comes_to_rest = true;
   71             for (dx, dy) in [(0, 1), (-1, 1), (1, 1)] {
   72                 let sand_next = Coord(sand_curr.0 + dx, sand_curr.1 + dy);
   73                 if !sim.contains_key(&sand_next) {
   74                     sand_curr = sand_next;
   75                     comes_to_rest = false;
   76                     break;
   77                 }
   78             }
   79             if comes_to_rest {
   80                 sim.insert(sand_curr, Terrain::Sand);
   81                 continue 'outer;
   82             }
   83         }
   84         break;
   85     }
   86     sim.values()
   87         .filter(|x| if let Terrain::Sand = x { true } else { false })
   88         .count()
   89 }
   90 
   91 fn part_2(input: &HashMap<Coord, Terrain>, source: Coord, floor_offset: i32) -> usize {
   92     let y_max = input.keys().map(|c| c.1).max().unwrap() + floor_offset;
   93     let mut sim: HashMap<Coord, Terrain> = input.clone();
   94     while !sim.contains_key(&source) {
   95         let mut sand_curr = source;
   96         loop {
   97             let mut comes_to_rest = true;
   98             for (dx, dy) in [(0, 1), (-1, 1), (1, 1)] {
   99                 let sand_next = Coord(sand_curr.0 + dx, sand_curr.1 + dy);
  100                 if !sim.contains_key(&sand_next) {
  101                     sand_curr = sand_next;
  102                     comes_to_rest = false;
  103                     break;
  104                 }
  105             }
  106             comes_to_rest = comes_to_rest || sand_curr.1 == y_max - 1;
  107             if comes_to_rest {
  108                 sim.insert(sand_curr, Terrain::Sand);
  109                 break;
  110             }
  111         }
  112     }
  113     sim.values()
  114         .filter(|x| if let Terrain::Sand = x { true } else { false })
  115         .count()
  116 }