Skip to content

Instantly share code, notes, and snippets.

@ykon
Last active October 24, 2017 13:18
Show Gist options
  • Save ykon/56a976dd8cf68defc834051c722a5015 to your computer and use it in GitHub Desktop.
Save ykon/56a976dd8cf68defc834051c722a5015 to your computer and use it in GitHub Desktop.
Basic FP in F#
(*
* 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