euler/src/bin/problem_26.rs

142 lines
4.1 KiB
Rust

use std::collections::{HashMap, HashSet};
use utils::{
fraction::Fraction,
number::{Number, Sign},
};
fn main() {
println!("Start");
let mut longest = (0, 0);
for denominator in 2..1000 {
let f = Fraction::new(1.into(), denominator.into()).unwrap();
if let Some(rep) = get_recurring(&f) {
if longest.1 < rep.digits.len() {
longest = (denominator, rep.digits.len());
}
}
}
println!("longest {}", longest.0);
}
pub fn get_recurring(fraction: &Fraction) -> Option<Number> {
let mut div_memory = HashMap::new();
let mut rem_memory = HashSet::new();
rem_memory.insert(1.into());
let mut div_with = fraction.numerator.clone();
let mut rational = Vec::new();
if div_with < fraction.denominator {
div_with = div_with * 10;
}
loop {
while div_with < fraction.denominator {
rational.push(0);
div_memory
.entry(0)
.and_modify(|value| *value += 1)
.or_insert(1);
div_with = div_with * 10;
rem_memory.insert(div_with.clone());
}
let (div, rem) =
Number::div_with_rem(div_with.clone(), fraction.denominator.clone()).unwrap();
if rem == 0.into() {
return None;
}
let next_digit = div.digits[0];
if div_memory.contains_key(&next_digit) && rem_memory.contains(&rem) && next_digit != 0 {
let mut digits = vec![];
if div_memory.values().min() != div_memory.values().max() {
rational.push(div.digits[0]);
digits = rational;
let (l, r) = digits.split_at(digits.len() / 2);
if l == r {
digits = l.to_vec();
}
} else {
let idx = rational
.iter()
.position(|digit| digit == &div.digits[0])
.unwrap();
if idx == rational.len() - 1 {
digits.push(div.digits[0]);
} else {
for digit in &rational[idx..] {
if digits.contains(digit) {
break;
}
digits.push(*digit);
}
}
}
return Some(Number {
digits,
sign: Sign::Positif,
});
}
div_memory
.entry(next_digit)
.and_modify(|count| *count += 1)
.or_insert(1);
rem_memory.insert(rem.clone());
rational.push(div.digits[0]);
div_with = rem * 10;
}
}
#[cfg(test)]
mod test {
use utils::{fraction::Fraction, number::Number};
use crate::get_recurring;
#[test]
fn test_1_div_2() {
let f = Fraction::new(1.into(), 2.into()).unwrap();
let rep = get_recurring(&f);
assert_eq!(rep, None);
}
#[test]
fn test_1_div_6() {
let f = Fraction::new(1.into(), 6.into()).unwrap();
let rep = get_recurring(&f);
assert_eq!(rep, Some(Number::from("6")));
}
#[test]
fn test_1_div_7() {
let f = Fraction::new(1.into(), 7.into()).unwrap();
let rep = get_recurring(&f);
assert_eq!(rep, Some(Number::from("142857")));
}
#[test]
fn test_1_div_11() {
let f = Fraction::new(1.into(), 11.into()).unwrap();
let rep = get_recurring(&f);
assert_eq!(rep, Some(Number::from("09")));
}
#[test]
fn test_1_div_12() {
let f = Fraction::new(1.into(), 12.into()).unwrap();
let rep = get_recurring(&f);
assert_eq!(rep, Some(Number::from("3")));
}
#[test]
fn test_1_div_14() {
let f = Fraction::new(1.into(), 14.into()).unwrap();
let rep = get_recurring(&f);
assert_eq!(rep, Some(Number::from("714285")));
}
#[test]
fn test_1_div_101() {
let f = Fraction::new(1.into(), 101.into()).unwrap();
let rep = get_recurring(&f);
assert_eq!(rep, Some(Number::from("0099")));
}
}