Last active
October 24, 2017 13:18
-
-
Save ykon/56a976dd8cf68defc834051c722a5015 to your computer and use it in GitHub Desktop.
Basic FP in F#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* | |
* Copyright (c) 2017 Yuki Ono | |
* Licensed under the MIT License. | |
*) | |
open System | |
open System.Collections.Generic | |
let proceduralSum (ns:int list): int = | |
let mutable sum = 0 | |
for n in ns do | |
sum <- sum + n | |
sum | |
let rec recSum (ns:int list): int = | |
match ns with | |
| [] -> 0 | |
| n :: rest -> n + recSum(rest) | |
let tailRecSum (ns:int list): int = | |
let rec loop l acc = | |
match l with | |
| [] -> acc | |
| n :: rest -> loop rest (n + acc) | |
loop ns 0 | |
let foldSum (ns:int list): int = | |
List.fold (fun acc n -> acc + n) 0 ns | |
let foldBackSum (ns:int list): int = | |
List.foldBack (fun n acc -> acc + n) ns 0 | |
let reduceSum (ns:int list): int = | |
List.reduce (fun acc n -> acc + n) ns | |
let reduceBackSum (ns:int list): int = | |
List.reduceBack (fun n acc -> acc + n) ns | |
let sumSum (ns:int list): int = | |
List.sum ns | |
let proceduralFactorial (num:uint32): bigint = | |
let mutable fn = 1I | |
let mutable i = 1u | |
while i <= num do | |
fn <- fn * bigint(i) | |
i <- i + 1u | |
fn | |
let rec recFactorial (num:uint32): bigint = | |
match num with | |
| 0u -> 1I | |
| n -> recFactorial(n - 1u) * bigint(n) | |
let tailRecFactorial (num:uint32): bigint = | |
let rec loop n acc = | |
match n with | |
| 0u -> acc | |
| _ -> loop (n - 1u) (acc * bigint(n)) | |
loop num 1I | |
let foldFactorial (num:uint32): bigint = | |
List.fold (fun acc n -> acc * bigint(n:uint32)) 1I [1u .. num] | |
let foldBackFactorial (num:uint32): bigint = | |
List.foldBack (fun n acc -> acc * bigint(n:uint32)) [1u .. num] 1I | |
let proceduralFib (num:int): int = | |
if num < 2 then | |
num | |
else | |
let mutable a = 0 | |
let mutable b = 1 | |
let mutable i = 2 | |
while i <= num do | |
let temp = a | |
a <- b | |
b <- temp + b | |
i <- i + 1 | |
b | |
let rec recFib (num:int): int = | |
match num with | |
| n when n < 2 -> n | |
| n -> recFib(n - 1) + recFib(n - 2) | |
let tailRecFib (num:int): int = | |
let rec loop n a b = | |
match n with | |
| 0 -> a | |
| _ -> loop (n - 1) b (a + b) | |
loop num 0 1 | |
let rec memoFib (num:int): int = | |
let memo = new Dictionary<int, int>() | |
let fib n = | |
match n with | |
| n when n < 2 -> n | |
| _ -> memoFib(n - 1) + memoFib(n - 2) | |
match memo.TryGetValue num with | |
| true, value -> value | |
| _ -> | |
let res = fib num | |
memo.[num] <- res | |
res | |
let proceduralX2 (ns:int list): int list = | |
let mutList = new List<int>() | |
for n in ns do | |
mutList.Add(n * 2) | |
List.ofSeq mutList | |
let rec recX2 (ns:int list): int list = | |
match ns with | |
| [] -> [] | |
| n :: rest -> (n * 2) :: recX2(rest) | |
let tailRecX2 (ns:int list): int list = | |
let rec loop l acc = | |
match l with | |
| [] -> acc | |
| n :: rest -> loop rest (n * 2 :: acc) | |
loop ns [] |> List.rev | |
let foldX2 (ns:int list): int list = | |
List.fold (fun acc n -> n * 2 :: acc) [] ns | |
|> List.rev | |
let foldBackX2 (ns:int list): int list = | |
List.foldBack (fun n acc -> n * 2 :: acc) ns [] | |
let mapX2 (ns: int list): int list = | |
let x2 n = n * 2 | |
List.map x2 ns | |
//List.map (fun n -> n * 2) ns | |
let proceduralEven (ns:int list): int list = | |
let mutList = new List<int>() | |
for n in ns do | |
if n % 2 = 0 then | |
mutList.Add(n) | |
List.ofSeq mutList | |
let rec recEven (ns:int list): int list = | |
match ns with | |
| [] -> [] | |
| n :: rest -> if n % 2 = 0 then n :: recEven rest else recEven rest | |
let tailRecEven (ns: int list): int list = | |
let rec loop l acc = | |
match l with | |
| [] -> acc | |
| n :: rest -> loop rest (if n % 2 = 0 then n :: acc else acc) | |
loop ns [] |> List.rev | |
let filterEven (ns: int list): int list = | |
let isEven n = n % 2 = 0 | |
List.filter isEven ns | |
//List.filter (fun n -> n % 2 = 0) ns | |
[<EntryPoint>] | |
let main argv = | |
let numbers = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] | |
//let numbers = [1 .. 10] | |
printfn "*** Sum ***" | |
printfn "%d" (proceduralSum numbers) |> ignore | |
printfn "%d" (recSum numbers) |> ignore | |
printfn "%d" (tailRecSum numbers) |> ignore | |
printfn "%d" (foldSum numbers) |> ignore | |
printfn "%d" (foldBackSum numbers) |> ignore | |
printfn "%d" (reduceSum numbers) |> ignore | |
printfn "%d" (reduceBackSum numbers) |> ignore | |
printfn "%d" (sumSum numbers) |> ignore | |
printfn "\n*** Factorial ***" | |
printfn "%A" (proceduralFactorial 10u) |> ignore | |
printfn "%A" (recFactorial 10u) |> ignore | |
printfn "%A" (tailRecFactorial 10u) |> ignore | |
printfn "%A" (foldFactorial 10u) |> ignore | |
printfn "%A" (foldBackFactorial 10u) |> ignore | |
printfn "\n*** Fibonacci ***" | |
printfn "%d" (proceduralFib 10) |> ignore | |
printfn "%d" (recFib 10) |> ignore | |
printfn "%d" (tailRecFib 10) |> ignore | |
printfn "%d" (memoFib 10) |> ignore | |
printfn "\n*** X2 ***" | |
printfn "%A" (proceduralX2 numbers) | |
printfn "%A" (recX2 numbers) | |
printfn "%A" (tailRecX2 numbers) | |
printfn "%A" (foldX2 numbers) | |
printfn "%A" (foldBackX2 numbers) | |
printfn "%A" (mapX2 numbers) | |
printfn "\n*** Even ***" | |
printfn "%A" (proceduralEven numbers) | |
printfn "%A" (recEven numbers) | |
printfn "%A" (tailRecEven numbers) | |
printfn "%A" (filterEven numbers) | |
Console.Read() |> ignore | |
0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment