[TASK] Solved day 10 pt 1
This commit is contained in:
133
src/day10.rs
Normal file
133
src/day10.rs
Normal file
@@ -0,0 +1,133 @@
|
||||
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>
|
||||
}
|
||||
|
||||
impl Day10 {
|
||||
|
||||
pub fn create(input: String) -> Self {
|
||||
// let lines = input.lines();
|
||||
|
||||
// Put the input into the day struct
|
||||
return Day10 {
|
||||
grid: Grid {
|
||||
width: input.lines().next().unwrap().len(),
|
||||
data: input.replace("\n", "").chars().collect(),
|
||||
default: Some('.')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_connected_south(&self, p: &Coord<usize>) -> bool {
|
||||
let c = self.grid.get(&p.x, &p.y);
|
||||
return c == &'|' || c == &'F' || c == &'7' || c == &'S';
|
||||
}
|
||||
|
||||
fn is_connected_north(&self, p: &Coord<usize>) -> bool {
|
||||
let c = self.grid.get(&p.x, &p.y);
|
||||
return c == &'|' || c == &'L' || c == &'J' || c == &'S';
|
||||
}
|
||||
|
||||
fn is_connected_east(&self, p: &Coord<usize>) -> bool {
|
||||
let c = self.grid.get(&p.x, &p.y);
|
||||
return c == &'-' || c == &'L' || c == &'F' || c == &'S';
|
||||
}
|
||||
|
||||
fn is_connected_west(&self, p: &Coord<usize>) -> bool {
|
||||
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()],
|
||||
width: self.grid.width,
|
||||
default: Some(0)
|
||||
};
|
||||
let start_pos = self.grid.find(&'S').unwrap();
|
||||
dist_grid.set(&start_pos.x, &start_pos.y, 0);
|
||||
let mut to_search = Vec::new();
|
||||
let mut searched = HashSet::new();
|
||||
to_search.push((start_pos, 0));
|
||||
while !to_search.is_empty() {
|
||||
to_search.sort_by_key(|(_, d)| usize::MAX - d);
|
||||
let (cur, dist) = to_search.pop().unwrap();
|
||||
let neighbor_dist = dist + 1;
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
to_search.push((east_pos, neighbor_dist));
|
||||
}
|
||||
}
|
||||
|
||||
searched.insert(cur);
|
||||
}
|
||||
// self.grid.print();
|
||||
// println!();
|
||||
// dist_grid.print();
|
||||
return dist_grid.data.iter().filter(|d| d < &&usize::MAX).max().unwrap().to_string();
|
||||
}
|
||||
|
||||
fn solve_part2(&mut self) -> String {
|
||||
return 0.to_string();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part1() {
|
||||
let mut day = Day10::create(String::from("-L|F7
|
||||
7S-7|
|
||||
L|7||
|
||||
-L-J|
|
||||
L|-JF"));
|
||||
assert_eq!("4", day.solve_part1());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part1_2() {
|
||||
let mut day = Day10::create(String::from("7-F7-
|
||||
.FJ|7
|
||||
SJLL7
|
||||
|F--J
|
||||
LJ.LJ"));
|
||||
assert_eq!("8", day.solve_part1());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part2() {
|
||||
let mut day = Day10::create(read_file("input/dayX_example.txt"));
|
||||
assert_eq!("EXAMPLE_ANSWER", day.solve_part2());
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
extern crate core;
|
||||
|
||||
use std::time::Instant;
|
||||
use crate::day10::Day10;
|
||||
use crate::day1::Day1;
|
||||
use crate::day2::Day2;
|
||||
use crate::day3::Day3;
|
||||
@@ -24,8 +25,9 @@ mod day6;
|
||||
mod day7;
|
||||
mod day8;
|
||||
mod day9;
|
||||
mod day10;
|
||||
|
||||
const MAX_DAY: u8 = 9;
|
||||
const MAX_DAY: u8 = 10;
|
||||
const DEFAULT_BENCHMARK_AMOUNT: u32 = 100;
|
||||
|
||||
fn main() {
|
||||
@@ -105,6 +107,7 @@ fn build_day_solver(day: u8, input: String) -> Option<Box<dyn DaySolver>> {
|
||||
7 => Some(Box::new(Day7::create(input))),
|
||||
8 => Some(Box::new(Day8::create(input))),
|
||||
9 => Some(Box::new(Day9::create(input))),
|
||||
10 => Some(Box::new(Day10::create(input))),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
34
src/util.rs
34
src/util.rs
@@ -1,5 +1,6 @@
|
||||
use std::fs;
|
||||
use std::fmt::Display;
|
||||
use itertools::Itertools;
|
||||
|
||||
use num::Integer;
|
||||
|
||||
@@ -18,7 +19,9 @@ pub fn into_lines(input: String) -> Vec<String> {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Grid<T> {
|
||||
pub(crate) width: usize,
|
||||
pub(crate) data: Vec<T>
|
||||
pub(crate) data: Vec<T>,
|
||||
/** What to return if a coordinate that is out of bounds is requested */
|
||||
pub(crate) default: Option<T>
|
||||
}
|
||||
|
||||
impl<T: Clone + Sized> Grid<T> {
|
||||
@@ -48,8 +51,14 @@ impl<T: Clone + Sized> Grid<T> {
|
||||
}
|
||||
|
||||
pub(crate) fn get(&self, x: &usize, y: &usize) -> &T {
|
||||
let idx = self.idx(x, y);
|
||||
&self.data[idx]
|
||||
if self.in_bounds(x, y) {
|
||||
let idx = self.idx(x, y);
|
||||
&self.data[idx]
|
||||
} else if let Some(x) = &self.default {
|
||||
return x;
|
||||
} else {
|
||||
panic!("Out of grid bounds: {}, {}", x, y);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -57,6 +66,14 @@ impl<T: Clone + Sized> Grid<T> {
|
||||
let idx = self.idx(x, y);
|
||||
self.data[idx] = v;
|
||||
}
|
||||
|
||||
pub fn in_bounds(&self, x: &usize, y: &usize) -> bool {
|
||||
return x < &self.width && y < &self.height()
|
||||
}
|
||||
|
||||
pub fn validate(&self) {
|
||||
debug_assert!(&self.data.len() % self.width == 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl <T: Display + Clone + Sized> Grid<T> {
|
||||
@@ -79,6 +96,17 @@ impl <T: Display + Clone + Sized> Grid<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl <T: PartialEq> Grid<T> {
|
||||
|
||||
pub fn find(&self, v: &T) -> Option<Coord<usize>> {
|
||||
return if let Some((i, _)) = self.data.iter().find_position(|x| x == &v) {
|
||||
return Some(Coord::new(i % self.width, i / self.width))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Coord<T> where T: Sized {
|
||||
pub x: T,
|
||||
|
||||
Reference in New Issue
Block a user