day18: formatting and cleanup
This commit is contained in:
		@@ -1,9 +1,7 @@
 | 
			
		||||
use itertools::Itertools;
 | 
			
		||||
use std::collections::{HashMap, LinkedList};
 | 
			
		||||
use std::fmt::{Display, Write};
 | 
			
		||||
use std::collections::LinkedList;
 | 
			
		||||
use std::fs::File;
 | 
			
		||||
use std::io::{BufRead, BufReader, Lines};
 | 
			
		||||
use std::ops::Range;
 | 
			
		||||
use std::time::Instant;
 | 
			
		||||
 | 
			
		||||
// BOILERPLATE
 | 
			
		||||
@@ -47,12 +45,7 @@ enum Turn {
 | 
			
		||||
 | 
			
		||||
impl Direction {
 | 
			
		||||
    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 {
 | 
			
		||||
        match self {
 | 
			
		||||
@@ -127,13 +120,7 @@ impl From<&str> for DigInstruction {
 | 
			
		||||
        let (dir, count, color) = (
 | 
			
		||||
            parts.next().unwrap(),
 | 
			
		||||
            parts.next().unwrap(),
 | 
			
		||||
            parts
 | 
			
		||||
                .next()
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .chars()
 | 
			
		||||
                .skip(2)
 | 
			
		||||
                .take(6)
 | 
			
		||||
                .collect::<String>(),
 | 
			
		||||
            parts.next().unwrap().chars().skip(2).take(6).collect::<String>(),
 | 
			
		||||
        );
 | 
			
		||||
        Self {
 | 
			
		||||
            dir: dir.into(),
 | 
			
		||||
@@ -152,7 +139,7 @@ impl DigInstruction {
 | 
			
		||||
            "1" => Direction::Down,
 | 
			
		||||
            "2" => Direction::Left,
 | 
			
		||||
            "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 {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            position: (0, 0),
 | 
			
		||||
        }
 | 
			
		||||
        Self { position: (0, 0) }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -188,9 +173,6 @@ type Position = (isize, isize);
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
struct DigHole {
 | 
			
		||||
    tiles_loop: LinkedList<DigTile>,
 | 
			
		||||
    tiles_map: HashMap<Position, DigTile>,
 | 
			
		||||
    x_range: Range<isize>,
 | 
			
		||||
    y_range: Range<isize>,
 | 
			
		||||
    area: u64,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -203,9 +185,6 @@ impl DigHole {
 | 
			
		||||
    fn new() -> Self {
 | 
			
		||||
        DigHole {
 | 
			
		||||
            tiles_loop: LinkedList::new(),
 | 
			
		||||
            tiles_map: HashMap::new(),
 | 
			
		||||
            x_range: 0..0,
 | 
			
		||||
            y_range: 0..0,
 | 
			
		||||
            area: 0,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -215,9 +194,7 @@ impl DigHole {
 | 
			
		||||
    fn run_plan(&mut self, plan: &DigPlan) {
 | 
			
		||||
        let mut cur_pos = (0, 0);
 | 
			
		||||
 | 
			
		||||
        self.tiles_loop.push_back(DigTile {
 | 
			
		||||
            position: cur_pos,
 | 
			
		||||
        });
 | 
			
		||||
        self.tiles_loop.push_back(DigTile { position: cur_pos });
 | 
			
		||||
        let mut move_offset;
 | 
			
		||||
        for (idx, i) in plan.instructions.iter().enumerate() {
 | 
			
		||||
            let prev_instruction = if idx > 0 {
 | 
			
		||||
@@ -225,17 +202,14 @@ impl DigHole {
 | 
			
		||||
            } else {
 | 
			
		||||
                &plan.instructions[plan.instructions.len() - 1]
 | 
			
		||||
            };
 | 
			
		||||
            let Some(next_instruction) = plan
 | 
			
		||||
                .instructions
 | 
			
		||||
                .get(idx + 1)
 | 
			
		||||
                .or(Some(&plan.instructions[0]))
 | 
			
		||||
            else {
 | 
			
		||||
            let Some(next_instruction) = plan.instructions.get(idx + 1).or(Some(&plan.instructions[0])) else {
 | 
			
		||||
                panic!()
 | 
			
		||||
            };
 | 
			
		||||
            let cur_turn = prev_instruction.dir.turn_kind(i.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) {
 | 
			
		||||
                (Turn::RightNinety, Turn::RightNinety) => 1,
 | 
			
		||||
                (Turn::RightNinety, Turn::LeftNinety) => 0,
 | 
			
		||||
@@ -244,14 +218,8 @@ impl DigHole {
 | 
			
		||||
                t => panic!("turn {:?} not allowed here", t),
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            cur_pos = self.pos_offset_n(
 | 
			
		||||
                cur_pos,
 | 
			
		||||
                i.dir.offset(),
 | 
			
		||||
                (i.count as isize + move_offset) as usize,
 | 
			
		||||
            );
 | 
			
		||||
            self.tiles_loop.push_back(DigTile {
 | 
			
		||||
                position: cur_pos,
 | 
			
		||||
            });
 | 
			
		||||
            cur_pos = self.pos_offset_n(cur_pos, i.dir.offset(), (i.count as isize + move_offset) as usize);
 | 
			
		||||
            self.tiles_loop.push_back(DigTile { position: cur_pos });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 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 {
 | 
			
		||||
    fn from(lines: Lines<T>) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            instructions: lines
 | 
			
		||||
                .map(|line| DigInstruction::from(line.unwrap().as_str()))
 | 
			
		||||
                .collect(),
 | 
			
		||||
            instructions: lines.map(|line| DigInstruction::from(line.unwrap().as_str())).collect(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PROBLEM 1 solution
 | 
			
		||||
 | 
			
		||||
fn problem1<T: BufRead>(input: Lines<T>) -> u64 {
 | 
			
		||||
    let plan = DigPlan::from(input);
 | 
			
		||||
    let mut dig = DigHole::new();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user