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 // }