diff options
Diffstat (limited to 'src/bin')
-rw-r--r-- | src/bin/day_1.rs | 80 |
1 files changed, 33 insertions, 47 deletions
diff --git a/src/bin/day_1.rs b/src/bin/day_1.rs index 7c8f104..b9a6c18 100644 --- a/src/bin/day_1.rs +++ b/src/bin/day_1.rs @@ -1,57 +1,56 @@ +use derive_more; use std::io; use std::io::prelude::*; use std::iter; -use std::iter::Sum; -use std::num::ParseIntError; -use std::ops::Add; -use std::str::FromStr; + +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +#[structopt(name = "Day 1: The Tyranny of the Rocket Equation")] +/// Calculates the fuel needed for your rocket to save Santa. +/// +/// The weight of each module is read from stdin, one module weight +/// per line. See https://adventofcode.com/2019/day/1 for details. +struct Opt { + /// Includes the weight of flue + #[structopt(short = "i", long = "include-fuel-weight")] + include_fuel_weight: bool, +} fn main() { let stdin = io::stdin(); + let opt = Opt::from_args(); let input = stdin .lock() .lines() .map(|l| l.unwrap().parse::<Module>().unwrap()); - dbg!(fuel_required(input)); + println!("{}", fuel_required(input, opt.include_fuel_weight)) } -// TODO: If this were a nice CLI program, it would probably have a switch to choose between these two rather than doing both? -fn fuel_required(it: impl Iterator<Item = Module>) -> (Fuel, Fuel) { - it.map(|m| { - ( - m.fuel_excluding_fuel_weight(), - m.fuel_including_fuel_weight(), - ) - }) - .fold((Fuel(0), Fuel(0)), |(sum_x, sum_y), (x, y)| { - (sum_x + x, sum_y + y) +fn fuel_required(it: impl Iterator<Item = Module>, include_fuel_weight: bool) -> Fuel { + it.map(if include_fuel_weight { + Module::fuel_including_fuel_weight + } else { + Module::fuel_excluding_fuel_weight }) + .sum() } +#[derive(Debug, derive_more::FromStr, Clone, Copy)] struct Module { weight: Weight, } -impl FromStr for Module { - type Err = ParseIntError; - - fn from_str(s: &str) -> Result<Self, Self::Err> { - Ok(Module { - weight: Weight(s.parse()?), - }) - } -} - impl Module { - fn fuel_excluding_fuel_weight(&self) -> Fuel { + fn fuel_excluding_fuel_weight(self) -> Fuel { self.weight.required_fuel() } - fn fuel_including_fuel_weight(&self) -> Fuel { + fn fuel_including_fuel_weight(self) -> Fuel { iter::successors(Some(self.weight.required_fuel()), |fuel| { - if fuel.weight().is_zero() { + if fuel.is_zero() { None } else { Some(fuel.weight().required_fuel()) @@ -61,37 +60,24 @@ impl Module { } } +#[derive(Debug, derive_more::FromStr, Clone, Copy)] struct Weight(u32); impl Weight { - fn is_zero(&self) -> bool { - self.0 == 0 - } - - fn required_fuel(&self) -> Fuel { + fn required_fuel(self) -> Fuel { Fuel((self.0 / 3).saturating_sub(2)) } } -#[derive(Debug)] +#[derive(Debug, derive_more::Add, derive_more::Sum, Clone, Copy, derive_more::Display)] struct Fuel(u32); impl Fuel { - fn weight(&self) -> Weight { + fn weight(self) -> Weight { Weight(self.0) } -} - -impl Add for Fuel { - type Output = Self; - - fn add(self, other: Self) -> Self { - Fuel(self.0 + other.0) - } -} -impl Sum for Fuel { - fn sum<I: Iterator<Item = Self>>(iter: I) -> Self { - iter.fold(Fuel(0), Add::add) + fn is_zero(self) -> bool { + self.0 == 0 } } |