I'm an experienced C# developer trying to teach myself F#. I spent a day or 3 reading throught the F# wikibook trying to get to know the syntax and F# fundamentals.
As an exercise I'm trying to go through the Project Euler problems to get a better feeling of the syntax and working with the language.
I've just solved problem 5 (finding the least common multiple of 1, 2, 3, …, 20). But I'm not so happy about the hoops I had to jump through to get a data structure that represents my solution. I've used this blogpost to get to the algorithm for solving the problem.
I was wondering if anyone could give me some pointers as to how this code could be improved? My guess is that the inherent immutability of F# values is causing me to have to perform a lot of steps to get the exact data I want...
This is my code:
let main argv = //calculates the prime factors of a number let findPrimeFactors x = let primes = [|2I;3I;5I;7I;11I;13I;17I;19I|] let rec loop acc counter = function | x when x = 1I -> failwith "A PRIME IS BY DEFINITION GREATER THAN 1" | x when primes |> Array.contains x -> x :: acc | x when counter = primes.Length -> failwith "MY LIST OF KNOWN PRIMES IS NOT BIG ENOUGH" | x when x%primes.[counter]=0I-> loop (primes.[counter]::acc) (counter) (x/primes.[counter]) | x -> loop acc (counter + 1) x let primeFactor = loop  0 x |> List.rev primeFactor //calculates the prime factors for each of the numbers between 2 and n //then, for each of the prime factorizations it tries to find the highest power for each occurring prime factor let findPrimeFactorsPowers n = //builds a map of all the prime factor powers for all prime factorizations let rec addCounterFactorPowers factorPowers = function | counter when counter = n -> factorPowers | (counter : int) -> addCounterFactorPowers ((findPrimeFactors (counter|>bigint) |> List.countBy (fun x-> x)) @ factorPowers) (counter + 1) let allFactorPowers = addCounterFactorPowers  2 //group all the powers per prime factor let groupedFactorPowers = allFactorPowers |> List.groupBy (fun (factor, power) -> factor) //get the highest power per prime factor let maxFactorPowers = groupedFactorPowers |> List.map (fun (key, powers) -> (key, powers |> List.map (fun (factor, power) -> power) |> List.max)) //return the result maxFactorPowers let n = 20; let primeFactorSet = findPrimeFactorsPowers n printfn "%A" primeFactorSet let smallestNumberDivisableByAllNumbersBelown = (primeFactorSet |> List.fold (fun state (factor, power) -> state * pown factor power) 1I) printfn "Result %A" smallestNumberDivisableByAllNumbersBelown System.Console.ReadKey(true)|>ignore 0 // return an integer exit code