#![feature(stmt_expr_attributes)]
use clap::{load_yaml, App, ArgMatches};
use failure::Error;
use std::num::ParseIntError;
use acm::divisors::divisors;
use acm::factor::factor;
use acm::ArithmeticCongruenceMonoid as ACM;
fn req_arg(matches: &ArgMatches, arg: &'static str) -> Result<u64, ParseIntError> {
matches.value_of(arg).unwrap().parse()
}
fn opt_arg(matches: &ArgMatches, arg: &'static str, default: u64) -> Result<u64, ParseIntError> {
matches.value_of(arg).map_or(Ok(default), |arg| arg.parse())
}
fn cli() -> Result<(), Error> {
let yaml = load_yaml!("acm-cli.yml");
let matches = App::from_yaml(yaml).get_matches();
let subcommand = matches.subcommand_name().unwrap();
let matches = matches.subcommand_matches(subcommand).unwrap();
match subcommand {
"factor" => println!("{:?}", factor(req_arg(&matches, "n")?)),
"divisors" => println!("{:?}", divisors(req_arg(&matches, "n")?)),
"acm" => {
let a = req_arg(&matches, "a")?;
let b = req_arg(&matches, "b")?;
let mut acm: ACM<u64> = ACM::new(a, b)?;
let subcommand = matches.subcommand_name().unwrap();
let matches = matches.subcommand_matches(subcommand).unwrap();
let n = req_arg(&matches, "n")?;
match subcommand {
"nearest" => println!("{}", acm.nearest(n)),
"nth" => println!("{}", acm.ith(n)),
"contains" => println!("{}", acm.contains(&n)),
"factor" => println!("{:?}", acm.factor(n)),
"divisors" => println!("{:?}", acm.divisors(n)),
"atomic" => println!("{}", acm.atomic(&n)),
"n_elements" => println!(
"{:?}",
acm.iter()
.take(opt_arg(&matches, "s", a)? as usize)
.collect::<Vec<u64>>()
),
"n_atoms" => println!(
"{:?}",
acm.iter()
.filter(|x| acm.atomic(x))
.take(opt_arg(&matches, "s", a)? as usize)
.collect::<Vec<u64>>()
),
"n_reducibles" => println!(
"{:?}",
acm.iter()
.filter(|x| !acm.atomic(x))
.take(opt_arg(&matches, "s", a)? as usize)
.collect::<Vec<u64>>()
),
_ => unreachable!(),
}
}
_ => unreachable!(),
}
Ok(())
}
fn main() {
if let Err(err) = cli() {
println!("Error: {:?}", err);
}
}