Simulating coin flips and plotting a histogram

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
5
down vote
favorite
I started playing around recently with F# and I find it quite elegant and succinct language.
A common problem I like to solve in every language I start to learn is the coin flip problem, with the code below being the solution to this particular problem.
What the code does is to flip a coin N times and perform M tests for each flip series. Finally, it prints in console a binomial distribution visual.
I am new to F# and I might being hasty here, I probably will learn this myself much later, but is anybody that can suggest a refactoring? Is it possible to make this even more succinct?
I solved the problem with code very similar to imperative style and I refactored my way to the following code, trying keep it as much as declarative as I could.
open System
let heads (random: Random) =
random.Next(0, 2) = 1
let add x y = x + y
let rec calculateHeads n random =
match n with
| 0 -> 0
| _ ->
let result = calculateHeads (n - 1) random
let addToResult v = add v result
match heads (random) with
| true -> addToResult 1
| false -> addToResult 0
let rec fill frequency n m random =
match m with
| v when v < 0 -> frequency
| _ ->
let count = calculateHeads n random
Array.set frequency count (frequency.[count] + 1)
fill frequency n (m - 1) random
let getFrequencies n m =
let random = new Random()
let frequency = Array.create (n + 1) 0
fill frequency n m random
let rec displayAsterisk length =
match length with
| v when v = 1 -> "*"
| v when v < 1 -> ""
| _ -> "*" + (displayAsterisk (length - 10))
let rec displayRecursive list =
match list with
| -> ()
| head::tail ->
displayRecursive tail
printfn "%d%s -- (%d)" head (displayAsterisk (head)) head
let displayCoin (frequency:int) =
displayRecursive (frequency |> Array.toList)
[<EntryPoint>]
let main argv =
let frequency = getFrequencies 32 1000
displayCoin frequency
0
f# statistics simulation ascii-art data-visualization
add a comment |Â
up vote
5
down vote
favorite
I started playing around recently with F# and I find it quite elegant and succinct language.
A common problem I like to solve in every language I start to learn is the coin flip problem, with the code below being the solution to this particular problem.
What the code does is to flip a coin N times and perform M tests for each flip series. Finally, it prints in console a binomial distribution visual.
I am new to F# and I might being hasty here, I probably will learn this myself much later, but is anybody that can suggest a refactoring? Is it possible to make this even more succinct?
I solved the problem with code very similar to imperative style and I refactored my way to the following code, trying keep it as much as declarative as I could.
open System
let heads (random: Random) =
random.Next(0, 2) = 1
let add x y = x + y
let rec calculateHeads n random =
match n with
| 0 -> 0
| _ ->
let result = calculateHeads (n - 1) random
let addToResult v = add v result
match heads (random) with
| true -> addToResult 1
| false -> addToResult 0
let rec fill frequency n m random =
match m with
| v when v < 0 -> frequency
| _ ->
let count = calculateHeads n random
Array.set frequency count (frequency.[count] + 1)
fill frequency n (m - 1) random
let getFrequencies n m =
let random = new Random()
let frequency = Array.create (n + 1) 0
fill frequency n m random
let rec displayAsterisk length =
match length with
| v when v = 1 -> "*"
| v when v < 1 -> ""
| _ -> "*" + (displayAsterisk (length - 10))
let rec displayRecursive list =
match list with
| -> ()
| head::tail ->
displayRecursive tail
printfn "%d%s -- (%d)" head (displayAsterisk (head)) head
let displayCoin (frequency:int) =
displayRecursive (frequency |> Array.toList)
[<EntryPoint>]
let main argv =
let frequency = getFrequencies 32 1000
displayCoin frequency
0
f# statistics simulation ascii-art data-visualization
add a comment |Â
up vote
5
down vote
favorite
up vote
5
down vote
favorite
I started playing around recently with F# and I find it quite elegant and succinct language.
A common problem I like to solve in every language I start to learn is the coin flip problem, with the code below being the solution to this particular problem.
What the code does is to flip a coin N times and perform M tests for each flip series. Finally, it prints in console a binomial distribution visual.
I am new to F# and I might being hasty here, I probably will learn this myself much later, but is anybody that can suggest a refactoring? Is it possible to make this even more succinct?
I solved the problem with code very similar to imperative style and I refactored my way to the following code, trying keep it as much as declarative as I could.
open System
let heads (random: Random) =
random.Next(0, 2) = 1
let add x y = x + y
let rec calculateHeads n random =
match n with
| 0 -> 0
| _ ->
let result = calculateHeads (n - 1) random
let addToResult v = add v result
match heads (random) with
| true -> addToResult 1
| false -> addToResult 0
let rec fill frequency n m random =
match m with
| v when v < 0 -> frequency
| _ ->
let count = calculateHeads n random
Array.set frequency count (frequency.[count] + 1)
fill frequency n (m - 1) random
let getFrequencies n m =
let random = new Random()
let frequency = Array.create (n + 1) 0
fill frequency n m random
let rec displayAsterisk length =
match length with
| v when v = 1 -> "*"
| v when v < 1 -> ""
| _ -> "*" + (displayAsterisk (length - 10))
let rec displayRecursive list =
match list with
| -> ()
| head::tail ->
displayRecursive tail
printfn "%d%s -- (%d)" head (displayAsterisk (head)) head
let displayCoin (frequency:int) =
displayRecursive (frequency |> Array.toList)
[<EntryPoint>]
let main argv =
let frequency = getFrequencies 32 1000
displayCoin frequency
0
f# statistics simulation ascii-art data-visualization
I started playing around recently with F# and I find it quite elegant and succinct language.
A common problem I like to solve in every language I start to learn is the coin flip problem, with the code below being the solution to this particular problem.
What the code does is to flip a coin N times and perform M tests for each flip series. Finally, it prints in console a binomial distribution visual.
I am new to F# and I might being hasty here, I probably will learn this myself much later, but is anybody that can suggest a refactoring? Is it possible to make this even more succinct?
I solved the problem with code very similar to imperative style and I refactored my way to the following code, trying keep it as much as declarative as I could.
open System
let heads (random: Random) =
random.Next(0, 2) = 1
let add x y = x + y
let rec calculateHeads n random =
match n with
| 0 -> 0
| _ ->
let result = calculateHeads (n - 1) random
let addToResult v = add v result
match heads (random) with
| true -> addToResult 1
| false -> addToResult 0
let rec fill frequency n m random =
match m with
| v when v < 0 -> frequency
| _ ->
let count = calculateHeads n random
Array.set frequency count (frequency.[count] + 1)
fill frequency n (m - 1) random
let getFrequencies n m =
let random = new Random()
let frequency = Array.create (n + 1) 0
fill frequency n m random
let rec displayAsterisk length =
match length with
| v when v = 1 -> "*"
| v when v < 1 -> ""
| _ -> "*" + (displayAsterisk (length - 10))
let rec displayRecursive list =
match list with
| -> ()
| head::tail ->
displayRecursive tail
printfn "%d%s -- (%d)" head (displayAsterisk (head)) head
let displayCoin (frequency:int) =
displayRecursive (frequency |> Array.toList)
[<EntryPoint>]
let main argv =
let frequency = getFrequencies 32 1000
displayCoin frequency
0
f# statistics simulation ascii-art data-visualization
edited May 26 at 5:30
200_success
123k14143399
123k14143399
asked May 25 at 23:25
gdyrrahitis
1284
1284
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
I had some smaller points to make on several aspects of your code but I won't mention them since the whole thing can be written more idiomatic and simple style without using any recursion or mutation.
Note the use of Seq.sumBy and Array.countBy to cut down on a lot of the work:
let random = System.Random()
let heads () = random.Next(0, 2) = 1
let calculateHeads n =
1 .. n |> Seq.sumBy (fun _ -> if heads () then 1 else 0)
let getFrequencies n m =
let counts =
Array.init m (fun _ -> calculateHeads n)
|> Array.countBy id
|> Map
Array.init (n + 1) (fun i -> counts.TryFind i |> Option.defaultValue 0)
let displayCoin frequency =
for c in frequency do
printfn "%d%s -- (%d)" c (String.replicate (c / 10) "*") c
let frequency = getFrequencies 32 1000
displayCoin frequency
I also made random a module level value instead of passing it around everywhere. The downside of this is you can't test individual functions deterministically.
If you're not already doing so, you should send code to F# interactive in your IDE to get a much faster feedback cycle for trying out ideas and exploring data.
Just a minor fix, ondisplayCoinmethod, it should print the current index in array, so it'd look like this:let displayCoin (frequency:int) = for i = 0 to frequency.Length - 1 do let value = frequency.[i] printfn "%d%s -- (%d)" i (String.replicate (value / 10) "*") valueGreat answer nonetheless, simplifies my code greatly!
â gdyrrahitis
May 27 at 22:13
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
I had some smaller points to make on several aspects of your code but I won't mention them since the whole thing can be written more idiomatic and simple style without using any recursion or mutation.
Note the use of Seq.sumBy and Array.countBy to cut down on a lot of the work:
let random = System.Random()
let heads () = random.Next(0, 2) = 1
let calculateHeads n =
1 .. n |> Seq.sumBy (fun _ -> if heads () then 1 else 0)
let getFrequencies n m =
let counts =
Array.init m (fun _ -> calculateHeads n)
|> Array.countBy id
|> Map
Array.init (n + 1) (fun i -> counts.TryFind i |> Option.defaultValue 0)
let displayCoin frequency =
for c in frequency do
printfn "%d%s -- (%d)" c (String.replicate (c / 10) "*") c
let frequency = getFrequencies 32 1000
displayCoin frequency
I also made random a module level value instead of passing it around everywhere. The downside of this is you can't test individual functions deterministically.
If you're not already doing so, you should send code to F# interactive in your IDE to get a much faster feedback cycle for trying out ideas and exploring data.
Just a minor fix, ondisplayCoinmethod, it should print the current index in array, so it'd look like this:let displayCoin (frequency:int) = for i = 0 to frequency.Length - 1 do let value = frequency.[i] printfn "%d%s -- (%d)" i (String.replicate (value / 10) "*") valueGreat answer nonetheless, simplifies my code greatly!
â gdyrrahitis
May 27 at 22:13
add a comment |Â
up vote
2
down vote
accepted
I had some smaller points to make on several aspects of your code but I won't mention them since the whole thing can be written more idiomatic and simple style without using any recursion or mutation.
Note the use of Seq.sumBy and Array.countBy to cut down on a lot of the work:
let random = System.Random()
let heads () = random.Next(0, 2) = 1
let calculateHeads n =
1 .. n |> Seq.sumBy (fun _ -> if heads () then 1 else 0)
let getFrequencies n m =
let counts =
Array.init m (fun _ -> calculateHeads n)
|> Array.countBy id
|> Map
Array.init (n + 1) (fun i -> counts.TryFind i |> Option.defaultValue 0)
let displayCoin frequency =
for c in frequency do
printfn "%d%s -- (%d)" c (String.replicate (c / 10) "*") c
let frequency = getFrequencies 32 1000
displayCoin frequency
I also made random a module level value instead of passing it around everywhere. The downside of this is you can't test individual functions deterministically.
If you're not already doing so, you should send code to F# interactive in your IDE to get a much faster feedback cycle for trying out ideas and exploring data.
Just a minor fix, ondisplayCoinmethod, it should print the current index in array, so it'd look like this:let displayCoin (frequency:int) = for i = 0 to frequency.Length - 1 do let value = frequency.[i] printfn "%d%s -- (%d)" i (String.replicate (value / 10) "*") valueGreat answer nonetheless, simplifies my code greatly!
â gdyrrahitis
May 27 at 22:13
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
I had some smaller points to make on several aspects of your code but I won't mention them since the whole thing can be written more idiomatic and simple style without using any recursion or mutation.
Note the use of Seq.sumBy and Array.countBy to cut down on a lot of the work:
let random = System.Random()
let heads () = random.Next(0, 2) = 1
let calculateHeads n =
1 .. n |> Seq.sumBy (fun _ -> if heads () then 1 else 0)
let getFrequencies n m =
let counts =
Array.init m (fun _ -> calculateHeads n)
|> Array.countBy id
|> Map
Array.init (n + 1) (fun i -> counts.TryFind i |> Option.defaultValue 0)
let displayCoin frequency =
for c in frequency do
printfn "%d%s -- (%d)" c (String.replicate (c / 10) "*") c
let frequency = getFrequencies 32 1000
displayCoin frequency
I also made random a module level value instead of passing it around everywhere. The downside of this is you can't test individual functions deterministically.
If you're not already doing so, you should send code to F# interactive in your IDE to get a much faster feedback cycle for trying out ideas and exploring data.
I had some smaller points to make on several aspects of your code but I won't mention them since the whole thing can be written more idiomatic and simple style without using any recursion or mutation.
Note the use of Seq.sumBy and Array.countBy to cut down on a lot of the work:
let random = System.Random()
let heads () = random.Next(0, 2) = 1
let calculateHeads n =
1 .. n |> Seq.sumBy (fun _ -> if heads () then 1 else 0)
let getFrequencies n m =
let counts =
Array.init m (fun _ -> calculateHeads n)
|> Array.countBy id
|> Map
Array.init (n + 1) (fun i -> counts.TryFind i |> Option.defaultValue 0)
let displayCoin frequency =
for c in frequency do
printfn "%d%s -- (%d)" c (String.replicate (c / 10) "*") c
let frequency = getFrequencies 32 1000
displayCoin frequency
I also made random a module level value instead of passing it around everywhere. The downside of this is you can't test individual functions deterministically.
If you're not already doing so, you should send code to F# interactive in your IDE to get a much faster feedback cycle for trying out ideas and exploring data.
answered May 26 at 11:04
TheQuickBrownFox
38116
38116
Just a minor fix, ondisplayCoinmethod, it should print the current index in array, so it'd look like this:let displayCoin (frequency:int) = for i = 0 to frequency.Length - 1 do let value = frequency.[i] printfn "%d%s -- (%d)" i (String.replicate (value / 10) "*") valueGreat answer nonetheless, simplifies my code greatly!
â gdyrrahitis
May 27 at 22:13
add a comment |Â
Just a minor fix, ondisplayCoinmethod, it should print the current index in array, so it'd look like this:let displayCoin (frequency:int) = for i = 0 to frequency.Length - 1 do let value = frequency.[i] printfn "%d%s -- (%d)" i (String.replicate (value / 10) "*") valueGreat answer nonetheless, simplifies my code greatly!
â gdyrrahitis
May 27 at 22:13
Just a minor fix, on
displayCoin method, it should print the current index in array, so it'd look like this: let displayCoin (frequency:int) = for i = 0 to frequency.Length - 1 do let value = frequency.[i] printfn "%d%s -- (%d)" i (String.replicate (value / 10) "*") value Great answer nonetheless, simplifies my code greatly!â gdyrrahitis
May 27 at 22:13
Just a minor fix, on
displayCoin method, it should print the current index in array, so it'd look like this: let displayCoin (frequency:int) = for i = 0 to frequency.Length - 1 do let value = frequency.[i] printfn "%d%s -- (%d)" i (String.replicate (value / 10) "*") value Great answer nonetheless, simplifies my code greatly!â gdyrrahitis
May 27 at 22:13
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f195190%2fsimulating-coin-flips-and-plotting-a-histogram%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password