add 2023/10/2
This commit is contained in:
parent
8cc873f4fe
commit
b9c3ebc7d7
@ -1,5 +1,6 @@
|
|||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
use fnv::FnvHashSet as HashSet;
|
||||||
use std::mem::transmute;
|
use std::mem::transmute;
|
||||||
|
|
||||||
use aoc2023::{
|
use aoc2023::{
|
||||||
@ -41,14 +42,14 @@ impl Pipe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Parsed<'a> = (Pos, Vec<&'a [Pipe]>);
|
type Parsed<'a> = (Pos, Vec<&'a [Pipe]>);
|
||||||
type Pos = Position2D<usize>;
|
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
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.zip(0..)
|
||||||
.find_map(|(y, line)| line.iter().enumerate().find_map(|(x, p)| (*p == Pipe::Start).then_some(PositionND([x, y]))))
|
.find_map(|(line, y)| line.iter().zip(0..).find_map(|(p, x)| (*p == Pipe::Start).then_some(PositionND([x, y]))))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
(start, grid)
|
(start, grid)
|
||||||
}
|
}
|
||||||
@ -66,24 +67,71 @@ fn part1((start, grid): &Parsed) -> usize {
|
|||||||
ALL_DIRECTIONS
|
ALL_DIRECTIONS
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|mut dir| {
|
.filter_map(|mut dir| {
|
||||||
let mut pos = *start;
|
let mut pos = *start;
|
||||||
let mut steps = 0;
|
let mut steps = 0;
|
||||||
loop {
|
loop {
|
||||||
steps += 1;
|
steps += 1;
|
||||||
pos = step(pos, dir);
|
pos = step(pos, dir);
|
||||||
if &pos == start {
|
if &pos == start {
|
||||||
return steps / 2;
|
return Some(steps / 2);
|
||||||
}
|
}
|
||||||
dir = *grid[pos.0[1]][pos.0[0]].openings().iter().find(|&&o| o != !dir).unwrap();
|
dir = *grid.get(pos.0[1] as usize)?.get(pos.0[0] as usize)?.openings().iter().find(|&&o| o != !dir).unwrap();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.max()
|
.max()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(parsed: &Parsed) -> usize {
|
fn part2((start, grid): &Parsed) -> usize {
|
||||||
unimplemented!()
|
let mut corners = Vec::new();
|
||||||
|
let mut dir = Direction::Down; // I got this from my part 1 solution.
|
||||||
|
let mut pos = *start;
|
||||||
|
let mut points = HashSet::default();
|
||||||
|
loop {
|
||||||
|
pos = step(pos, dir);
|
||||||
|
let pipe = grid[pos.0[1] as usize][pos.0[0] as usize];
|
||||||
|
points.insert(pos);
|
||||||
|
if matches!(pipe, Pipe::Start | Pipe::TopLeft | Pipe::TopRight | Pipe::BottomLeft | Pipe::BottomRight) {
|
||||||
|
corners.push(pos);
|
||||||
|
}
|
||||||
|
if &pos == start {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dir = *pipe.openings().iter().find(|&&o| o != !dir).unwrap();
|
||||||
|
}
|
||||||
|
let ylen = grid.len() as isize;
|
||||||
|
let xlen = grid[0].len() as isize;
|
||||||
|
(0..ylen)
|
||||||
|
.flat_map(|y| (0..xlen).map(move |x| PositionND([x, y])))
|
||||||
|
.filter(|p| !points.contains(p))
|
||||||
|
.filter(|p| is_inside(p, &corners))
|
||||||
|
.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_inside(p: &Pos, polygon: &Vec<Pos>) -> bool {
|
||||||
|
let mut counter = 0;
|
||||||
|
let mut p1 = polygon[0];
|
||||||
|
let mut p2;
|
||||||
|
for i in 1..=polygon.len() {
|
||||||
|
p2 = polygon[i % polygon.len()];
|
||||||
|
if p[1] > p1[1].min(p2[1]) {
|
||||||
|
if p[1] <= p1[1].max(p2[1]) {
|
||||||
|
if p[0] <= p1[0].max(p2[0]) {
|
||||||
|
if p1[1] != p2[1] {
|
||||||
|
let xinters = (p[1] - p1[1]) * (p2[0] - p1[0]) / (p2[1] - p1[1]) + p1[0];
|
||||||
|
if p1[0] == p2[0] || p[0] <= xinters {
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p1 = p2;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Counter for {p:?} was {counter}");
|
||||||
|
return counter % 2 != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
boilerplate! {
|
boilerplate! {
|
||||||
@ -95,9 +143,36 @@ L|7||
|
|||||||
L|-JF",
|
L|-JF",
|
||||||
tests: {
|
tests: {
|
||||||
part1: { TEST_INPUT => 4 },
|
part1: { TEST_INPUT => 4 },
|
||||||
part2: { TEST_INPUT => 0 },
|
part2: {
|
||||||
|
INPUT_P2 => 4,
|
||||||
|
INPUT_P2_2 => 10,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
bench1 == 6923,
|
bench1 == 6923,
|
||||||
bench2 == 0,
|
bench2 == 529,
|
||||||
bench_parse: |p: &Parsed| (p.0, p.1.len()) => (PositionND([114, 117]), 140),
|
bench_parse: |p: &Parsed| (p.0, p.1.len()) => (PositionND([114, 117]), 140),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
const INPUT_P2: &str = "\
|
||||||
|
..........
|
||||||
|
.S------7.
|
||||||
|
.|F----7|.
|
||||||
|
.||....||.
|
||||||
|
.||....||.
|
||||||
|
.|L-7F-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";
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
use impl_ops::*;
|
use impl_ops::*;
|
||||||
use std::{
|
use std::{
|
||||||
ops,
|
fmt, ops,
|
||||||
ops::{AddAssign, Not},
|
ops::{AddAssign, Not},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ALL_DIRECTIONS: [Direction; 4] = [Direction::Up, Direction::Down, Direction::Left, Direction::Right];
|
pub const ALL_DIRECTIONS: [Direction; 4] = [Direction::Up, Direction::Down, Direction::Left, Direction::Right];
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum Direction {
|
pub enum Direction {
|
||||||
Right = 0,
|
Right = 0,
|
||||||
@ -14,6 +15,21 @@ pub enum Direction {
|
|||||||
Up = 3,
|
Up = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Direction {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
match self {
|
||||||
|
Direction::Up => "Up",
|
||||||
|
Direction::Down => "Down",
|
||||||
|
Direction::Left => "Left",
|
||||||
|
Direction::Right => "Right",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AddAssign<i8> for Direction {
|
impl AddAssign<i8> for Direction {
|
||||||
fn add_assign(&mut self, rhs: i8) {
|
fn add_assign(&mut self, rhs: i8) {
|
||||||
*self = *self + rhs;
|
*self = *self + rhs;
|
||||||
|
@ -3,7 +3,7 @@ use std::{
|
|||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
iter::Step,
|
iter::Step,
|
||||||
ops::{Add, AddAssign},
|
ops::{Add, AddAssign, Index},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{common::Inc, direction::Direction};
|
use crate::{common::Inc, direction::Direction};
|
||||||
@ -55,6 +55,14 @@ where I: AddAssign<I> + Copy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<I, const D: usize> Index<usize> for PositionND<I, D> {
|
||||||
|
type Output = I;
|
||||||
|
|
||||||
|
fn index(&self, index: usize) -> &Self::Output {
|
||||||
|
&self.0[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<I: Copy + Default + Step> PositionND<I, 2> {
|
impl<I: Copy + Default + Step> PositionND<I, 2> {
|
||||||
pub fn neighbors_no_diagonals(&self) -> [PositionND<I, 2>; 4] {
|
pub fn neighbors_no_diagonals(&self) -> [PositionND<I, 2>; 4] {
|
||||||
let PositionND([x, y]) = *self;
|
let PositionND([x, y]) = *self;
|
||||||
|
@ -8,8 +8,8 @@ macro_rules! boilerplate {
|
|||||||
$(unittests: {
|
$(unittests: {
|
||||||
$($unittest: ident: { $($($utpi: expr),+ => $uto: expr),+$(,)? }),*$(,)?
|
$($unittest: ident: { $($($utpi: expr),+ => $uto: expr),+$(,)? }),*$(,)?
|
||||||
},)?
|
},)?
|
||||||
bench1$(($bi1: literal))? == $b1: literal,
|
bench1$(($bi1: literal))? == $b1: expr,
|
||||||
bench2$(($bi2: literal))? == $b2: literal,
|
bench2$(($bi2: literal))? == $b2: expr,
|
||||||
bench_parse: $input_fn: expr => $it: expr$(,)?
|
bench_parse: $input_fn: expr => $it: expr$(,)?
|
||||||
) => {
|
) => {
|
||||||
fn main() {
|
fn main() {
|
||||||
|
Loading…
Reference in New Issue
Block a user