use std::fmt::{Display, Formatter};
use num_bigint::BigInt;
use serde::{Deserialize, Serialize};
use crate::utils::{deserialize_string_to_bigint, deserialize_u64_to_bigint};
#[derive(Deserialize, Serialize, Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Factor(
#[serde(deserialize_with = "deserialize_string_to_bigint")] BigInt,
#[serde(deserialize_with = "deserialize_u64_to_bigint")] BigInt,
);
impl Factor {
pub fn base(&self) -> &BigInt {
&self.0
}
pub fn exponent(&self) -> &BigInt {
&self.1
}
pub fn iter(&self) -> Iter {
Iter {
base: &self.0,
remaining_exp: self.1.clone(),
}
}
}
impl Display for Factor {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
self.iter()
.map(|n| n.to_string())
.collect::<Vec<_>>()
.join(" ")
)
}
}
impl IntoIterator for Factor {
type Item = BigInt;
type IntoIter = IntoIter;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
base: self.0,
remaining_exp: self.1,
}
}
}
pub struct Iter<'f> {
base: &'f BigInt,
remaining_exp: BigInt,
}
impl<'f> Iterator for Iter<'f> {
type Item = &'f BigInt;
fn next(&mut self) -> Option<Self::Item> {
if self.remaining_exp > BigInt::from(0) {
self.remaining_exp -= 1;
Some(self.base)
} else {
None
}
}
}
pub struct IntoIter {
base: BigInt,
remaining_exp: BigInt,
}
impl Iterator for IntoIter {
type Item = BigInt;
fn next(&mut self) -> Option<Self::Item> {
if self.remaining_exp > BigInt::from(0) {
self.remaining_exp -= 1;
Some(self.base.clone())
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_factor_iter() {
let a_million = Factor(BigInt::from(10), BigInt::from(6));
assert_eq!(
a_million.iter().product::<BigInt>(),
BigInt::from(1_000_000)
);
assert_eq!(
a_million.iter().cloned().collect::<Vec<_>>(),
vec![
BigInt::from(10),
BigInt::from(10),
BigInt::from(10),
BigInt::from(10),
BigInt::from(10),
BigInt::from(10)
]
)
}
#[test]
fn test_factor_into_iter() {
let a_million = Factor(BigInt::from(10), BigInt::from(6));
assert_eq!(
a_million.clone().into_iter().product::<BigInt>(),
BigInt::from(1_000_000)
);
assert_eq!(
a_million.into_iter().collect::<Vec<_>>(),
vec![
BigInt::from(10),
BigInt::from(10),
BigInt::from(10),
BigInt::from(10),
BigInt::from(10),
BigInt::from(10)
]
)
}
}