Day 16
p1 is pipesv2 but fun and cool (especially forced optimization) p2 is really bad at making you optimize lol
This commit is contained in:
parent
6240299f1b
commit
78c41799e7
2 changed files with 197 additions and 0 deletions
194
lib/src/day16/mod.rs
Normal file
194
lib/src/day16/mod.rs
Normal file
|
@ -0,0 +1,194 @@
|
|||
use itertools::Itertools;
|
||||
|
||||
use crate::utils::Day;
|
||||
|
||||
pub struct Beam {
|
||||
pub position: Position,
|
||||
pub direction: Direction
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
|
||||
pub struct Position {
|
||||
pub x: usize,
|
||||
pub y: usize
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug)]
|
||||
pub enum Direction {
|
||||
Up,
|
||||
Down,
|
||||
Right,
|
||||
Left
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Day16 {
|
||||
pub input: String,
|
||||
}
|
||||
|
||||
impl Day for Day16 {
|
||||
fn part1(&mut self) -> String {
|
||||
let grid = self.input.lines().map(|l| l.chars().collect_vec()).collect_vec();
|
||||
let mut heated = Vec::<(Position, Direction)>::new();
|
||||
let mut beams = Vec::from(const { [Beam { position: Position { x: 0, y: 0 }, direction: Direction::Right }] });
|
||||
|
||||
while beams.len() > 0 {
|
||||
|
||||
// Step all beams
|
||||
for mut beam in std::mem::take(&mut beams).into_iter() {
|
||||
let already_heated = heated.iter().filter(|(pos, dir)| pos == &beam.position && dir == &beam.direction).collect_vec();
|
||||
|
||||
if already_heated.len() == 0 {
|
||||
heated.push((beam.position.clone(), beam.direction.clone()));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
match grid[beam.position.y][beam.position.x] {
|
||||
'/' => match beam.direction {
|
||||
Direction::Up => beam.direction = Direction::Right,
|
||||
Direction::Down => beam.direction = Direction::Left,
|
||||
Direction::Right => beam.direction = Direction::Up,
|
||||
Direction::Left => beam.direction = Direction::Down,
|
||||
},
|
||||
'\\' => match beam.direction {
|
||||
Direction::Up => beam.direction = Direction::Left,
|
||||
Direction::Down => beam.direction = Direction::Right,
|
||||
Direction::Right => beam.direction = Direction::Down,
|
||||
Direction::Left => beam.direction = Direction::Up,
|
||||
},
|
||||
'|' => match beam.direction {
|
||||
Direction::Left | Direction::Right => {
|
||||
if beam.position.y != 0 { beams.push(Beam { position: Position { x: beam.position.x, y: beam.position.y - 1 }, direction: Direction::Up }) }
|
||||
if beam.position.y != grid.len() - 1 { beams.push(Beam { position: Position { x: beam.position.x, y: beam.position.y + 1 }, direction: Direction::Down }) }
|
||||
continue
|
||||
},
|
||||
_ => ()
|
||||
},
|
||||
'-' => match beam.direction {
|
||||
Direction::Up | Direction::Down => {
|
||||
if beam.position.x != 0 { beams.push(Beam { position: Position { x: beam.position.x - 1, y: beam.position.y }, direction: Direction::Left }) }
|
||||
if beam.position.x != grid[0].len() - 1 { beams.push(Beam { position: Position { x: beam.position.x + 1, y: beam.position.y }, direction: Direction::Right }) }
|
||||
continue
|
||||
},
|
||||
_ => ()
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
|
||||
match beam.direction {
|
||||
Direction::Up if beam.position.y != 0 => beam.position.y -= 1,
|
||||
Direction::Down if beam.position.y != grid.len() - 1 => beam.position.y += 1,
|
||||
Direction::Right if beam.position.x != grid[0].len() - 1 => beam.position.x += 1,
|
||||
Direction::Left if beam.position.x != 0 => beam.position.x -= 1,
|
||||
_ => continue // If it hit the wall, skull issue, don't add it back to the vec
|
||||
}
|
||||
|
||||
beams.push(beam);
|
||||
}
|
||||
}
|
||||
|
||||
// println!(
|
||||
// "{}",
|
||||
// grid
|
||||
// .iter()
|
||||
// .enumerate()
|
||||
// .map(|(y, l)| l.iter().enumerate().map(|(x, b)| if heated.iter().any(|(pos, _)| pos.x == x && pos.y == y) { '#' } else { '.' }).collect::<String>())
|
||||
// .collect::<Vec<_>>()
|
||||
// .join("\n")
|
||||
// );
|
||||
|
||||
heated.into_iter().map(|(pos, _)| pos).sorted().dedup().count().to_string()
|
||||
}
|
||||
|
||||
// TODO Don't do this the stupid way, use DP/caching lol
|
||||
fn part2(&mut self) -> String {
|
||||
let grid = self.input.lines().map(|l| l.chars().collect_vec()).collect_vec();
|
||||
let mut max = 0usize;
|
||||
|
||||
for y in 0..grid.len() {
|
||||
for x in 0..grid[0].len() {
|
||||
let dir =
|
||||
if x == 0 { Direction::Left }
|
||||
else if x == grid[0].len() - 1 { Direction::Right }
|
||||
else if y == 0 { Direction::Down }
|
||||
else if y == grid.len() - 1 { Direction::Up }
|
||||
else { continue };
|
||||
|
||||
let mut heated = Vec::<(Position, Direction)>::new();
|
||||
let mut beams = Vec::from([Beam { position: Position { x, y }, direction: dir }]);
|
||||
|
||||
while beams.len() > 0 {
|
||||
|
||||
// Step all beams
|
||||
for mut beam in std::mem::take(&mut beams).into_iter() {
|
||||
let already_heated = heated.iter().filter(|(pos, dir)| pos == &beam.position && dir == &beam.direction).collect_vec();
|
||||
|
||||
if already_heated.len() == 0 {
|
||||
heated.push((beam.position.clone(), beam.direction.clone()));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
match grid[beam.position.y][beam.position.x] {
|
||||
'/' => match beam.direction {
|
||||
Direction::Up => beam.direction = Direction::Right,
|
||||
Direction::Down => beam.direction = Direction::Left,
|
||||
Direction::Right => beam.direction = Direction::Up,
|
||||
Direction::Left => beam.direction = Direction::Down,
|
||||
},
|
||||
'\\' => match beam.direction {
|
||||
Direction::Up => beam.direction = Direction::Left,
|
||||
Direction::Down => beam.direction = Direction::Right,
|
||||
Direction::Right => beam.direction = Direction::Down,
|
||||
Direction::Left => beam.direction = Direction::Up,
|
||||
},
|
||||
'|' => match beam.direction {
|
||||
Direction::Left | Direction::Right => {
|
||||
if beam.position.y != 0 { beams.push(Beam { position: Position { x: beam.position.x, y: beam.position.y - 1 }, direction: Direction::Up }) }
|
||||
if beam.position.y != grid.len() - 1 { beams.push(Beam { position: Position { x: beam.position.x, y: beam.position.y + 1 }, direction: Direction::Down }) }
|
||||
continue
|
||||
},
|
||||
_ => ()
|
||||
},
|
||||
'-' => match beam.direction {
|
||||
Direction::Up | Direction::Down => {
|
||||
if beam.position.x != 0 { beams.push(Beam { position: Position { x: beam.position.x - 1, y: beam.position.y }, direction: Direction::Left }) }
|
||||
if beam.position.x != grid[0].len() - 1 { beams.push(Beam { position: Position { x: beam.position.x + 1, y: beam.position.y }, direction: Direction::Right }) }
|
||||
continue
|
||||
},
|
||||
_ => ()
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
|
||||
match beam.direction {
|
||||
Direction::Up if beam.position.y != 0 => beam.position.y -= 1,
|
||||
Direction::Down if beam.position.y != grid.len() - 1 => beam.position.y += 1,
|
||||
Direction::Right if beam.position.x != grid[0].len() - 1 => beam.position.x += 1,
|
||||
Direction::Left if beam.position.x != 0 => beam.position.x -= 1,
|
||||
_ => continue // If it hit the wall, skull issue, don't add it back to the vec
|
||||
}
|
||||
|
||||
beams.push(beam);
|
||||
}
|
||||
}
|
||||
|
||||
// println!(
|
||||
// "{}",
|
||||
// grid
|
||||
// .iter()
|
||||
// .enumerate()
|
||||
// .map(|(y, l)| l.iter().enumerate().map(|(x, b)| if heated.iter().any(|(pos, _)| pos.x == x && pos.y == y) { '#' } else { '.' }).collect::<String>())
|
||||
// .collect::<Vec<_>>()
|
||||
// .join("\n")
|
||||
// );
|
||||
|
||||
let result = heated.into_iter().map(|(pos, _)| pos).sorted().dedup().count();
|
||||
if max < result { max = result; }
|
||||
}
|
||||
}
|
||||
|
||||
max.to_string()
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ use day12::Day12;
|
|||
use day13::Day13;
|
||||
use day14::Day14;
|
||||
use day15::Day15;
|
||||
use day16::Day16;
|
||||
use day2::Day2;
|
||||
use day3::Day3;
|
||||
use day4::Day4;
|
||||
|
@ -30,6 +31,7 @@ pub mod day12;
|
|||
pub mod day13;
|
||||
pub mod day14;
|
||||
pub mod day15;
|
||||
pub mod day16;
|
||||
pub mod day2;
|
||||
pub mod day3;
|
||||
pub mod day4;
|
||||
|
@ -76,6 +78,7 @@ pub fn get_day(day: u8, input: String) -> Box<dyn Day> {
|
|||
13 => Box::new(Day13 { input }),
|
||||
14 => Box::new(Day14 { input }),
|
||||
15 => Box::new(Day15 { input }),
|
||||
16 => Box::new(Day16 { input }),
|
||||
_ => panic!("Invalid day #"),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue