Project Euler

2025 – Ongoing

When I found out about Project Euler I was especially interested in the challenge to solve a problem efficiently. Below is how I have gone about approaching the problems I have solved so far. Project Euler allows problems 1 to 100 to be shared for educational purposes, and I am a big fan of allowing others the ability to have that "aha!" moment as well so I have removed function calls and any outputted answers.

For more information, check out the Project Euler site here. (opens in a new tab)

My Project Euler badge(opens Project Euler in a new tab)
  • 001 Multiples of 3 or 5
    projecteuler.net/problem=1 ↗(opens in a new tab)

    If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

    Find the sum of all the multiples of 3 or 5 below 1000.

    Solution in Rust

    fn main() {
        let mut multiples_sum = 0;
        for i in 0..1000 {
            if i % 3 == 0 || i % 5 == 0 {
                multiples_sum += i;
            }
        }
    }
  • 002 Even Fibonacci Numbers
    projecteuler.net/problem=2 ↗(opens in a new tab)

    Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …

    By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

    Solution in Rust

    fn get_even_fib_sum(max_val: i32) -> i32 {
        let mut even_sum = 2;
        let mut sequence = [1, 2, 3];
        while sequence[2] < max_val {
            sequence = [sequence[1], sequence[2], sequence[1] + sequence[2]];
            if sequence[2] % 2 == 0 {
                even_sum += sequence[2];
            }
        }
        even_sum
    }
  • 003 Largest Prime Factor
    projecteuler.net/problem=3 ↗(opens in a new tab)

    The prime factors of 13195 are 5, 7, 13 and 29.

    What is the largest prime factor of the number 600851475143?

    Solution in Rust

    // function to determine if number is prime
    fn is_prime(n: i64) -> bool {
        if n % 2 == 0 {
            return false;
        }
        if n == 3 {
            return true;
        }
        let mut search_val = 3;
        let max_val = ((n as f64).sqrt().ceil() as i64) + 1;
        while search_val <= max_val {
            if n % search_val == 0 {
                return false
            }
            search_val += 2;
        }
        return true;
    }
    
    // start at the maximum possible prime number, then work
    // down until the first prime is found
    fn largest_prime(num: i64) -> i64 {
        let mut val = (num as f64).sqrt().ceil() as i64 + 1;
        while val > 0 {
            if (num % val) == 0 {
                if is_prime(val) {
                    return val
                }
            }
            val -= 1;
        }
        1
    }
  • 004 Largest Palindrome Product   (one of my favorites)
    projecteuler.net/problem=4 ↗(opens in a new tab)

    A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.

    Find the largest palindrome made from the product of two 3-digit numbers.

    Solution in Rust

    // function to determine if a number is a palindrome
    fn is_palindrome(num: i64) -> bool {
        // convert to string
        let num_string = num.to_string();
        // store in vector
        let num_vec = num_string.split("").collect::<Vec<_>>();
        // start on either ends of the vector, check if values are the same
        let (mut start, mut end) = (1, num_vec.len() - 2);
        while start < end {
            // if any do not match, return false
            if num_vec[start] != num_vec[end] {
                return false
            }
            start += 1;
            end -= 1;
        }
        return true
    }
    
    // finds the largest palindromic number made from the products 
    // of two numbers that are each digit_num in length
    fn largest_palindrome(digit_num: u32) -> i64{
        let (mut digit1, mut digit2) = (0, 0);
        let mut largest_pal: i64 = 0;
        // max val that is digit_num number of digits
        let max_val = 1 * (10i32.pow(digit_num)) - 1;
        // iterate through the combinations of numbers that are digit_num in length
        for x1 in 0..=max_val / 10 {
            for x2 in 0..=max_val / 10 {
                let product: i64 = (max_val - x1) as i64 * (max_val - x2) as i64;
                if is_palindrome(product) {
                    if max_val - x1 >= digit1 || max_val - x2 >= digit2 {
                        if product > largest_pal {
                            largest_pal = product;
                            (digit1, digit2) = (max_val - x1, max_val - x2);
                        }
                    }
                    // end if both values that are multiplied are less than the
                    // current max palindromic number factors
                    else if max_val - x1 < digit1 && max_val - x2 < digit2{
                        break
                    }
                }
            }
        }
        return largest_pal;
    }
  • 005 Smallest Multiple
    projecteuler.net/problem=5 ↗(opens in a new tab)

    2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.

    What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?

    Solution in Rust

    // div_by_all takes num as input and finds the smallest positive number that is
    // evenly divisible by all numbers from 1 to num
    fn div_by_all(num: i64) -> i64 {
        // set value equal to max number to be divided by
        let mut test_val = num;
        // begin loop to check for each value of test_val, increment by num each loop
        loop {
            for i in 2..=num {
                if test_val % i != 0 {
                    break;
                }
                // if all numbers are checked, the number has been found
                else if i == num {
                    return test_val;
                }
            }
            test_val += num;
        }
    }
  • 006 Sum Square Difference
    projecteuler.net/problem=6 ↗(opens in a new tab)

    The sum of the squares of the first ten natural numbers is: 1² + 2² + … + 10² = 385

    The square of the sum of the first ten natural numbers is: (1 + 2 + … + 10)² = 55² = 3025

    Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 - 385 = 2640.

    Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.

    Solution in Rust

    fn sum_square_diff(num: i32) -> i32 {
        let mut sum_of_squares = 0;
        let mut square_of_sum = 0;
        for x in 1..=num {
            sum_of_squares += x.pow(2);
            square_of_sum += x;
        }
        square_of_sum = square_of_sum.pow(2);
        square_of_sum - sum_of_squares
    }
  • 007 10,001st Prime   (one of my favorites)
    projecteuler.net/problem=7 ↗(opens in a new tab)

    By listing the first six prime numbers: 2, 3, 5, 7, 11 and 13, we can see that the 6th prime is 13.

    What is the 10,001st prime number?

    Solution in Rust

    fn is_prime(n: i64) -> bool {
        if n % 2 == 0 {
            return false;
        }
        if n == 3 {
            return true;
        }
        let mut search_val = 3 as i64;
        let max_val = ((n as f64).sqrt().ceil() as i64) + 1;
        while search_val <= max_val {
            if n % search_val == 0 {
                return false;
            }
            search_val += 2;
        }
        return true;
    }
     
    fn find_nth_prime(n: i64) -> i64{
        let mut curr_prime = 1;
        let mut x = 1;
        while curr_prime < n {
            x += 2;
            if is_prime(x) {
                curr_prime += 1;
            }
        }
        x
    }
  • 009 Special Pythagorean Triplet   (one of my favorites)
    projecteuler.net/problem=9 ↗(opens in a new tab)

    A Pythagorean triplet is a set of three natural numbers, a < b < c, for which a² + b² = c².

    For example, 3² + 4² = 9 + 16 = 25 = 5².

    There exists exactly one Pythagorean triplet for which a + b + c = 1000. Find the product abc.

    Solution in Rust

    // return true if the triplet is a Pythagorean triplet
    fn is_triplet(a: i32, b: i32, c: i32) -> bool {
        if a < b && b < c {
            if a.pow(2) + b.pow(2) == c.pow(2) {
                return true
            }
        }
        false
    }
     
    fn find_triplets(sum_val: i32) -> (i32, i32, i32) {
        let (mut a, mut b, mut c) = (1, 2, sum_val - 3);
        while a < b {
            while b < c {
                if is_triplet(a, b, c){
                    return (a, b, c)
                }
                (b, c) = (b + 1, c - 1);
            }
            (a, b) = (a + 1, a + 2);
            c = sum_val - a - b;
        }
        (a, b, c)
    }
  • 013 Large Sum   (one of my favorites)
    projecteuler.net/problem=13 ↗(opens in a new tab)

    Work out the first ten digits of the sum of the following one-hundred 50-digit numbers (listed below).

    Solution in Rust

    fn find_large_sum(numbers: Vec<&str>) -> String {
        let mut sum = String::new();
        let (mut processed_nums, mut remainder) = (0, 0);
        // create copy of vector to perform pop operation on
        let mut numbers_list: Vec<String> = vec![];
        for number in 0..numbers.len() {
            numbers_list.push(numbers[number].to_string());
        }
        while processed_nums < numbers.len(){
            processed_nums = 0;
            // pop last digit of each number, add it to the remainder value
            for num in 0..numbers_list.len() {
                let digit = numbers_list[num].pop();
                if digit.is_some() {
                    remainder += digit.unwrap().to_digit(10).unwrap();
                }
                // once all values no longer have a number to pop, we know we are done
                else{
                    processed_nums += 1;
                }
            }
            sum = (remainder % 10).to_string() + &sum;
            remainder = remainder / 10;
        }
        // put rest of remainder on front of number
        sum = remainder.to_string() + &sum;
        sum
    }
     
    let numbers  = vec![
        "37107287533902102798797998220837590246510135740250",
        "46376937677490009712648124896970078050417018260538",
        "74324986199524741059474233309513058123726617309629",
        "91942213363574161572522430563301811072406154908250",
        "23067588207539346171171980310421047513778063246676",
        "89261670696623633820136378418383684178734361726757",
        "28112879812849979408065481931592621691275889832738",
        "44274228917432520321923589422876796487670272189318",
        "47451445736001306439091167216856844588711603153276",
        "70386486105843025439939619828917593665686757934951",
        "62176457141856560629502157223196586755079324193331",
        "64906352462741904929101432445813822663347944758178",
        "92575867718337217661963751590579239728245598838407",
        "58203565325359399008402633568948830189458628227828",
        "80181199384826282014278194139940567587151170094390",
        "35398664372827112653829987240784473053190104293586",
        "86515506006295864861532075273371959191420517255829",
        "71693888707715466499115593487603532921714970056938",
        "54370070576826684624621495650076471787294438377604",
        "53282654108756828443191190634694037855217779295145",
        "36123272525000296071075082563815656710885258350721",
        "45876576172410976447339110607218265236877223636045",
        "17423706905851860660448207621209813287860733969412",
        "81142660418086830619328460811191061556940512689692",
        "51934325451728388641918047049293215058642563049483",
        "62467221648435076201727918039944693004732956340691",
        "15732444386908125794514089057706229429197107928209",
        "55037687525678773091862540744969844508330393682126",
        "18336384825330154686196124348767681297534375946515",
        "80386287592878490201521685554828717201219257766954",
        "78182833757993103614740356856449095527097864797581",
        "16726320100436897842553539920931837441497806860984",
        "48403098129077791799088218795327364475675590848030",
        "87086987551392711854517078544161852424320693150332",
        "59959406895756536782107074926966537676326235447210",
        "69793950679652694742597709739166693763042633987085",
        "41052684708299085211399427365734116182760315001271",
        "65378607361501080857009149939512557028198746004375",
        "35829035317434717326932123578154982629742552737307",
        "94953759765105305946966067683156574377167401875275",
        "88902802571733229619176668713819931811048770190271",
        "25267680276078003013678680992525463401061632866526",
        "36270218540497705585629946580636237993140746255962",
        "24074486908231174977792365466257246923322810917141",
        "91430288197103288597806669760892938638285025333403",
        "34413065578016127815921815005561868836468420090470",
        "23053081172816430487623791969842487255036638784583",
        "11487696932154902810424020138335124462181441773470",
        "63783299490636259666498587618221225225512486764533",
        "67720186971698544312419572409913959008952310058822",
        "95548255300263520781532296796249481641953868218774",
        "76085327132285723110424803456124867697064507995236",
        "37774242535411291684276865538926205024910326572967",
        "23701913275725675285653248258265463092207058596522",
        "29798860272258331913126375147341994889534765745501",
        "18495701454879288984856827726077713721403798879715",
        "38298203783031473527721580348144513491373226651381",
        "34829543829199918180278916522431027392251122869539",
        "40957953066405232632538044100059654939159879593635",
        "29746152185502371307642255121183693803580388584903",
        "41698116222072977186158236678424689157993532961922",
        "62467957194401269043877107275048102390895523597457",
        "23189706772547915061505504953922979530901129967519",
        "86188088225875314529584099251203829009407770775672",
        "11306739708304724483816533873502340845647058077308",
        "82959174767140363198008187129011875491310547126581",
        "97623331044818386269515456334926366572897563400500",
        "42846280183517070527831839425882145521227251250327",
        "55121603546981200581762165212827652751691296897789",
        "32238195734329339946437501907836945765883352399886",
        "75506164965184775180738168837861091527357929701337",
        "62177842752192623401942399639168044983993173312731",
        "32924185707147349566916674687634660915035914677504",
        "99518671430235219628894890102423325116913619626622",
        "73267460800591547471830798392868535206946944540724",
        "76841822524674417161514036427982273348055556214818",
        "97142617910342598647204516893989422179826088076852",
        "87783646182799346313767754307809363333018982642090",
        "10848802521674670883215120185883543223812876952786",
        "71329612474782464538636993009049310363619763878039",
        "62184073572399794223406235393808339651327408011116",
        "66627891981488087797941876876144230030984490851411",
        "60661826293682836764744779239180335110989069790714",
        "85786944089552990653640447425576083659976645795096",
        "66024396409905389607120198219976047599490197230297",
        "64913982680032973156037120041377903785566085089252",
        "16730939319872750275468906903707539413042652315011",
        "94809377245048795150954100921645863754710598436791",
        "78639167021187492431995700641917969777599028300699",
        "15368713711936614952811305876380278410754449733078",
        "40789923115535562561142322423255033685442488917353",
        "44889911501440648020369068063960672322193204149535",
        "41503128880339536053299340368006977710650566631954",
        "81234880673210146739058568557934581403627822703280",
        "82616570773948327592232845941706525094512325230608",
        "22918802058777319719839450180888072429661980811197",
        "77158542502016545090413245809786882778948721859617",
        "72107838435069186155435662884062257473692284509516",
        "20849603980134001723930671666823555245252804609722",
        "53503534226472524250874054075591789781264330331690",
    ];
  • 021 Amicable Numbers
    projecteuler.net/problem=21 ↗(opens in a new tab)

    Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n). If d(a) = b and d(b) = a, where a ≠ b, then a and b are an amicable pair and each of a and b are called amicable numbers.

    For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110; therefore d(220) = 284. The proper divisors of 284 are 1, 2, 4, 71 and 142; so d(284) = 220.

    Evaluate the sum of all the amicable numbers under 10,000.

    Solution in Rust

    fn sum_amicable_nums(val: i32) -> i32 {
        let mut amicable_sum = 0;
        let mut known_amicables: Vec<i32> = Vec::new();
        for a in 1..=val {
            let da = find_divisor_sum(a);
            if !known_amicables.contains(&a) && !known_amicables.contains(&da){
                let db = find_divisor_sum(da);
                if (a == db) && (da != a) && (a < 10000) && (da < 10000){
                    known_amicables.push(a);
                    known_amicables.push(da);
                    amicable_sum += a + da;
                }
            }
        }
        amicable_sum
    }
    
    fn find_divisor_sum(val: i32) -> i32 {
        let mut divisor_sum = 0;
        for x in 1..=(val / 2) + 1{
            if val % x == 0 {
                divisor_sum += x;
            }
        }
        divisor_sum
    }
  • 023 Non-Abundant Sums
    projecteuler.net/problem=23 ↗(opens in a new tab)

    A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.

    A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.

    As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.

    Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.

    Solution in Rust

    fn is_abundant(val: i32) -> bool {
        let mut div_sum: i32 = 1;
        for x in 2..=val / 2 {
            if val % x == 0 {
                div_sum += x;
            }
        }
        if div_sum > val {
            true
        }
        else {
            false
        }
    }
    
    fn find_abundant_nums(max: i32) -> Vec<i32> {
        let mut abundant_nums: Vec<i32> = Vec::new();
        for x in 1..=max {
            if is_abundant(x){
                abundant_nums.push(x);
            }
        }
        abundant_nums
    }
    
    fn find_abundant_sums(abundant_nums: Vec<i32>, max: i32) -> Vec<i32> {
        let mut abundant_sums: Vec<i32> = vec![0; max as usize];
        for x in 0..abundant_nums.len() {
            for y in x..abundant_nums.len() {
                let sum = abundant_nums[x] + abundant_nums[y];
                if sum < max {
                    abundant_sums[sum as usize] = 1;
                }
            }
        }
        abundant_sums
    }
    
    fn find_non_sums_sum(abundant_sums: Vec<i32>) -> usize {
        let mut sum: usize = 0;
        for val in 1..abundant_sums.len() {
            if abundant_sums[val] == 0 {
                sum += val;
            }
        }
        sum
    }
  • 024 Lexicographic Permutations   (one of my favorites)
    projecteuler.net/problem=24 ↗(opens in a new tab)

    A permutation is an ordered arrangement of objects. For example, 3124 is one possible permutation of the digits 1, 2, 3 and 4. If all of the permutations are listed numerically or alphabetically, we call it lexicographic order. The lexicographic permutations of 0, 1 and 2 are: 012 021 102 120 201 210

    What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?

    Solution in Rust

    fn factorial(val: usize) -> usize {
        let mut product = 1;
        for x in 1..=val {
            product *= x;
        }
        product
    }
    
    fn find_lexicographic_permutation(mut digits: Vec::<usize>, mut p_target: usize) -> usize {
        let mut permutation = String::from("");
        p_target -= 1;
        for _x in 1..digits.len() {
            let digit = p_target / factorial(digits.len() - 1);
            permutation = format!("{}{}", &permutation, digits[digit]);
            digits.remove(digit);
            p_target %= factorial(digits.len());
        }
        if digits == [0] {
            permutation = format!("{}{}", &permutation, 0);
        }
        permutation.parse::<usize>().unwrap()
    }
  • 026 Reciprocal Cycles
    projecteuler.net/problem=26 ↗(opens in a new tab)

    A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given: 1/2 = 0.5 1/3 = 0.(3) 1/4 = 0.25 1/5 = 0.2 1/6 = 0.1(6) 1/7 = 0.(142857) 1/8 = 0.125 1/9 = 0.(1) 1/10 = 0.1

    Where 0.1(6) means 0.166666…, and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle.

    Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.

    Solution in Rust

    fn longest_recurring_cycle (val: f64) {
        let mut d = 2;
        for x in 2..val as i32 {
            let fraction: f64 = 1.0 / x as f64;
            println!("x: {}, {:.}", x, fraction);
        }
    }
    
    fn main() {
        let start = std::time::Instant::now();
        longest_recurring_cycle(1000 as f64);
        println!("Elapsed: {:?}", start.elapsed());
    }

Problems from projecteuler.net(opens in a new tab), licensed under CC BY-NC-SA 4.0(opens in a new tab).