summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2020/rust/day10/Cargo.toml9
-rw-r--r--2020/rust/day10/src/main.rs94
2 files changed, 103 insertions, 0 deletions
diff --git a/2020/rust/day10/Cargo.toml b/2020/rust/day10/Cargo.toml
new file mode 100644
index 0000000..75eae97
--- /dev/null
+++ b/2020/rust/day10/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "day10"
+version = "0.1.0"
+authors = ["cos <cos>"]
+edition = "2018"
+
+[dependencies]
+aoc = { path = "../aoc" }
+anyhow = "1.0"
diff --git a/2020/rust/day10/src/main.rs b/2020/rust/day10/src/main.rs
new file mode 100644
index 0000000..905c525
--- /dev/null
+++ b/2020/rust/day10/src/main.rs
@@ -0,0 +1,94 @@
+use anyhow::Result;
+use std::collections::HashMap;
+use std::env::args;
+use std::fs::File;
+use std::io::{BufRead, BufReader};
+use std::path::Path;
+
+fn read_input<T: AsRef<Path>>(filename: T) -> Result<Vec<usize>> {
+ let f = File::open(filename)?;
+ let reader = BufReader::new(f);
+
+ let values = reader.lines()
+ .map(|v| v?.parse::<usize>().map_err(anyhow::Error::new)).collect();
+
+ values
+}
+
+fn part1(input: &[usize]) -> Option<usize> {
+ let mut sorted = input.to_vec();
+ sorted.push(0);
+ sorted.sort();
+ let max = sorted[sorted.len()-1];
+ sorted.push(max+3);
+ let (_prev, count) = sorted.iter().fold((None, vec![0, 0, 0, 0]), |acc, jolt| {
+ let mut res = acc.1.clone();
+ if let Some(prev) = acc.0 {
+ let diff = jolt - prev;
+ res[diff] += 1;
+ }
+ (Some(jolt), res)
+ });
+
+ Some(count[1] * count[3])
+}
+
+fn part2(input: &[usize]) -> Option<u128> {
+ let mut sorted = input.to_vec();
+ sorted.push(0);
+ sorted.sort();
+ let max = sorted[sorted.len()-1];
+ sorted.push(max+3);
+ let mut paths: HashMap<usize, u128> = HashMap::new();
+ paths.insert(max+3, 1);
+ sorted.iter().rev().fold(0, |_, elem| {
+ let count = (1..=3).map(|jump| {
+ let pos = *elem + jump;
+ if sorted.contains(&pos) {
+ paths.get(&pos).copied().unwrap_or(0)
+ } else {
+ 0
+ }
+ }).sum();
+ let lm = paths.entry(*elem).or_insert(0);
+ *lm += count;
+ count
+ });
+
+ Some(paths[&0])
+}
+
+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) {
+ Some(solution) => println!("Part1: {}", solution),
+ None => {
+ eprintln!("Part1, no solution found");
+ std::process::exit(1);
+ }
+ };
+ }
+ if do_part_2 {
+ match part2(&input) {
+ Some(solution) => println!("Part2: {}", solution),
+ None => {
+ eprintln!("Part2, no solution found");
+ std::process::exit(1);
+ }
+ };
+ }
+ },
+ Err(err) => eprintln!("Could not read input: {}", err),
+ }
+}