Does contains() consume vector values?

I am running Rust 1.60.0 (7737e0b5c 2022-04-04) on Windows 10 Pro 64-bit and I am using CLion with the Rust plugin. I am learning Rust by converting C++ programs to Rust.

I have the following program that successfully finds all of the amicable numbers smaller than a number entered by the user. This program works but it currently displays each pair twice. In C++ I was able to track the numbers already computed with a vector. I placed the numbers found in the vector and check for previous values each time through a loop.

However, when I add this vector to my Rust code, the code enters an infinite loop. The code that causes this problem seems to be caused by the commented code in the while loop in main (six lines plus one line defining the vector).

If I remove the commented lines in 'fn main', and debug this code in CLion, I put a breakpoint on the if clause checking if the vector contains the current 'i' value -- if vector_pair_added.contains(&i) -- see below. When the value of 'i' gets to 220, the values 220 and 284 are added to the vector. BUT, when the value of 'i' gets to 284, the values in the vector disappear and the vector length is zero. Then the code never seems to get past that block without continuing. To me (a beginner) this is confusing and I need clarification.

Are the elements in the vector "consumed" by an iterator?
Is this the behavior that everyone else witnesses?
What do I have to do to fix this code to prevent the vector from being empty?
If this behavior is detailed in the Rust documentation, I cannot find it, so would someone point me to this documented behavior?

    ///
    /// Program that prints the list of all pairs of amicable numbers
    ///  smaller than a number entered by the user up to 1,000,000.
    ///
    //  NOTE:
    //        The amicable pairs under 10,000 include:
    //            220 and 284
    //            1184 and 1210
    //            2620 and 2924
    //            5020 and 5564
    //            6232 and 6368
    //
    use std::io::Write; 
    
    ///
    /// Returns the sum of the proper divisors for the integer value
    /// passed to this function.
    ///
    fn sum_proper_divisors(num: u32) -> u32 {
        let mut result: u32 = 0;
    
        if num == 1 {
            return result;
        }
    
        let mut i = 2;
        while i * i <= num {
            if num % i == 0 {
                // Add a divisor once if both are the same
                if i == (num / i) {
                    result += i;
                } else {
                    result += i + (num / i);
                }
            }
            i += 1;
        }
    
        // Always add one as a proper divisor for num > 1
        return result + 1;
    } 
    
    ///
    /// Function to obtain user input from the command line in the
    /// form of an integer value.
    ///
    fn get_user_input_gen<T: std::str::FromStr>() -> T
    where
        <T as std::str::FromStr>::Err: std::fmt::Debug,
    {
        let mut user_line = String::new();
        std::io::stdin().read_line(&mut user_line).unwrap();
        let user_number: T = user_line.trim().parse().unwrap();
        return user_number;
    }
    
    fn main() {
        print!("Enter a positive integer: ");
        std::io::stdout()
            .flush()
            .expect("ERROR: Error flushing stdout. ");
    
        let user_limit: u32 = get_user_input_gen();
    
        if user_limit > 0 && user_limit < 1000000 {
            // let mut vector_pair_added = Vec::new();
    
            let mut i = 2;
            while i <= user_limit {
                // if vector_pair_added.contains(&i)
                // {
                //     continue;
                // }
                let sum1 = sum_proper_divisors(i);
                if sum1 < user_limit {
                    let sum2 = sum_proper_divisors(sum1);
                    if sum2 == i && i != sum1 {
                        // vector_pair_added.push(i);
                        // vector_pair_added.push(sum1);
                        println!("Found amicable pair: {} and {}.", i, sum1);
                    }
                }
                i += 1;
            }
        } else {
            println!(
                "ERROR: Please enter a positive integer value less than {}.",
                1000000
            );
        }
    }

The problem is that, when you hit the vector_pair_added.contains(&i) condition, you go to the next loop iteration without increasing i - therefore hitting the exact same condition again and again. I've replaced while i <= user_limit with for i in 2..=user_limit, and the code seems to run correctly - the pair (220, 284) was printed only once.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.