aoc2022

Advent of Code 2022 solutions in Rust
git clone git://code.mfashby.net:/aoc2022
Log | Files | Refs

day14.rs (4421B)


      1 const AIR: char = '.';
      2 const ROCK: char = '#';
      3 //const SANDSPAWN: char = '+';
      4 //const MOVING_SAND: char = '*';
      5 const STUCK_SAND: char  = 'o';
      6 
      7 pub fn run(input: String) {
      8     // line segments
      9     let ls: Vec<Vec<(i32,i32)>> = input.lines().map(|line| {
     10         let cornersstr = line.split("->");
     11         cornersstr.map(|cornerstr| {
     12             let (xs,ys) = cornerstr.split_once(",").expect("coordinate didn't have a , in it!");
     13             (xs.trim().parse::<i32>().expect("xs wasn't a i32!"), ys.trim().parse::<i32>().expect("ys wasn't a i32!"))
     14         }).collect()
     15     }).collect();
     16     // Find our grid bounds,no need to have a 590 cell wide grid... or maybe you just should? idk.
     17     // yeah you'll need a buffer to the left for the sand to fall off of, otherwise it hits the side and that's no good.
     18     // let ((max_x, max_y),(min_x,min_y)) = ls.iter().flatten().fold(((0,0),(usize::MAX,usize::MAX)), |((max_x,max_y),(min_x,min_y)),(x,y)| {
     19     //     ((x.max(*max_x), y.max(max_y)), 
     20     //         (x.min(min_x), y.min(min_y)))
     21     // });
     22     let (max_x, max_y) = ls.iter().flatten().fold((0 as i32,0 as i32), |(max_x,max_y),(x,y)| {
     23         (*x.max(&max_x),*y.max(&max_y))
     24     });
     25     // +2, give a row/col of buffer
     26     // Actually x2, in case we have a pyramid of sand... 
     27     let mut grid: Vec<Vec<char>> = (0..=(max_y+2)).map(|_| {
     28         //(0..(max_x+2)).map(|_| {
     29         (0..(max_x*2+2)).map(|_| {
     30             AIR
     31         }).collect()
     32     }).collect();
     33 
     34     // pt2; add the floor
     35     let floor: usize = (max_y+2).try_into().unwrap();
     36     for i in 0..(max_x*2+2) {
     37         grid[floor][i as usize] = '#';
     38     }
     39 
     40     for l in ls {
     41         for cs in l[..].windows(2) {
     42             if cs.len() != 2 { panic!("window function failed???") }
     43             let (c1, c2) = (cs[0], cs[1]);
     44             let xd = c1.0 - c2.0;
     45             let yd = c1.1 - c2.1;
     46             if xd != 0 && yd != 0 { panic!("diagonal line segment???") } 
     47             if xd != 0 {
     48                 let y = c1.1 as usize;
     49                 for x in (c1.0.min(c2.0))..=(c1.0.max(c2.0)) {
     50                     grid[y][x as usize] = ROCK;
     51                 }
     52             } else if yd != 0 {
     53                 let x = c1.0 as usize;
     54                 for y in (c1.1.min(c2.1))..=(c1.1.max(c2.1)) {
     55                     grid[y as usize][x] = ROCK;
     56                 }
     57             } else {
     58                 panic!("0 length line segment???")
     59             }
     60         }
     61     }
     62     let sandspawn = (500,0);
     63     let mut sand = sandspawn;
     64     let mut ix = 0;
     65 
     66     'lp: loop {
     67         if let Some(np) = mov(&grid,&sand) {
     68             // if np.1 >= max_y.try_into().expect("max_y couldn't fit a usize???") {
     69             //     println!("sand reached the end!");
     70             //     break 'lp;
     71             // }
     72             sand = np;
     73         } else {
     74             // Convert the sand to a stuck sand
     75             grid[sand.1][sand.0] = STUCK_SAND;
     76             
     77             if sand == sandspawn {
     78                 // If we couldn't move, and we're still on the spawn, then we're done!
     79                 break 'lp;   
     80             } else {
     81                 // Otherwise, spawn a new sand
     82                 sand = sandspawn;
     83             }
     84         }
     85         
     86         ix += 1;
     87         if ix > 1_000_000_000 {
     88             eprint!("not getting out of here!");
     89             break 'lp;
     90         }
     91     }
     92 
     93     // Count the stuck sand
     94     //print(&grid, &sandspawn, &sand);
     95     let c_stuck_sand = grid.into_iter().flatten().filter(|ch| {*ch == STUCK_SAND}).count();
     96     println!("Day 14: {}", c_stuck_sand);
     97 }
     98 
     99 fn mov(grid: &Vec<Vec<char>>, sand: &(usize,usize)) -> Option<(usize,usize)> {
    100     if grid[sand.1+1][sand.0] == AIR {
    101         Some((sand.0,sand.1+1))
    102     } else if grid[sand.1+1][sand.0-1] == AIR {
    103         Some((sand.0-1,sand.1+1))
    104     } else if grid[sand.1+1][sand.0+1] == AIR {
    105         Some((sand.0+1,sand.1+1))
    106     } else {
    107         None
    108     }
    109 }
    110 
    111 // fn print(grid: &Vec<Vec<char>>, sandspawn: &(usize,usize), sand: &(usize,usize)) {
    112 //     for (y, line) in grid.into_iter().enumerate() {
    113 //         for (x, ch) in line.into_iter().enumerate().skip(480) {
    114 //             let pt = (x,y);
    115 //             if sand == &pt {
    116 //                 print!("{}", MOVING_SAND);
    117 //             } else if sandspawn == &pt {
    118 //                 print!("{}", SANDSPAWN);
    119 //             } else {
    120 //                 print!("{}", ch);
    121 //             }
    122 //         }
    123 //         print!("\n");
    124 //     }
    125 // }