1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use clap::Parser;
use rustutils_runnable::Runnable;
use std::error::Error;
#[derive(Parser, Clone, Debug)]
#[clap(author, version, about, long_about = None)]
pub struct Factor {
#[clap(short, long)]
unique: bool,
#[clap(short, long)]
json: bool,
number: Vec<u64>,
}
#[derive(thiserror::Error, Debug)]
pub enum StdinError {
#[error("Error reading a line from standard input: {0:}")]
ReadingLine(#[from] std::io::Error),
#[error("Error parsing {0:?} as a number: {1:}")]
ParsingNumber(String, std::num::ParseIntError),
}
impl Factor {
pub fn run(&self) -> Result<(), Box<dyn Error>> {
if self.json {
let mut output = std::collections::BTreeMap::new();
self.handle(|num, factors| {
output.insert(num.to_string(), factors.to_vec());
})?;
println!("{}", serde_json::to_string(&output)?);
} else {
self.handle(|num, factors| {
let factors: String = factors.iter().map(|factor| format!(" {factor}")).collect();
println!("{num}:{}", factors);
})?;
}
Ok(())
}
pub fn handle(&self, callback: impl FnMut(u64, &[u64])) -> Result<(), Box<dyn Error>> {
if self.number.is_empty() {
self.handle_stdin(callback)?;
} else {
self.handle_numbers(callback);
}
Ok(())
}
pub fn handle_numbers(&self, mut callback: impl FnMut(u64, &[u64])) {
for number in &self.number {
let factors = self.factor(*number);
callback(*number, &factors);
}
}
pub fn handle_stdin(&self, mut callback: impl FnMut(u64, &[u64])) -> Result<(), StdinError> {
let stdin = std::io::stdin();
for line in stdin.lines() {
let line = line.map_err(|e| StdinError::ReadingLine(e))?;
let number: u64 = line
.parse()
.map_err(|e| StdinError::ParsingNumber(line, e))?;
let factors = self.factor(number);
callback(number, &factors);
}
Ok(())
}
pub fn factor(&self, number: u64) -> Vec<u64> {
if self.unique {
primes::factors_uniq(number)
} else {
primes::factors(number)
}
}
}
impl Runnable for Factor {
fn run(&self) -> Result<(), Box<dyn Error>> {
self.run()?;
Ok(())
}
}