No more expect, we use Result now
continuous-integration/drone/push Build is passing Details

main
Julius 2021-12-07 19:40:41 +01:00
parent 605921453d
commit c75d35d80d
Signed by: j00lz
GPG Key ID: AF241B0AA237BBA2
11 changed files with 246 additions and 193 deletions

7
Cargo.lock generated
View File

@ -11,10 +11,17 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "anyhow"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
[[package]] [[package]]
name = "aoc2021" name = "aoc2021"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow",
"chrono", "chrono",
"clap", "clap",
] ]

View File

@ -8,3 +8,4 @@ edition = "2021"
[dependencies] [dependencies]
clap = "2.34.0" clap = "2.34.0"
chrono = "0.4.19" chrono = "0.4.19"
anyhow = "1.0.51"

View File

@ -1,5 +1,7 @@
use anyhow::Result;
pub trait Day { pub trait Day {
fn init(content: String) -> Self where Self: Sized; fn init(content: String) -> Result<Self> where Self: Sized;
fn part1(&self) -> String; fn part1(&self) -> Result<String>;
fn part2(&self) -> String; fn part2(&self) -> Result<String>;
} }

View File

@ -1,21 +1,22 @@
use anyhow::Result;
pub struct Day01(Vec<i32>); pub struct Day01(Vec<i32>);
impl crate::day::Day for Day01 { impl crate::day::Day for Day01 {
fn init(f: String) -> Self { fn init(f: String) -> Result<Self> {
let v = f.lines().map(|x| x.parse::<i32>().unwrap()).collect::<Vec<i32>>(); let v = f.lines().map(str::parse).collect::<Result<Vec<_>, _>>()?;
Self(v) Ok(Self(v))
} }
fn part1(&self) -> String { fn part1(&self) -> Result<String> {
let (a, _) = self.0.iter().copied().fold((0, -1), increments); let (a, _) = self.0.iter().copied().fold((0, -1), increments);
format!("{}", a) Ok(format!("{}", a))
} }
fn part2(&self) -> String { fn part2(&self) -> Result<String> {
let ws = self.0.windows(3).map(|a| a.iter().fold(0, std::ops::Add::add)).collect::<Vec<i32>>(); let ws = self.0.windows(3).map(|a| a.iter().fold(0, std::ops::Add::add)).collect::<Vec<i32>>();
let (a, _) = ws.iter().copied().fold((0, -1), increments); let (a, _) = ws.iter().copied().fold((0, -1), increments);
format!("{}", a) Ok(format!("{}", a))
} }
} }
@ -37,32 +38,36 @@ pub mod tests {
use crate::day::Day; use crate::day::Day;
#[test] #[test]
pub fn part1_real() { pub fn part1_real() -> anyhow::Result<()> {
let f = read_to_string("./input/day01").expect("Could not load input"); let f = read_to_string("./input/day01")?;
let d = Day01::init(f); let d = Day01::init(f)?;
assert_eq!("1466", d.part1()) assert_eq!("1466", d.part1()?);
Ok(())
} }
#[test] #[test]
pub fn part2_real() { pub fn part2_real() -> anyhow::Result<()> {
let f = read_to_string("./input/day01").expect("Could not load input"); let f = read_to_string("./input/day01")?;
let d = Day01::init(f); let d = Day01::init(f)?;
assert_eq!("1491", d.part2()) assert_eq!("1491", d.part2()?);
Ok(())
} }
#[test] #[test]
pub fn part1_test() { pub fn part1_test() -> anyhow::Result<()>{
let v = vec![199, 200, 208, 210, 200, 207, 240, 269, 260, 263]; let v = vec![199, 200, 208, 210, 200, 207, 240, 269, 260, 263];
let strs = v.iter().map(i32::to_string).collect::<Vec<String>>().join("\n"); let strs = v.iter().map(i32::to_string).collect::<Vec<String>>().join("\n");
let d = Day01::init(strs); let d = Day01::init(strs)?;
assert_eq!("7", d.part1()) assert_eq!("7", d.part1()?);
Ok(())
} }
#[test] #[test]
pub fn part2_test() { pub fn part2_test() -> anyhow::Result<()>{
let v = vec![199, 200, 208, 210, 200, 207, 240, 269, 260, 263]; let v = vec![199, 200, 208, 210, 200, 207, 240, 269, 260, 263];
let strs = v.iter().map(i32::to_string).collect::<Vec<String>>().join("\n"); let strs = v.iter().map(i32::to_string).collect::<Vec<String>>().join("\n");
let d = Day01::init(strs); let d = Day01::init(strs)?;
assert_eq!("5", d.part2()) assert_eq!("5", d.part2()?);
Ok(())
} }
} }

