diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/day14.rs | 125 | ||||
-rw-r--r-- | src/main.rs | 2 |
2 files changed, 127 insertions, 0 deletions
diff --git a/src/day14.rs b/src/day14.rs new file mode 100644 index 0000000..97c06fe --- /dev/null +++ b/src/day14.rs @@ -0,0 +1,125 @@ +const AIR: char = '.'; +const ROCK: char = '#'; +const SANDSPAWN: char = '+'; +const MOVING_SAND: char = '*'; +const STUCK_SAND: char = 'o'; + +pub fn run(input: String) { + // line segments + let ls: Vec<Vec<(i32,i32)>> = input.lines().map(|line| { + let cornersstr = line.split("->"); + cornersstr.map(|cornerstr| { + let (xs,ys) = cornerstr.split_once(",").expect("coordinate didn't have a , in it!"); + (xs.trim().parse::<i32>().expect("xs wasn't a i32!"), ys.trim().parse::<i32>().expect("ys wasn't a i32!")) + }).collect() + }).collect(); + // Find our grid bounds,no need to have a 590 cell wide grid... or maybe you just should? idk. + // 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. + // 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)| { + // ((x.max(*max_x), y.max(max_y)), + // (x.min(min_x), y.min(min_y))) + // }); + let (max_x, max_y) = ls.iter().flatten().fold((0 as i32,0 as i32), |(max_x,max_y),(x,y)| { + (*x.max(&max_x),*y.max(&max_y)) + }); + // +2, give a row/col of buffer + // Actually x2, in case we have a pyramid of sand... + let mut grid: Vec<Vec<char>> = (0..=(max_y+2)).map(|_| { + //(0..(max_x+2)).map(|_| { + (0..(max_x*2+2)).map(|_| { + AIR + }).collect() + }).collect(); + + // pt2; add the floor + let floor: usize = (max_y+2).try_into().unwrap(); + for i in 0..(max_x*2+2) { + grid[floor][i as usize] = '#'; + } + + for l in ls { + for cs in l[..].windows(2) { + if cs.len() != 2 { panic!("window function failed???") } + let (c1, c2) = (cs[0], cs[1]); + let xd = c1.0 - c2.0; + let yd = c1.1 - c2.1; + if xd != 0 && yd != 0 { panic!("diagonal line segment???") } + if xd != 0 { + let y = c1.1 as usize; + for x in (c1.0.min(c2.0))..=(c1.0.max(c2.0)) { + grid[y][x as usize] = ROCK; + } + } else if yd != 0 { + let x = c1.0 as usize; + for y in (c1.1.min(c2.1))..=(c1.1.max(c2.1)) { + grid[y as usize][x] = ROCK; + } + } else { + panic!("0 length line segment???") + } + } + } + let sandspawn = (500,0); + let mut sand = sandspawn; + let mut ix = 0; + + 'lp: loop { + if let Some(np) = mov(&grid,&sand) { + // if np.1 >= max_y.try_into().expect("max_y couldn't fit a usize???") { + // println!("sand reached the end!"); + // break 'lp; + // } + sand = np; + } else { + // Convert the sand to a stuck sand + grid[sand.1][sand.0] = STUCK_SAND; + + if sand == sandspawn { + // If we couldn't move, and we're still on the spawn, then we're done! + break 'lp; + } else { + // Otherwise, spawn a new sand + sand = sandspawn; + } + } + + ix += 1; + if ix > 1_000_000_000 { + eprint!("not getting out of here!"); + break 'lp; + } + } + + // Count the stuck sand + //print(&grid, &sandspawn, &sand); + let c_stuck_sand = grid.into_iter().flatten().filter(|ch| {*ch == STUCK_SAND}).count(); + println!("Day 14: {}", c_stuck_sand); +} + +fn mov(grid: &Vec<Vec<char>>, sand: &(usize,usize)) -> Option<(usize,usize)> { + if grid[sand.1+1][sand.0] == AIR { + Some((sand.0,sand.1+1)) + } else if grid[sand.1+1][sand.0-1] == AIR { + Some((sand.0-1,sand.1+1)) + } else if grid[sand.1+1][sand.0+1] == AIR { + Some((sand.0+1,sand.1+1)) + } else { + None + } +} + +fn print(grid: &Vec<Vec<char>>, sandspawn: &(usize,usize), sand: &(usize,usize)) { + for (y, line) in grid.into_iter().enumerate() { + for (x, ch) in line.into_iter().enumerate().skip(480) { + let pt = (x,y); + if sand == &pt { + print!("{}", MOVING_SAND); + } else if sandspawn == &pt { + print!("{}", SANDSPAWN); + } else { + print!("{}", ch); + } + } + print!("\n"); + } +}
\ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 0b427f1..38ed88d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,7 @@ mod day10; mod day11; mod day12; mod day13; +mod day14; fn main() { day1::run(fs::read_to_string("input/day1.txt").expect("Failed to read input file!")); @@ -30,4 +31,5 @@ fn main() { day11::run(fs::read_to_string("input/day11.txt").expect("Failed to read input file!")); day12::run(fs::read_to_string("input/day12.txt").expect("Failed to read input file!")); day13::run(fs::read_to_string("input/day13.txt").expect("Failed to read input file!")); + day14::run(fs::read_to_string("input/day14.txt").expect("Failed to read input file!")); } |