Project Euler – Problem 34 Solution

Yan Cui

I help clients go faster for less using serverless technologies.

Problem

145 is a curious number, as 1! + 4! + 5! = 1 + 24 + 120 = 145.

Find the sum of all numbers which are equal to the sum of the factorial of their digits.

Note: as 1! = 1 and 2! = 2 are not sums they are not included.

Solution

open System.Collections.Generic

// factorial function
let factorial n = if (n = 0) then 1 else [1..n] |> List.reduce (fun acc x -> acc * x)

// create a cache of sorts to help improve performance
let factorials = new Dictionary<int, int>()

let start = [0..9] |> List.iter (fun n -> factorials.Add(n, (factorial n)))

// get the digits of a number into an array
let getDigits (n:bigint) =
    n.ToString().ToCharArray()
    |> Array.map (fun c -> int(c.ToString()))

// get the sum of the factorials of a number's digits
let getDigitsToFactSum (n:bigint) =
    bigint(getDigits(n) |> Array.map (fun n -> factorials.[n]) |> Array.sum)

// get the max sum achievable by a number of the given number of digits
let upperBound (digits:int) = bigint(digits) * bigint(factorial 9)

// find the last number of digits n, where the max sum achievable by the factorials of the
// digits of a number of n digits is greater than the smallest number of n digits
// any number with more than n digits do not need to be checked
let digitsToCheck =
    let n =
        Seq.unfold (fun state -> Some(state, (state+1))) 1
        |> Seq.filter (fun x -> (upperBound x).ToString().ToCharArray().Length < x)
        |> Seq.head
    n-1

// get the next number with the given number of digits
let maxNumber digits = [1..digits] |> List.map (fun x -> 9I * pown 10I (x-1)) |> List.sum

let answer =
    let max = maxNumber digitsToCheck
    [3I..max] |> List.filter (fun n -> n = getDigitsToFactSum n) |> List.sum

This solution is very similar to my solution for problem 30, with the main difference being that the sum is calculated using the factorials of the digits rather the fifth power.


 

Whenever you’re ready, here are 4 ways I can help you:

  1. If you want a one-stop shop to help you quickly level up your serverless skills, you should check out my Production-Ready Serverless workshop. Over 20 AWS Heroes & Community Builders have passed through this workshop, plus 1000+ students from the likes of AWS, LEGO, Booking, HBO and Siemens.
  2. If you want to learn how to test serverless applications without all the pain and hassle, you should check out my latest course, Testing Serverless Architectures.
  3. If you’re a manager or founder and want to help your team move faster and build better software, then check out my consulting services.
  4. If you just want to hang out, talk serverless, or ask for help, then you should join my FREE Community.

 


Leave a Comment

Your email address will not be published. Required fields are marked *