diff --git a/rust/input/day_03.txt b/rust/input/day_03.txt new file mode 100644 index 0000000..03504fc --- /dev/null +++ b/rust/input/day_03.txt @@ -0,0 +1 @@ +^><^>>>^<^v<<^<><^<^v>^vv<>v>>^^^v<<<^>^<^v<^>^v><<<^>><>v>v^<<^>^<<^^^>v>>v^^>^>vv>>^>>v^>^v>^<^^v>^>^^v^^>v^^v><^><^<<>v^<^<^vv^>>>v^v^>^<>^v<^^vv^>^<>^^<vv<>^>v<^>^v>v^>^v<>^><>>v^v<><>v^v>>>>v^^>^><^^<^>^v^v<>v<<<^<v^^^<^^^>v<^v>>>>>v<^^^^>v<^<>>>>>>v^vvvv^^^v<^v^>v><^>^v<<>>vv^>v>v^^>vv^<^vvv<>><>><><^^^^<^^^<^v>>v>^v^^^>v^^^v>>^v^^<^>>^>^<>>^^<>>^vv>v^<^>>>><><^^v<><<<<^^<>>^<>vv^<^>v^^><^v>^^>v<>^v^<>^vv^>vvv>v>^>^>>^>><>>>^^^^v^<>v^^>^<>v<^^v><^v><>^^^^^v^v>>^^v><<><^^^^><^>v>><<<^v>v^^>^v^<^^v>v<^<<>>^v<<>v<^v^>v^>^v<<v>v>>v>v^^v>^v^>>>><>^>v>^v^>>>>v^<<<>vvv>><^^>^<><^^<^v^v^<^^>^<^v^<<<^^v^v>>><>^^>vv<<^v^<<<<^^>>>v>v<<<>^^>>>v>^>v>vv<<>^<^>^^<^>^v^<>v^><^^^>vv>><^v<^<<<><<^^<><>v>^>^<>>^^v>vv^<^^v>><^vv^<<<>vv^v<^<>v^^>><>^<^v<<<^<<^>>>^^<^^v>v^vvvv>v<>><^>^<<<v^^^v<>v>^^<v>>v>>v^>^<>v><>>>v^>^v<^<><<^>^^^>^><>^><^<>vv<>>v^v>^>^>^<^><>v<><>>>^^^<^v>>^<>>>vv^>vvvv>>><^>v<>^^^>v>>v^v^>^^<<^>^>>v<<><>v^^>v^><<^v^>^^<v><<<^v^<>^<>^>>^<^^<>^v<>v^>>><>^><>>vv>v^<^^^>v>^^>^v<><>>><>><^<>>v>v^^>^^<^^>^>>v>vv^^v<^<^v>><<^>^v>^^^<<>v^<^^v<<<>^^vv<^>vv>^>^<><<>vv<^>v^vv>^^^v><<^vv>^v<>vv^^<^<>^^v^<^vvv>v^^<>^^>^^>^<><<^v>^><^^vvvv<><>^v<>^><>v>><>vv^<<><<>><>v<^>^v>>^^v><<<>>^<^v^^^<^<><><^><<<<^^<>><><>>v><<vvvv^^vv><<^v^vvv><>v><>v<<<^><^^>v^>^^^v^v>><<>^v<>v^v<<<<^^^v^v<<>>>v>>vv>^^<><^v<>>v^>>>>>^>v^v^<^v^v^vvv>vvv^<vv>>v^^vv<^v>>>>vv<>v<>^^vv^v^>>vvv<<v>v>^><<<^>v^>^v^^^><<><<<^^<^^<>^^v<^v>^v<^>^>><>^v^v<<^>^>v><^>^vv^^^v^v^>^<<>>>>>v^<>^>v^vv^><<>>^^<>v^>^vvv^>v^v><>^><<>v>v<^<^><^^vv<<><>>v>>v>>^v<<>^vv<>^vv>v>v>^>^>>><><<>v^<<^v^^<<<>>vv<^<<>v<^^^<<^v^>^v>^^^v^v>>>v>v^v>^>^vv<^^<^<<v^<><<^vvv^^><>vv^v>v>^><<^^^^vvv^><^v<^>^<>>^>>vv^<>>^v>^>v>^<^<^^^<>>>>>>v>^<>^^v^><>><^v^^><>v^v<^<<<<^>^^>vv>><^v^vvv>v^^><^^<^<>>^^v^vv<>v<^<<v>v<>^v^><>v<^v>><<^<^v^>><^<^><>v>>^vv<^v>^>v<^>>^>>v^>^v<^v^v><<><>^><<<><>^<>^^^^v>^>^vvvvv>v>>v><<<^><<^v><^v>>>>^v<^v<<>>^>^<v>><<^>^>^v><><>^><v^><<^v^<^^><^^v^<<^v^^>>^v^<^>v^^<<^^^<><>^>v^v>v^>^v^vv>^^>>>>^^<^>>>^^v<^^v><<<>^>^^>^>^v<<<<>>^<<>>>v>^^<^v<>v<>v^>v^><^<^^>^^vv><>v>^<<<^><^^<^<^^v<^>v^v^^^><^>v^v>>^^v^>>>>><<>^>v>v<>>>v>^^^^>>v^<<^>>><^v^<<>>v><>^v^^><<>>^>^>vv<^<>^vvv^vv^v>^^<<<<<>^v^>^<>v^^<>v^v^<>vv^<^vv>>><<>v^^^>^>^^>>>vvv>^>v>v>>>^>vv^><>^><>v>^^^><><<<>>v^v<^<>^^<>^^<<><>^v<><>>>^vv<^<<^<^v>v<<<<<^^v<^v<><^>v>^v>>^v^><^^^^v<><><>vv^<>vv<^v<^^><^^v^v^<^^<<>v<>v^v<^>vvv><<^v>>v><>>>v<^>>v>^<>><>^v<^^>^<^v<^<<^^v<>>^>^>^v^^v^v>v>v<>v^>v^^>^^>><<>><<^^>><^v<<><<>>>>>>^^^^^<<>^<<^><<^^vvv<<>vv><<>v>v^v>>>>>^<>><^^^><<<<>>v<^>>>^^vvv>v<>>>>v>>^v^vvv<<>vvv<<^^^<>vv^^v<<>^^^>>^<^v^<^^>v^>>^<<^v<v^>>^>v^><^><>^>>>vv>><^^^>vv<<^^vv><^<>^>^^<^<>>^vv^>>^v><>v^>>><<<^^<^>^>v<^>^<^^<>>><^^<>^v^<<>vvv>v^v<<^^^><<^vv^v>v>v<<^v^<<<>^><>v>^vv^v<>vv^>^^<^>^>v^^v><>>^v<^<><><^vv<><<>v^^>^^<><<>^<^<<<>v>><^<<>^>^v^v<^>>^v<^>v<<>^^^<^v>>>^vvvv<vvvv>v<>v^<><>vvv<>^<<>^>>>>v^<^<><^v>v^>>v><>^><^<<>^>^v^>^v>^<>v^<^^>v>^>>>v^v>>>^<>^<>>>>>v>>vv^v<><<<><><<>>vv<^^v<<>v^v<^v<>>^v>>vvv^^v>>v>^>^>v><^>^^<<>^v<^<<<<^>v<^>>v^<^v>^v<<>^>^vvv<^^vv>^vv>vv<>>v>v>v^<<<<<^^v^>v>^<<>v^<<>>^<^>^^<>>>>^<^v<>v^^>^<^^v<^><>>>^v^vv<^v<^><><>><^^>^<^v^<^<>v<<<^v>v^^^<>v^^v^>><>^^<<^^v^<>^<^vv>>><^v>vv<^v<<>v>v^v>^v<^<>v^vvv>^vv<<<<^>>^^>><^v><<^>v^^<<<<<>^v<<^^>v<<<<^>^>^>>^>>>v^<>^^v>>>^vvv<^v<>>>vv>^^><^v>vv^>>v>v^<>^^>^<<^>^^^>>^vv>^^>vvvv<>>^^^^>>>v>v^^>vv>vv^<<>^><^><<>>^>^><^v^>v^<>^>v^^v^>^^>v<<<<^<<^>>v>v^^^<<>>^^v>v<<<<^^^v>^vv^>><>^v<>>>v>vvv^v^^v^>>vv>^>><>^v><^v^><^^>vv>^<^<^>>v>><><>^>^>v>vv>vv>^^>v>v^>^>^v>^^v>^<^v<>>vvv^^>^>vvv^^v<^<^>vv^^<^^^>v>vv<v<^>^v^<^>v<^>^<>vv^><>>^>>^<^><<>^<^>v>v><>>>^<<^><<^v<>>vv<^>>v>v>>>>^^>v<^v^>><<^<>>v><^><<^>^<<>>^^<><^^v>^^>vv>^v>^^v^<^<<>>v^^^<^><^<<><><<>^v>vvv^vvv^^>>^<^><>^<<<<^^<>>>v^<<^^v>><><v>^vv>vv^><>^><<><^^>^>^<><>><^^<><>^>><^v<<<<>>^v>^^vv^v^<><<vv>>v>>^v^<>>vv^<^>^<<>v<<<^vv<^vv^vv<^v^^^v>>v<^^<^^vvv<^^v<>>>^>v^>^^><>vv>v>v<<<^^v<^vv^v>^^^>>>^^<>^^<^vvv>><><<><^><<>^>^^vv>vv^^<^^<<><><v><<>v>vvv<^^^^<^>>><<<^^^<^>vv^^v>>v<vvv^^v^^<^v<^<>^<^v>>^><><>v>>>^^>>v^>><>v<><>>><>>>>><<^vvv<<><><<>^><><<^^v><<^>v>^>^v>v>>^^<><^>vv<^<^v>v<><^<<^><>^^^^^v>><>^>^vvv>v^vv^v^>v><>v^><>v>^^^^><^v^^^>^^><<^^>v>v<^v^^vv^<<<<^>v>v^v><>^><><>^v^<>^v>^v>v^<><^>>v<<^><^vv^<><^<>><>><<^^^^>v<^<^vv<><^vv><<^<v^>>^v>^>v^^v>vvv<v<>^>>vv^>>><>^v^^<^>v<<^<^^v^^v^<vv^><^v<^>>>vv^^^^v>^><^^^<><<^^>v<><><><>vv^><<^>^><^v<^<^v^v<<<<<<><vv>v<^><<><><<>>v>><^>^v>^v^<>v^^^><^^<<<^vv^vv>^v^vvv^^>v^><^<^<^<>^vv^^^>vv^v>>><<<^<>>v>v<^^<>>><><^v^^<<><<<>^<^^v^>v><^<^>^>>^<>^v><>>^vv^>^^<<<^v<>>^v<>vvv<<^^<<>>>>^^<><>^><>^vv^v<^>^v<>v^vv<><^vvv<><<^>>^^><><>^<>^>v^^v^><>>v>><^v>^v<<<>vvv^<^^v^<>^>>v<>^^><>>^><^^vv>><<>><^><>>^vv>vv^v^^v<<^^v^^vv<<^<<><>^<><^<^<>>^vvv>>^<^vv>^vv^>v>^<><^><^<>v^v^^<^<>^^v>>><^v<>v^v<<^>v><>^^<v^>>v>^<>^>^>^<^>v><<><><><<<>^>><^>>>^v<<<^<<>^><<^>>>>>v<^>v>>v^^>v^^><>v^v^vvvvv>>><<>^<v>^>^vv^^<^>>v>vv^v<^<>^v^<^<<><<<^vvv^>^^<<>>>vv<<^<><^v<^<><<^^>vv^v>v^^^>>>>^>vv<v>>^^v^^><>v<<^><^>^>v^v>><^v^>v<<^<^<^<^<>>v^^>><<<>vv<^^>^vv<<<^^v^^>v<<><^<>^^>^v<>v>><^^^vv^>^><>v^^>^v>^<<^v>^>>>>><^^^<>v>v^^<^v^>>v^<^>v^v>>>>^>>vv<>^<^v>v>v^v>^<>^>v<<>^<>>^<>>^<>v^><<>^v>>^^^^<<^v><>^<^>^^v><^^<^^v>v<<^>^>><<^^^vvv<<^vv<^^>v^^vv^<^^<<^^>>^^<v^>>v^^>v<^>^>vv>><v><^<^vv>^^v>^>v<<^vv><^^^^^^><<^>>>^v<>^^v<<<>><<<>^<<v^>^^^<^>^^^v<<>v^><<^^<<^v<<>^v>>vv>><<^v^^>v^v>^^v<><^^^<^^>v>^<>vvv^v^^^>v^^v<^>^^>>^v<><^><^<<^vv^<><<>v^vv^<<<^^>v<<>>>v<>v<><<^v>^^v>^^>v>^>^>v<>><>^>^>^vvvv<^^^^^v>v>><>^>^><>^^>v^^<<><^><<<<>v>^^>^v<<<>vvv>>v<^v>>v>v^<<<>^>^>^<>v<^^vv><^v<<^vv<^<<^^vv^^>vv<^>v>^^<^>v<<^^<^>^^^v^^>>v^vv^<^v>^<>^<^>>^<^v<>v><^^<><>^>v<^<^vv>><^v>^<>^^>^<><<>^<>><<>vvv^<<^^>>v<^>>vv>^v^^^v<>v<>><>^vv^>vv^ \ No newline at end of file diff --git a/rust/src/day.rs b/rust/src/day.rs index 9e3439a..68e64d9 100644 --- a/rust/src/day.rs +++ b/rust/src/day.rs @@ -1,6 +1,6 @@ use std::io; pub trait Day { - fn new(String) -> Self; - fn solve(self) -> io::Result; + fn new(&String) -> Self; + fn solve(&self) -> io::Result; } diff --git a/rust/src/day_01.rs b/rust/src/day_01.rs index 6ef6e12..a2be84a 100644 --- a/rust/src/day_01.rs +++ b/rust/src/day_01.rs @@ -8,12 +8,12 @@ pub struct Day01 { } impl Day for Day01 { - fn new(input: String) -> Day01 { - Day01 { input: input } + fn new(input: &String) -> Day01 { + Day01 { input: input.clone() } } - fn solve(self) -> io::Result { - let elevator = Elevator::new(self.input); + fn solve(&self) -> io::Result { + let elevator = Elevator::new(&self.input); Ok(1 + elevator.run().position(|f| f == -1).unwrap_or(0) as i32) } } @@ -23,8 +23,8 @@ struct Elevator { } impl<'a> Elevator { - fn new(input: String) -> Self { - Elevator { instructions: input } + fn new(input: &String) -> Self { + Elevator { instructions: input.clone() } } fn run(self: &'a Self) -> ElevatorIterator<'a> { diff --git a/rust/src/day_02.rs b/rust/src/day_02.rs index be5a315..a694858 100644 --- a/rust/src/day_02.rs +++ b/rust/src/day_02.rs @@ -7,12 +7,12 @@ pub struct Day02 { } impl Day for Day02 { - fn new(input: String) -> Day02 { + fn new(input: &String) -> Day02 { let presents = input.split("\n").map(|line| Present::new(line)); Day02 { presents: presents.collect::>() } } - fn solve(self) -> io::Result { + fn solve(&self) -> io::Result { Ok(self.presents.iter().fold(0u32, |acc, present| acc + present.ribbon()) as i32) } } diff --git a/rust/src/day_03.rs b/rust/src/day_03.rs new file mode 100644 index 0000000..a6d5472 --- /dev/null +++ b/rust/src/day_03.rs @@ -0,0 +1,140 @@ +use std::cmp::Eq; +use std::collections::HashMap; +use std::fmt; +use std::io; +use std::ops::Add; +use std::str::Chars; + +use day::Day; + +pub struct Day03 { + directions: String, +} + +impl Day for Day03 { + fn new(input: &String) -> Day03 { + Day03 { directions: input.clone() } + } + + fn solve(&self) -> io::Result { + let houses = Santa::houses_visited(&self.directions); + Ok(houses.len() as i32) + } +} + +struct Santa<'a> { + location: Point, + directions: Chars<'a>, +} + +impl<'a> Santa<'a> { + fn new(directions: &str) -> Santa { + Santa { + location: Point::origin(), + directions: directions.chars(), + } + } + + fn houses_visited(directions: &str) -> HashMap { + let santa = Santa::new(directions); + let mut houses = HashMap::new(); + houses.insert(Point::origin(), 1); + + for point in santa { + *houses.entry(point).or_insert(0) += 1; + } + + houses + } +} + +impl<'a> Iterator for Santa<'a> { + type Item = Point; + + fn next(&mut self) -> Option { + let offset = match self.directions.next() { + Some('^') => Point { x: 0, y: 1 }, + Some('v') => Point { x: 0, y: -1 }, + Some('>') => Point { x: 1, y: 0 }, + Some('<') => Point { x: -1, y: 0 }, + _ => return None, + }; + self.location = self.location.clone() + offset; + Some(self.location.clone()) + } +} + +#[test] +fn test_one() { + let directions = ">"; + let santa = Santa::new(directions); + + let points = santa.collect::>(); + let expected = vec![Point { x: 1, y: 0 }]; + assert_eq!(expected, points); + + let houses = Santa::houses_visited(directions); + assert_eq!(2, houses.len()); + assert_eq!(&1, houses.get(&Point::origin()).unwrap()); + assert_eq!(&1, houses.get(&Point { x: 1, y: 0 }).unwrap()); +} + +#[test] +fn test_two() { + let directions = "^>v<"; + let houses = Santa::houses_visited(directions); + assert_eq!(4, houses.len()); + assert_eq!(&2, houses.get(&Point::origin()).unwrap()); + assert_eq!(&1, houses.get(&Point { x: 1, y: 0 }).unwrap()); +} + +#[test] +fn test_three() { + let directions = "^v^v^v^v^v"; + let houses = Santa::houses_visited(directions); + assert_eq!(2, houses.len()); + assert_eq!(&6, houses.get(&Point::origin()).unwrap()); + assert_eq!(&5, houses.get(&Point { x: 0, y: 1 }).unwrap()); +} + +#[derive(Clone,Debug,Eq,Hash)] +struct Point { + x: i32, + y: i32, +} + +impl Point { + fn origin() -> Point { + Point { x: 0, y: 0 } + } +} + +impl Add for Point { + type Output = Point; + + fn add(self, other: Point) -> Point { + Point { + x: self.x + other.x, + y: self.y + other.y, + } + } +} + +impl fmt::Display for Point { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "({}, {})", self.x, self.y) + } +} + +impl PartialEq for Point { + fn eq(&self, other: &Self) -> bool { + self.x == other.x && self.y == other.y + } +} + +#[test] +fn test_point() { + let point = Point { x: 10, y: -10 }; + let offset = Point { x: -10, y: 10 }; + assert_eq!(Point::origin(), point + offset); +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 3fbf4e5..4c15b7f 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -9,4 +9,5 @@ macro_rules! import_day { import_day!(day, day_01, - day_02); + day_02, + day_03); diff --git a/rust/src/main.rs b/rust/src/main.rs index cd6d806..804f92c 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -19,7 +19,7 @@ fn read_input(filename: &str) -> Result { } fn main() { - let input = read_input("day_02").unwrap(); - let day = Day02::new(input); + let input = read_input("day_03").unwrap(); + let day = Day03::new(&input); println!("{}", day.solve().unwrap()); }