day10: problem 1 solution

This commit is contained in:
2023-12-09 23:24:58 -08:00
parent b84b0b04e2
commit 26f990840a
4 changed files with 351 additions and 0 deletions

196
10/src/main.rs Normal file
View File

@ -0,0 +1,196 @@
use std::fs::File;
use std::io::{BufRead, BufReader, Lines};
// BOILERPLATE
type InputIter = Lines<BufReader<File>>;
fn get_input() -> InputIter {
let f = File::open("input").unwrap();
let br = BufReader::new(f);
br.lines()
}
fn main() {
println!("Problem 1 solution: {}", problem1(get_input()));
println!("Problem 2 solution: {}", problem2(get_input()));
}
// PARSE
#[derive(Debug)]
struct PipeSection {
dist: u64,
kind: char,
}
impl From<char> for PipeSection {
fn from(c: char) -> Self {
PipeSection { dist: 0, kind: c }
}
}
#[derive(Debug)]
struct PipeMap {
map: Vec<Vec<PipeSection>>,
start: (usize, usize),
}
const ALL_ADJ: [(isize, isize); 8] = [
(-1, -1),
(0, -1),
(1, -1),
(-1, 0),
(1, 0),
(-1, 1),
(0, 1),
(1, 1),
];
impl PipeMap {
fn adjacencies(c: char) -> Option<[(isize, isize); 2]> {
match c {
'|' => Some([(0, -1), (0, 1)]),
'-' => Some([(-1, 0), (1, 0)]),
'L' => Some([(0, -1), (1, 0)]),
'J' => Some([(0, -1), (-1, 0)]),
'7' => Some([(0, 1), (-1, 0)]),
'F' => Some([(0, 1), (1, 0)]),
'.' => None,
'S' => None,
_ => panic!("unhandled type"),
}
}
fn valid_pos(&self, pos: (isize, isize)) -> bool {
pos.0 >= 0
&& pos.0 < self.map[0].len() as isize
&& pos.1 >= 0
&& pos.1 < self.map.len() as isize
}
fn apply_adj(&self, pos: (usize, usize), adj: (isize, isize)) -> Option<(usize, usize)> {
if self.valid_pos((pos.0 as isize + adj.0, pos.1 as isize + adj.1)) {
Some((
(pos.0 as isize + adj.0) as usize,
(pos.1 as isize + adj.1) as usize,
))
} else {
None
}
}
fn adjacent_positions(&self, pos: (usize, usize)) -> Option<[(usize, usize); 2]> {
let adj = Self::adjacencies(self.map[pos.1][pos.0].kind);
if let Some(adj) = adj {
let mut positions = adj.iter().filter_map(|adj| self.apply_adj(pos, *adj));
Some([positions.next().unwrap(), positions.next().unwrap()])
} else {
None
}
}
fn start_adjacencies(&self) -> [(usize, usize); 2] {
let mut adj_positions = Vec::new();
for neighbour in ALL_ADJ
.iter()
.filter_map(|adj| self.apply_adj(self.start, *adj))
{
if let Some(neigh_adjs) = self.adjacent_positions(neighbour) {
if neigh_adjs.contains(&self.start) {
adj_positions.push(neighbour)
}
}
}
[adj_positions[0], adj_positions[1]]
}
}
impl<T: BufRead> From<Lines<T>> for PipeMap {
fn from(lines: Lines<T>) -> Self {
let mut map: Vec<Vec<PipeSection>> = Vec::new();
for line in lines {
map.push(line.unwrap().chars().map(PipeSection::from).collect());
}
let start = map
.iter()
.enumerate()
.map(|(idx, row)| (row.iter().position(|p| p.kind == 'S'), idx))
.find(|(x, _)| x.is_some())
.unwrap();
let start = (start.0.unwrap(), start.1);
let mut pipemap = PipeMap { map, start };
let mut cur_positions = pipemap.start_adjacencies();
let mut cur_distance = 1;
loop {
for pos in cur_positions {
pipemap.map[pos.1][pos.0].dist = cur_distance;
}
cur_distance += 1;
if let Some(new_pos1) = pipemap.adjacent_positions(cur_positions[0]) {
if let Some(new_pos1) = new_pos1.iter().find(|pos| {
pipemap.map[pos.1][pos.0].dist == 0 && pipemap.map[pos.1][pos.0].kind != 'S'
}) {
cur_positions[0] = *new_pos1;
} else {
break;
}
}
if let Some(new_pos2) = pipemap.adjacent_positions(cur_positions[1]) {
if let Some(new_pos2) = new_pos2.iter().find(|pos| {
pipemap.map[pos.1][pos.0].dist == 0 && pipemap.map[pos.1][pos.0].kind != 'S'
}) {
cur_positions[1] = *new_pos2;
} else {
break;
}
}
if cur_positions[0] == cur_positions[1] {
pipemap.map[cur_positions[0].1][cur_positions[0].0].dist = cur_distance;
break;
}
}
pipemap
}
}
// PROBLEM 1 solution
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
let map = PipeMap::from(input);
map.map.iter().map(|row| row.iter().map(|cell| cell.dist).max().unwrap()).max().unwrap()
}
// PROBLEM 2 solution
fn problem2<T: BufRead>(input: Lines<T>) -> u64 {
0
}
#[cfg(test)]
mod tests {
use crate::*;
use std::io::Cursor;
const EXAMPLE: &str = &"..F7.
.FJ|.
SJ.L7
|F--J
LJ...";
#[test]
fn problem1_example() {
let c = Cursor::new(EXAMPLE);
assert_eq!(problem1(c.lines()), 8);
}
#[test]
fn problem2_example() {
let c = Cursor::new(EXAMPLE);
assert_eq!(problem2(c.lines()), 0);
}
}