immutability - Why do I have the feeling my F# code could be more concise -
i'm experienced c# developer trying teach myself f#. spent day or 3 reading throught f# wikibook trying know syntax , f# fundamentals.
as exercise i'm trying go through project euler problems better feeling of syntax , working language.
i've solved problem 5. i'm not happy hoops had jump through data structure represents solution. i've used this blogpost algorithm solving problem.
i wondering if give me pointers how code improved? guess inherent immutability of f# values causing me have perform lot of steps exact data want...
this code:
let main argv = //calculates prime factors of 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 definition greater 1" | x when primes |> array.contains x -> x :: acc | x when counter = primes.length -> failwith "my list of known primes 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 prime factors each of numbers between 2 , n //then, each of prime factorizations tries find highest power each occurring prime factor let findprimefactorspowers n = //builds map of prime factor powers 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 powers per prime factor let groupedfactorpowers = allfactorpowers |> list.groupby (fun (factor, power) -> factor) //get highest power per prime factor let maxfactorpowers = groupedfactorpowers |> list.map (fun (key, powers) -> (key, powers |> list.map (fun (factor, power) -> power) |> list.max)) //return 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 integer exit code
there many direct simplifications can apply code, don't think that's best approach.
this way solve problem in f#:
let rec trydivide n m = if m = 1 true else if n % m = 0 trydivide n (m-1) else false let rec findit m = if trydivide m else findit (i+1) m findit 1 20
it's bit slower yours because doesn't use hardcoded primes, they're calculated on fly, still takes less 2 secs on computer right answer.
note i'm not using list-like data structure , no need rely on big integers in specific problem.
update
here's better approach based on kvb's proposed solution:
let rec gcd x y = if y = 0 abs x else gcd y (x % y) let lcm b = match (a, b) | (_, 0) | (0, _) -> 0 | (x, y) -> abs ((x / (gcd x y)) * y) seq.fold lcm 1 {2..20}
Comments
Post a Comment