[TASK] Solved day 10 pt 2

This commit is contained in:
2023-12-14 00:08:39 +01:00
parent 70a56313d0
commit efa51586d5
2 changed files with 209 additions and 21 deletions

View File

@@ -2,8 +2,6 @@ use std::collections::HashSet;
use crate::day_solver::DaySolver;
use crate::util::{Coord, Grid};
#[cfg(test)]
use crate::util::read_file;
pub struct Day10 {
grid: Grid<char>
@@ -43,20 +41,15 @@ impl Day10 {
let c = self.grid.get(&p.x, &p.y);
return c == &'-' || c == &'J' || c == &'7' || c == &'S';
}
}
impl DaySolver for Day10 {
fn solve_part1(&mut self) -> String {
self.grid.validate();
let mut dist_grid: Grid<usize> = Grid {
data: vec![0; self.grid.data.len()],
fn build_loop_dist_grid(&self) -> Grid<Option<usize>> {
let mut dist_grid: Grid<Option<usize>> = Grid {
data: vec![None; self.grid.data.len()],
width: self.grid.width,
default: Some(0)
default: Some(None)
};
let start_pos = self.grid.find(&'S').unwrap();
dist_grid.set(&start_pos.x, &start_pos.y, 0);
dist_grid.set(&start_pos.x, &start_pos.y, Some(0));
let mut to_search = Vec::new();
let mut searched = HashSet::new();
to_search.push((start_pos, 0));
@@ -67,45 +60,189 @@ impl DaySolver for Day10 {
if self.is_connected_north(&cur) && cur.y > 0 {
let north_pos = Coord::new(cur.x, cur.y - 1);
if !searched.contains(&north_pos) && self.is_connected_south(&north_pos) {
dist_grid.set(&north_pos.x, &north_pos.y, neighbor_dist);
dist_grid.set(&north_pos.x, &north_pos.y, Some(neighbor_dist));
to_search.push((north_pos, neighbor_dist));
}
}
if self.is_connected_south(&cur) {
let south_pos = Coord::new(cur.x, cur.y + 1);
if !searched.contains(&south_pos) && self.is_connected_north(&south_pos) {
dist_grid.set(&south_pos.x, &south_pos.y, neighbor_dist);
dist_grid.set(&south_pos.x, &south_pos.y, Some(neighbor_dist));
to_search.push((south_pos, neighbor_dist));
}
}
if self.is_connected_west(&cur) && cur.x > 0 {
let west_pos = Coord::new(cur.x - 1, cur.y);
if !searched.contains(&west_pos) && self.is_connected_east(&west_pos) {
dist_grid.set(&west_pos.x, &west_pos.y, neighbor_dist);
dist_grid.set(&west_pos.x, &west_pos.y, Some(neighbor_dist));
to_search.push((west_pos, neighbor_dist));
}
}
if self.is_connected_east(&cur) {
let east_pos = Coord::new(cur.x + 1, cur.y);
if !searched.contains(&east_pos) && self.is_connected_west(&east_pos) {
dist_grid.set(&east_pos.x, &east_pos.y, neighbor_dist);
dist_grid.set(&east_pos.x, &east_pos.y, Some(neighbor_dist));
to_search.push((east_pos, neighbor_dist));
}
}
searched.insert(cur);
}
return dist_grid;
}
}
impl DaySolver for Day10 {
fn solve_part1(&mut self) -> String {
self.grid.validate();
let dist_grid = self.build_loop_dist_grid();
// self.grid.print();
// println!();
// dist_grid.print();
return dist_grid.data.iter().filter(|d| d < &&usize::MAX).max().unwrap().to_string();
return dist_grid.data.iter().filter(|d| d.is_some()).map(|d| d.unwrap()).max().unwrap().to_string();
}
fn solve_part2(&mut self) -> String {
return 0.to_string();
// let dist_grid = self.build_loop_dist_grid();
// let max_dist= dist_grid.data.iter().filter(|d| d.is_some()).map(|d| d.unwrap()).max().unwrap();
// let mut cur_positions: Vec<Coord<usize>> = dist_grid.data.iter().enumerate()
// .filter(|(i, d)| d == &&Some(1))
// .map(|(i, _)| Coord::new(i % dist_grid.width, i / dist_grid.width))
// .collect();
// We're gonna follow the loop, and, depending on the direction of each step, we mark the 4 neighboring cells of the (left or right) as region A or B
// Then we figure out if A or B is inside the loop
// And then we "flood" the "inside" parts to get the full count
// We're marking the grid as:
// ? = unknown
// # = loop
// A = Area A
// B = Area B
let mut loop_grid = Grid {
data: vec!['?'; self.grid.data.len()],
width: self.grid.width,
default: Some('?')
};
let start = self.grid.find(&'S').unwrap();
let mut pos = start.clone();
loop {
loop_grid.set(&pos.x, &pos.y, '#');
if self.is_connected_north(&pos) {
if let Some(north) = pos.north() {
if loop_grid.get(&north.x, &north.y) != &'#' && self.is_connected_south(&north) {
// Find next part of the loop! let's mark the neighbors
mark(&mut loop_grid, &pos.west(), 'A');
mark(&mut loop_grid, &pos.east(), 'B');
mark(&mut loop_grid, &north.west(), 'A');
mark(&mut loop_grid, &north.east(), 'B');
pos = north;
continue;
}
}
}
if self.is_connected_south(&pos) {
if let Some(south) = pos.south() {
if loop_grid.get(&south.x, &south.y) != &'#' && self.is_connected_north(&south) {
// Find next part of the loop! let's mark the neighbors
mark(&mut loop_grid, &pos.west(), 'B');
mark(&mut loop_grid, &pos.east(), 'A');
mark(&mut loop_grid, &south.west(), 'B');
mark(&mut loop_grid, &south.east(), 'A');
pos = south;
continue;
}
}
}
if self.is_connected_east(&pos) {
if let Some(east) = pos.east() {
if loop_grid.get(&east.x, &east.y) != &'#' && self.is_connected_west(&east) {
// Find next part of the loop! let's mark the neighbors
mark(&mut loop_grid, &pos.north(), 'A');
mark(&mut loop_grid, &pos.south(), 'B');
mark(&mut loop_grid, &east.north(), 'A');
mark(&mut loop_grid, &east.south(), 'B');
pos = east;
continue;
}
}
}
if self.is_connected_west(&pos) {
if let Some(west) = pos.west() {
if loop_grid.get(&west.x, &west.y) != &'#' && self.is_connected_east(&west) {
// Find next part of the loop! let's mark the neighbors
mark(&mut loop_grid, &pos.north(), 'B');
mark(&mut loop_grid, &pos.south(), 'A');
mark(&mut loop_grid, &west.north(), 'B');
mark(&mut loop_grid, &west.south(), 'A');
pos = west;
continue;
}
}
}
break;
}
// Now to flood the grid
let to_flood: Vec<Coord<usize>> = loop_grid.data.iter().enumerate()
.filter(|(_, d)| d == &&'A' || d == &&'B')
.map(|(i, _)| loop_grid.coord(i))
.collect();
for c in to_flood {
flood(&mut loop_grid, c);
}
// loop_grid.print();
// Now we find if A or B is on the edge of the grid
let edge_type = find_edge_type(&loop_grid);
let loop_type = if edge_type == 'A' { 'B' } else { 'A' };
return loop_grid.data.iter().filter(|d| d == &&loop_type).count().to_string();
}
}
fn mark(loop_grid: &mut Grid<char>, pos: &Option<Coord<usize>>, c: char) {
if let Some(p) = pos {
if loop_grid.get(&p.x, &p.y) == &'?' {
loop_grid.set(&p.x, &p.y, c);
}
}
}
fn flood(loop_grid: &mut Grid<char>, pos: Coord<usize>) {
let c = loop_grid.get(&pos.x, &pos.y).clone();
let mut to_check = Vec::new();
to_check.push(pos);
while !to_check.is_empty() {
let p = to_check.pop().unwrap();
for n in p.compass() {
if loop_grid.in_bounds(&n.x, &n.y) && loop_grid.get(&n.x, &n.y) == &'?' {
loop_grid.set(&n.x, &n.y, c);
to_check.push(n);
}
}
}
}
fn find_edge_type(loop_grid: &Grid<char>) -> char {
for x in 0..loop_grid.width {
for y in [0, loop_grid.height() - 1]
{
let c = loop_grid.get(&x, &y);
if c == &'A' || c == &'B' {
return c.to_owned();
}
}
}
panic!("Can't find the edge type...")
}
#[test]
fn test_part1() {
let mut day = Day10::create(String::from("-L|F7
@@ -127,7 +264,16 @@ LJ.LJ"));
}
#[test]
fn test_part2() {
let mut day = Day10::create(read_file("input/dayX_example.txt"));
assert_eq!("EXAMPLE_ANSWER", day.solve_part2());
fn test_part2_1() {
let mut day = Day10::create(String::from("\
...........
.S-------7.
.|F-----7|.
.||.....||.
.||.....||.
.|L-7.F-J|.
.|..|.|..|.
.L--J.L--J.
..........."));
assert_eq!("4", day.solve_part2());
}

View File

@@ -46,6 +46,10 @@ impl<T: Clone + Sized> Grid<T> {
y * self.width + x
}
pub(crate) fn coord(&self, i: usize) -> Coord<usize> {
return Coord::new(i % self.width, i / self.width);
}
pub(crate) fn height(&self) -> usize {
self.data.len() / self.width
}
@@ -128,3 +132,41 @@ impl <T> Coord<T> where T: Integer + Copy {
}
}
impl Coord<usize> {
pub fn north(&self) -> Option<Coord<usize>> {
if self.y == 0 { return None }
return Some(Coord::new(self.x, self.y - 1));
}
pub fn south(&self) -> Option<Coord<usize>> {
return Some(Coord::new(self.x, self.y + 1));
}
pub fn east(&self) -> Option<Coord<usize>> {
return Some(Coord::new(self.x + 1, self.y));
}
pub fn west(&self) -> Option<Coord<usize>> {
if self.x == 0 { return None }
return Some(Coord::new(self.x - 1, self.y));
}
pub fn compass(&self) -> Vec<Coord<usize>> {
let mut res = Vec::with_capacity(4);
if let Some(north) = self.north() {
res.push(north);
}
if let Some(south) = self.south() {
res.push(south);
}
if let Some(east) = self.east() {
res.push(east);
}
if let Some(west) = self.west() {
res.push(west);
}
res
}
}