finish part 1

This commit is contained in:
nora 2023-12-10 18:26:42 +01:00
parent 62e7e74862
commit 0a5735fce7
3 changed files with 96 additions and 30 deletions

View file

@ -0,0 +1,5 @@
--S-7
F7L7|
||.||
|L-J|
L---J

View file

@ -0,0 +1,3 @@
FS---------7
|----------|
L----------J

View file

@ -1,3 +1,5 @@
use std::collections::VecDeque;
use helper::{Day, Variants}; use helper::{Day, Variants};
pub fn main() { pub fn main() {
@ -34,21 +36,22 @@ const TOP_RIGHT: u8 = b'7';
const BOTTOM_LEFT: u8 = b'L'; const BOTTOM_LEFT: u8 = b'L';
const BOTTOM_RIGHT: u8 = b'J'; const BOTTOM_RIGHT: u8 = b'J';
struct Candidates { struct Candidates<'a> {
v: Vec<Candidate>, v: VecDeque<Candidate>,
width: usize, width: usize,
len: usize, len: usize,
bytes: &'a [u8],
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
struct Candidate { struct Candidate {
count: u64, count: u64,
pos: usize, pos: usize,
skip: Skip, came_from: Direction,
} }
#[derive(Clone, Copy, PartialEq, Eq)] #[derive(Clone, Copy, PartialEq, Eq)]
enum Skip { enum Direction {
Left, Left,
Right, Right,
Top, Top,
@ -56,42 +59,62 @@ enum Skip {
None, None,
} }
impl Candidates { impl Candidates<'_> {
fn push(&mut self, new: Candidate) {
match (new.came_from, self.bytes[new.pos]) {
(Direction::Left, VERTICAL | TOP_LEFT | BOTTOM_LEFT) => {}
(Direction::Right, VERTICAL | TOP_RIGHT | BOTTOM_RIGHT) => {}
(Direction::Top, HORIZONTAL | TOP_LEFT | TOP_RIGHT) => {}
(Direction::Bottom, HORIZONTAL | BOTTOM_LEFT | BOTTOM_RIGHT) => {}
_ => self.v.push_back(new),
}
}
fn push_left(&mut self, from: Candidate) { fn push_left(&mut self, from: Candidate) {
if from.skip != Skip::Left && from.pos % self.width > 0 { if from.came_from != Direction::Left && from.pos % self.width > 0 {
self.v self.push(Candidate::new(
.push(Candidate::new(from.count + 1, from.pos - 1, Skip::Right)); from.count + 1,
from.pos - 1,
Direction::Right,
));
} }
} }
fn push_right(&mut self, from: Candidate) { fn push_right(&mut self, from: Candidate) {
if from.skip != Skip::Right && (from.pos % self.width) < (self.width - 1) { if from.came_from != Direction::Right && (from.pos % self.width) < (self.width - 1) {
self.v self.push(Candidate::new(
.push(Candidate::new(from.count + 1, from.pos + 1, Skip::Left)); from.count + 1,
from.pos + 1,
Direction::Left,
));
} }
} }
fn push_top(&mut self, from: Candidate) { fn push_top(&mut self, from: Candidate) {
if from.skip != Skip::Top && from.pos >= self.width { if from.came_from != Direction::Top && from.pos >= self.width {
self.v.push(Candidate::new( self.push(Candidate::new(
from.count + 1, from.count + 1,
from.pos - self.width, from.pos - self.width,
Skip::Bottom, Direction::Bottom,
)); ));
} }
} }
fn push_bottom(&mut self, from: Candidate) { fn push_bottom(&mut self, from: Candidate) {
if from.skip != Skip::Bottom && from.pos < (self.len - self.width) { if from.came_from != Direction::Bottom && from.pos < (self.len - self.width) {
self.v.push(Candidate::new( self.push(Candidate::new(
from.count + 1, from.count + 1,
from.pos + self.width, from.pos + self.width,
Skip::Top, Direction::Top,
)); // BOTTOM ));
} }
} }
} }
impl Candidate { impl Candidate {
fn new(count: u64, pos: usize, skip: Skip) -> Self { fn new(count: u64, pos: usize, skip: Direction) -> Self {
Self { count, pos, skip } Self {
count,
pos,
came_from: skip,
}
} }
} }
@ -105,30 +128,51 @@ fn part1(input: &str) -> u64 {
.filter(|&b| b != b'\n') .filter(|&b| b != b'\n')
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let mut seen = bytes.iter().map(|_| false).collect::<Vec<_>>(); let mut seen = bytes.iter().map(|_| (0, false)).collect::<Vec<_>>();
let s = bytes.iter().position(|&b| b == S).unwrap(); let s = bytes.iter().position(|&b| b == S).unwrap();
let mut cs = Candidates { let mut cs = Candidates {
v: Vec::new(), v: VecDeque::new(),
len: bytes.len(), len: bytes.len(),
width, width,
bytes: bytes.as_slice(),
}; };
cs.v.push(Candidate { cs.v.push_back(Candidate {
count: 0, count: 0,
pos: s, pos: s,
skip: Skip::None, came_from: Direction::None,
}); });
let mut highest = 0; let mut highest = 0;
while let Some(c) = cs.v.pop() { let print = false;
if seen[c.pos] {
highest = highest.max(c.count - 1); while let Some(c) = cs.v.pop_front() {
if print {
for (i, _) in bytes.as_slice().iter().enumerate() {
if (i as usize) % width == 0 {
println!();
}
if c.pos == i {
print!("NOW ");
} else if cs.v.iter().any(|c| c.pos == i) {
print!("CAND ");
} else if seen[i].1 {
print!("{:<5} ", seen[i].0);
} else {
print!(". ");
}
}
println!();
}
if seen[c.pos].1 {
highest = highest.max(seen[c.pos].0);
break; break;
} }
seen[c.pos] = true; seen[c.pos] = (c.count, true);
match bytes[c.pos] { match bytes[c.pos] {
S => { S => {
cs.push_left(c); cs.push_left(c);
@ -164,7 +208,19 @@ fn part1(input: &str) -> u64 {
_ => panic!(), _ => panic!(),
} }
} }
if print {
for (i, _) in bytes.as_slice().iter().enumerate() {
if (i as usize) % width == 0 {
println!();
}
if seen[i].1 {
print!("{:<5} ", seen[i].0);
} else {
print!(". ");
}
}
println!();
}
highest highest
} }
@ -177,7 +233,9 @@ helper::tests! {
part1 { part1 {
"../input_small11.txt" => 4; "../input_small11.txt" => 4;
"../input_small12.txt" => 8; "../input_small12.txt" => 8;
"../input.txt" => 0; "../input_small13.txt" => 11;
"../input_small14.txt" => 13;
"../input.txt" => 6903;
} }
part2 { part2 {
"../input.txt" => 0; "../input.txt" => 0;