diff --git a/inputs/day3.txt b/inputs/day3.txt new file mode 100644 index 0000000..174ba13 --- /dev/null +++ b/inputs/day3.txt @@ -0,0 +1,323 @@ +.##......#.##..#..#..##....#... +...##.....#...###........###... +#....##....#.....#.....#..##.## +.......#.###.#......#..#..#..#. +##..........#....#.#...#....... +###.#.#.#......##...#.......... +.#.##........#..............#.. +..#..........#...##..#.......## +.........##...#...#....###.#... +#.......#.....#.#.#...###.##.#. +...#...#...#......#........#.## +....#..........#.....#..#....## +.#.#.##....#.#...#............. +#....#..#.....#.#.............. +........#....#....#..#........# +..#.......#...#....##.#........ +......#.........##.......#.#... +............#.......#.......... +.....#..#.#..#........##...#... +....#.....................###.. +..#.......#.........#..##....## +..#........#..#...#........#... +..............#....##..##....#. +....#..#.#.......#....#..#...## +.#........##......#.#..#.#..... +............#.##...##...#...##. +.......#........#.........##... +...#...........#.#...#..#...... +#...#............#..####....... +..#..#..#..#.....#...#.#.#..... +....#.#..............#.....##.. +#.....##........#......#....... +.....#..#................##.#.. +.###.#...................#..... +....#....#...#.##..........#... +.#.....#....#.......#...#...... +.....#...#.##.##............#.. +..........#..#....#...#.#..#... +#...#..#..............###.#...# +......#....#.#....##....#...... +............#......#......##... +.#....#...#........#.#.#..#.... +..#.....#.......#.....#.#...... +#....#......#.......#......#... +....#..##.....#...#........#... +.#..#......#..#................ +.#...#...#....#.#...#.....#...# +......#..#...#...#..#.......##. +...#..#...#.#.......#.......#.. +..#...#.........#......#......# +......#...#..#..........#...... +.#..#......#....#.#.#...#....#. +.#.#....#.#.#..#..#..#........# +....###.#...##..#.#..#....#.... +...#.#.#................#...... +.#.....#..#..........##..#....# +..........#..#......#.........# +.....#....#...#.#..##....#.#.#. +........#.##......###.......... +##......#.#..#.....#..##.#..... +.#.......#..#....##.....##..... +.....##....#................... +##......#....##........#.....#. +..##...#...........##........#. +...#....#..##.#....#......##... +#....#...##....#..........#.... +......##....#...............#.. +...#.#.#...#...#...#........... +....#..#...#.#....#.#......#... +.......#...#...............#... +.##..#....#...#....#.#........# +.....#..##............#......#. +...##...#.....#..........#.#..# +..#..##.............#....#..... +.....#.#.....#.........#......# +........#..........#.#.#...#..# +#........#.#................... +......#......##..............#. +......#..#.#.....#...#.#...#... +.#..##.....#...##.......#...... +#.......#....#..##....#..#.#... +#..#..#....#...........#.##.... +..##....#....##.....#...#...##. +.#.......#.......#....#.......# +.#..#..#...#...#............... +.#..............#.....#........ +..........##...#....#.#......## +..........#..........#.......#. +..#..##....##...#.......#...... +.#......#.#........##.#........ +...#......#..#....#...#....#... +...............#....#..#.##...# +....#.......................#.. +#....##.#......#....#.......... +.......#.#......#........#..##. +..#.....#...#...........##..#.. +#........#.#....#............#. +.........##..................#. +........#...#..#...#......#...# +...#.......#...####.#...#...... +....#..###......###..#......... +.....#...........#......#...... +.#.....#......#.....#.....##.## +.#.#...##..........#........#.# +..#....#.....##...............# +.....##.....#...##..#.......... +.#......##.......#..##.##.#...# +.#..#...#.##.....#.#........... +.........#....##...#.....##.... +#..........#.............#..#.# +...........#........#.#...#.... +........#..###...#...........#. +#.........#...#....#..##.##.... +........#....##.......#.#....#. +..........#..............#..... +....##...#...##..........#..... +...#..##.#...###..#............ +...##..#####....#.............# +.#..#.......##.......#........# +....##..........#.......#.#.... +......#.........####.......#... +...............#......#..#..... +...#...##...#.#.#.....##.#.#... +..#....#..#..............#....# +#..............#............#.. +.#.#..#....#.....#.#.#...#..... +......#......#..#..#.....#..... +.#.#..#.##.#........#.......... +..##.#......#..#.......#....... +.##...##....#..#.#.........#.## +.........#........#.#..###....# +.....#...............#......... +......##..........#.....#...... +.#.....#.#.#..#.#.....#..#.#### +.......###.##......#.....#.#..# +..#.....#....#.#.##......#....# +.....##..#................#..## +.#......#.....#..#.....#..##### +.........#.#.......#..##...#... +.#.#..#.......##.....#....#.... +.....#...###.#...#......#....#. +.#....#....#...#..#.#........#. +......##........##.#...#..#..#. +.##.##.###..#.....#........###. +.....#..#.#.......#..#.#....... +##.#.#..............#..##...... +....#.........#.......#.#...... +.....#..#.....#...#.#....#.#... +...#..#.#.#..................#. +........##.#.###............... +..#...#.#.......#......#....... +.......#.##....#...#....#...... +......#.#.............#........ +........#......#........##.##.. +.....#...#......##............. +...#.#..#.....#.#...#.......... +.#.#..#.....#............#..... +.#.#..#.#.##.#...#.##..##...#.. +.........##........#.##..#..... +##.#.#......###..#.##.#........ +.##...#..#...#.#..#....##.....# +#......#..........#.#...#.....# +..........#......#...#.......#. +.............#..........#...... +#.#....#.......##..#.....#.#... +##......#..#......#.#..#.#....# +..#.#..#.....#.#......#....#..# +...#......#......##.....#..#.#. +....#......#.....#....#.#.#..#. +.....#..#..#.....#...........## +....#.....#...#........##.#.#.# +..#......#.......#........#.... +#.......##..##......#...####..# +#..........#......#.#..#..#.... +.................##............ +...#..#..#.#.....#.##.#.....#.# +...#....###.................... +....#.......#..#.#............. +#......#................#...... +..........#........#..#........ +.....#......##..#......#..###.. +...#....#.......#.............. +.#....#.#.#........#.....#...#. +.......#.....##.#.....#....#... +.........#.#.........##..#...#. +......#......#....#.....##.#.#. +####...#.........#.....#......# +...#.#..#..#.............#..... +......#.........#....#.#..##..# +.........#.....#.#..##..##..#.. +.#......##.............#....... +....#...#......#...#.....#.#.## +......#..##....#..#.....#...... +......#..............#....##... +.........#.###..........#.##... +#....#..........#..#.......#... +...........#...#.....#.......#. +..#..#........#................ +...###.........#............... +.....#.##...#.................# +..#.#..#...###......#........#. +#......#......#.#.............# +.........#.#.....#..#........#. +........#..#......#......##.... +.....#......#...#.....##...#.## +.##...#..#....##..........###.. +.......#............#........## +.##.....#.......#...#.......... +..###..........#.............## +#....#....#.#....#............# +#...#......................#... +....#..#..#..#.......###....#.. +#..###.#..#.....#.............# +..........#.##.....#.........## +...#.............#....#....##.. +#........................#..#.. +........#...#.....#.....#..##.. +#........#......#....#..#....#. +.....#.#.#....#.#..#....#...... +.....#....#.................... +.........#..#..#....#......#... +..........#.#.#.......#........ +.......#.#.....#..#.....##..... +.....#....#.#.....#.......#..#. +.#..###.......#......#..#..#... +..##.#.....#.........##.#...... +.....#.......###.......##...... +#...#.......##.#.#......#.....# +.##........##.#...#...#........ +....#.......#....#..#.......#.. +.#..#.......#..####..##........ +..#..#..#..#..#..#............. +...#......#...#...#.#......##.# +........#.#..#.#.#......#...#.. +#.......#..##.......##........# +..##...#...............#.#....# +.####........##..........#..#.. +..#........#...##...#........#. +.#.#..........#...#...#........ +....###..........#....#........ +.#.#.#.###.#.##..#.#........#.. +..........#....##.#..##........ +.......#..#..##.......#........ +..#........#....#..####.#..#... +....#.......#..##..#..........# +.....#...........#....#....#... +.#.##..#......##.........#.#... +...#......##..##......#.....#.. +#........#..........#.#...#.... +.#.#........###........#..#.... +....#####.................##... +.........##...#......#......... +.......#....#....#.#....#...#.. +......#................#...#.#. +....#.....#.....#.#.....#.....# +#.........#..#........#.....#.. +....#...........#.....#.#...... +##..#....................#.#... +#.#.##....#.....##....#.......# +..#..#....###.......#..##...... +......##.....#.##...#....#..#.. +........#..#.#..#..#.#......... +#...#.....##..........##....... +....#.....#...#.###.......#.... +..........#..#...#........##..# +##..#...#.#.####.#..#..#...#... +................#......#..#.... +.......#...###...#........#.... +....#..##..#.#......#...#.#..## +.##......#...........#.......## +....#.#...#..#.#.......##...... +....#..##..#.....#........##... +...#...#..#.#.#....#.........#. +#....##.#....#..##............. +.#......##......#.#.##.......#. +.......#...#....#.##......#.... +..##..........#.....#.#......#. +#..##.....#..........##..#.#... +....#.#.......#.#.....#.....#.. +##.....#..#.....##...#.....#..# +...#.#..#...#..............#... +...............#..#............ +.#.......#......#........##.... +..#......#..##..####.....#...#. +.#.##.#.#..#..##..##........... +...##.............#.....#..#... +.##.....#..#.#......##........# +##....#.............#...#...... +......#.....###...........##... +.#.#...#.............##..#..### +..#.##.##...#.....#...........# +.....#.....##...#...#........#. +........#..##.......##.....#... +.#........####.......#.#...#... +...#..........#......##........ +.......#......#..##..#...#..... +..#...........#.#.#..#.#.#..... +#..........#....#....###.#..... +....#.................#...##... +#....#.###......#..#.....#...## +.#.......##.....###.....#...#.. +....##............#...........# +...#.#.#.........#...#..#..#..# +.....#..###.................#.. +.#.....#.....#....###.#..#...#. +................#...#.......... +..#....#..##....#.##........#.. +....##....#...........#..#..... +...##......###.......#...#..... +.......##............#......#.# +#####.....#..#.###..#.#........ +#.##.##..#.......#....#........ +....###..#.#.#......###.#...... +....#....#.....##.#..#....#...# +....#.....#.#...##.##.#.#....#. +.........#.#.###.#.....#....... +.#....#.......#..##...#....#... +...####...##.#.....#........... +#.....#.....#..........##..#... +................#.#.#......#... +.#...#.......#..#............#. +.##.#.......#..#....#.....#.... +.#...#..#.....#..............#. diff --git a/inputs/day3_test.txt b/inputs/day3_test.txt new file mode 100644 index 0000000..8f551de --- /dev/null +++ b/inputs/day3_test.txt @@ -0,0 +1,11 @@ +..##....... +#...#...#.. +.#....#..#. +..#.#...#.# +.#...##..#. +..#.##..... +.#.#.#....# +.#........# +#.##...#... +#...##....# +.#..#...#.# \ No newline at end of file diff --git a/src/bin/tobaggan.rs b/src/bin/tobaggan.rs new file mode 100644 index 0000000..81a7bd9 --- /dev/null +++ b/src/bin/tobaggan.rs @@ -0,0 +1,100 @@ +use advent2020::errors::{MapParseError, TopLevelError}; +use advent2020::map::Map; +use std::convert::TryFrom; +use std::env; +use std::fs; + +#[derive(Clone, Debug)] +enum Square { + Empty, + Tree, +} + +impl TryFrom for Square { + type Error = MapParseError; + + fn try_from(c: char) -> Result { + match c { + '.' => Ok(Square::Empty), + '#' => Ok(Square::Tree), + _ => Err(MapParseError::UnexpectedCharacter(c)), + } + } +} + +struct Encounters { + trees_encountered: usize, + clear_spots_encountered: usize, +} + +fn trail_for_slope(map: &Map, run: usize, fall: usize) -> Encounters { + let mut current_x = 0; + let mut current_y = 0; + let mut encounters = Encounters { + trees_encountered: 0, + clear_spots_encountered: 0, + }; + + loop { + match map.at(current_x, current_y) { + None => break, + Some(Square::Empty) => encounters.clear_spots_encountered += 1, + Some(Square::Tree) => encounters.trees_encountered += 1, + } + + current_x += run; + current_y += fall; + } + + encounters +} + +fn real_main() -> Result<(), TopLevelError> { + let mut maybe_map = None; + + for argument in env::args().skip(1) { + let fname = argument.clone(); + let contents = fs::read_to_string(argument)?; + match Map::::try_from(contents.as_str()) { + Err(e) => eprintln!("Skipping file {}: Parse error: {}", fname, e), + Ok(v) => { + maybe_map = Some(v); + break; + } + } + } + + let map = match maybe_map { + None => return Err(TopLevelError::NoInputFound), + Some(x) => x, + }; + + let initial = trail_for_slope(&map, 3, 1); + println!( + "For the initial slope, encountered {} trees and {} open spaces", + initial.trees_encountered, initial.clear_spots_encountered + ); + + let mut product = 1; + let slopes = [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)]; + + for (run, fall) in slopes.iter() { + let encounters = trail_for_slope(&map, *run, *fall); + println!( + "For slope ({},{}), encountered {} trees and {} open spaces", + run, fall, encounters.trees_encountered, encounters.clear_spots_encountered + ); + product *= encounters.trees_encountered; + } + + println!("The product of the trees encountered is {}", product); + + Ok(()) +} + +fn main() { + match real_main() { + Err(e) => eprintln!("ERROR: {}", e), + Ok(_) => {} + } +} diff --git a/src/errors.rs b/src/errors.rs index aa2e2b9..ab12aa5 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -15,6 +15,7 @@ macro_rules! convert_error { pub enum TopLevelError { IOError(io::Error), + NoInputFound, NoSolutionFound, UnknownError, } @@ -23,6 +24,7 @@ impl fmt::Display for TopLevelError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { TopLevelError::IOError(e) => write!(f, "IO error: {}", e), + TopLevelError::NoInputFound => write!(f, "No valid inputs found"), TopLevelError::NoSolutionFound => write!(f, "No solution found."), TopLevelError::UnknownError => { write!(f, "Unknown error occurred; this shouldn't be possible.") @@ -51,3 +53,19 @@ impl fmt::Display for PasswordParseError { convert_error!(ParseIntError, PasswordParseError, StringToIntError); convert_error!(nom::Err<()>, PasswordParseError, NomError); + +pub enum MapParseError { + UnexpectedCharacter(char), + UnevenLines(usize), +} + +impl fmt::Display for MapParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + MapParseError::UnevenLines(l) => write!(f, "Map has uneven width at line {}", l), + MapParseError::UnexpectedCharacter(c) => { + write!(f, "Unexpected character parsing map: {}", c) + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 629e98f..a596bef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,2 @@ pub mod errors; +pub mod map; diff --git a/src/map.rs b/src/map.rs new file mode 100644 index 0000000..86ccc4c --- /dev/null +++ b/src/map.rs @@ -0,0 +1,55 @@ +use crate::errors::MapParseError; +use std::convert::TryFrom; + +pub struct Map { + width: usize, + _height: usize, + data: Vec>, +} + +impl<'a, E, X> TryFrom<&'a str> for Map +where + X: Clone + TryFrom, + E: From, +{ + type Error = E; + + fn try_from(s: &str) -> Result, E> { + let mut width = 0; + let mut _height = 0; + let mut data = Vec::new(); + + for line in s.lines() { + let mut current_line = Vec::with_capacity(width); + + for char in line.chars() { + let item = X::try_from(char)?; + current_line.push(item); + } + + _height += 1; + if width == 0 { + width = current_line.len(); + } else { + if width != current_line.len() { + return Err(E::from(MapParseError::UnevenLines(_height))); + } + } + data.push(current_line); + } + + Ok(Map { + width, + _height, + data, + }) + } +} + +impl Map { + pub fn at(&self, x: usize, y: usize) -> Option { + let row = self.data.get(y)?; + let wrapped_x = x % self.width; + Some(row[wrapped_x].clone()) + } +}