shitbox/src/cmd/factor/mod.rs

75 lines
1.8 KiB
Rust
Raw Normal View History

use super::Cmd;
2023-01-03 19:47:00 -05:00
use clap::{value_parser, Arg, ArgMatches, Command};
use std::{
error::Error,
io::{self, BufRead},
};
2023-01-03 12:49:09 -05:00
#[derive(Debug, Default)]
pub struct Factor;
2023-01-03 12:49:09 -05:00
impl Cmd for Factor {
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\
2023-01-03 19:47:00 -05:00
specified on the command line, read them from standard input.",
2023-01-03 12:49:09 -05:00
)
.arg(
Arg::new("number")
.help("the numbers to factor")
.num_args(0..)
2023-01-03 19:47:00 -05:00
.value_parser(value_parser!(u64)),
2023-01-03 12:49:09 -05:00
)
}
fn run(&self, matches: Option<&ArgMatches>) -> Result<(), Box<dyn Error>> {
if let Some(matches) = matches {
match matches.get_many::<u64>("number") {
Some(numbers) => {
numbers.for_each(|n| print_factors(*n));
2023-01-03 19:47:00 -05:00
}
2023-01-03 12:49:09 -05:00
None => {
for line in io::stdin().lock().lines() {
2023-01-03 19:47:00 -05:00
for num in line?.split_whitespace() {
print_factors(num.parse()?);
2023-01-03 12:49:09 -05:00
}
}
2023-01-03 19:47:00 -05:00
}
2023-01-03 12:49:09 -05:00
}
}
Ok(())
}
fn path(&self) -> Option<crate::Path> {
Some(crate::Path::UsrBin)
2023-01-03 12:49:09 -05:00
}
}
2023-01-03 19:47:00 -05:00
fn first_factor(num: u64) -> u64 {
if num % 2 == 0 {
return 2;
2023-01-03 19:47:00 -05:00
}
for n in (3..=num).step_by(1) {
2023-01-03 19:47:00 -05:00
if num % n == 0 {
return n;
2023-01-03 12:49:09 -05:00
}
}
2023-01-03 19:47:00 -05:00
num
2023-01-03 12:49:09 -05:00
}
fn print_factors(num: u64) {
print!("{num}:");
2023-01-03 19:47:00 -05:00
let mut n = num;
loop {
let f = first_factor(n);
print!(" {f}");
if f == n {
break;
2023-01-03 12:49:09 -05:00
}
2023-01-03 19:47:00 -05:00
n /= f;
2023-01-03 12:49:09 -05:00
}
println!();
}