In the past, I’ve implemented Euler’s totient function for shits and giggles. It’s not a hard exercise by any means, but it can be if you haven’t had education in math at a level to understand the formula.

$$\varphi(n) =n \prod_{p\mid n} \left(1-\frac{1}{p}\right)$$

Admittedly, I had to google what the hell is going on. Technically, that’s just the framework, there are more details that follow in the form of rules. However, it was definitely a fun exercise to implement it. I think today I’m going to commit to downloading the latest version of rust and compiling that old code to see how much data I can generate. It’s really about all I can do to keep myself from going insane having to watch this robot perform the same tasks over and over until it gets them right. Yes, I have to intervene occasionally, but most of these debugs are very “hands off”.

Alright, I’ve revised my rust totient calculator to be easier to use, and more flexible. It’ll accept a “start” and “end” calculation value. That way you can start right away crunching some huge primes. I started with checking command line arguments, I also convert them safely to u128, and then off she goes. It’s really fast.

use std::env;

fn gcd(mut m: u128, mut n: u128) -> u128 {
   while m != 0 {
       let old_m = m;
       m = n % m;
       n = old_m;
   }
   n
}

fn totient(mut a: u128) -> u128 {
    let mut y = 0;
    let o = a;
    while a != 0 {
        if gcd(o, a) == 1 {
            y += 1;
        }
        a -= 1;
    }
    y
}

fn main() {
    let args: Vec<String> = env::args().collect();

    let x: Vec<u128> = <[String]>::iter(&args).filter_map(|c| {
       c.parse::<u128>().ok()
       }
    ).collect();

    println!("Arguments: {}", &x.len());

    match &x.len() {
        1 => {
            println!("Not enough arguments. Expecting two.")
        },
        2 => {
            for i in x[0]..x[1] {
                let o = totient(i);
                println!("{:?}, {:?}", i, o);
            }
        },
        3 => {
            println!("Too many. Only need two.")
        },
        _ => {
            println!("Only two arguments. Please.")
        }
    }
}

Alright, a few things to note, since the code is completely uncommented. First, you’ll notice I’m using .filter_map. That’s because Rust is fucking wild. It’s so “safe” that it’ll take a shit converting from “string” to u128 if the string has no numbers. That means pulling command line arguments is going to be more difficult with .map. By using .filter_map for an iterator we’re telling it “We don’t give a shit about what has no numbers in it”. God, I wish this stuff were better documented or more obvious.

   let args: Vec<String> = env::args().collect();

   let x: Vec<u128> = <[String]>::iter(&args).filter_map(|c| {
      c.parse::<u128>().ok()
      }
   ).collect();