View File

@ -1,4 +1,5 @@
use crate::Day; use crate::Day;
use anyhow::Result;
pub struct Day02(Vec<Instruction>); pub struct Day02(Vec<Instruction>);
@ -9,12 +10,12 @@ enum Instruction {
} }
impl Day for Day02 { impl Day for Day02 {
fn init(content: String) -> Self { fn init(content: String) -> Result<Self> {
let lines = content.lines().map(str_to_instr).collect::<Vec<Instruction>>(); let lines = content.lines().map(str_to_instr).collect::<Result<Vec<Instruction>>>()?;
Day02(lines) Ok(Self(lines))
} }
fn part1(&self) -> String { fn part1(&self) -> Result<String> {
let mut depth = 0; let mut depth = 0;
let mut fw = 0; let mut fw = 0;
for i in &self.0 { for i in &self.0 {
@ -24,10 +25,10 @@ impl Day for Day02 {
Instruction::Up(n) => depth -= n, Instruction::Up(n) => depth -= n,
} }
} }
format!("{}", depth * fw) Ok(format!("{}", depth * fw))
} }
fn part2(&self) -> String { fn part2(&self) -> Result<String> {
let mut depth = 0; let mut depth = 0;
let mut fw = 0; let mut fw = 0;
let mut aim = 0; let mut aim = 0;
@ -41,19 +42,19 @@ impl Day for Day02 {
Instruction::Up(n) => aim -= n, Instruction::Up(n) => aim -= n,
} }
} }
format!("{}", depth * fw) Ok(format!("{}", depth * fw))
} }
} }
fn str_to_instr(s: &str) -> Instruction { fn str_to_instr(s: &str) -> Result<Instruction> {
let v = s.split(' ').collect::<Vec<&str>>(); let v = s.split(' ').collect::<Vec<&str>>();
let name = v[0]; let name = v[0];
let height = v[1].parse().expect("This should be an int :p"); let height = v[1].parse()?;
match name { match name {
"forward" => Instruction::Forward(height), "forward" => Ok(Instruction::Forward(height)),
"up" => Instruction::Up(height), "up" => Ok(Instruction::Up(height)),
"down" => Instruction::Down(height), "down" => Ok(Instruction::Down(height)),
_ => panic!("How did this happen???") _ => Err(anyhow::Error::msg("This is not a valid direction!"))
} }
} }
@ -62,6 +63,7 @@ mod tests {
use std::fs::read_to_string; use std::fs::read_to_string;
use crate::day02::Day02; use crate::day02::Day02;
use crate::day::Day; use crate::day::Day;
use super::Result;
const D: &str = r"forward 5 const D: &str = r"forward 5
down 5 down 5
@ -71,28 +73,28 @@ down 8
forward 2"; forward 2";
#[test] #[test]
fn part1_test() { fn part1_test() -> Result<()> {
let d2 = Day02::init(String::from(D)); let d2 = Day02::init(String::from(D))?;
assert_eq!("150", d2.part1()) Ok(assert_eq!("150", d2.part1()?))
} }
#[test] #[test]
fn part2_test() { fn part2_test() -> Result<()> {
let d2 = Day02::init(String::from(D)); let d2 = Day02::init(String::from(D))?;
assert_eq!("900", d2.part2()) Ok(assert_eq!("900", d2.part2()?))
} }
#[test] #[test]
pub fn part1_real() { pub fn part1_real() -> Result<()> {
let f = read_to_string("./input/day02").expect("Could not load input"); let f = read_to_string("./input/day02")?;
let d = Day02::init(f); let d = Day02::init(f)?;
assert_eq!("1524750", d.part1()) Ok(assert_eq!("1524750", d.part1()?))
} }
#[test] #[test]
pub fn part2_real() { pub fn part2_real()-> Result<()> {
let f = read_to_string("./input/day02").expect("Could not load input"); let f = read_to_string("./input/day02")?;
let d = Day02::init(f); let d = Day02::init(f)?;
assert_eq!("1592426537", d.part2()) Ok(assert_eq!("1592426537", d.part2()?))
} }
} }

View File

