Day 12 part 1 with a little work on part 2

This commit is contained in:
Daniel Flanagan 2024-12-12 12:07:17 -06:00
parent e76498d60c
commit 61a5cd899e
2 changed files with 127 additions and 2 deletions

125
2024/rust/src/day12.rs Normal file
View file

@ -0,0 +1,125 @@
mod prelude;
pub use crate::prelude::*;
fn main() {
let input = day_input(12);
show_answers(part1(&input), part2(&input));
}
#[derive(Debug, Hash, PartialEq, Eq)]
enum Dir {
N,
S,
E,
W,
}
#[derive(Debug)]
struct Region {
locations: HashSet<(usize, usize)>,
perimeters: HashSet<(usize, usize, Dir)>,
}
impl Region {
fn measure_at(bytes: &Vec<Vec<u8>>, sx: usize, sy: usize) -> Self {
let target = bytes[sy][sx];
let (height, width) = (bytes.len(), bytes[0].len());
let mut candidates = vec![(sx, sy)];
let mut locations = HashSet::from_iter(candidates.clone());
let mut perimeters = HashSet::new();
while let Some((x, y)) = candidates.pop() {
print!("AT {x},{y}: ");
for (nx, ny, d) in [
(x, y.saturating_sub(1), Dir::N),
(x, y + 1, Dir::S),
(x + 1, y, Dir::E),
(x.saturating_sub(1), y, Dir::W),
] {
if (nx, ny) == (x, y) || nx >= width || ny >= height {
print!("EDGE@{nx},{ny}; ");
perimeters.insert((nx, ny, d));
continue;
}
if bytes[ny][nx] != target {
print!("EDGE@{nx},{ny}; ");
perimeters.insert((nx, ny, d));
continue;
}
if !locations.contains(&(nx, ny)) {
candidates.push((nx, ny));
locations.insert((nx, ny));
}
}
print!("\n");
}
Self {
locations,
perimeters,
}
}
}
fn part1(input: &str) -> usize {
let mut regions = vec![];
let bytes: Vec<Vec<u8>> = input
.trim()
.lines()
.map(|l| l.trim().bytes().collect())
.collect();
let mut regionated: HashSet<(usize, usize)> = HashSet::new();
for y in 0..bytes.len() {
for x in 0..bytes[y].len() {
if regionated.contains(&(x, y)) {
continue;
}
let region = Region::measure_at(&bytes, x, y);
println!(
"New Region: (Byte: {}, Area: {}, Perimeter: {})",
bytes[y][x],
&region.locations.len(),
&region.perimeters.len(),
);
regionated.extend(&region.locations);
regions.push(region);
}
}
println!("{regions:?}");
regions
.iter()
.map(|r| r.locations.len() * r.perimeters.len())
.sum()
}
fn part2(input: &str) -> usize {
0
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() {
let input = r#"RRRRIICCFF
RRRRIICCCF
VVRRRCCFFF
VVRCCCJFFF
VVVVCJJCFE
VVIVCCJJEE
VVIIICJJEE
MIIIIIJJEE
MIIISIJEEE
MMMISSJEEE"#;
let bytes: Vec<Vec<u8>> = input
.trim()
.lines()
.map(|l| l.trim().bytes().collect())
.collect();
let region = Region::measure_at(&bytes, 0, 0);
assert_eq!(region.locations.len(), 12);
assert_eq!(region.perimeters.len(), 18);
assert_eq!(part1(input), 1930);
assert_eq!(part2(input), 1206);
}
}

View file

@ -6,11 +6,11 @@ fn main() {
show_answers(part1(&input), part2(&input)); show_answers(part1(&input), part2(&input));
} }
fn part1(input: &str) -> i64 { fn part1(input: &str) -> usize {
0 0
} }
fn part2(input: &str) -> i64 { fn part2(input: &str) -> usize {
0 0
} }