day18: formatting and cleanup
This commit is contained in:
parent
3bc073f9b8
commit
8d178ddfc6
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user