Finished day 14 advent of code

This commit is contained in:
2023-01-10 16:38:39 +01:00
parent 8da7d3d1a8
commit 826bdd6db3
5 changed files with 366 additions and 0 deletions

View File

@@ -0,0 +1,150 @@
use std::{cmp::min, cmp::max, collections::{HashSet, HashMap}};
use nom::{
IResult,
multi::separated_list1,
character::complete::{self, multispace1},
sequence::separated_pair,
bytes::complete::tag,
};
fn parse_input(input: &str) -> IResult<&str, Vec<Vec<(u32, u32)>>> {
let (input, result) = separated_list1(
multispace1,
separated_list1(
tag(" -> "),
separated_pair(complete::u32, tag(","), complete::u32)
)
)(input)?;
Ok((input, result))
}
fn print_coords(coords: &Vec<Vec<(u32, u32)>>) {
for line in coords {
for (c1, c2) in line {
print!("{c1},{c2} -> ");
}
println!();
}
}
fn coords_to_map(coords: &Vec<Vec<(u32, u32)>>) -> (HashSet<(u32, u32)>, u32) {
let mut result = HashSet::new();
let mut lowest_tile = 0;
for rock in coords {
for i in 0..rock.len() - 1 {
let start = rock[i];
let end = rock[i+1];
lowest_tile = max(max(lowest_tile, start.1), end.1);
if start.0 == end.0 {
let x = start.0;
let y_start = min(start.1, end.1);
let y_end = max(start.1, end.1);
for y in y_start..=y_end {
result.insert((x, y));
}
} else {
let y = start.1;
let x_start = min(start.0, end.0);
let x_end = max(start.0, end.0);
for x in x_start..=x_end {
result.insert((x,y));
}
}
}
}
(result, lowest_tile)
}
fn fill_cave(cave_map: &mut HashSet<(u32, u32)>, lowest_tile: u32) -> bool {
let mut cur = (500, 0);
loop {
if cur.1 > lowest_tile {
return false;
}
if !cave_map.contains(&(cur.0, cur.1 + 1)) {
cur = (cur.0, cur.1 + 1);
continue;
}
else if !cave_map.contains(&(cur.0 - 1, cur.1 + 1)) {
cur = (cur.0 - 1, cur.1 + 1);
continue;
}
else if !cave_map.contains(&(cur.0 + 1, cur.1 + 1)) {
cur = (cur.0 + 1, cur.1 + 1);
continue;
}
else {
cave_map.insert(cur);
return true;
}
}
}
fn fill_cave_with_floor(cave_map: &mut HashSet<(u32, u32)>, lowest_tile: u32) -> (u32, u32) {
let mut cur = (500, 0);
loop {
if cur.1 == lowest_tile + 1 {
cave_map.insert(cur);
return cur;
}
else if !cave_map.contains(&(cur.0, cur.1 + 1)) {
cur = (cur.0, cur.1 + 1);
continue;
}
else if !cave_map.contains(&(cur.0 - 1, cur.1 + 1)) {
cur = (cur.0 - 1, cur.1 + 1);
continue;
}
else if !cave_map.contains(&(cur.0 + 1, cur.1 + 1)) {
cur = (cur.0 + 1, cur.1 + 1);
continue;
}
else {
cave_map.insert(cur);
return cur;
}
}
}
fn main() {
let input_text = include_str!("../input.txt");
let (_rest, coord_lines) = parse_input(input_text).unwrap();
// Test parsing
// print_coords(&coord_lines);
let (mut cave_map, lowest_tile) = coords_to_map(&coord_lines);
let mut units_of_sand = 0;
loop {
if !fill_cave(&mut cave_map, lowest_tile) {
break;
}
units_of_sand += 1;
}
println!("Units of sand needed: {units_of_sand}");
units_of_sand = 1;
let (mut cave_map, _) = coords_to_map(&coord_lines);
loop {
if fill_cave_with_floor(&mut cave_map, lowest_tile) == (500, 0) {
break;
}
units_of_sand += 1;
}
println!("Units of sand needed with infinite length floor: {units_of_sand}");
}