feat: day 17 (literally several hours, part 2 doesn't work)
This commit is contained in:
parent
a788ddaa44
commit
cb0c259251
3 changed files with 223 additions and 0 deletions
1
.aoc-cache/17.txt
Normal file
1
.aoc-cache/17.txt
Normal file
File diff suppressed because one or more lines are too long
221
src/bin/day_17.rs
Normal file
221
src/bin/day_17.rs
Normal file
|
@ -0,0 +1,221 @@
|
|||
#![feature(hash_drain_filter)]
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use aoc_2022::prelude::*;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct RockShape {
|
||||
shape: [[bool; 4]; 4],
|
||||
width: usize,
|
||||
height: usize,
|
||||
}
|
||||
|
||||
const ROCK_SHAPES: &[RockShape] = &[
|
||||
RockShape {
|
||||
shape: [
|
||||
[true, true, true, true ],
|
||||
[false, false, false, false],
|
||||
[false, false, false, false],
|
||||
[false, false, false, false],
|
||||
],
|
||||
width: 4,
|
||||
height: 1,
|
||||
},
|
||||
RockShape {
|
||||
shape: [
|
||||
[false, true , false, false],
|
||||
[true , true , true , false],
|
||||
[false, true , false, false],
|
||||
[false, false, false, false],
|
||||
],
|
||||
width: 3,
|
||||
height: 3,
|
||||
},
|
||||
RockShape {
|
||||
shape: [
|
||||
[true , true , true , false],
|
||||
[false, false, true , false],
|
||||
[false, false, true , false],
|
||||
[false, false, false, false],
|
||||
],
|
||||
width: 3,
|
||||
height: 3,
|
||||
},
|
||||
RockShape {
|
||||
shape: [
|
||||
[true , false, false, false],
|
||||
[true , false, false, false],
|
||||
[true , false, false, false],
|
||||
[true , false, false, false],
|
||||
],
|
||||
width: 1,
|
||||
height: 4,
|
||||
},
|
||||
RockShape {
|
||||
shape: [
|
||||
[true , true , false, false],
|
||||
[true , true , false, false],
|
||||
[false, false, false, false],
|
||||
[false, false, false, false],
|
||||
],
|
||||
width: 2,
|
||||
height: 2,
|
||||
},
|
||||
];
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum Direction {
|
||||
Left,
|
||||
Right,
|
||||
Down,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
fn offset(&self, pos: (usize, usize), width: usize) -> Option<(usize, usize)> {
|
||||
match self {
|
||||
Direction::Left if pos.0 > 0 => Some((pos.0 - 1, pos.1)),
|
||||
Direction::Right if pos.0 + width < 7 => Some((pos.0 + 1, pos.1)),
|
||||
Direction::Down if pos.1 > 0 => Some((pos.0, pos.1 - 1)),
|
||||
Direction::Down => None,
|
||||
_ => Some(pos),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Input = Vec<Direction>;
|
||||
|
||||
fn parse(s: &str) -> Result<Input> {
|
||||
Ok(
|
||||
s.chars()
|
||||
.filter_map(|c| match c {
|
||||
'<' => Some(Direction::Left),
|
||||
'>' => Some(Direction::Right),
|
||||
_ => None,
|
||||
})
|
||||
.flat_map(|i| [i, Direction::Down].into_iter())
|
||||
.collect::<Vec<_>>()
|
||||
)
|
||||
}
|
||||
|
||||
#[aoc(day = 17, parse = parse, test_cases = ["day_17.txt"])]
|
||||
fn day_17(input: Input) -> Result<()> {
|
||||
// Part 1
|
||||
let mut instruction = 0;
|
||||
|
||||
let mut map = HashSet::new();
|
||||
|
||||
// we need 2022 rocks
|
||||
for rock in 0..2022 {
|
||||
let rock = rock % ROCK_SHAPES.len();
|
||||
instruction %= input.len();
|
||||
simulate_rock(ROCK_SHAPES[rock], &input, &mut map, &mut instruction);
|
||||
}
|
||||
|
||||
let part_one = highest_point_in_map(&map).unwrap_or((0, 0)).1 + 1;
|
||||
|
||||
println!("Part one: {part_one}");
|
||||
|
||||
// Part 2
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_map(map: &HashSet<(usize, usize)>, falling: Option<((usize, usize), RockShape)>) {
|
||||
let max_y = highest_point_in_map(&map).unwrap_or((0, 0)).1 + 1;
|
||||
|
||||
let max_y = if let Some((pos, rock)) = falling {
|
||||
max_y.max(pos.1 + rock.height)
|
||||
} else {
|
||||
max_y
|
||||
};
|
||||
|
||||
for y in 0..max_y {
|
||||
let y = max_y - 1 - y;
|
||||
print!("|");
|
||||
for x in 0..7 {
|
||||
if map.contains(&(x, y)) {
|
||||
print!("#");
|
||||
} else {
|
||||
let mut is_falling_rock = false;
|
||||
if let Some((pos, rock)) = falling {
|
||||
for (ry, row) in rock.shape.iter().enumerate() {
|
||||
for (rx, is_solid) in row.iter().enumerate() {
|
||||
if *is_solid {
|
||||
let pos = (pos.0 + rx, pos.1 + ry);
|
||||
if pos.0 == x && pos.1 == y {
|
||||
print!("@");
|
||||
is_falling_rock = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !is_falling_rock {
|
||||
print!(".");
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("|");
|
||||
}
|
||||
println!("+-------+");
|
||||
println!();
|
||||
}
|
||||
|
||||
fn highest_point_in_map(map: &HashSet<(usize, usize)>) -> Option<(usize, usize)> {
|
||||
map.iter().max_by_key(|c| c.1).map(|c| *c)
|
||||
}
|
||||
|
||||
fn lowest_high_point(map: &HashSet<(usize, usize)>) -> Option<usize> {
|
||||
(0..7).into_iter()
|
||||
.filter_map(|x| map.iter().filter(|c| c.0 == x).map(|c| c.1).max())
|
||||
.min()
|
||||
}
|
||||
|
||||
fn simulate_rock(rock: RockShape, input: &Input, map: &mut HashSet<(usize, usize)>, instruction: &mut usize) {
|
||||
let mut position = if let Some(max_pos) = highest_point_in_map(map) {
|
||||
(2, max_pos.1 + 4)
|
||||
} else {
|
||||
(2, 3)
|
||||
};
|
||||
// display_map(&map, Some((position, rock)));
|
||||
|
||||
loop {
|
||||
let direction = input[*instruction];
|
||||
|
||||
*instruction += 1;
|
||||
*instruction %= input.len();
|
||||
|
||||
if let Some(new_pos) = direction.offset(position, rock.width) {
|
||||
let would_be_stuck = rock.shape.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(y, row)| row.iter()
|
||||
.enumerate()
|
||||
.filter_map(move |(x, present)| if *present { Some((x, y)) } else { None })
|
||||
)
|
||||
.map(|c| (c.0 + new_pos.0, c.1 + new_pos.1))
|
||||
.any(|c| map.contains(&c));
|
||||
|
||||
if would_be_stuck {
|
||||
if direction == Direction::Down {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
position = new_pos;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// println!("Came to rest at {position:?}");
|
||||
for (y, row) in rock.shape.iter().enumerate() {
|
||||
for (x, is_solid) in row.iter().enumerate() {
|
||||
if *is_solid {
|
||||
let pos = (position.0 + x, position.1 + y);
|
||||
map.insert(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
test_cases/day_17.txt
Normal file
1
test_cases/day_17.txt
Normal file
|
@ -0,0 +1 @@
|
|||
>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>
|
Loading…
Reference in a new issue