diff options
author | Justin Wernick <justin@worthe-it.co.za> | 2022-04-19 20:26:36 +0200 |
---|---|---|
committer | Justin Wernick <justin@worthe-it.co.za> | 2022-04-19 20:26:36 +0200 |
commit | 9892e3ebde304726903a1e5c358d05c2e343ea5e (patch) | |
tree | 404004f8d2131fa8d1e7524c6707a3ecdb0b44e0 /2019/src/bin/day_1.rs | |
parent | 48a9be141afadaa24182781a2db58594cb2ce522 (diff) |
Refile for merging repos
Diffstat (limited to '2019/src/bin/day_1.rs')
-rw-r--r-- | 2019/src/bin/day_1.rs | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/2019/src/bin/day_1.rs b/2019/src/bin/day_1.rs new file mode 100644 index 0000000..572d287 --- /dev/null +++ b/2019/src/bin/day_1.rs @@ -0,0 +1,93 @@ +use derive_more; +use std::io; +use std::io::prelude::*; +use std::iter; +use std::process; + +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 fuel + #[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| match l { + Ok(s) => match s.parse::<Module>() { + Ok(module) => module, + Err(e) => { + eprintln!("Invalid input \"{}\": {}", s, e); + process::exit(1); + } + }, + Err(e) => { + eprintln!("Error reading input: {}", e); + process::exit(1); + } + }); + + println!("{}", fuel_required(input, opt.include_fuel_weight)) +} + +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 Module { + fn fuel_excluding_fuel_weight(self) -> Fuel { + self.weight.required_fuel() + } + + fn fuel_including_fuel_weight(self) -> Fuel { + iter::successors(Some(self.weight.required_fuel()), |fuel| { + if fuel.is_zero() { + None + } else { + Some(fuel.weight().required_fuel()) + } + }) + .sum() + } +} + +#[derive(Debug, derive_more::FromStr, Clone, Copy)] +struct Weight(u32); + +impl Weight { + fn required_fuel(self) -> Fuel { + Fuel((self.0 / 3).saturating_sub(2)) + } +} + +#[derive(Debug, derive_more::Add, derive_more::Sum, Clone, Copy, derive_more::Display)] +struct Fuel(u32); + +impl Fuel { + fn weight(self) -> Weight { + Weight(self.0) + } + + fn is_zero(self) -> bool { + self.0 == 0 + } +} |