This commit is contained in:
sepia 2024-12-14 14:34:29 -06:00
parent a91b120155
commit 290789d5f5
5 changed files with 571 additions and 27 deletions

169
src/day14.rs Normal file
View file

@ -0,0 +1,169 @@
use itertools::Itertools;
use pest::{
iterators::{Pair, Pairs},
Parser,
};
use raylib::prelude::*;
use rayon::prelude::*;
const WIDTH: i64 = 101;
const HEIGHT: i64 = 103;
#[derive(Copy, Clone, PartialEq)]
enum PlayState {
Paused,
Forward(i64),
Backward(i64),
}
pub fn day14() {
let mut robots = parse_robots(&crate::input(14));
let (mut rl, thread) = raylib::init()
.size(1920, 1080)
.title("Advent of Code: Day 14")
.build();
let mut total_elapsed: u32 = 6440;
let mut play_state = PlayState::Forward(1);
let mut safety_score: usize = 0;
rl.set_target_fps(1);
while !rl.window_should_close() {
let pressed_key = rl.get_key_pressed();
match pressed_key {
Some(KeyboardKey::KEY_ENTER) => {
let mut quadrants: Vec<Vec<Robot>> = vec![vec![]; 4];
for robot in robots.iter() {
if let Some(quadrant) = robot.quadrant() {
quadrants[quadrant].push(*robot);
}
}
let safety_score = quadrants
.iter()
.map(Vec::len)
.reduce(|acc, e| acc * e)
.unwrap();
println!("Safety Score: {}", safety_score);
}
Some(KeyboardKey::KEY_D) => {
play_state = match play_state {
PlayState::Forward(speed) => PlayState::Forward((speed * 2).min(16)),
PlayState::Backward(speed) if speed == 1 => PlayState::Forward(1),
PlayState::Backward(speed) => PlayState::Backward(speed / 2),
_ => PlayState::Forward(1),
};
}
Some(KeyboardKey::KEY_A) => {
play_state = match play_state {
PlayState::Backward(speed) => PlayState::Backward((speed * 2).min(16)),
PlayState::Forward(speed) if speed == 1 => PlayState::Backward(1),
PlayState::Forward(speed) => PlayState::Forward(speed / 2),
_ => PlayState::Backward(1),
};
}
Some(KeyboardKey::KEY_SPACE) => {
play_state = match play_state {
PlayState::Paused => PlayState::Forward(1),
_ => PlayState::Paused,
};
let mut quadrants: Vec<usize> = vec![0; 4];
for robot in robots.iter() {
if let Some(q) = robot.quadrant() {
quadrants[q] += 1;
}
}
safety_score = quadrants.into_iter().reduce(|acc, e| acc * e).unwrap();
}
_ => {}
}
match play_state {
PlayState::Paused => {}
PlayState::Forward(speed) => {
rl.set_target_fps(speed as u32);
robots.par_iter_mut().for_each(|r| r.tick(1));
total_elapsed += 1;
}
PlayState::Backward(speed) => {
rl.set_target_fps(speed as u32);
robots.par_iter_mut().for_each(|r| r.tick(-1));
total_elapsed -= 1;
}
}
let mut d = rl.begin_drawing(&thread);
d.clear_background(Color::BLACK);
for robot in robots.iter() {
let x = (robot.p.0 as f32 / WIDTH as f32) * 1920.;
let y = (robot.p.1 as f32 / HEIGHT as f32) * 1080.;
d.draw_circle(x as i32, y as i32, 10., Color::GREEN);
}
d.draw_text(
format!("Elapsed: {}", total_elapsed).as_str(),
0,
0,
20,
Color::MAGENTA,
);
if play_state == PlayState::Paused {
d.draw_text(
format!("Safety Score: {}", safety_score).as_str(),
0,
40,
20,
Color::MAGENTA,
);
}
}
}
#[derive(Copy, Clone, Debug)]
struct Robot {
p: (i64, i64),
v: (i64, i64),
}
impl Robot {
fn tick(&mut self, delta: i64) {
self.p.0 = (self.p.0 + self.v.0 * delta).rem_euclid(WIDTH);
self.p.1 = (self.p.1 + self.v.1 * delta).rem_euclid(HEIGHT);
}
fn quadrant(&self) -> Option<usize> {
if self.p.0 == WIDTH / 2 || self.p.1 == HEIGHT / 2 {
return None;
}
Some(((self.p.1 > HEIGHT / 2) as usize) * 2 + (self.p.0 > WIDTH / 2) as usize)
}
}
#[derive(pest_derive::Parser)]
#[grammar = "grammars/day14.pest"]
struct RobotsParser {}
fn parse_robots(input: &str) -> Vec<Robot> {
RobotsParser::parse(Rule::robots, input)
.unwrap()
.nth(0)
.unwrap()
.into_inner()
.map(Pair::<'_, Rule>::into_inner)
.map(Robot::parse)
.collect()
}
impl Robot {
fn parse(input: Pairs<'_, Rule>) -> Self {
let (p, v) = input
.map(Pair::<'_, Rule>::into_inner)
.map(|a| {
a.map(|ns| ns.as_str().parse::<i64>().unwrap())
.collect_tuple()
.unwrap()
})
.collect_tuple()
.unwrap();
Self { p, v }
}
}

9
src/grammars/day14.pest Normal file
View file

@ -0,0 +1,9 @@
_WHITESPACE = _{ " " }
NEWLINE = _{ "\n" }
int = { "-"? ~ ASCII_DIGIT+ }
coord_statement = { ("p" | "v") ~ "=" ~ int ~ "," ~ int }
robot = { coord_statement ~ _WHITESPACE* ~ coord_statement ~ NEWLINE? }
eoi = _{ !ANY }
robots = { SOI ~ robot+ ~ eoi }

View file

@ -24,10 +24,12 @@ mod day10;
mod day11;
#[allow(dead_code)]
mod day12;
#[allow(dead_code)]
mod day13;
mod day14;
fn main() {
day13::day13();
day14::day14();
}
pub fn input(day: u8) -> String {