--- /dev/null
+use std::error::Error;
+use std::path::Path;
+use std::collections::HashMap;
+
+struct Puzzle {
+ map: HashMap<(isize, isize), char>,
+ start: (isize, isize),
+}
+
+impl Puzzle {
+ pub fn new(input: &str) -> Self {
+ let mut map: HashMap<(isize, isize), char> = HashMap::new();
+ let mut start: (isize, isize) = (-1, -1);
+
+ input.lines()
+ .enumerate()
+ .for_each(|(row, s)| {
+ s.chars()
+ .enumerate()
+ .for_each(|(col, c)| {
+ map.insert((row as isize, col as isize), c);
+ if c == '^' {
+ start = (row as isize, col as isize);
+ }
+ });
+ });
+
+ Self {
+ map,
+ start,
+ }
+ }
+}
+
+pub fn run(input: &str) -> Result<(), Box<dyn Error>> {
+ let res = run_part1(&input)?;
+ println!("{res}");
+
+ let res = run_part2(&input)?;
+ println!("{res}");
+
+ Ok(())
+}
+
+fn get_day() -> String {
+ let filename = file!();
+ Path::new(filename).file_stem().unwrap().to_str().unwrap().to_string()
+}
+
+fn run_part1(input: &str) -> Result<u32, Box<dyn Error>> {
+ println!("Running {} - part 1", get_day());
+
+ let mut turn_right: HashMap<(isize, isize), (isize, isize)> = HashMap::new();
+ turn_right.insert((-1,0), (0,1));
+ turn_right.insert((0,1), (1,0));
+ turn_right.insert((1,0), (0,-1));
+ turn_right.insert((0,-1), (-1,0));
+
+ let puzzle = Puzzle::new(input);
+
+ let mut map = puzzle.map;
+ let mut pos: (isize, isize) = puzzle.start;
+ let mut dir: (isize, isize) = (-1, 0);
+ while map.contains_key(&pos) {
+ let mut c = map.get_mut(&pos).unwrap();
+ if "^.".contains(*c) {
+ *c = 'X';
+ }
+ if "#".contains(*c) {
+ pos = (pos.0 - dir.0, pos.1 - dir.1);
+ dir = *turn_right.get(&dir).unwrap();
+ }
+ pos = (pos.0 + dir.0, pos.1 + dir.1);
+ }
+
+ let res = map.into_iter()
+ .filter(|(_, c)| *c == 'X')
+ .count() as u32;
+
+ Ok(res)
+}
+
+fn run_part2(input: &str) -> Result<u32, Box<dyn Error>> {
+ println!("Running {} - part 2", get_day());
+
+ Ok(0)
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ static TEXT_INPUT: &str = "\
+....#.....
+.........#
+..........
+..#.......
+.......#..
+..........
+.#..^.....
+........#.
+#.........
+......#...";
+
+ #[test]
+ fn test_part1() {
+ assert_eq!(41, run_part1(TEXT_INPUT).unwrap());
+ }
+
+ #[test]
+ fn test_part2() {
+ assert_eq!(0, run_part2(TEXT_INPUT).unwrap());
+ }
+}