0
\$\begingroup\$

See code below and my comment with questions:

pub fn factors(n: u64) -> Vec<u64> {
    let mut m = n; // is it possible to convert n to a mutable type without using another variable?
    let mut a:Vec<u64> = Vec::new();
    while m % 2 == 0 {
        m /= 2;
        a.push(2);
    }
    // in C we can just write for (int i = 3; i <= sqrt(m); i+= 2) ... just saying... and C is not even as fast as python to code... am I really doing it right??
    for i in (3..((m as f64).sqrt() as usize + 1usize)).step_by(2) { 
        while m % i as u64 == 0 { // is there a way to avoid all the casts to u64
            a.push(i as u64);
            m /= i as u64;
        }
    }
    if m > 2 {
        a.push(m);
    }
    return a;
}
  • Is it possible to convert n to a mutable type without using another variable?
  • The C equivalent of the main loop use twice less ink. Is Rust so verbose by design?
  • Is there a way to avoid all the casts to u64
  • any other insight welcome
\$\endgroup\$
3
  • \$\begingroup\$ Your while loop is infinite, because m never changes. Does this code have a copy-paste error? \$\endgroup\$ – Winston Ewert Apr 1 at 5:05
  • 1
    \$\begingroup\$ The first while loop \$\endgroup\$ – Winston Ewert Apr 1 at 5:07
  • \$\begingroup\$ copy/paste, I edit \$\endgroup\$ – Antonin GAVREL Apr 1 at 5:08
3
\$\begingroup\$
pub fn factors(n: u64) -> Vec<u64> {
    let mut m = n; // is it possible to convert n to a mutable type without using another variable?

use pub fn factors(mut n: u64) to allow the parameter to be mutable

    let mut a:Vec<u64> = Vec::new();

You don't need : Vec<u64>, rust will infer it.

    while m % 2 == 0 {
        m /= 2;
        a.push(2);
    }


    // in C we can just write for (int i = 3; i <= sqrt(m); i+= 2) ... just saying... and C is not even as fast as python to code... am I really doing it right??
    for i in (3..((m as f64).sqrt() as usize + 1usize)).step_by(2) { 

Generally speaking, Rust is less verbose than C, but you've hit one of the major exceptions. Rust is pickier about types, it won't let you mix and match different numeric types. But we can make some improvements here.

  • You don't need 1usize just use 1.
  • You can also use 3 ..= (m as f64).sqrt() as usize (..= includes the end)

Alternatively, you could reverse the check:

for index in (3..).step_by(2).take_while(|i| i * i <= m)

I'm not sure if that's better or not.

        while m % i as u64 == 0 { // is there a way to avoid all the casts to u64
            a.push(i as u64);
            m /= i as u64;
        }

You need casts because you are being inconsistent about your types. If you change the usize in the for loop to u64 there will be no need for casts.

    }
    if m > 2 {
        a.push(m);
    }
    return a;
}
\$\endgroup\$
4
  • \$\begingroup\$ Thanks so much Winston! Just a quick question, in C, even though most of the time the compiler would optimize the following with optimization flags, it is better to compute an expression outside of loop or when it changes, what about Rush for (m as f64).sqrt() ? \$\endgroup\$ – Antonin GAVREL Apr 1 at 5:38
  • \$\begingroup\$ Also how comes index are only implemented for usize and not for u8,u16,u32,u64 etc? Would it be a breaking change? \$\endgroup\$ – Antonin GAVREL Apr 1 at 5:41
  • 1
    \$\begingroup\$ In Rust, 3 .. .(m as f64).sqrt() is evaluated once before the loop starts. It's not like C where the expressions are repeatedly evaluated. So there is no optimization reason to move the sqrt calculation. \$\endgroup\$ – Winston Ewert Apr 1 at 5:45
  • \$\begingroup\$ As for indexes, I think it follows from Rust's general practice of not allowing implicit type conversions. usize has a size depending on your architecture and thus isn't compatible with any of the types. But I really haven't looked closely at the rationale for that decision. \$\endgroup\$ – Winston Ewert Apr 1 at 5:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.