use crate::Cmd; use clap::{value_parser, Arg, ArgMatches, Command}; use std::{ error::Error, io::{self, BufRead}, }; #[derive(Debug)] pub struct Factor { name: &'static str, path: Option, } pub const FACTOR: Factor = Factor { name: "factor", path: Some(crate::Path::UsrBin), }; impl Cmd for Factor { fn name(&self) -> &str { self.name } fn cli(&self) -> Command { Command::new("factor") .about("factor numbers") .after_help( "Print the prime factors of each specified integer NUMBER. If none are\n\ specified on the command line, read them from standard input.", ) .arg( Arg::new("number") .help("the numbers to factor") .num_args(0..) .value_parser(value_parser!(u64)), ) } fn run(&self, matches: Option<&ArgMatches>) -> Result<(), Box> { if let Some(matches) = matches { match matches.get_many::("number") { Some(numbers) => { numbers.for_each(|n| print_factors(*n)); } None => { for line in io::stdin().lock().lines() { for num in line?.split_whitespace() { print_factors(num.parse()?); } } } } } Ok(()) } fn path(&self) -> Option { self.path } } fn first_factor(num: u64) -> u64 { if crate::math::is_prime(num) { return num; } for n in 2..=num { if num % n == 0 { return n; } } num } fn print_factors(num: u64) { print!("{num}:"); let mut n = num; loop { let f = first_factor(n); print!(" {f}"); if f == n { break; } n /= f; } println!(); }