From 397a970a2cf00e4a40d8ffbcc1bc94522c919827 Mon Sep 17 00:00:00 2001 From: spectre Date: Sun, 10 Dec 2023 19:52:44 +0100 Subject: [PATCH] horrible, unreadable spaghetti code. will refactor later --- aoc2023/src/day10.rs | 184 ++++++++++++++++++++++++++++++++++++++++++- src/main.rs | 6 +- 2 files changed, 185 insertions(+), 5 deletions(-) diff --git a/aoc2023/src/day10.rs b/aoc2023/src/day10.rs index 2b164ca..517959e 100644 --- a/aoc2023/src/day10.rs +++ b/aoc2023/src/day10.rs @@ -1,13 +1,193 @@ +use std::collections::HashSet; +use std::process::abort; use shared::{Solution, Answer}; pub struct Day10; impl Solution for Day10 { fn part_1(&self, input: &str) -> Answer { - Answer::Unimplemented + let width: i64 = input.lines().next().unwrap().len() as i64; + let grid: Vec<_> = input.lines().collect::>().join("").chars().map(Pipes::from).collect(); + + let animal = grid.iter().position(|x| x == &Pipes::Animal).unwrap(); + + let mut seen: HashSet = HashSet::new(); + + let mut len = 2; + let mut current ; + + if grid[animal + 1] == Pipes::Horizontal || grid[animal + 1] == Pipes::EtoS || grid[animal + 1] == Pipes::NtoE { + current = animal + 1; + } else if grid[animal - 1] == Pipes::Horizontal || grid[animal - 1] == Pipes::WtoN || grid[animal - 1] == Pipes::StoW { + current = animal - 1; + } else { current = animal + width as usize } + + seen.insert(animal); + seen.insert(current); + + loop { + let next = traverse(&grid, current as i64, width); + if next.is_none() { panic!() } + let (next1, next2) = next.unwrap(); + if seen.contains(&next1) && seen.contains(&next2) { + break; + } else if !seen.contains(&next1) { + current = next1; + seen.insert(next1); + len += 1; + } else if !seen.contains(&next2) { + current = next2; + seen.insert(next2); + len += 1; + } else { panic!() } + } + + Answer::from(len) } fn part_2(&self, input: &str) -> Answer { - Answer::Unimplemented + let width: usize = input.lines().next().unwrap().len(); + let mut grid: Vec<_> = input.lines().collect::>().join("").chars().map(Pipes::from).collect(); + + let animal = grid.iter().position(|x| x == &Pipes::Animal).unwrap(); + replace_animal(&mut grid, animal, width); + println!("{:?}", grid[animal]); + + let mut seen: HashSet = HashSet::new(); + + let mut len = 2; + let mut current ; + + if grid[animal + 1] == Pipes::Horizontal || grid[animal + 1] == Pipes::EtoS || grid[animal + 1] == Pipes::NtoE { + current = animal + 1; + } else if grid[animal - 1] == Pipes::Horizontal || grid[animal - 1] == Pipes::WtoN || grid[animal - 1] == Pipes::StoW { + current = animal - 1; + } else { current = animal + width as usize } + + seen.insert(animal); + seen.insert(current); + + loop { + let next = traverse(&grid, current as i64, width as i64); + if next.is_none() { panic!() } + let (next1, next2) = next.unwrap(); + if seen.contains(&next1) && seen.contains(&next2) { + break; + } else if !seen.contains(&next1) { + current = next1; + seen.insert(next1); + len += 1; + } else if !seen.contains(&next2) { + current = next2; + seen.insert(next2); + } else { panic!() } + } + + let mut parity = grid.chunks(width).map(|_| [0].repeat(width)).collect::>(); + + for (i, line) in grid.chunks(width).enumerate() { + for (j, letter) in line.iter().enumerate() { + if seen.contains(&(width * i + j)) { + for k in j..width { + parity[i][k] += match letter { + Pipes::Vertical => 2, // using 2 and 1 instead of 1 and .5 for half parity, because integers + Pipes::StoW => 1, + Pipes::NtoE => 1, + Pipes::EtoS => -1, + Pipes::WtoN => -1, + _ => 0 + } + } + } + } + } + for i in seen { + parity[i / width][i % width] = 0; + } + + let mut enclosed = 0; + + for line in parity { + enclosed += line.iter().map(|x| (x % 4 / 2)).map(i32::abs).sum::(); + println!("{:?}", line); + } + + Answer::from(enclosed) } } + +#[derive(Debug, PartialEq, Eq)] +enum Pipes { + Ground, + Vertical, + Horizontal, + WtoN, + NtoE, + EtoS, + StoW, + Animal +} + +impl From for Pipes { + fn from(value: char) -> Self { + match value { + '|' => Pipes::Vertical, + '-' => Pipes::Horizontal, + 'J' => Pipes::WtoN, + 'L' => Pipes::NtoE, + 'F' => Pipes::EtoS, + '7' => Pipes::StoW, + '.' => Pipes::Ground, + 'S' => Pipes::Animal, + _ => unreachable!() + } + } +} + +fn traverse(grid: &Vec, current: i64, width: i64) -> Option<(usize, usize)> { + let next1 = current + match grid[current as usize] { + Pipes::Vertical => -width, + Pipes::Horizontal => -1, + Pipes::WtoN => -1, + Pipes::NtoE => -width, + Pipes::EtoS => 1, + Pipes::StoW => width, + Pipes::Animal => 0, + Pipes::Ground => unreachable!() + }; + let next2 = current + match grid[current as usize] { + Pipes::Vertical => width, + Pipes::Horizontal => 1, + Pipes::WtoN => -width, + Pipes::NtoE => 1, + Pipes::EtoS => width, + Pipes::StoW => -1, + Pipes::Animal => 0, + Pipes::Ground => unreachable!() + }; + + // println!("{next1}, {next2}: Current={current}, Width={width}"); + + // if next1 - current == -1 || next1 - current == width || next1 == -1 || next1 == (grid.len() as i64) { return None }; + // if next2 - current == -1 || next2 - current == width || next2 == -1 || next2 == (grid.len() as i64) { return None }; + + Some((next1 as usize, next2 as usize)) +} + +fn replace_animal(grid: &mut Vec, animal: usize, width: usize) { + let east = grid[animal + 1] == Pipes::Horizontal || grid[animal + 1] == Pipes::WtoN || grid[animal + 1] == Pipes::StoW; + let north = grid[animal - width] == Pipes::Vertical || grid[animal - width] == Pipes::WtoN || grid[animal - width] == Pipes::NtoE; + let west = grid[animal - 1] == Pipes::Horizontal || grid[animal - 1] == Pipes::WtoN || grid[animal - 1] == Pipes::StoW; + let south = grid[animal + width] == Pipes::Vertical || grid[animal + width] == Pipes::StoW || grid[animal + width] == Pipes::EtoS; + + match (east, north, south, west) { + (false, false, true, true) => grid[animal] = Pipes::StoW, + (false, true, true, false) => grid[animal] = Pipes::Vertical, + (true, true, false, false) => grid[animal] = Pipes::NtoE, + (false, true, false, true) => grid[animal] = Pipes::WtoN, + (true, false, true, false) => grid[animal] = Pipes::EtoS, + (true, false, false, true) => grid[animal] = Pipes::Horizontal, + _ => unreachable!() + } +} + diff --git a/src/main.rs b/src/main.rs index 902a8af..8ac0506 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,10 +8,10 @@ use std::time::Instant; fn main() { let now = Instant::now(); - let Ok(data) = load_actual(2023, 9) - else { return; }; + let Ok(data) = load_actual(2023, 10) + else { panic!("No Input Data"); }; - let result = aoc2023::day09::Day09.part_2(&data); + let result = aoc2023::day10::Day10.part_2(&data); let elapsed = now.elapsed();