From 9892e3ebde304726903a1e5c358d05c2e343ea5e Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Tue, 19 Apr 2022 20:26:36 +0200 Subject: Refile for merging repos --- 2019/src/bin/day_1.rs | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 2019/src/bin/day_1.rs (limited to '2019/src/bin/day_1.rs') 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::() { + 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, 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 + } +} -- cgit v1.2.3