This will be a part of a series on my rust-learning journey. The goal of this post is to document my process of creating a simple program that determine if the number given is a perfect number1. And also list the perfect number until the given number.

Imports

1
use std::io;

This is the common input / output modules.

Function to determine the perfect number

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
fn is_perfect_number(n: i32) ->  bool {
    let mut sum: i32 = 1;
    let mut i: i32 = 2;

    while i * i <= n {
        if n % i == 0 {
            sum = sum + i + n / i;
        }
        i += 1;
    }
    if sum == n && n != 1 {
        return true
    } else {
        return false
    }
}

This will calculate if the number is a perfect number or not.

Function to list all the perfect number

1
2
3
4
5
6
7
8
9
fn perfect_number_list(n: i32) ->  Vec<i32>{
    let mut numbers: Vec<i32> = vec![];
    for num in 1..n {
        if is_perfect_number(num) {
            numbers.push(num);
        }
    }
    return numbers;
}

This will calculate all the perfect number up to the given number. The return type is a vector, which is a resizeable arrays in rust. It size is unknown at compile time, and it can shrink or grow at any time.

The main function

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
fn main() {
    println!("Input a number!\n");
    let mut input_number = String::new();
    io::stdin()
        .read_line(&mut input_number)
        .expect("failed to read input.");
    let x: i32 = input_number
        .trim()
        .parse()
        .expect("Not an integer");
    println!("Your input is: {}", x);
    if is_perfect_number(x) {
        println!("{} is a perfect number", x)
    } else {
        println!("{} is not a perfect number", x)
    }

    println!("Input a number!\n");
    let mut number_range = String::new();
    io::stdin()
        .read_line(&mut number_range)
        .expect("Failed to read input.");
    let y: i32 = number_range
        .trim()
        .parse()
        .expect("Not an integer");
    print!("The perfect number from 1 to {} is: ", y);
    for element in &perfect_number_list(y) {
        print!("{} ", element);
    }
    println!(); // for whitespace
}

There’s alot going on here:

Reading user input

I’m sure there are packages that simplify this process, but when I’m learning new programming languages I try to stick with the builtins first. But basically it goes like this:

String::new
It creates an empty string. I don’t actually know if all stdin should be treated as string.
io::stdin
From the std::io module.
.readline
The actual reading. The &mut before the variable input_number means it is a mutable reference to the variable input_number.
.expect
In case the input is not a string.

The conversion from string to integer is done by declaring it into another variable and:

.trim
clear the whitespaces if any.
.parse
parsing it into another type, in this case i32, and lastly,
.expect
Guard it in case it is a different type

The rest of this main function is by using the two functions earlier.

The Whole Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use std::io;

fn is_perfect_number(n: i32) ->  bool {
    let mut sum: i32 = 1;
    let mut i: i32 = 2;

    while i * i <= n {
        if n % i == 0 {
            sum = sum + i + n / i;
        }
        i += 1;
    }
    if sum == n && n != 1 {
        return true
    } else {
        return false
    }
}

fn perfect_number_list(n: i32) ->  Vec<i32>{
    let mut numbers: Vec<i32> = vec![];
    for num in 1..n {
        if is_perfect_number(num) {
            numbers.push(num);
        }
    }
    return numbers;
}

fn main() {
    println!("Input a number!\n");
    let mut input_number = String::new();
    io::stdin()
        .read_line(&mut input_number)
        .expect("failed to read input.");
    let x: i32 = input_number
        .trim()
        .parse()
        .expect("Not an integer");
    println!("Your input is: {}", x);
    if is_perfect_number(x) {
        println!("{} is a perfect number", x)
    } else {
        println!("{} is not a perfect number", x)
    }

    println!("Input a number!\n");
    let mut number_range = String::new();
    io::stdin()
        .read_line(&mut number_range)
        .expect("Failed to read input.");
    let y: i32 = number_range
        .trim()
        .parse()
        .expect("Not an integer");
    print!("The perfect number from 1 to {} is: ", y);
    for element in &perfect_number_list(y) {
        print!("{} ", element);
    }
    println!(); // for whitespace
}

This is the running code.

Figure 1: the code in action

Figure 1: the code in action