@ -1,19 +1,20 @@
use crate::Day; use crate::Day;
use anyhow::Result;
pub struct Day03(Vec<Vec<bool>>); pub struct Day03(Vec<Vec<bool>>);
impl Day for Day03 { impl Day for Day03 {
fn init(content: String) -> Self { fn init(content: String) -> Result<Self> {
let v = content.lines().map(split_lines).collect(); let v = content.lines().map(split_lines).collect();
Self(v) Ok(Self(v))
} }
fn part1(&self) -> String { fn part1(&self) -> Result<String> {
format!("{}", self.gamma() * self.epsilon()) Ok(format!("{}", self.gamma() * self.epsilon()))
} }
fn part2(&self) -> String { fn part2(&self) -> Result<String> {
format!("{}", self.ox() * self.co2()) Ok(format!("{}", self.ox() * self.co2()))
} }
} }
@ -127,6 +128,7 @@ mod tests {
use crate::Day03; use crate::Day03;
use crate::day::Day; use crate::day::Day;
use anyhow::Result;
const INPUT: &str = r"00100 const INPUT: &str = r"00100
11110 11110
@ -142,32 +144,36 @@ mod tests {
01010"; 01010";
#[test] #[test]
fn part1_test() { fn part1_test() -> Result<()>{
let t = Day03::init(String::from(INPUT)); let t = Day03::init(String::from(INPUT))?;
let p1 = t.part1(); let p1 = t.part1()?;
assert_eq!("198", p1) assert_eq!("198", p1);
Ok(())
} }
#[test] #[test]
fn part2_test() { fn part2_test() -> Result<()>{
let t = Day03::init(String::from(INPUT)); let t = Day03::init(String::from(INPUT))?;
let p2 = t.part2(); let p2 = t.part2()?;
assert_eq!("230", p2) assert_eq!("230", p2);
Ok(())
} }
#[test] #[test]
fn part1_real() { fn part1_real() -> Result<()>{
let f = read_to_string("./input/day03").expect("Could not load input"); let f = read_to_string("./input/day03")?;
let t = Day03::init(f); let t = Day03::init(f)?;
let p1 = t.part1(); let p1 = t.part1()?;
assert_eq!("4118544", p1) assert_eq!("4118544", p1);
Ok(())
} }
#[test] #[test]
fn part2_real() { fn part2_real() -> Result<()>{
let f = read_to_string("./input/day03").expect("Could not load input"); let f = read_to_string("./input/day03")?;
let t = Day03::init(f); let t = Day03::init(f)?;
let p2 = t.part2(); let p2 = t.part2()?;
assert_eq!("3832770", p2) assert_eq!("3832770", p2);
Ok(())
} }
} }

View File

