diff options
author | cos <cos> | 2020-12-03 08:04:08 +0100 |
---|---|---|
committer | cos <cos> | 2020-12-04 10:25:55 +0100 |
commit | 31c4288918624c5af2adbe642e578d2cb70a0fe0 (patch) | |
tree | 527f6ea078647bf8a1f715cb238dbc5ed19a4524 /2020 | |
parent | 616e32ade5e53fc2388fb942c5b2202f5f0b333b (diff) | |
download | adventofcode-31c4288918624c5af2adbe642e578d2cb70a0fe0.zip |
Add day03, 2020
Diffstat (limited to '2020')
-rw-r--r-- | 2020/rust/Cargo.toml | 2 | ||||
-rw-r--r-- | 2020/rust/day03/Cargo.toml | 10 | ||||
-rw-r--r-- | 2020/rust/day03/src/main.rs | 151 |
3 files changed, 162 insertions, 1 deletions
diff --git a/2020/rust/Cargo.toml b/2020/rust/Cargo.toml index febab99..6ecd67b 100644 --- a/2020/rust/Cargo.toml +++ b/2020/rust/Cargo.toml @@ -3,7 +3,7 @@ members = [ "aoc", "day01", "day02", -# "day03", + "day03", # "day04", # "day05", # "day06", diff --git a/2020/rust/day03/Cargo.toml b/2020/rust/day03/Cargo.toml new file mode 100644 index 0000000..e34114a --- /dev/null +++ b/2020/rust/day03/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day03" +version = "0.1.0" +authors = ["cos <cos>"] +edition = "2018" + +[dependencies] +aoc = { path = "../aoc" } +anyhow = "1.0" +thiserror = "1.0" diff --git a/2020/rust/day03/src/main.rs b/2020/rust/day03/src/main.rs new file mode 100644 index 0000000..900bd8a --- /dev/null +++ b/2020/rust/day03/src/main.rs @@ -0,0 +1,151 @@ +use anyhow::{Result, anyhow}; +use std::env::args; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::ops::AddAssign; +use std::path::Path; +use thiserror::Error; + +#[derive(Clone,Copy)] +struct CoordPair { + x: usize, + y: usize, +} + +impl AddAssign for CoordPair { + fn add_assign(&mut self, other: Self) { + *self = Self { + x: self.x + other.x, + y: self.y + other.y, + }; + } +} + +#[derive(Debug)] +struct TreeMap { + width: usize, + height: usize, + map: Vec<bool>, +} + +#[derive(Error, Debug)] +pub enum TreeError { + #[error("Could not access TreeMap")] + Invalid, +} + +impl TreeMap { + fn is_tree(&self, pos: CoordPair) -> Result<bool, TreeError> { + let mut p = pos; + p.x %= self.width; + self.map.get(p.y * self.width + p.x).copied().ok_or(TreeError::Invalid) + } +} + +fn read_input<T: AsRef<Path>>(filename: T) -> Result<TreeMap> { + let f = File::open(filename)?; + let reader = BufReader::new(f); + + let tree_map = reader.lines() + .fold(Ok(TreeMap { width: 0, height: 0, map: vec![] }), |acc, l| { + let line = l?; + let row: Result<Vec<bool>> = line.chars().map(|c| match c { + '#' => Ok(true), + '.' => Ok(false), + _ => Err(anyhow!("Invalid map character: '{}'", c)), + }).collect(); + + match acc { + Ok(mut a) => { + a.map.append(&mut row?); + a.height += 1; + Ok(a) + }, + Err(err) => Err(err) + } + }); + match tree_map { + Ok(mut tm) => { + tm.width = tm.map.len()/tm.height; + Ok(tm) + }, + err => err, + } +} + +fn part1(input: &TreeMap) -> Result<usize> { + let mut pos = CoordPair { x: 0, y: 0, }; + let slope = CoordPair { x: 3, y: 1, }; + let mut collision_count = 0; + + while pos.y < input.height { + if input.is_tree(pos)? { + collision_count += 1; + } + pos += slope; + } + + Ok(collision_count) +} + +fn part2(input: &TreeMap) -> Result<usize> { + let slopes = vec![ + CoordPair { x: 1, y: 1, }, + CoordPair { x: 3, y: 1, }, + CoordPair { x: 5, y: 1, }, + CoordPair { x: 7, y: 1, }, + CoordPair { x: 1, y: 2, }, + ]; + + let res = slopes.iter().map(|slope| { + let mut pos = CoordPair { x: 0, y: 0, }; + let mut collision_count = 0; + + while pos.y < input.height { + if input.is_tree(pos)? { + collision_count += 1; + } + pos += *slope; + } + + Ok(collision_count) + }).product(); + + res +} + +fn main() { + let ( do_part_1, do_part_2 ) = aoc::do_parts(); + + let filename = match args().nth(1) { + Some(f) => f, + None => { + eprintln!("Missing input filename"); + std::process::exit(1); + }, + }; + match read_input(filename) { + Ok(input) => { + if do_part_1 { + match part1(&input) { + Ok(solution) => println!("Part1: would encounter {} trees", solution), + Err(err) => { + eprintln!("Part1, no solution found: {}", err); + std::process::exit(1); + } + }; + } + if do_part_2 { + match part2(&input) { + Ok(solution) => println!("Part2: {} is the product of all tree collisions", solution), + Err(err) => { + eprintln!("Part2, no solution found: {}", err); + std::process::exit(1); + } + }; + } + }, + Err(err) => eprintln!("Could not read input: {}", err), + } +} + |