day18: formatting and cleanup

This commit is contained in:
Keenan Tims 2023-12-18 02:03:48 -08:00
parent 3bc073f9b8
commit 8d178ddfc6
Signed by: ktims
GPG Key ID: 11230674D69038D4

View File

@ -1,9 +1,7 @@
use itertools::Itertools; use itertools::Itertools;
use std::collections::{HashMap, LinkedList}; use std::collections::LinkedList;
use std::fmt::{Display, Write};
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader, Lines}; use std::io::{BufRead, BufReader, Lines};
use std::ops::Range;
use std::time::Instant; use std::time::Instant;
// BOILERPLATE // BOILERPLATE
@ -47,12 +45,7 @@ enum Turn {
impl Direction { impl Direction {
const fn all() -> &'static [Self; 4] { const fn all() -> &'static [Self; 4] {
&[ &[Direction::Left, Direction::Right, Direction::Up, Direction::Down]
Direction::Left,
Direction::Right,
Direction::Up,
Direction::Down,
]
} }
const fn opposite(&self) -> Self { const fn opposite(&self) -> Self {
match self { match self {
@ -127,13 +120,7 @@ impl From<&str> for DigInstruction {
let (dir, count, color) = ( let (dir, count, color) = (
parts.next().unwrap(), parts.next().unwrap(),
parts.next().unwrap(), parts.next().unwrap(),
parts parts.next().unwrap().chars().skip(2).take(6).collect::<String>(),
.next()
.unwrap()
.chars()
.skip(2)
.take(6)
.collect::<String>(),
); );
Self { Self {
dir: dir.into(), dir: dir.into(),
@ -152,7 +139,7 @@ impl DigInstruction {
"1" => Direction::Down, "1" => Direction::Down,
"2" => Direction::Left, "2" => Direction::Left,
"3" => Direction::Up, "3" => Direction::Up,
s => panic!("`{}` is not a valid direction code", s) s => panic!("`{}` is not a valid direction code", s),
}; };
} }
} }
@ -177,9 +164,7 @@ struct DigTile {
impl Default for DigTile { impl Default for DigTile {
fn default() -> Self { fn default() -> Self {
Self { Self { position: (0, 0) }
position: (0, 0),
}
} }
} }
@ -188,9 +173,6 @@ type Position = (isize, isize);
#[derive(Debug)] #[derive(Debug)]
struct DigHole { struct DigHole {
tiles_loop: LinkedList<DigTile>, tiles_loop: LinkedList<DigTile>,
tiles_map: HashMap<Position, DigTile>,
x_range: Range<isize>,
y_range: Range<isize>,
area: u64, area: u64,
} }
@ -203,9 +185,6 @@ impl DigHole {
fn new() -> Self { fn new() -> Self {
DigHole { DigHole {
tiles_loop: LinkedList::new(), tiles_loop: LinkedList::new(),
tiles_map: HashMap::new(),
x_range: 0..0,
y_range: 0..0,
area: 0, area: 0,
} }
} }
@ -215,9 +194,7 @@ impl DigHole {
fn run_plan(&mut self, plan: &DigPlan) { fn run_plan(&mut self, plan: &DigPlan) {
let mut cur_pos = (0, 0); let mut cur_pos = (0, 0);
self.tiles_loop.push_back(DigTile { self.tiles_loop.push_back(DigTile { position: cur_pos });
position: cur_pos,
});
let mut move_offset; let mut move_offset;
for (idx, i) in plan.instructions.iter().enumerate() { for (idx, i) in plan.instructions.iter().enumerate() {
let prev_instruction = if idx > 0 { let prev_instruction = if idx > 0 {
@ -225,17 +202,14 @@ impl DigHole {
} else { } else {
&plan.instructions[plan.instructions.len() - 1] &plan.instructions[plan.instructions.len() - 1]
}; };
let Some(next_instruction) = plan let Some(next_instruction) = plan.instructions.get(idx + 1).or(Some(&plan.instructions[0])) else {
.instructions
.get(idx + 1)
.or(Some(&plan.instructions[0]))
else {
panic!() panic!()
}; };
let cur_turn = prev_instruction.dir.turn_kind(i.dir); let cur_turn = prev_instruction.dir.turn_kind(i.dir);
let next_turn = i.dir.turn_kind(next_instruction.dir); let next_turn = i.dir.turn_kind(next_instruction.dir);
// point needs to live on the 'outside' corner of the character. to
// achieve this we need to offset the move by the following // Point needs to live on the 'outside' corner of the character. to achieve this we need to offset the move
// by the following. Found this empirically but there's probably some mathematical principle behind it...
move_offset = match (cur_turn, next_turn) { move_offset = match (cur_turn, next_turn) {
(Turn::RightNinety, Turn::RightNinety) => 1, (Turn::RightNinety, Turn::RightNinety) => 1,
(Turn::RightNinety, Turn::LeftNinety) => 0, (Turn::RightNinety, Turn::LeftNinety) => 0,
@ -244,14 +218,8 @@ impl DigHole {
t => panic!("turn {:?} not allowed here", t), t => panic!("turn {:?} not allowed here", t),
}; };
cur_pos = self.pos_offset_n( cur_pos = self.pos_offset_n(cur_pos, i.dir.offset(), (i.count as isize + move_offset) as usize);
cur_pos, self.tiles_loop.push_back(DigTile { position: cur_pos });
i.dir.offset(),
(i.count as isize + move_offset) as usize,
);
self.tiles_loop.push_back(DigTile {
position: cur_pos,
});
} }
// Shoelace formula // Shoelace formula
@ -266,36 +234,15 @@ impl DigHole {
} }
} }
impl Display for DigHole {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for y in self.y_range.clone() {
for x in self.x_range.clone() {
f.write_char(if (x, y) == (133, -267) {
'*'
} else if self.tiles_map.contains_key(&(x, y)) {
'#'
} else {
'.'
})?;
}
writeln!(f)?;
}
Ok(())
}
}
impl<T: BufRead> From<Lines<T>> for DigPlan { impl<T: BufRead> From<Lines<T>> for DigPlan {
fn from(lines: Lines<T>) -> Self { fn from(lines: Lines<T>) -> Self {
Self { Self {
instructions: lines instructions: lines.map(|line| DigInstruction::from(line.unwrap().as_str())).collect(),
.map(|line| DigInstruction::from(line.unwrap().as_str()))
.collect(),
} }
} }
} }
// PROBLEM 1 solution // PROBLEM 1 solution
fn problem1<T: BufRead>(input: Lines<T>) -> u64 { fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
let plan = DigPlan::from(input); let plan = DigPlan::from(input);
let mut dig = DigHole::new(); let mut dig = DigHole::new();