Day 14, puzzle 1
This commit is contained in:
		
							
								
								
									
										17
									
								
								src/bin/d14p1.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/bin/d14p1.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					use aoc22::{day14, util};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn main() {
 | 
				
			||||||
 | 
					    let mut cave = day14::parse_cave(&util::parse_input());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    println!("Initial cave:");
 | 
				
			||||||
 | 
					    cave.print();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut sand = 0;
 | 
				
			||||||
 | 
					    while cave.drop_sand() {
 | 
				
			||||||
 | 
					        sand += 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    println!("Final cave:");
 | 
				
			||||||
 | 
					    cave.print();
 | 
				
			||||||
 | 
					    println!("Total sand dropped: {}", sand);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										121
									
								
								src/day14.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								src/day14.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,121 @@
 | 
				
			|||||||
 | 
					use std::collections::HashSet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use itertools::Itertools;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::util::Coord;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const SAND_SOURCE: Coord = (0, 500);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct Cave {
 | 
				
			||||||
 | 
					    pub rows: usize,
 | 
				
			||||||
 | 
					    pub cols: usize,
 | 
				
			||||||
 | 
					    pub blocked: Vec<Vec<bool>>,
 | 
				
			||||||
 | 
					    pub sand_source: Coord,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Cave {
 | 
				
			||||||
 | 
					    pub fn print(&self) {
 | 
				
			||||||
 | 
					        for row in 0..self.rows {
 | 
				
			||||||
 | 
					            for col in 0..self.cols {
 | 
				
			||||||
 | 
					                if (row, col) == self.sand_source {
 | 
				
			||||||
 | 
					                    print!("+")
 | 
				
			||||||
 | 
					                } else if self.blocked[row][col] {
 | 
				
			||||||
 | 
					                    print!("#");
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    print!(".");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            print!("\n")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn drop_sand(&mut self) -> bool {
 | 
				
			||||||
 | 
					        let (y, x) = self.sand_source;
 | 
				
			||||||
 | 
					        let mut y = y as isize;
 | 
				
			||||||
 | 
					        let mut x = x as isize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while y < self.rows as isize && x > 0 && x < self.cols as isize {
 | 
				
			||||||
 | 
					            if !self.is_blocked(y + 1, x) {
 | 
				
			||||||
 | 
					                y += 1;
 | 
				
			||||||
 | 
					            } else if !self.is_blocked(y + 1, x - 1) {
 | 
				
			||||||
 | 
					                y += 1;
 | 
				
			||||||
 | 
					                x -= 1;
 | 
				
			||||||
 | 
					            } else if !self.is_blocked(y + 1, x + 1) {
 | 
				
			||||||
 | 
					                y += 1;
 | 
				
			||||||
 | 
					                x += 1;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                self.blocked[y as usize][x as usize] = true;
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        false
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn is_blocked(&self, y: isize, x: isize) -> bool {
 | 
				
			||||||
 | 
					        !(y < 0 || y >= self.rows as isize || x < 0 || x >= self.cols as isize)
 | 
				
			||||||
 | 
					            && self.blocked[y as usize][x as usize]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn parse_cave(input: &String) -> Cave {
 | 
				
			||||||
 | 
					    let mut paths = HashSet::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for line in input.lines() {
 | 
				
			||||||
 | 
					        let mut path = line.split("->").map(|n| parse_coord(n.trim()));
 | 
				
			||||||
 | 
					        let mut last = path.next().unwrap();
 | 
				
			||||||
 | 
					        paths.insert(last);
 | 
				
			||||||
 | 
					        for next in path {
 | 
				
			||||||
 | 
					            let y_min = next.0.min(last.0);
 | 
				
			||||||
 | 
					            let y_max = next.0.max(last.0);
 | 
				
			||||||
 | 
					            let x_min = next.1.min(last.1);
 | 
				
			||||||
 | 
					            let x_max = next.1.max(last.1);
 | 
				
			||||||
 | 
					            let horizontal = y_min == y_max;
 | 
				
			||||||
 | 
					            let vertical = x_min == x_max;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            assert!(horizontal ^ vertical);
 | 
				
			||||||
 | 
					            if horizontal {
 | 
				
			||||||
 | 
					                for x in x_min..=x_max {
 | 
				
			||||||
 | 
					                    paths.insert((y_min, x));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                for y in y_min..=y_max {
 | 
				
			||||||
 | 
					                    paths.insert((y, x_max));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            last = next;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert_ne!(paths.len(), 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let (y_min, y_max) = paths.iter().map(|c| c.0).minmax().into_option().unwrap();
 | 
				
			||||||
 | 
					    let (x_min, x_max) = paths.iter().map(|c| c.1).minmax().into_option().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Sand source is always at y = 0, x = 500
 | 
				
			||||||
 | 
					    let y_min = y_min.min(SAND_SOURCE.0);
 | 
				
			||||||
 | 
					    let x_min = x_min.min(SAND_SOURCE.1);
 | 
				
			||||||
 | 
					    let x_max = x_max.max(SAND_SOURCE.1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let rows = y_max - y_min + 1;
 | 
				
			||||||
 | 
					    let cols = x_max - x_min + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut blocked = vec![vec![false; cols]; rows];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for coord in paths {
 | 
				
			||||||
 | 
					        blocked[coord.0 - y_min][coord.1 - x_min] = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Cave {
 | 
				
			||||||
 | 
					        rows,
 | 
				
			||||||
 | 
					        cols,
 | 
				
			||||||
 | 
					        blocked,
 | 
				
			||||||
 | 
					        sand_source: (SAND_SOURCE.0 - y_min, SAND_SOURCE.1 - x_min),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn parse_coord(input: &str) -> Coord {
 | 
				
			||||||
 | 
					    let (x, y) = input.split_once(',').unwrap();
 | 
				
			||||||
 | 
					    (y.parse().unwrap(), x.parse().unwrap())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -3,6 +3,7 @@ pub mod day10;
 | 
				
			|||||||
pub mod day11;
 | 
					pub mod day11;
 | 
				
			||||||
pub mod day12;
 | 
					pub mod day12;
 | 
				
			||||||
pub mod day13;
 | 
					pub mod day13;
 | 
				
			||||||
 | 
					pub mod day14;
 | 
				
			||||||
pub mod day2;
 | 
					pub mod day2;
 | 
				
			||||||
pub mod day3;
 | 
					pub mod day3;
 | 
				
			||||||
pub mod day4;
 | 
					pub mod day4;
 | 
				
			||||||
 | 
				
			|||||||
@ -35,3 +35,5 @@ pub fn max_n<T: Ord + Copy>(slice: &[T], n: usize) -> Result<Vec<T>, ()> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    Ok(max_vals)
 | 
					    Ok(max_vals)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub type Coord = (usize, usize);
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user