slighly clean up day 10

This commit is contained in:
kageru 2023-12-10 22:08:38 +01:00
parent b9c3ebc7d7
commit 79e6931c13
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
2 changed files with 30 additions and 55 deletions

@ -1,18 +1,20 @@
#![feature(test)] #![feature(test)]
extern crate test; extern crate test;
use fnv::FnvHashSet as HashSet;
use std::mem::transmute;
use aoc2023::{ use aoc2023::{
boilerplate, boilerplate,
common::*, common::*,
direction::{Direction, ALL_DIRECTIONS}, direction::{Direction, ALL_DIRECTIONS},
position::{Position2D, PositionND}, position::{Position2D, PositionND},
}; };
use itertools::Itertools; use fnv::FnvHashSet as HashSet;
use itertools::{Itertools, MinMaxResult};
use std::mem::transmute;
const DAY: usize = 10; const DAY: usize = 10;
type Parsed<'a> = (Pos, Vec<&'a [Pipe]>);
type Pos = Position2D<isize>;
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
#[repr(u8)] #[repr(u8)]
@ -29,21 +31,19 @@ enum Pipe {
impl Pipe { impl Pipe {
fn openings(self) -> [Direction; 2] { fn openings(self) -> [Direction; 2] {
use self::{Direction::*, Pipe::*};
match self { match self {
Pipe::Vertical => [Direction::Up, Direction::Down], Vertical => [Up, Down],
Pipe::Horizontal => [Direction::Left, Direction::Right], Horizontal => [Left, Right],
Pipe::TopRight => [Direction::Up, Direction::Right], TopRight => [Up, Right],
Pipe::TopLeft => [Direction::Up, Direction::Left], TopLeft => [Up, Left],
Pipe::BottomRight => [Direction::Down, Direction::Right], BottomRight => [Down, Right],
Pipe::BottomLeft => [Direction::Down, Direction::Left], BottomLeft => [Down, Left],
Pipe::None | Pipe::Start => unimplemented!(), None | Start => unimplemented!(),
} }
} }
} }
type Parsed<'a> = (Pos, Vec<&'a [Pipe]>);
type Pos = Position2D<isize>;
fn parse_input(raw: &str) -> Parsed { fn parse_input(raw: &str) -> Parsed {
let grid = raw.lines().rev().map(|l| unsafe { transmute::<&str, &[Pipe]>(l) }).collect_vec(); let grid = raw.lines().rev().map(|l| unsafe { transmute::<&str, &[Pipe]>(l) }).collect_vec();
let start = grid let start = grid
@ -100,38 +100,26 @@ fn part2((start, grid): &Parsed) -> usize {
} }
dir = *pipe.openings().iter().find(|&&o| o != !dir).unwrap(); dir = *pipe.openings().iter().find(|&&o| o != !dir).unwrap();
} }
let ylen = grid.len() as isize; let MinMaxResult::MinMax(&ymin, &ymax) = corners.iter().map(|PositionND([y, _])| y).minmax() else { unreachable!() };
let xlen = grid[0].len() as isize; let MinMaxResult::MinMax(&xmin, &xmax) = corners.iter().map(|PositionND([_, x])| x).minmax() else { unreachable!() };
(0..ylen) (ymin..=ymax)
.flat_map(|y| (0..xlen).map(move |x| PositionND([x, y]))) .flat_map(|y| (xmin..=xmax).map(move |x| PositionND([x, y])))
.filter(|p| !points.contains(p)) .filter(|p| !points.contains(p))
.filter(|p| is_inside(p, &corners)) .filter(|p| is_inside(p, &corners))
.count() .count()
} }
fn is_inside(p: &Pos, polygon: &Vec<Pos>) -> bool { // A reimplementation of https://www.eecs.umich.edu/courses/eecs380/HANDOUTS/PROJ2/InsidePoly.html
let mut counter = 0; fn is_inside(p: &Pos, polygon: &[Pos]) -> bool {
let mut p1 = polygon[0]; // Zip with next and wrap for the last element
let mut p2; polygon
for i in 1..=polygon.len() { .iter()
p2 = polygon[i % polygon.len()]; .zip(polygon.iter().cycle().skip(1))
if p[1] > p1[1].min(p2[1]) { .filter(|(p1, p2)| p[1] > p1[1].min(p2[1]) && p[1] <= p1[1].max(p2[1]) && p[0] <= p1[0].max(p2[0]) && p1[1] != p2[1])
if p[1] <= p1[1].max(p2[1]) { .filter(|(p1, p2)| p1[0] == p2[0] || p[0] <= (p[1] - p1[1]) * (p2[0] - p1[0]) / (p2[1] - p1[1]) + p1[0])
if p[0] <= p1[0].max(p2[0]) { .count()
if p1[1] != p2[1] { & 1
let xinters = (p[1] - p1[1]) * (p2[0] - p1[0]) / (p2[1] - p1[1]) + p1[0]; == 1
if p1[0] == p2[0] || p[0] <= xinters {
counter += 1;
}
}
}
}
}
p1 = p2;
}
println!("Counter for {p:?} was {counter}");
return counter % 2 != 0;
} }
boilerplate! { boilerplate! {
@ -145,7 +133,6 @@ L|-JF",
part1: { TEST_INPUT => 4 }, part1: { TEST_INPUT => 4 },
part2: { part2: {
INPUT_P2 => 4, INPUT_P2 => 4,
INPUT_P2_2 => 10,
}, },
}, },
bench1 == 6923, bench1 == 6923,
@ -164,15 +151,3 @@ const INPUT_P2: &str = "\
.|..||..|. .|..||..|.
.L--JL--J. .L--JL--J.
.........."; ..........";
#[cfg(test)]
const INPUT_P2_2: &str = "\
FF7FSF7F7F7F7F7F---7
L|LJ||||||||||||F--J
FL-7LJLJ||||||LJL-77
F--JF--7||LJLJIF7FJ-
L---JF-JLJIIIIFJLJJ7
|F|F-JF---7IIIL7L|7|
|FFJF7L7F-JF7IIL---7
7-L-JL7||F7|L7F-7F7|
L.L7LFJ|||||FJL7||LJ
L7JLJL-JLJLJL--JLJ.L";

@ -6,7 +6,7 @@ use std::{
ops::{Add, AddAssign, Index}, ops::{Add, AddAssign, Index},
}; };
use crate::{common::Inc, direction::Direction}; use crate::common::Inc;
#[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)] #[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)]
pub struct PositionND<I, const DIMS: usize>(pub [I; DIMS]); pub struct PositionND<I, const DIMS: usize>(pub [I; DIMS]);