Skip to content

Commit

Permalink
Attempt to make p357 not slow
Browse files Browse the repository at this point in the history
  • Loading branch information
LivInTheLookingGlass committed Aug 22, 2024
1 parent 1a7b254 commit e3c1f9b
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 3 deletions.
71 changes: 71 additions & 0 deletions rust/src/include/factors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use std::collections::HashSet;
use std::cmp::Ord;
use std::hash::Hash;
use std::ops::{Add,Div,Mul,Rem};

use num_traits::{one,One,Zero};
use itertools::Itertools;

use crate::include::primes::prime_factors;

pub struct ProperDivisors<I>
{
seen: HashSet<I>,
factors: Vec<I>,
current_batch: Vec<I>,
curr_index: usize,
next_size: usize,
}

pub fn proper_divisors<I>(num: I) -> ProperDivisors<I>
{
return ProperDivisors::<I>::new(num);
}

impl<I> ProperDivisors<I>
where I: Hash + Zero + One + Add + Ord + Copy + Div<Output=I> + Rem<Output=I>
{
pub fn new(num: I) -> Self {
return ProperDivisors::<I>{
seen: HashSet::new(),
factors: prime_factors(num).collect(),
current_batch: vec![],
curr_index: 0,
next_size: 1,
};
}
}

impl<I> Iterator for ProperDivisors<I>
where I: Hash + Zero + One + Add + Ord + Copy + Div<Output=I> + Rem<Output=I> + Mul<Output=I>
{
type Item = I;

fn next(&mut self) -> Option<Self::Item> {
loop {
if self.next_size > self.factors.len() {
return None;
}
if self.curr_index == self.current_batch.len() {
self.current_batch = self.factors
.iter()
.cloned()
.combinations(self.next_size)
.map(|v| v.into_iter().fold(one(), |x, y| x * y))
.collect();
self.next_size += 1;
self.curr_index = 0;
}
while self.curr_index < self.current_batch.len() {
let result = self.current_batch[self.curr_index];
self.curr_index += 1;
if !self.seen.contains(&result) {
self.seen.insert(result);
return Some(result);
}
}
self.current_batch.clear();
self.curr_index = 0;
}
}
}
2 changes: 1 addition & 1 deletion rust/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ seq!(N in 01..=20 {
#[case::problem_76(76)]
#[case::problem_77(77)]
#[case::problem_87(87)]
// #[case::problem_357(357)]
#[case::problem_357(357)]
#[case::problem_836(836)]
fn test_problem(#[case] id: usize) -> Result<(), String> {
let Some((_, func, _slow)) = get_problem(id) else { panic!() };
Expand Down
5 changes: 3 additions & 2 deletions rust/src/p0357.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ such that for every divisor d of n, d+n/d is prime.
*/
use std::collections::HashSet;

use crate::include::primes::{is_prime,primes_until,proper_divisors};
use crate::include::primes::{is_prime,primes_until};
use crate::include::factors::proper_divisors;
use crate::include::utils::Answer;

pub fn p0357() -> Answer {
Expand All @@ -24,7 +25,7 @@ pub fn p0357() -> Answer {
for n in (6..100000000).step_by(4) {
// n can't be odd (unless 1) because then n + n/d is even, and can't be a multiple of 4 as shown below
let mut broken = false;
for d in proper_divisors(n).into_iter().chain(vec![n].into_iter()) {
for d in proper_divisors(n).chain(vec![n].into_iter()) {
if prime_squares.contains(&d) || !is_prime(d + n / d) {
// this works because if n=kp^2, then whenever d=p, (p + kp^2/p) = (k+1)p, which isn't prime
// but since detecting if n % d^2 == 0 is expensive, I just wait for p^2 to show up
Expand Down

0 comments on commit e3c1f9b

Please sign in to comment.