@ -1,4 +1,5 @@
use crate::Day; use crate::Day;
use anyhow::Result;
#[derive(Clone)] #[derive(Clone)]
pub struct Day04 { pub struct Day04 {
@ -10,11 +11,11 @@ pub struct Day04 {
struct Board(Vec<Vec<Option<u32>>>); struct Board(Vec<Vec<Option<u32>>>);
impl Day for Day04 { impl Day for Day04 {
fn init(content: String) -> Self where Self: Sized { fn init(content: String) -> Result<Self> {
let l = content.lines().collect::<Vec<&str>>(); let l = content.lines().collect::<Vec<&str>>();
let (a, b) = l.split_at(2); let (a, b) = l.split_at(2);
let first = a[0]; let first = a[0];
let nums = first.split(',').map(|x| x.parse::<u32>().expect("wat?")).collect(); let nums = first.split(',').map(str::parse).collect::<Result<Vec<_>, _>>()?;
let split = b.split(|x| x.is_empty()); let split = b.split(|x| x.is_empty());
@ -25,13 +26,13 @@ impl Day for Day04 {
).map(Option::Some).collect()).collect() ).map(Option::Some).collect()).collect()
).map(Board).collect(); ).map(Board).collect();
Day04 { Ok(Self {
numbers: nums, numbers: nums,
boards, boards,
} })
} }
fn part1(&self) -> String { fn part1(&self) -> Result<String> {
let z = self.clone(); let z = self.clone();
let mut boards = z.boards; let mut boards = z.boards;
for number in z.numbers { for number in z.numbers {
@ -39,15 +40,15 @@ impl Day for Day04 {
let res = board.mark(number); let res = board.mark(number);
if res { if res {
let s = board.unmarked_sum(); let s = board.unmarked_sum();
return format!("{}", s * number); return Ok(format!("{}", s * number));
} }
} }
} }
panic!("no board can win?") Err(anyhow::Error::msg("could not find a working sum..."))
} }
fn part2(&self) -> String { fn part2(&self) -> Result<String> {
let z = self.clone(); let z = self.clone();
let mut boards = z.boards; let mut boards = z.boards;
for number in z.numbers { for number in z.numbers {
@ -56,13 +57,13 @@ impl Day for Day04 {
let res = board.mark(number); let res = board.mark(number);
if res && len == 1 { if res && len == 1 {
let s = board.unmarked_sum(); let s = board.unmarked_sum();
return format!("{}", s * number); return Ok(format!("{}", s * number));
} }
} }
boards = boards.iter().filter(|x| !x.complete()).cloned().collect(); boards = boards.iter().filter(|x| !x.complete()).cloned().collect();
} }
panic!("no board can win?") Err(anyhow::Error::msg("could not find a working sum..."))
} }
} }
@ -130,6 +131,7 @@ mod tests {
use crate::Day04; use crate::Day04;
use crate::day04::Board; use crate::day04::Board;
use crate::day::Day; use crate::day::Day;
use anyhow::Result;
const INPUT: &str = r"7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1 const INPUT: &str = r"7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
@ -190,33 +192,37 @@ mod tests {
} }
#[test] #[test]
fn part1_test() { fn part1_test() -> Result<()> {
let t = Day04::init(INPUT.to_string()); let t = Day04::init(INPUT.to_string())?;
let p1 = t.part1(); let p1 = t.part1()?;
assert_eq!("4512", p1) assert_eq!("4512", p1);
Ok(())
} }
#[test] #[test]
fn part2_test() { fn part2_test() -> Result<()> {
let t = Day04::init(INPUT.to_string()); let t = Day04::init(INPUT.to_string())?;
let p2 = t.part2(); let p2 = t.part2()?;
assert_eq!("1924", p2) assert_eq!("1924", p2);
Ok(())
} }
#[test] #[test]
fn part1_real() { fn part1_real() -> Result<()> {
let f = read_to_string("./input/day04").expect("Could not load input"); let f = read_to_string("./input/day04")?;
let t = Day04::init(f); let t = Day04::init(f)?;
let p1 = t.part1(); let p1 = t.part1()?;
assert_eq!("8136", p1) assert_eq!("8136", p1);
Ok(())
} }
#[test] #[test]
fn part2_real() { fn part2_real() -> Result<()> {
let f = read_to_string("./input/day04").expect("Could not load input"); let f = read_to_string("./input/day04")?;
let t = Day04::init(f); let t = Day04::init(f)?;
let p2 = t.part2(); let p2 = t.part2()?;
assert_eq!("12738", p2) assert_eq!("12738", p2);
Ok(())
} }
} }

View File

