use clap::{Arg, ArgMatches, Command, value_parser}; use crate::Cmd; 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 value in line.unwrap().split_whitespace() { let num: u64 = value.parse()?; print_factors(num); } } }, } } Ok(()) } fn path(&self) -> Option { self.path } } fn is_prime(num: u64) -> bool { match num { 0 | 1 => false, 2 | 3 | 5 | 7 | 11 | 13 => true, x if x % 2 == 0 => false, _ => { let mut x: u64 = 2; while x < num / 2 { if num % x == 0 { return false; } x += 1; } true } } } fn print_factors(num: u64) { print!("{num}:"); for n in 2..=num / 2 { if num % n == 0 && is_prime(n) { print!(" {n}"); } } println!(); }