How can it be improved? Well, it all depends on your goals with the code. I'll assume the goal is to make it prettier and more in line with typical Rust style.
First of all, while
loops are rare in Rust code and you should replace them with for
. This is because while
works on your hand-rolled logic, whereas for .. in ..
works with external iteration that is composable and idiomatic Rust.
I see you have one for
loop already. Let's turn all others into for
.
You always start with 1
, so the first iterator will be (1..)
. We keep taking elements of the range as long as a condition is satisfied, so the next element of the iteration pipeline will be .take_while(|&b|
...)
. This Rust standard library method best fits the situation.
fn main()
{
for a in 1..101
{
for b in (1..).take_while(|&b| a*a-b*b >= 0)
{
for c in (1..b).take_while(|&c| a*a-b*b-c*c>=0)
{
for d in (1..c).take_while(|&d| a*a-b*b-c*c-d*d>=0)
{
if a*a-b*b-c*c-d*d==0
{
println!("{}²={}²+{}²+{}²",a,b,c,d);
}
}
}
}
}
}
This code is much more idiomatic already. Next up, I noticed that the intent of the two inner loops is to iterate until we hit the number above, so let's make two simple changes:
for c in (1..b).take_while(|&c| a*a-b*b-c*c>=0)
for d in (1..c).take_while(|&d| a*a-b*b-c*c-d*d>=0)
For readability, we can Don't-Repeat-Yourself by making a tiny function.
fn square_diff(a: i32, b: i32, c: i32, d: i32) -> i32 { a*a-b*b-c*c-d*d }
For all instances of a*a-b*b
or a*a-b*b-c*c
or ..., we replace them with square_diff(a, b, 0, 0)
etc.
One more observation: (1..).take_while(|b| square_diff(a, b, 0, 0) >= 0)
is equivalent to 1..=a
.
Next up, we don't do C-style indentation in Rust. We put a single space after every comma in arguments. The result so far is:
fn main() {
for a in 1..101 {
for b in 1..=a {
for c in (1..b).take_while(|&c| square_diff(a, b, c, 0) >= 0) {
for d in (1..c).take_while(|&d| square_diff(a, b, c, d) >= 0) {
if square_diff(a, b, c, d) == 0 {
println!("{}²={}²+{}²+{}²", a, b, c, d);
}
}
}
}
}
}
fn square_diff(a: i32, b: i32, c: i32, d: i32) -> i32 { a*a - b*b - c*c - d*d }
I tried to test whether these abstractions really reduce to zero-cost, but
alas, Rust@godbolt failed me. Benchmarking is left as a small exercise.
Good luck on your Rust journeys.