@ -1,10 +1,9 @@
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::HashMap; use std::collections::HashMap;
use crate::Day; use crate::Day;
use anyhow::Result;
pub struct Day05 { pub struct Day05(Vec<Path>);
vents: Vec<Path>,
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)] #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
struct Path { struct Path {
@ -20,20 +19,18 @@ struct Coordinate {
} }
impl Day for Day05 { impl Day for Day05 {
fn init(content: String) -> Self { fn init(content: String) -> Result<Self> {
let paths = content.lines().map(str_to_vent).collect::<Vec<Path>>(); let paths = content.lines().map(str_to_vent).collect::<Result<Vec<Path>, _>>()?;
Self { Ok(Self(paths))
vents: paths,
}
} }
fn part1(&self) -> String { fn part1(&self) -> Result<String> {
let new_vents = self.vents.iter().filter(|p| p.is_straight()).cloned().collect::<Vec<Path>>(); let new_vents = self.0.iter().filter(|p| p.is_straight()).cloned().collect::<Vec<Path>>();
format!("{}", covered_twice(&new_vents)) Ok(format!("{}", covered_twice(&new_vents)))
} }
fn part2(&self) -> String { fn part2(&self) -> Result<String> {
format!("{}", covered_twice(&self.vents)) Ok(format!("{}", covered_twice(&self.0)))
} }
} }
@ -115,12 +112,12 @@ impl Direction {
} }
} }
fn str_to_vent(st: &str) -> Path { fn str_to_vent(st: &str) -> Result<Path> {
let mut v = st.split(" -> "); let mut v = st.split(" -> ");
let a = v.next().unwrap(); let a = v.next().ok_or_else(|| anyhow::Error::msg("could not get next..."))?;
let b = v.next().unwrap(); let b = v.next().ok_or_else(|| anyhow::Error::msg("could not get next..."))?;
let start = a.split(',').map(|x| x.parse().unwrap()).collect::<Vec<i64>>(); let start = a.split(',').map(str::parse).collect::<Result<Vec<i64>,_>>()?;
let end = b.split(',').map(|x| x.parse().unwrap()).collect::<Vec<i64>>(); let end = b.split(',').map(str::parse).collect::<Result<Vec<i64>,_>>()?;
let start = Coordinate::from_vec(&start); let start = Coordinate::from_vec(&start);
let end = Coordinate::from_vec(&end); let end = Coordinate::from_vec(&end);
@ -135,11 +132,11 @@ fn str_to_vent(st: &str) -> Path {
} }
covers.push(end.clone()); covers.push(end.clone());
Path { Ok(Path {
start, start,
end, end,
covers, covers,
} })
} }
#[cfg(test)] #[cfg(test)]
@ -147,6 +144,7 @@ mod tests {
use crate::Day05; use crate::Day05;
use crate::day05::{Coordinate, Direction}; use crate::day05::{Coordinate, Direction};
use crate::day::Day; use crate::day::Day;
use anyhow::Result;
const INPUT: &str = r"0,9 -> 5,9 const INPUT: &str = r"0,9 -> 5,9
8,0 -> 0,8 8,0 -> 0,8
@ -172,26 +170,30 @@ mod tests {
} }
#[test] #[test]
fn part1_test() { fn part1_test() -> Result<()> {
let d = Day05::init(INPUT.to_string()); let d = Day05::init(INPUT.to_string())?;
assert_eq!("5", d.part1()); assert_eq!("5", d.part1()?);
Ok(())
} }
#[test] #[test]
fn part2_test() { fn part2_test() -> Result<()> {
let d = Day05::init(INPUT.to_string()); let d = Day05::init(INPUT.to_string())?;
assert_eq!("12", d.part2()); assert_eq!("12", d.part2()?);
Ok(())
} }
#[test] #[test]
fn part1_real() { fn part1_real() -> Result<()> {
let d = Day05::init(crate::load_input("05")); let d = Day05::init(crate::load_input("05")?)?;
assert_eq!("6564", d.part1()); assert_eq!("6564", d.part1()?);
Ok(())
} }
#[test] #[test]
fn part2_real() { fn part2_real() -> Result<()> {
let d = Day05::init(crate::load_input("05")); let d = Day05::init(crate::load_input("05")?)?;
assert_eq!("19172", d.part2()); assert_eq!("19172", d.part2()?);
Ok(())
} }
} }

View File

