No more expect, we use Result now
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
605921453d
commit
c75d35d80d
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -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",
|
||||||
]
|
]
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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>;
|
||||||
}
|
}
|
47
src/day01.rs
47
src/day01.rs
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
56
src/day02.rs
56
src/day02.rs
|
@ -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()?))
|
||||||
}
|
}
|
||||||
}
|
}
|
54
src/day03.rs
54
src/day03.rs
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
62
src/day04.rs
62
src/day04.rs
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
66
src/day05.rs
66
src/day05.rs
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
51
src/day06.rs
51
src/day06.rs
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
50
src/day07.rs
50
src/day07.rs
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
37
src/main.rs
37
src/main.rs
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue