slighly clean up day 10
This commit is contained in:
parent
b9c3ebc7d7
commit
79e6931c13
@ -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]);
|
||||||
|
Loading…
Reference in New Issue
Block a user