@ -1,23 +1,24 @@
use crate::Day; use crate::Day;
use anyhow::Result;
pub struct Day06([u64; 9]); pub struct Day06([u64; 9]);
impl Day for Day06 { impl Day for Day06 {
fn init(content: String) -> Self { fn init(content: String) -> anyhow::Result<Self> {
let c = content.split(',').map(|x| x.parse().expect("This is not an int!")).collect::<Vec<usize>>(); let c = content.split(',').map(str::parse).collect::<Result<Vec<usize>, _>>()?;
let mut w: [u64; 9] = [0, 0, 0, 0, 0, 0, 0, 0, 0]; let mut w: [u64; 9] = [0, 0, 0, 0, 0, 0, 0, 0, 0];
for z in c { for z in c {
w[z as usize] += 1; w[z as usize] += 1;
} }
Self(w) Ok(Self(w))
} }
fn part1(&self) -> String { fn part1(&self) -> Result<String> {
format!("{}", self.do_magic(80)) Ok(format!("{}", self.do_magic(80)))
} }
fn part2(&self) -> String { fn part2(&self) -> Result<String> {
format!("{}", self.do_magic(256)) Ok(format!("{}", self.do_magic(256)))
} }
} }
@ -35,30 +36,42 @@ impl Day06 {
mod tests { mod tests {
use crate::day06::Day06; use crate::day06::Day06;
use crate::day::Day; use crate::day::Day;
use anyhow::Result;
const INPUT: &str = r"3,4,3,1,2"; const INPUT: &str = r"3,4,3,1,2";
#[test] #[test]
fn part1_test() { fn part1_test() -> Result<()> {
let d = Day06::init(INPUT.to_string()); let d = Day06::init(INPUT.to_string())?;
assert_eq!("5934", d.part1()); assert_eq!("5934", d.part1()?);
Ok(())
} }
#[test] #[test]
fn part2_test() { fn part2_test() -> Result<()> {
let d = Day06::init(INPUT.to_string()); let d = Day06::init(INPUT.to_string())?;
assert_eq!("26984457539", d.part2()); assert_eq!("26984457539", d.part2()?);
Ok(())
} }
#[test] #[test]
fn part1_real() { fn part1_real() -> Result<()> {
let d = Day06::init(crate::load_input("06")); let d = Day06::init(crate::load_input("06")?)?;
assert_eq!("362740", d.part1()); assert_eq!("362740", d.part1()?);
Ok(())
} }
#[test] #[test]
fn part2_real() { fn part2_real() -> Result<()> {
let d = Day06::init(crate::load_input("06")); let d = Day06::init(crate::load_input("06")?)?;
assert_eq!("1644874076764", d.part2()); assert_eq!("1644874076764", d.part2()?);
Ok(())
}
#[test]
fn youri_test() -> Result<()> {
let d = Day06::init(String::from("3,4,3,1,2"))?;
assert_eq!(17614907331943978900, d.do_magic(489));
Ok(())
} }
} }

View File

@ -1,30 +1,31 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::Day; use crate::Day;
use anyhow::Result;
pub struct Day07(HashMap<i32, i32>); pub struct Day07(HashMap<i32, i32>);
impl Day for Day07 { impl Day for Day07 {
fn init(content: String) -> Self { fn init(content: String) -> Result<Self> {
let mut hm = HashMap::new(); let mut hm = HashMap::new();
for n in &content.split(',').map(|x| x.parse().expect("This is not a number?")).collect::<Vec<_>>() { for n in &content.split(',').map(str::parse).collect::<Result<Vec<_>, std::num::ParseIntError>>()? {
let entry = hm.entry(*n).or_insert(0); let entry = hm.entry(*n).or_insert(0);
*entry += 1; *entry += 1;
} }
Self(hm) Ok(Self(hm))
} }
fn part1(&self) -> String { fn part1(&self) -> Result<String> {
let m = self.0.keys().copied().map( let m = self.0.keys().copied().map(
|x| self.0.iter().map( |x| self.0.iter().map(
|(n, count)| (x - *n).abs() * (*count) |(n, count)| (x - *n).abs() * (*count)
).sum::<i32>() ).sum::<i32>()
).min().expect("there is no min?"); ).min().ok_or_else(|| anyhow::Error::msg("Could not find min"))?;
format!("{}", m) Ok(format!("{}", m))
} }
fn part2(&self) -> String { fn part2(&self) -> Result<String> {
let max = *self.0.keys().max().expect("This should have a value..."); let max = *self.0.keys().max().ok_or_else(|| anyhow::Error::msg("Could not find max"))?;
let m = (0..=max).map( let m = (0..=max).map(
|x| self.0.iter().map( |x| self.0.iter().map(
|(n, count)| { |(n, count)| {
@ -32,8 +33,8 @@ impl Day for Day07 {
(n * (n + 1) / 2) * (*count) (n * (n + 1) / 2) * (*count)
} }
).sum::<i32>() ).sum::<i32>()
).min().expect("there is no min?"); ).min().ok_or_else(|| anyhow::Error::msg("Could not find min"))?;
format!("{}", m) Ok(format!("{}", m))
} }
} }
@ -41,30 +42,35 @@ impl Day for Day07 {
mod tests { mod tests {
use crate::day07::Day07; use crate::day07::Day07;
use crate::day::Day; use crate::day::Day;
use anyhow::Result;
const INPUT: &str = "16,1,2,0,4,2,7,1,2,14"; const INPUT: &str = "16,1,2,0,4,2,7,1,2,14";
#[test] #[test]
fn part1_test() { fn part1_test() -> Result<()> {
let d = Day07::init(INPUT.to_string()); let d = Day07::init(INPUT.to_string())?;
assert_eq!("37", d.part1()) assert_eq!("37", d.part1()?);
Ok(())
} }
#[test] #[test]
fn part2_test() { fn part2_test() -> Result<()> {
let d = Day07::init(INPUT.to_string()); let d = Day07::init(INPUT.to_string())?;
assert_eq!("168", d.part2()) assert_eq!("168", d.part2()?);
Ok(())
} }
#[test] #[test]
fn part1_real() { fn part1_real() -> Result<()> {
let d = Day07::init(crate::load_input("07")); let d = Day07::init(crate::load_input("07")?)?;
assert_eq!("357353", d.part1()) assert_eq!("357353", d.part1()?);
Ok(())
} }
#[test] #[test]
fn part2_real() { fn part2_real() -> Result<()> {
let d = Day07::init(crate::load_input("07")); let d = Day07::init(crate::load_input("07")?)?;
assert_eq!("104822130", d.part2()) assert_eq!("104822130", d.part2()?);
Ok(())
} }
} }

View File

@ -9,6 +9,7 @@ use crate::day05::Day05;
use crate::day06::Day06; use crate::day06::Day06;
use crate::day07::Day07; use crate::day07::Day07;
use crate::day::Day; use crate::day::Day;
use anyhow::Result;
mod day; mod day;
mod day01; mod day01;
@ -19,22 +20,23 @@ mod day05;
mod day06; mod day06;
mod day07; mod day07;
fn load_input(day: &str) -> String { fn load_input(day: &str) -> Result<String> {
read_to_string(format!("./input/day{}", day)).expect("Could not load input") read_to_string(format!("./input/day{}", day)).map_err(|x| x.into())
} }
fn run_day(days: &[Box<dyn Day>], day: usize) { fn run_day(days: &[Box<dyn Day>], day: usize) -> Result<()> {
if let Some(d) = days.get(day - 1) { if let Some(d) = days.get(day - 1) {
let day_code = d; let day_code = d;
println!("Running day {}!", day); println!("Running day {}!", day);
println!("\tPart 1: {}", d.part1()); println!("\tPart 1: {}", d.part1()?);
println!("\tPart 2: {}", day_code.part2()); println!("\tPart 2: {}", day_code.part2()?);
} else { } else {
eprintln!("Day {} is not available!", day); eprintln!("Day {} is not available!", day);
} }
Ok(())
} }
fn main() { fn main() -> anyhow::Result<()> {
let matches = App::new("AOC Time!") let matches = App::new("AOC Time!")
.version("1.0") .version("1.0")
.author("J00LZ") .author("J00LZ")
@ -52,31 +54,32 @@ fn main() {
.multiple(true)) .multiple(true))
.get_matches(); .get_matches();
let days: Vec<Box<dyn Day>> = vec![Box::new(Day01::init(load_input("01"))), let days: Vec<Box<dyn Day>> = vec![Box::new(Day01::init(load_input("01")?)?),
Box::new(Day02::init(load_input("02"))), Box::new(Day02::init(load_input("02")?)?),
Box::new(Day03::init(load_input("03"))), Box::new(Day03::init(load_input("03")?)?),
Box::new(Day04::init(load_input("04"))), Box::new(Day04::init(load_input("04")?)?),
Box::new(Day05::init(load_input("05"))), Box::new(Day05::init(load_input("05")?)?),
Box::new(Day06::init(load_input("06"))), Box::new(Day06::init(load_input("06")?)?),
Box::new(Day07::init(load_input("07")))]; Box::new(Day07::init(load_input("07")?)?)];
let _verbosity = matches.occurrences_of("v"); let _verbosity = matches.occurrences_of("v");
if matches.is_present("all") { if matches.is_present("all") {
let l = days.len(); let l = days.len();
println!("running {} days!", l); println!("running {} days!", l);
for v in 1..=l { for v in 1..=l {
run_day(&days, v); run_day(&days, v)?;
} }
} else if let Some(d) = matches.values_of("DAY") { } else if let Some(d) = matches.values_of("DAY") {
let d = d.map(|x| x.parse::<usize>().expect("Did not provide an int!")); let d = d.map(str::parse);
for v in d { for v in d {
run_day(&days, v); run_day(&days, v?)?;
} }
} else { } else {
let v = chrono::Local::now(); let v = chrono::Local::now();
if v.month() != 12 { if v.month() != 12 {
println!("This was really only meant to be used in december..."); println!("This was really only meant to be used in december...");
} }
run_day(&days, v.day() as usize); run_day(&days, v.day() as usize)?;
} }
Ok(())
} }