Finish day 6 part 1
This commit is contained in:
@@ -3,13 +3,136 @@
|
||||
// Run command: cargo run ./input.txt
|
||||
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
env,
|
||||
error::Error,
|
||||
fmt::Display,
|
||||
fs::File,
|
||||
io::{BufReader, prelude::*},
|
||||
};
|
||||
|
||||
fn load_map(input_file: &str) -> Result<(Vec<Vec<bool>>, (usize, usize)), Box<dyn Error>> {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum Facing {
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||
struct Position {
|
||||
x: isize,
|
||||
y: isize,
|
||||
}
|
||||
|
||||
impl Position {
|
||||
fn new(x: isize, y: isize) -> Position {
|
||||
Position { x, y }
|
||||
}
|
||||
|
||||
fn x(&self) -> isize {
|
||||
self.x
|
||||
}
|
||||
|
||||
fn y(&self) -> isize {
|
||||
self.y
|
||||
}
|
||||
|
||||
fn advance(&mut self, facing: Facing) {
|
||||
match facing {
|
||||
Facing::Up => self.y -= 1,
|
||||
Facing::Down => self.y += 1,
|
||||
Facing::Left => self.x -= 1,
|
||||
Facing::Right => self.x += 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn next_position(&self, facing: Facing) -> Position {
|
||||
let mut next_position = *self;
|
||||
next_position.advance(facing);
|
||||
next_position
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct Guard {
|
||||
facing: Facing,
|
||||
position: Position,
|
||||
}
|
||||
|
||||
impl Guard {
|
||||
pub fn new(position_x: isize, position_y: isize, facing: Facing) -> Guard {
|
||||
Guard {
|
||||
facing,
|
||||
position: Position::new(position_x, position_y),
|
||||
}
|
||||
}
|
||||
|
||||
fn turn_clockwise(&mut self) {
|
||||
match self.facing {
|
||||
Facing::Up => self.facing = Facing::Right,
|
||||
Facing::Down => self.facing = Facing::Left,
|
||||
Facing::Left => self.facing = Facing::Up,
|
||||
Facing::Right => self.facing = Facing::Down,
|
||||
}
|
||||
}
|
||||
|
||||
fn advance(&mut self) {
|
||||
self.position.advance(self.facing);
|
||||
}
|
||||
|
||||
fn position(&self) -> &Position {
|
||||
&self.position
|
||||
}
|
||||
|
||||
fn next_position(&self) -> Position {
|
||||
self.position.next_position(self.facing)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Map {
|
||||
data: Vec<Vec<bool>>,
|
||||
width: usize,
|
||||
height: usize,
|
||||
}
|
||||
|
||||
impl Map {
|
||||
pub fn new(data: Vec<Vec<bool>>) -> Map {
|
||||
let height = data.len();
|
||||
let width = data[0].len();
|
||||
Map {
|
||||
data,
|
||||
width,
|
||||
height,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_location(&self, x: isize, y: isize) -> Option<bool> {
|
||||
if x < 0 || x >= self.width as isize || y < 0 || y >= self.height as isize {
|
||||
return None;
|
||||
}
|
||||
Some(self.data[y as usize][x as usize])
|
||||
}
|
||||
|
||||
pub fn get_position(&self, position: Position) -> Option<bool> {
|
||||
self.get_location(position.x(), position.y())
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Map {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "Map:")?;
|
||||
for row in &self.data {
|
||||
write!(f, " ")?;
|
||||
let row = String::from_iter(row.iter().map(|b| if *b { '#' } else { '.' }));
|
||||
writeln!(f, "{}", row)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn load_map(input_file: &str) -> Result<(Map, Guard), Box<dyn Error>> {
|
||||
let buffer = BufReader::new(File::open(input_file)?);
|
||||
let mut lines = buffer.lines().peekable();
|
||||
|
||||
@@ -22,7 +145,7 @@ fn load_map(input_file: &str) -> Result<(Vec<Vec<bool>>, (usize, usize)), Box<dy
|
||||
};
|
||||
|
||||
let mut data: Vec<Vec<bool>> = Vec::new();
|
||||
let mut guard_position = (0, 0);
|
||||
let mut guard_position = Guard::new(0, 0, Facing::Up);
|
||||
|
||||
for (y, line) in lines.enumerate() {
|
||||
let line = line?;
|
||||
@@ -35,16 +158,15 @@ fn load_map(input_file: &str) -> Result<(Vec<Vec<bool>>, (usize, usize)), Box<dy
|
||||
.enumerate()
|
||||
.map(|(x, c)| {
|
||||
if c == '^' {
|
||||
guard_position = (x, y);
|
||||
guard_position = Guard::new(x as isize, y as isize, Facing::Up);
|
||||
};
|
||||
c == '#'
|
||||
})
|
||||
.collect();
|
||||
data.push(parsed_data);
|
||||
}
|
||||
let height = data.len();
|
||||
|
||||
Ok((data, guard_position))
|
||||
Ok((Map::new(data), guard_position))
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
@@ -52,13 +174,33 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() != 2 {
|
||||
panic!(
|
||||
"{} must be run with a single argument of files name!",
|
||||
"{} must be run with a single argument of file name!",
|
||||
&args[0]
|
||||
)
|
||||
}
|
||||
let input_file = &args[1];
|
||||
let (data, guard_position) = load_map(input_file)?;
|
||||
println!("{:?}", data);
|
||||
let (map, mut guard_position) = load_map(input_file)?;
|
||||
|
||||
println!("{}", map);
|
||||
println!("{:?}", guard_position);
|
||||
let mut visited_set: HashSet<Position> = HashSet::new();
|
||||
visited_set.insert(*guard_position.position());
|
||||
|
||||
loop {
|
||||
let next_position = guard_position.next_position();
|
||||
match map.get_position(next_position) {
|
||||
Some(true) => {
|
||||
guard_position.turn_clockwise();
|
||||
}
|
||||
Some(false) => {
|
||||
guard_position.advance();
|
||||
visited_set.insert(next_position);
|
||||
}
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
println!("Number of locations visited: {}", visited_set.len());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user