2022 day 17 part 1
This commit is contained in:
parent
72e6defff9
commit
aa436bcc26
1
2022/rust/inputs/day17.txt
Normal file
1
2022/rust/inputs/day17.txt
Normal file
File diff suppressed because one or more lines are too long
|
@ -18,5 +18,6 @@ fn main() {
|
|||
// solutions::day13::run();
|
||||
// solutions::day14::run();
|
||||
// solutions::day15::run();
|
||||
solutions::day16::run();
|
||||
// solutions::day16::run();
|
||||
solutions::day17::run();
|
||||
}
|
||||
|
|
163
2022/rust/src/solutions/day17.rs
Normal file
163
2022/rust/src/solutions/day17.rs
Normal file
|
@ -0,0 +1,163 @@
|
|||
use std::fmt::{Display, Formatter};
|
||||
use std::iter::Cycle;
|
||||
use std::vec::IntoIter;
|
||||
use crate::utils;
|
||||
|
||||
|
||||
pub fn run() -> () {
|
||||
let data = parse_data(&utils::read_lines(utils::Source::Day(17)));
|
||||
|
||||
println!("Day 17");
|
||||
println!("Part 1: {}", solve1(&data));
|
||||
println!("Part 2: {}", solve2(&data));
|
||||
}
|
||||
|
||||
|
||||
const ROCK_W: [isize; 5] = [4, 3, 3, 1, 2];
|
||||
const ROCK_H: [usize; 5] = [1, 3, 3, 4, 2];
|
||||
const ROCKS: [[u8; 4]; 5] = [
|
||||
[0b1111, 0b0000, 0b0000, 0b0000],
|
||||
[0b0100, 0b1110, 0b0100, 0b0000],
|
||||
[0b0010, 0b0010, 0b1110, 0b0000],
|
||||
[0b1000, 0b1000, 0b1000, 0b1000],
|
||||
[0b1100, 0b1100, 0b0000, 0b0000],
|
||||
];
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Cave {
|
||||
wind: Cycle<IntoIter<Wind>>,
|
||||
hole: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Display for Cave {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
for i in (0..self.hole.len()).rev() {
|
||||
writeln!(f, "{:#010b}", self.hole[i])?;
|
||||
}
|
||||
writeln!(f, "")
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy)]
|
||||
enum Wind {
|
||||
L, R
|
||||
}
|
||||
|
||||
impl Cave {
|
||||
fn new(wind: &[Wind]) -> Self {
|
||||
Cave {
|
||||
wind: Vec::from(wind).into_iter().cycle(),
|
||||
hole: vec![u8::MAX],
|
||||
}
|
||||
}
|
||||
|
||||
fn insert(&mut self, rock: usize) {
|
||||
self.hole.resize(self.count_occupied() + 3 + ROCK_H[rock], 0);
|
||||
|
||||
let mut offset: isize = 1;
|
||||
let mut height: usize = self.hole.len() - 1;
|
||||
|
||||
loop {
|
||||
match self.wind.next().unwrap() {
|
||||
Wind::L => if offset < 3 && !self.check_collision(rock, offset + 1, height) {
|
||||
offset += 1
|
||||
},
|
||||
Wind::R => if offset > ROCK_W[rock] - 4 && !self.check_collision(rock, offset - 1, height) {
|
||||
offset -= 1
|
||||
},
|
||||
}
|
||||
|
||||
if self.check_collision(rock, offset, height - 1) {
|
||||
self.add_rock(rock, offset, height);
|
||||
break;
|
||||
}
|
||||
|
||||
height -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn add_rock(&mut self, rock: usize, offset: isize, height: usize) {
|
||||
for i in 0..4 {
|
||||
let rock_row = match offset < 0 {
|
||||
false => ROCKS[rock][i] << offset,
|
||||
true => ROCKS[rock][i] >> -offset,
|
||||
};
|
||||
if rock_row == 0 { break };
|
||||
self.hole[height - i] |= rock_row;
|
||||
}
|
||||
}
|
||||
|
||||
fn check_collision(&self, rock: usize, offset: isize, height: usize) -> bool {
|
||||
for i in 0..4 {
|
||||
let rock_row = match offset < 0 {
|
||||
false => ROCKS[rock][i] << offset,
|
||||
true => ROCKS[rock][i] >> -offset,
|
||||
};
|
||||
if rock_row == 0 { break };
|
||||
if rock_row & self.hole[height - i] > 0 { return true; };
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn count_free(&self) -> usize {
|
||||
let mut free: usize = 0;
|
||||
for i in (0..self.hole.len()).rev() {
|
||||
if self.hole[i] == 0 { free += 1; }
|
||||
}
|
||||
free
|
||||
}
|
||||
|
||||
fn count_occupied(&self) -> usize {
|
||||
self.hole.len() - self.count_free()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn solve1(data: &[Wind]) -> usize {
|
||||
let mut rocks = (0..ROCKS.len()).into_iter().cycle();
|
||||
let mut cave = Cave::new(data);
|
||||
|
||||
for _ in 0..2022 {
|
||||
cave.insert(rocks.next().unwrap());
|
||||
};
|
||||
|
||||
cave.count_occupied() - 1 // first row is the bottom
|
||||
}
|
||||
|
||||
fn solve2(data: &[Wind]) -> i32 {
|
||||
2
|
||||
}
|
||||
|
||||
fn parse_data<T: AsRef<str>>(data: &[T]) -> Vec<Wind> {
|
||||
data.iter()
|
||||
.next()
|
||||
.map(|line| line.as_ref().chars()
|
||||
.map(|c| match c as u8 {
|
||||
b'>' => Wind::R,
|
||||
b'<' => Wind::L,
|
||||
_ => unreachable!()
|
||||
})
|
||||
.collect()
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
static DATA: &[&str] = &[">>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>"];
|
||||
|
||||
#[test]
|
||||
fn part1() {
|
||||
assert_eq!(3068, solve1(&parse_data(DATA)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2() {
|
||||
assert_eq!(2, solve2(&parse_data(DATA)));
|
||||
}
|
||||
}
|
|
@ -14,3 +14,4 @@ pub mod day13;
|
|||
pub mod day14;
|
||||
pub mod day15;
|
||||
pub mod day16;
|
||||
pub mod day17;
|
||||
|
|
Loading…
Reference in a new issue