Skip to content

Commit a76be44

Browse files
committed
Rust Day6 part 1
1 parent 0e41df3 commit a76be44

File tree

5 files changed

+175
-0
lines changed

5 files changed

+175
-0
lines changed

2024/Rust/aoc2024/.vscode/launch.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,5 +162,23 @@
162162
"program": "${workspaceFolder:Rust}/target/debug/aoc2024",
163163
"preLaunchTask": "rust: cargo build"
164164
},
165+
{
166+
"type": "lldb",
167+
"request": "launch",
168+
"name": "Day 6 part 1",
169+
"args": [
170+
"--input-file",
171+
"${workspaceFolder:problems}/day6-1.txt",
172+
"--part-number",
173+
"1",
174+
"day6"
175+
],
176+
"env": {
177+
"RUST_BACKTRACE": "1"
178+
},
179+
"cwd": "${workspaceFolder:Rust}",
180+
"program": "${workspaceFolder:Rust}/target/debug/aoc2024",
181+
"preLaunchTask": "rust: cargo build"
182+
},
165183
]
166184
}

2024/Rust/aoc2024/src/args.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ pub enum Commands {
2020
Day3,
2121
Day4,
2222
Day5,
23+
Day6,
2324
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
use std::io;
2+
use std::fs::read_to_string;
3+
use std::collections::HashSet;
4+
use std::iter::Extend;
5+
6+
pub fn handle(input_file: std::path::PathBuf, part_number: u8) -> Result<(), io::Error> {
7+
let contents = read_to_string(input_file)?;
8+
match part_number {
9+
1 => part_1(&contents),
10+
_ => Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid part number")),
11+
}
12+
}
13+
14+
#[derive(Clone, Hash, Copy, Debug, Eq, PartialEq)]
15+
struct Position {
16+
x: i32,
17+
y: i32,
18+
}
19+
20+
impl Position {
21+
fn next(&self, direction: &GuardDirection) -> Position {
22+
match direction {
23+
GuardDirection::Up => Position { x: self.x, y: self.y - 1 },
24+
GuardDirection::Down => Position { x: self.x, y: self.y + 1 },
25+
GuardDirection::Left => Position { x: self.x - 1, y: self.y },
26+
GuardDirection::Right => Position { x: self.x + 1, y: self.y },
27+
}
28+
}
29+
}
30+
31+
enum GuardDirection {
32+
Up,
33+
Down,
34+
Left,
35+
Right,
36+
}
37+
38+
impl GuardDirection {
39+
fn next(&self) -> GuardDirection {
40+
match self {
41+
GuardDirection::Up => GuardDirection::Right,
42+
GuardDirection::Right => GuardDirection::Down,
43+
GuardDirection::Down => GuardDirection::Left,
44+
GuardDirection::Left => GuardDirection::Up,
45+
}
46+
}
47+
}
48+
49+
enum MovementEnd {
50+
OnBoard(Vec<Position>),
51+
OffBoard(Vec<Position>),
52+
}
53+
54+
struct Map {
55+
locations: Vec<Vec<char>>,
56+
guard_position: Option<Position>,
57+
direction: GuardDirection,
58+
}
59+
60+
impl Map {
61+
fn new(contents: &str) -> Map {
62+
let locations = contents.split("\n").map(|line| line.chars().collect()).collect();
63+
Map::new_from_locations(locations)
64+
}
65+
66+
fn new_from_locations(locations: Vec<Vec<char>>) -> Map {
67+
// println!("{:?}", locations);
68+
let filtered_locations: Vec<Vec<char>> = locations
69+
.into_iter()
70+
.filter(|line| !line.is_empty())
71+
.collect();
72+
for (y, line) in filtered_locations.iter().enumerate() {
73+
match line.iter().position(|&c| c == '^') {
74+
Some(x) => {
75+
let guard_start_position = Position { x: x as i32, y: y as i32 };
76+
return Map {
77+
locations: filtered_locations,
78+
guard_position: Some(guard_start_position),
79+
direction: GuardDirection::Up,
80+
};
81+
}
82+
None => {}
83+
}
84+
}
85+
panic!("No guard start position found");
86+
}
87+
}
88+
89+
impl Map {
90+
fn character_at(&self, position: &Position) -> char {
91+
// println!("{:?}", position);
92+
self.locations[position.y as usize][position.x as usize]
93+
}
94+
95+
fn is_on_board(&self, position: &Position) -> bool {
96+
// println!("pos {:?} bounds {:?} {:?}", position, self.locations[0].len(), self.locations.len());
97+
position.x >= 0 && position.x < self.locations[0].len() as i32 && position.y >= 0 && position.y < self.locations.len() as i32
98+
}
99+
100+
fn guard_positions(&self, direction: &GuardDirection) -> MovementEnd {
101+
let mut positions: Vec<Position> = Vec::new();
102+
103+
match &self.guard_position {
104+
Some(guard_position) => {
105+
let mut next_position = guard_position.clone();
106+
while self.is_on_board(&next_position) && self.character_at(&next_position) != '#' {
107+
positions.push(next_position.clone());
108+
next_position = next_position.next(&direction);
109+
}
110+
if self.is_on_board(&next_position) {
111+
MovementEnd::OnBoard(positions)
112+
} else {
113+
MovementEnd::OffBoard(positions)
114+
}
115+
}
116+
None => panic!("Guard position not found"),
117+
}
118+
}
119+
120+
fn move_guard(&mut self) -> MovementEnd {
121+
let movement = self.guard_positions(&self.direction);
122+
match &movement {
123+
MovementEnd::OnBoard(positions) => {
124+
self.guard_position = Some(positions.last().unwrap().clone());
125+
self.direction = self.direction.next();
126+
}
127+
MovementEnd::OffBoard(_) => {
128+
self.guard_position = None;
129+
}
130+
}
131+
movement
132+
}
133+
}
134+
135+
fn part_1(contents: &str) -> Result<(), io::Error> {
136+
let mut map = Map::new(contents);
137+
let mut visited_positions: HashSet<Position> = HashSet::new();
138+
loop {
139+
let movement = map.move_guard();
140+
match movement {
141+
MovementEnd::OnBoard(positions) => {
142+
visited_positions.extend(positions.clone());
143+
// println!("on board {:?}", positions);
144+
}
145+
MovementEnd::OffBoard(positions) => {
146+
visited_positions.extend(positions.clone());
147+
// println!("off board {:?}", positions);
148+
break;
149+
}
150+
}
151+
}
152+
println!("{:?}", visited_positions.len());
153+
Ok(())
154+
}

2024/Rust/aoc2024/src/commands/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ pub mod day2;
33
pub mod day3;
44
pub mod day4;
55
pub mod day5;
6+
pub mod day6;

2024/Rust/aoc2024/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ fn main() -> Result<(), io::Error> {
1414
args::Commands::Day3 => commands::day3::handle(args.input_file, args.part_number),
1515
args::Commands::Day4 => commands::day4::handle(args.input_file, args.part_number),
1616
args::Commands::Day5 => commands::day5::handle(args.input_file, args.part_number),
17+
args::Commands::Day6 => commands::day6::handle(args.input_file, args.part_number),
1718
}
1819
}

0 commit comments

Comments
 (0)