-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add an iterative rational implementation for exact results
Adds an implementation in golang using rational number types to get exact results, and an iterative algorithm for performance improvement compared to recursive approaches. Outputs to CSV for easy data integration with tooling.
- Loading branch information
Showing
4 changed files
with
88 additions
and
1 deletion.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Build go binary | ||
|
||
frog |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,39 @@ | ||
# frog_problem | ||
Here is the frog problem code I wrote in an Edinburgh pub. | ||
|
||
Feel free to make better version. This one has not changed since I wrote it. V1 was the same code but saved before I changed it to work for different distances so I have not bothered upload it as well (it was still very unifinished). | ||
Feel free to make better version. This one has not changed since I wrote it. V1 | ||
was the same code but saved before I changed it to work for different distances | ||
so I have not bothered upload it as well (it was still very unifinished). | ||
|
||
Video is here: https://youtu.be/ZLTyX4zL2Fc | ||
|
||
## Iterative Rational Implmentation | ||
|
||
Written in Golang by Taylor Wrobel | ||
|
||
Makes use of big rationals in golang to get exact expectation for all number of | ||
pads, up to and including the specified target number of pads (including target | ||
bank). Makes use of an interative approach, which performs better than its | ||
recursive equivalent (calculating all results up to 1,000 pads takes ~12.5 | ||
seconds for me). | ||
|
||
Outputs to STDOUT in CSV format with the following columns (output for `n=10` | ||
displayed in table form): | ||
|
||
n | numerator | denominator | float64 representation | ||
-- | --------- | ----------- | ---------------------- | ||
1 | 1 | 1 | 1.000000 | ||
2 | 3 | 2 | 1.500000 | ||
3 | 11 | 6 | 1.833333 | ||
4 | 25 | 12 | 2.083333 | ||
5 | 137 | 60 | 2.283333 | ||
6 | 49 | 20 | 2.450000 | ||
7 | 363 | 140 | 2.592857 | ||
8 | 761 | 280 | 2.717857 | ||
9 | 7129 | 2520 | 2.828968 | ||
10 | 7381 | 2520 | 2.928968 | ||
|
||
|
||
Building: `go build` | ||
Running: `./frog [n]` (`n` defaults to 10 if not provided) | ||
Outputting to file (on a UNIX system): `./frog 100 > output.csv` |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module wrobel.dev/frog | ||
|
||
go 1.12 |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/csv" | ||
"fmt" | ||
"math/big" | ||
"os" | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
func main() { | ||
// Parse input value from command line args. Do simple validation. | ||
n := 10 | ||
if len(os.Args) > 1 { | ||
parsed, err := strconv.ParseInt(os.Args[1], 10, 64) | ||
if err != nil || parsed < 1 { | ||
panic("Input target must be a positive integer") | ||
} | ||
n = int(parsed) | ||
} | ||
|
||
// Likelihoods is a slice that's built up iteratively, as the expected value | ||
// on lillypad n is dependent on the expected value for all lillypads from | ||
// 1 to n-1. | ||
likelihoods := make([]*big.Rat, n+1) | ||
likelihoods[0] = big.NewRat(0, 1) | ||
|
||
w := csv.NewWriter(os.Stdout) | ||
|
||
for i := 1; i <= n; i++ { | ||
expected := big.NewRat(0, 1) | ||
for j := 0; j < i; j++ { | ||
value := big.NewRat(0, 1) | ||
value.Add(big.NewRat(1, 1), likelihoods[j]) | ||
value.Mul(value, big.NewRat(1, int64(i))) | ||
|
||
expected.Add(expected, value) | ||
} | ||
likelihoods[i] = expected | ||
|
||
numDenom := strings.Split(expected.String(), "/") | ||
f, _ := expected.Float64() | ||
w.Write([]string{fmt.Sprintf("%d", i), numDenom[0], numDenom[1], fmt.Sprintf("%f", f)}) | ||
} | ||
|
||
w.Flush() | ||
} |