Totients
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();