[TASK] Solved day 10 pt 2
This commit is contained in:
188
src/day10.rs
188
src/day10.rs
@@ -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());
|
||||
}
|
||||
|
||||
42
src/util.rs
42
src/util.rs
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user