try to squeeze

This commit is contained in:
nora 2023-12-12 07:51:45 +01:00
parent a7e9248e9c
commit 1820e11337

View file

@ -49,7 +49,7 @@ struct Candidate {
came_from: Direction, came_from: Direction,
} }
#[derive(Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Direction { enum Direction {
Left, Left,
Right, Right,
@ -58,6 +58,18 @@ enum Direction {
None, None,
} }
impl Direction {
fn adjacent(self) -> &'static [Self] {
match self {
Self::Left => &[Self::Top, Self::Bottom],
Self::Right => &[Self::Top, Self::Bottom],
Self::Top => &[Self::Left, Self::Right],
Self::Bottom => &[Self::Left, Self::Right],
Self::None => &[],
}
}
}
fn left(pos: usize, width: usize) -> Option<usize> { fn left(pos: usize, width: usize) -> Option<usize> {
(pos % width > 0).then(|| pos - 1) (pos % width > 0).then(|| pos - 1)
} }
@ -242,33 +254,38 @@ fn part1(input: &str) -> u64 {
} }
fn surroundings(pos: usize, width: usize, len: usize, byte: u8) -> impl Iterator<Item = usize> { fn surroundings(pos: usize, width: usize, len: usize, byte: u8) -> impl Iterator<Item = usize> {
surroundings_opt(pos, width, len, byte).flatten() all_surroundings(pos, width, len)
.flatten()
.filter(move |(d, _)| points_to(byte, *d))
.map(|(_, pos)| pos)
} }
fn surroundings_opt( fn all_surroundings(
pos: usize, pos: usize,
width: usize, width: usize,
len: usize, len: usize,
byte: u8, ) -> impl Iterator<Item = Option<(Direction, usize)>> {
) -> impl Iterator<Item = Option<usize>> {
[ [
// TODO: also use these filters in part 1 // TODO: also use these filters in part 1
left(pos, width).filter(|_| points_to(byte, Direction::Left)), left(pos, width).map(|pos| (Direction::Left, pos)),
right(pos, width).filter(|_| points_to(byte, Direction::Right)), right(pos, width).map(|pos| (Direction::Right, pos)),
top(pos, width).filter(|_| points_to(byte, Direction::Top)), top(pos, width).map(|pos| (Direction::Top, pos)),
bottom(pos, len, width).filter(|_| points_to(byte, Direction::Bottom)), bottom(pos, len, width).map(|pos| (Direction::Bottom, pos)),
] ]
.into_iter() .into_iter()
} }
#[derive(Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
enum State { enum Cell {
#[default]
Empty, Empty,
Path, Path,
Outside, Outside,
OpenLeft, }
OpenRight,
OpenTop, #[derive(Clone, Copy, Default)]
OpenBottom, struct State {
cell: Cell,
sqeeze: [bool; 4],
} }
fn part2(input: &str) -> u64 { fn part2(input: &str) -> u64 {
@ -284,15 +301,15 @@ fn part2(input: &str) -> u64 {
width, width,
bytes, bytes,
} = get_loop(input); } = get_loop(input);
let mut tiles = vec![State::Empty; step_map.len()]; let mut tiles = vec![State::default(); step_map.len()];
let mut start_surroundings = surroundings(target, width, bytes.len(), bytes[target]) let mut start_surroundings = surroundings(target, width, bytes.len(), bytes[target])
.filter(|&pos| step_map[pos].1 && step_map[pos].0 == highest_value - 1); .filter(|&pos| step_map[pos].1 && step_map[pos].0 == highest_value - 1);
tiles[target] = State::Path; tiles[target].cell = Cell::Path;
let mut ab = start_surroundings.collect_array::<2>().unwrap(); let mut ab = start_surroundings.collect_array::<2>().unwrap();
ab.iter().for_each(|&a| tiles[a] = State::Path); ab.iter().for_each(|&a| tiles[a].cell = Cell::Path);
let mut value = highest_value - 1; let mut value = highest_value - 1;
while value > 0 { while value > 0 {
@ -303,7 +320,7 @@ fn part2(input: &str) -> u64 {
}); });
value -= 1; value -= 1;
ab.iter().for_each(|&a| tiles[a] = State::Path); ab.iter().for_each(|&a| tiles[a].cell = Cell::Path);
} }
print_tiles(&tiles, width, &bytes); print_tiles(&tiles, width, &bytes);
@ -315,40 +332,63 @@ fn part2(input: &str) -> u64 {
std::thread::sleep(std::time::Duration::from_secs(1)); std::thread::sleep(std::time::Duration::from_secs(1));
for i in 0..tiles.len() { for i in 0..tiles.len() {
let byte = bytes[i];
let before = tiles[i]; let before = tiles[i];
if before != State::Empty {
continue;
}
for around in surroundings_opt(i, width, bytes.len(), bytes[i]) { for around in all_surroundings(i, width, bytes.len()) {
// TODO: squeeeeze // TODO: squeeeeze
match around { match around {
None => { None if before.cell == Cell::Empty => {
tiles[i] = State::Outside; tiles[i].cell = Cell::Outside;
changed = true; changed = true;
} }
Some(around) => { None => {}
if tiles[around] == State::Outside { Some((_, around)) if before.cell == Cell::Empty => {
tiles[i] = State::Outside; if tiles[around].cell == Cell::Outside {
tiles[i].cell = Cell::Outside;
changed = true; changed = true;
} }
} }
Some((direction, around)) if before.cell == Cell::Path => {
println!("path {i} {:?}", tiles[around].cell);
if tiles[around].cell == Cell::Outside {
println!("checking {direction:?}");
if !points_to(byte, direction) {
for &adjacent in direction.adjacent() {
if !points_to(byte, adjacent) {
println!("sq");
tiles[i].sqeeze[adjacent as usize] = true;
}
}
}
} else if tiles[around].cell == Cell::Path {
// continue the sqeeze
}
}
_ => {}
} }
} }
} }
print_tiles(&tiles, width, &bytes); print_tiles(&tiles, width, &bytes);
} }
tiles.iter().filter(|&&state| state == State::Empty).count() as u64 tiles
.iter()
.filter(|&&state| state.cell == Cell::Empty)
.count() as u64
} }
fn print_tiles(tiles: &[State], width: usize, bytes: &[u8]) { fn print_tiles(tiles: &[State], width: usize, bytes: &[u8]) {
print(&tiles, width, |i, state| { print(&tiles, width, |i, state| {
let c = fancy_char(bytes[i]); let c = fancy_char(bytes[i]);
match state { match state.cell {
State::Empty => print!("{c}"), Cell::Empty => print!("{c}"),
State::Path => print!("\x1B[1;31m{c}\x1B[1;0m"), Cell::Path if state.sqeeze.iter().any(|&sq| sq) => {
State::Outside => print!("\x1B[1;34m{c}\x1B[1;0m"), print!("\x1B[1;32m{c}\x1B[1;0m")
}
Cell::Path => print!("\x1B[1;31m{c}\x1B[1;0m"),
Cell::Outside => print!("\x1B[1;34m{c}\x1B[1;0m"),
_ => print!("\x1B[1;33m{c}\x1B[1;0m"), _ => print!("\x1B[1;33m{c}\x1B[1;0m"),
} }
}); });