use std::fmt; use std::io; use std::io::prelude::*; use std::process; use std::str::FromStr; use structopt::StructOpt; #[derive(Debug, StructOpt)] #[structopt(name = "Day 6: Universal Orbit Map")] /// Counts the total number of direct and indirect orbits between planets. /// /// Input is read from stdin, one direct orbit per line, in the format /// `A)B` (B is orbiting A). /// /// See https://adventofcode.com/2019/day/6 for details. struct Opt {} fn main() { let stdin = io::stdin(); let opt = Opt::from_args(); let orbits = stdin .lock() .lines() .map(|x| exit_on_failed_assertion(x, "Error reading input")) .map(|x| exit_on_failed_assertion(x.parse::(), "Input was not a valid orbit")); println!("{}", count_orbits(orbits)); } fn exit_on_failed_assertion(data: Result, message: &str) -> A { match data { Ok(data) => data, Err(e) => { eprintln!("{}: {}", message, e); process::exit(1); } } } #[derive(Debug)] struct StrError { str: String, } impl fmt::Display for StrError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.str) } } impl std::error::Error for StrError {} struct Orbit { a: String, b: String, } impl FromStr for Orbit { type Err = StrError; fn from_str(s: &str) -> Result { match s.split(')').collect::>()[..] { [a, b] => Ok(Orbit { a: a.to_string(), b: b.to_string(), }), _ => Err(StrError { str: format!("{} is not a valid orbit description", s), }), } } } fn count_orbits(it: impl Iterator) -> usize { // TODO 0 }