Updating all of the new ones that are done.

This commit is contained in:
Brian Buller 2016-09-02 14:26:22 -05:00
parent 36dc090a89
commit ec45e6b2eb
15 changed files with 1390 additions and 12 deletions

339
go/beer-song/README.md Normal file
View File

@ -0,0 +1,339 @@
# Beer Song
Write a program which produces the lyrics to that beloved classic, that field-trip favorite: 99 Bottles of Beer on the Wall.
Note that not all verses are identical.
```plain
99 bottles of beer on the wall, 99 bottles of beer.
Take one down and pass it around, 98 bottles of beer on the wall.
98 bottles of beer on the wall, 98 bottles of beer.
Take one down and pass it around, 97 bottles of beer on the wall.
97 bottles of beer on the wall, 97 bottles of beer.
Take one down and pass it around, 96 bottles of beer on the wall.
96 bottles of beer on the wall, 96 bottles of beer.
Take one down and pass it around, 95 bottles of beer on the wall.
95 bottles of beer on the wall, 95 bottles of beer.
Take one down and pass it around, 94 bottles of beer on the wall.
94 bottles of beer on the wall, 94 bottles of beer.
Take one down and pass it around, 93 bottles of beer on the wall.
93 bottles of beer on the wall, 93 bottles of beer.
Take one down and pass it around, 92 bottles of beer on the wall.
92 bottles of beer on the wall, 92 bottles of beer.
Take one down and pass it around, 91 bottles of beer on the wall.
91 bottles of beer on the wall, 91 bottles of beer.
Take one down and pass it around, 90 bottles of beer on the wall.
90 bottles of beer on the wall, 90 bottles of beer.
Take one down and pass it around, 89 bottles of beer on the wall.
89 bottles of beer on the wall, 89 bottles of beer.
Take one down and pass it around, 88 bottles of beer on the wall.
88 bottles of beer on the wall, 88 bottles of beer.
Take one down and pass it around, 87 bottles of beer on the wall.
87 bottles of beer on the wall, 87 bottles of beer.
Take one down and pass it around, 86 bottles of beer on the wall.
86 bottles of beer on the wall, 86 bottles of beer.
Take one down and pass it around, 85 bottles of beer on the wall.
85 bottles of beer on the wall, 85 bottles of beer.
Take one down and pass it around, 84 bottles of beer on the wall.
84 bottles of beer on the wall, 84 bottles of beer.
Take one down and pass it around, 83 bottles of beer on the wall.
83 bottles of beer on the wall, 83 bottles of beer.
Take one down and pass it around, 82 bottles of beer on the wall.
82 bottles of beer on the wall, 82 bottles of beer.
Take one down and pass it around, 81 bottles of beer on the wall.
81 bottles of beer on the wall, 81 bottles of beer.
Take one down and pass it around, 80 bottles of beer on the wall.
80 bottles of beer on the wall, 80 bottles of beer.
Take one down and pass it around, 79 bottles of beer on the wall.
79 bottles of beer on the wall, 79 bottles of beer.
Take one down and pass it around, 78 bottles of beer on the wall.
78 bottles of beer on the wall, 78 bottles of beer.
Take one down and pass it around, 77 bottles of beer on the wall.
77 bottles of beer on the wall, 77 bottles of beer.
Take one down and pass it around, 76 bottles of beer on the wall.
76 bottles of beer on the wall, 76 bottles of beer.
Take one down and pass it around, 75 bottles of beer on the wall.
75 bottles of beer on the wall, 75 bottles of beer.
Take one down and pass it around, 74 bottles of beer on the wall.
74 bottles of beer on the wall, 74 bottles of beer.
Take one down and pass it around, 73 bottles of beer on the wall.
73 bottles of beer on the wall, 73 bottles of beer.
Take one down and pass it around, 72 bottles of beer on the wall.
72 bottles of beer on the wall, 72 bottles of beer.
Take one down and pass it around, 71 bottles of beer on the wall.
71 bottles of beer on the wall, 71 bottles of beer.
Take one down and pass it around, 70 bottles of beer on the wall.
70 bottles of beer on the wall, 70 bottles of beer.
Take one down and pass it around, 69 bottles of beer on the wall.
69 bottles of beer on the wall, 69 bottles of beer.
Take one down and pass it around, 68 bottles of beer on the wall.
68 bottles of beer on the wall, 68 bottles of beer.
Take one down and pass it around, 67 bottles of beer on the wall.
67 bottles of beer on the wall, 67 bottles of beer.
Take one down and pass it around, 66 bottles of beer on the wall.
66 bottles of beer on the wall, 66 bottles of beer.
Take one down and pass it around, 65 bottles of beer on the wall.
65 bottles of beer on the wall, 65 bottles of beer.
Take one down and pass it around, 64 bottles of beer on the wall.
64 bottles of beer on the wall, 64 bottles of beer.
Take one down and pass it around, 63 bottles of beer on the wall.
63 bottles of beer on the wall, 63 bottles of beer.
Take one down and pass it around, 62 bottles of beer on the wall.
62 bottles of beer on the wall, 62 bottles of beer.
Take one down and pass it around, 61 bottles of beer on the wall.
61 bottles of beer on the wall, 61 bottles of beer.
Take one down and pass it around, 60 bottles of beer on the wall.
60 bottles of beer on the wall, 60 bottles of beer.
Take one down and pass it around, 59 bottles of beer on the wall.
59 bottles of beer on the wall, 59 bottles of beer.
Take one down and pass it around, 58 bottles of beer on the wall.
58 bottles of beer on the wall, 58 bottles of beer.
Take one down and pass it around, 57 bottles of beer on the wall.
57 bottles of beer on the wall, 57 bottles of beer.
Take one down and pass it around, 56 bottles of beer on the wall.
56 bottles of beer on the wall, 56 bottles of beer.
Take one down and pass it around, 55 bottles of beer on the wall.
55 bottles of beer on the wall, 55 bottles of beer.
Take one down and pass it around, 54 bottles of beer on the wall.
54 bottles of beer on the wall, 54 bottles of beer.
Take one down and pass it around, 53 bottles of beer on the wall.
53 bottles of beer on the wall, 53 bottles of beer.
Take one down and pass it around, 52 bottles of beer on the wall.
52 bottles of beer on the wall, 52 bottles of beer.
Take one down and pass it around, 51 bottles of beer on the wall.
51 bottles of beer on the wall, 51 bottles of beer.
Take one down and pass it around, 50 bottles of beer on the wall.
50 bottles of beer on the wall, 50 bottles of beer.
Take one down and pass it around, 49 bottles of beer on the wall.
49 bottles of beer on the wall, 49 bottles of beer.
Take one down and pass it around, 48 bottles of beer on the wall.
48 bottles of beer on the wall, 48 bottles of beer.
Take one down and pass it around, 47 bottles of beer on the wall.
47 bottles of beer on the wall, 47 bottles of beer.
Take one down and pass it around, 46 bottles of beer on the wall.
46 bottles of beer on the wall, 46 bottles of beer.
Take one down and pass it around, 45 bottles of beer on the wall.
45 bottles of beer on the wall, 45 bottles of beer.
Take one down and pass it around, 44 bottles of beer on the wall.
44 bottles of beer on the wall, 44 bottles of beer.
Take one down and pass it around, 43 bottles of beer on the wall.
43 bottles of beer on the wall, 43 bottles of beer.
Take one down and pass it around, 42 bottles of beer on the wall.
42 bottles of beer on the wall, 42 bottles of beer.
Take one down and pass it around, 41 bottles of beer on the wall.
41 bottles of beer on the wall, 41 bottles of beer.
Take one down and pass it around, 40 bottles of beer on the wall.
40 bottles of beer on the wall, 40 bottles of beer.
Take one down and pass it around, 39 bottles of beer on the wall.
39 bottles of beer on the wall, 39 bottles of beer.
Take one down and pass it around, 38 bottles of beer on the wall.
38 bottles of beer on the wall, 38 bottles of beer.
Take one down and pass it around, 37 bottles of beer on the wall.
37 bottles of beer on the wall, 37 bottles of beer.
Take one down and pass it around, 36 bottles of beer on the wall.
36 bottles of beer on the wall, 36 bottles of beer.
Take one down and pass it around, 35 bottles of beer on the wall.
35 bottles of beer on the wall, 35 bottles of beer.
Take one down and pass it around, 34 bottles of beer on the wall.
34 bottles of beer on the wall, 34 bottles of beer.
Take one down and pass it around, 33 bottles of beer on the wall.
33 bottles of beer on the wall, 33 bottles of beer.
Take one down and pass it around, 32 bottles of beer on the wall.
32 bottles of beer on the wall, 32 bottles of beer.
Take one down and pass it around, 31 bottles of beer on the wall.
31 bottles of beer on the wall, 31 bottles of beer.
Take one down and pass it around, 30 bottles of beer on the wall.
30 bottles of beer on the wall, 30 bottles of beer.
Take one down and pass it around, 29 bottles of beer on the wall.
29 bottles of beer on the wall, 29 bottles of beer.
Take one down and pass it around, 28 bottles of beer on the wall.
28 bottles of beer on the wall, 28 bottles of beer.
Take one down and pass it around, 27 bottles of beer on the wall.
27 bottles of beer on the wall, 27 bottles of beer.
Take one down and pass it around, 26 bottles of beer on the wall.
26 bottles of beer on the wall, 26 bottles of beer.
Take one down and pass it around, 25 bottles of beer on the wall.
25 bottles of beer on the wall, 25 bottles of beer.
Take one down and pass it around, 24 bottles of beer on the wall.
24 bottles of beer on the wall, 24 bottles of beer.
Take one down and pass it around, 23 bottles of beer on the wall.
23 bottles of beer on the wall, 23 bottles of beer.
Take one down and pass it around, 22 bottles of beer on the wall.
22 bottles of beer on the wall, 22 bottles of beer.
Take one down and pass it around, 21 bottles of beer on the wall.
21 bottles of beer on the wall, 21 bottles of beer.
Take one down and pass it around, 20 bottles of beer on the wall.
20 bottles of beer on the wall, 20 bottles of beer.
Take one down and pass it around, 19 bottles of beer on the wall.
19 bottles of beer on the wall, 19 bottles of beer.
Take one down and pass it around, 18 bottles of beer on the wall.
18 bottles of beer on the wall, 18 bottles of beer.
Take one down and pass it around, 17 bottles of beer on the wall.
17 bottles of beer on the wall, 17 bottles of beer.
Take one down and pass it around, 16 bottles of beer on the wall.
16 bottles of beer on the wall, 16 bottles of beer.
Take one down and pass it around, 15 bottles of beer on the wall.
15 bottles of beer on the wall, 15 bottles of beer.
Take one down and pass it around, 14 bottles of beer on the wall.
14 bottles of beer on the wall, 14 bottles of beer.
Take one down and pass it around, 13 bottles of beer on the wall.
13 bottles of beer on the wall, 13 bottles of beer.
Take one down and pass it around, 12 bottles of beer on the wall.
12 bottles of beer on the wall, 12 bottles of beer.
Take one down and pass it around, 11 bottles of beer on the wall.
11 bottles of beer on the wall, 11 bottles of beer.
Take one down and pass it around, 10 bottles of beer on the wall.
10 bottles of beer on the wall, 10 bottles of beer.
Take one down and pass it around, 9 bottles of beer on the wall.
9 bottles of beer on the wall, 9 bottles of beer.
Take one down and pass it around, 8 bottles of beer on the wall.
8 bottles of beer on the wall, 8 bottles of beer.
Take one down and pass it around, 7 bottles of beer on the wall.
7 bottles of beer on the wall, 7 bottles of beer.
Take one down and pass it around, 6 bottles of beer on the wall.
6 bottles of beer on the wall, 6 bottles of beer.
Take one down and pass it around, 5 bottles of beer on the wall.
5 bottles of beer on the wall, 5 bottles of beer.
Take one down and pass it around, 4 bottles of beer on the wall.
4 bottles of beer on the wall, 4 bottles of beer.
Take one down and pass it around, 3 bottles of beer on the wall.
3 bottles of beer on the wall, 3 bottles of beer.
Take one down and pass it around, 2 bottles of beer on the wall.
2 bottles of beer on the wall, 2 bottles of beer.
Take one down and pass it around, 1 bottle of beer on the wall.
1 bottle of beer on the wall, 1 bottle of beer.
Take it down and pass it around, no more bottles of beer on the wall.
No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.
```
## For bonus points
Did you get the tests passing and the code clean? If you want to, these
are some additional things you could try:
* Remove as much duplication as you possibly can.
* Optimize for readability, even if it means introducing duplication.
* If you've removed all the duplication, do you have a lot of
conditionals? Try replacing the conditionals with polymorphism, if it
applies in this language. How readable is it?
Then please share your thoughts in a comment on the submission. Did this
experiment make the code better? Worse? Did you learn anything from it?
To run the tests simply run the command `go test` in the exercise directory.
If the test suite contains benchmarks, you can run these with the `-bench`
flag:
go test -bench .
For more detailed info about the Go track see the [help
page](http://exercism.io/languages/go).
## Source
Learn to Program by Chris Pine [http://pine.fm/LearnToProgram/?Chapter=06](http://pine.fm/LearnToProgram/?Chapter=06)
## Submitting Incomplete Problems
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

66
go/beer-song/beer.go Normal file
View File

@ -0,0 +1,66 @@
package beer
import (
"errors"
"strconv"
"strings"
)
// buildBase builds the basic "x bottle(s) of beer"
func buildBase(num int) string {
var ret string
if num == 0 {
ret = "No more"
} else {
ret = strconv.Itoa(num)
}
ret += " bottle"
if num != 1 {
ret += "s"
}
ret += " of beer"
return ret
}
// Verse generates a single verse
func Verse(num int) (string, error) {
var ret string
if num > 99 || num < 0 {
return "", errors.New("Invalid verse requested")
}
ret += buildBase(num) + " on the wall, " + strings.ToLower(buildBase(num)) + ".\n"
if num == 0 {
ret += "Go to the store and buy some more, " + buildBase(99) + " on the wall.\n"
} else {
ret += "Take "
if num == 1 {
ret += "it "
} else {
ret += "one "
}
ret += "down and pass it around, " + strings.ToLower(buildBase(num-1)) + " on the wall.\n"
}
return ret, nil
}
// Verses generates all verses starting at 'st' and going to 'end'
func Verses(st, end int) (string, error) {
if st < end {
return "", errors.New("Start less than stop")
}
var r, ret string
var err error
for i := st; i >= end; i-- {
if r, err = Verse(i); err != nil {
return "", err
}
ret += r + "\n"
}
return ret, nil
}
// Song generates the entire song (all 100 verses)
func Song() string {
r, _ := Verses(99, 0)
return r
}

139
go/beer-song/beer_test.go Normal file
View File

@ -0,0 +1,139 @@
package beer
import (
"testing"
)
const verse8 = "8 bottles of beer on the wall, 8 bottles of beer.\nTake one down and pass it around, 7 bottles of beer on the wall.\n"
const verse3 = "3 bottles of beer on the wall, 3 bottles of beer.\nTake one down and pass it around, 2 bottles of beer on the wall.\n"
const verse2 = "2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n"
const verse1 = "1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n"
const verse0 = "No more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n"
const verses86 = `8 bottles of beer on the wall, 8 bottles of beer.
Take one down and pass it around, 7 bottles of beer on the wall.
7 bottles of beer on the wall, 7 bottles of beer.
Take one down and pass it around, 6 bottles of beer on the wall.
6 bottles of beer on the wall, 6 bottles of beer.
Take one down and pass it around, 5 bottles of beer on the wall.
`
const verses75 = `7 bottles of beer on the wall, 7 bottles of beer.
Take one down and pass it around, 6 bottles of beer on the wall.
6 bottles of beer on the wall, 6 bottles of beer.
Take one down and pass it around, 5 bottles of beer on the wall.
5 bottles of beer on the wall, 5 bottles of beer.
Take one down and pass it around, 4 bottles of beer on the wall.
`
var verseTestCases = []struct {
description string
verse int
expectedVerse string
expectErr bool
}{
{"a typical verse", 8, verse8, false},
{"another typical verse", 3, verse3, false},
{"verse 2", 2, verse2, false},
{"verse 1", 1, verse1, false},
{"verse 0", 0, verse0, false},
{"invalid verse", 104, "", true},
}
func TestBottlesVerse(t *testing.T) {
for _, tt := range verseTestCases {
actualVerse, err := Verse(tt.verse)
if actualVerse != tt.expectedVerse {
t.Fatalf("Verse(%d):\nexpected\n%s\nactual\n%s", tt.verse, tt.expectedVerse, actualVerse)
}
// if we expect an error and there isn't one
if tt.expectErr && err == nil {
t.Errorf("Verse(%d): expected an error, but error is nil", tt.verse)
}
// if we don't expect an error and there is one
if !tt.expectErr && err != nil {
t.Errorf("Verse(%d): expected no error, but error is: %s", tt.verse, err)
}
}
}
var versesTestCases = []struct {
description string
upperBound int
lowerBound int
expectedVerse string
expectErr bool
}{
{"multiple verses", 8, 6, verses86, false},
{"a different set of verses", 7, 5, verses75, false},
{"invalid start", 109, 5, "", true},
{"invalid stop", 99, -20, "", true},
{"start less than stop", 8, 14, "", true},
}
func TestSeveralVerses(t *testing.T) {
for _, tt := range versesTestCases {
actualVerse, err := Verses(tt.upperBound, tt.lowerBound)
if actualVerse != tt.expectedVerse {
t.Fatalf("Verses(%d, %d):\nexpected\n%s\nactual\n%s", tt.upperBound, tt.lowerBound, tt.expectedVerse, actualVerse)
}
// if we expect an error and there isn't one
if tt.expectErr && err == nil {
t.Errorf("Verses(%d, %d): expected an error, but error is nil", tt.upperBound, tt.lowerBound)
}
// if we don't expect an error and there is one
if !tt.expectErr && err != nil {
t.Errorf("Verses(%d, %d): expected no error, but error is: %s", tt.upperBound, tt.lowerBound, err)
}
}
}
func BenchmarkSeveralVerses(b *testing.B) {
b.StopTimer()
for _, tt := range versesTestCases {
b.StartTimer()
for i := 0; i < b.N; i++ {
Verses(tt.upperBound, tt.lowerBound)
}
b.StopTimer()
}
}
func TestEntireSong(t *testing.T) {
expected, err := Verses(99, 0)
if err != nil {
t.Fatalf("unexpected error calling Verses(99,0)")
}
actual := Song()
if expected != actual {
msg := `
Did not sing the whole song correctly.
Expected:
%v
Actual:
%v
`
t.Fatalf(msg, expected, actual)
}
}
func BenchmarkEntireSong(b *testing.B) {
for i := 0; i < b.N; i++ {
Song()
}
}

View File

@ -0,0 +1,56 @@
# Diffie Hellman
Diffie-Hellman key exchange.
Alice and Bob use Diffie-Hellman key exchange to share secrets. They
start with prime numbers, pick private keys, generate and share public
keys, and then generate a shared secret key.
## Step 0
The test program supplies prime numbers p and g.
## Step 1
Alice picks a private key, a, greater than 1 and less than p. Bob does
the same to pick a private key b.
## Step 2
Alice calculates a public key A.
A = g**a mod p
Using the same p and g, Bob similarly calculates a public key B from his
private key b.
## Step 3
Alice and Bob exchange public keys. Alice calculates secret key s.
s = B**a mod p
Bob calculates
s = A**b mod p
The calculations produce the same result! Alice and Bob now share
secret s.
To run the tests simply run the command `go test` in the exercise directory.
If the test suite contains benchmarks, you can run these with the `-bench`
flag:
go test -bench .
For more detailed info about the Go track see the [help
page](http://exercism.io/languages/go).
## Source
Wikipedia, 1024 bit key from www.cryptopp.com/wiki. [http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange](http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange)
## Submitting Incomplete Problems
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

View File

@ -0,0 +1,183 @@
// Diffie-Hellman-Merkle key exchange
//
// Step 1: PrivateKey(p *big.Int) *big.Int
// Step 2: PublicKey(private, p *big.Int, g int64) *big.Int
// Step 2.1: NewPair(p *big.Int, g int64) (private, public *big.Int)
// Step 3: SecretKey(private1, public2, p *big.Int) *big.Int
//
// Private keys should be generated randomly.
package diffiehellman
import (
"math/big"
"testing"
)
type testCase struct {
g int64 // prime, generator
p *big.Int // prime, modulus
a, b *big.Int // private keys
A, B *big.Int // public keys
s *big.Int // secret key
}
// WP example
var smallTest = testCase{
5,
big.NewInt(23),
big.NewInt(6), big.NewInt(15),
big.NewInt(8), big.NewInt(19),
big.NewInt(2),
}
// 1024 bit example modulus from cryptopp.com wiki, random private keys
var biggerTest = testCase{
2,
mph("ab359aa76a6773ed7a93b214db0c25d0160817b8a893c001c761e198a3694509" +
"ebe87a5313e0349d95083e5412c9fc815bfd61f95ddece43376550fdc624e92f" +
"f38a415783b97261204e05d65731bba1ccff0e84c8cd2097b75feca1029261ae" +
"19a389a2e15d2939314b184aef707b82eb94412065181d23e04bf065f4ac413f"),
mph("2f6afe91cb53ecfa463d45cd800c948f7cb83bb9ddc62a07b5b3fd302d0cdf52" +
"18ae53ad015a632d137001a3b34239d54715606a292b6cf895b09d7dcf1bdf7a"),
mph("3651007bfa8a8b1cbaed2ae9326327599249c3bb6e9d8744b7407f3d4732cb8a" +
"0708d95c382747bad640d444f135e7e599618d11b15b9ef32e7ac7194e547f4b"),
mph("57d5489e3858cbd8fae75120907d1521f8e935cce2206d285b11762847e2a4c4" +
"a341a4eea18bdd8b40036c8d0004ffc323d5ae19da55176b08ff6f2d0ac97c65" +
"357c1f16756a6901ff926c8544c8af0a90ed2705966851f79a115cb77aac66be" +
"ceff569aadd7f02859539c28d55c08c62a03e45613bc52d205ace0704ea7c610"),
mph("6b189a36db5ca3ff83b66fb2c226078294c323f4c7cef35c506c237b0db7906d" +
"64cceb05af15a3603a30fd49834d3a6971d917f520d9a577c159d3b7d2bd8813" +
"5d19db47a9618340e4a51ec8845dbf5d50a4c6f14d6161def1eeaacecee8018f" +
"8816113a294959399989b759f4618e35dbffc570ab2a5a74ac59fccef35f684c"),
mph("64f74babc466f8e56d9b77ce2cc65d65fe1603b931c018b98a2a615d66172590" +
"803a94ac230db02de4b8ae567497c1844a6f7bd5bed69b95d3137acc1a6462d5" +
"aeba5b2b83a0e6b8ed4c072e5135a57c87b654ebe04cf128bbff49ee06df33b7" +
"8615e0067fdc9df22f7673b1e0501fb57598c7bff9ff173ddff47270fbd6f98f"),
}
// must parse hex, short name contrived just to make test data line up with
// tab width 4.
func mph(h string) *big.Int {
p, ok := new(big.Int).SetString(h, 16)
if !ok {
panic("invalid hex: " + h)
}
return p
}
var tests = []testCase{
smallTest,
biggerTest,
}
var _one = big.NewInt(1)
// test that PrivateKey returns numbers in range, returns different numbers.
func TestPrivateKey(t *testing.T) {
priv := func(p *big.Int) *big.Int {
a := PrivateKey(p)
if a.Cmp(_one) <= 0 || a.Cmp(p) >= 0 {
t.Fatalf("PrivateKey(%d) = %d, out of range (1, %d)", p, a, p)
}
return a
}
ms := map[string]bool{}
mb := map[string]bool{}
for i := 0; i < 100; i++ {
ms[priv(smallTest.p).String()] = true
mb[priv(biggerTest.p).String()] = true
}
if len(ms) == 1 {
t.Fatalf("For prime %d same key generated every time. "+
"Want random keys.", smallTest.p)
}
if len(mb) < 100 {
t.Fatal("For prime %d duplicate keys generated. "+
"Want unique keys.", biggerTest.p)
}
}
// test that PublicKey returns known results.
func TestPublicKey(t *testing.T) {
tp := func(a, A, p *big.Int, g int64) {
if k := PublicKey(a, p, g); k.Cmp(A) != 0 {
t.Fatalf("PublicKey(%x,\n%x,\n%d)\n= %x,\nwant %x.",
a, p, g, k, A)
}
}
for _, test := range tests {
tp(test.a, test.A, test.p, test.g)
tp(test.b, test.B, test.p, test.g)
}
}
// test that SecretKey returns known results.
func TestSecretKeys(t *testing.T) {
tp := func(a, B, p, s *big.Int) {
if k := SecretKey(a, B, p); k.Cmp(s) != 0 {
t.Fatalf("SecretKey(%x,\n%x,\n%x)\n= %x,\nwant %x.",
a, B, p, k, s)
}
}
for _, test := range tests {
tp(test.a, test.B, test.p, test.s)
tp(test.b, test.A, test.p, test.s)
}
}
// test that NewPair produces working keys
func TestNewPair(t *testing.T) {
p, g := biggerTest.p, biggerTest.g
test := func(a, A *big.Int) {
if a.Cmp(_one) <= 0 || a.Cmp(p) >= 0 {
t.Fatalf("NewPair(%d, %d) private key = %d, out of range (1, %d)",
p, g, a, p)
}
if A.Cmp(_one) <= 0 || A.Cmp(p) >= 0 {
t.Fatalf("NewPair(%d, %d) public key = %d, out of range (1, %d)",
p, g, A, p)
}
}
a, A := NewPair(p, g)
test(a, A)
for i := 0; i < 20; i++ {
b, B := NewPair(p, g)
test(b, B)
sa := SecretKey(a, B, p)
sb := SecretKey(b, A, p)
if sa.Cmp(sb) != 0 {
t.Fatalf("NewPair() produced non-working keys.")
}
a, A = b, B
}
}
func BenchmarkPrivateKey(b *testing.B) {
for i := 0; i < b.N; i++ {
PrivateKey(biggerTest.p)
}
}
func BenchmarkPublicKey(b *testing.B) {
for i := 0; i < b.N; i++ {
PublicKey(biggerTest.a, biggerTest.p, biggerTest.g)
}
}
func BenchmarkNewPair(b *testing.B) {
for i := 0; i < b.N; i++ {
NewPair(biggerTest.p, biggerTest.g)
}
}
func BenchmarkSecretKey(b *testing.B) {
for i := 0; i < b.N; i++ {
SecretKey(biggerTest.a, biggerTest.B, biggerTest.p)
}
}

View File

@ -0,0 +1,34 @@
package diffiehellman
import (
"math/big"
"math/rand"
"time"
)
// Random number generator
var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
// PrivateKey generates a number greater than 1 and less than p
func PrivateKey(p *big.Int) *big.Int {
ret := &big.Int{}
return ret.Add(big.NewInt(2), ret.Rand(rnd, ret.Sub(p, big.NewInt(2))))
}
// PublicKey generates the public key for private key p
func PublicKey(pKey, p *big.Int, g int64) *big.Int {
ret := big.NewInt(g)
return ret.Exp(ret, pKey, p)
}
// NewPair generates a public/private key pair from given primes p & g
func NewPair(p *big.Int, g int64) (*big.Int, *big.Int) {
priv := PrivateKey(p)
return priv, PublicKey(priv, p, g)
}
// SecretKey returns a secret key given private & public keys and the prime p
func SecretKey(priv, pub, p *big.Int) *big.Int {
ret := &big.Int{}
return ret.Exp(pub, priv, p)
}

View File

@ -2,21 +2,21 @@ package prime
var sieve []int
// Nth finds the nth prime and 'true' if the 0th prime wasn't requested
func Nth(n int) (int, bool) {
if len(sieve) == 0 {
sieve = append(sieve, 0)
sieve = append(sieve, 2)
}
if n == 0 {
return 0, false
}
for i := sieve[len(sieve)-1]; n <= len(sieve); i++ {
// Check if i is a prime
if len(sieve) == 0 {
// Let's just do some initialization
sieve = append(sieve, 0)
sieve = append(sieve, 2)
}
sieveLen := len(sieve)
for i := sieve[len(sieve)-1]; sieveLen <= n; i++ {
isPrime := true
for j := 1; j < len(sieve); j++ {
for j := 1; j < sieveLen; j++ {
if i%sieve[j] == 0 {
// Not a prime
isPrime = false
break
}
@ -24,9 +24,7 @@ func Nth(n int) (int, bool) {
if isPrime {
// Found a new prime
sieve = append(sieve, i)
if len(sieve) >= n {
break
}
sieveLen = len(sieve)
}
}
return sieve[n], true

96
go/ocr-numbers/README.md Normal file
View File

@ -0,0 +1,96 @@
# Ocr Numbers
Write a program that, given a 3 x 4 grid of pipes, underscores, and spaces, can determine which number is represented, or whether it is garbled.
# Step One
To begin with, convert a simple binary font to a string containing 0 or 1.
The binary font uses pipes and underscores, four rows high and three columns wide.
```
_ #
| | # zero.
|_| #
# the fourth row is always blank
```
Is converted to "0"
```
#
| # one.
| #
# (blank fourth row)
```
Is converted to "1"
If the input is the correct size, but not recognizable, your program should return '?'
If the input is the incorrect size, your program should return an error.
# Step Two
Update your program to recognize multi-character binary strings, replacing garbled numbers with ?
# Step Three
Update your program to recognize all numbers 0 through 9, both individually and as part of a larger string.
```
_
_|
|_
```
Is converted to "2"
```
_ _ _ _ _ _ _ _ #
| _| _||_||_ |_ ||_||_|| | # decimal numbers.
||_ _| | _||_| ||_| _||_| #
# fourth line is always blank
```
Is converted to "1234567890"
# Step Four
Update your program to handle multiple numbers, one per line. When converting several lines, join the lines with commas.
```
_ _
| _| _|
||_ _|
_ _
|_||_ |_
| _||_|
_ _ _
||_||_|
||_| _|
```
Is converted to "123,456,789"
To run the tests simply run the command `go test` in the exercise directory.
If the test suite contains benchmarks, you can run these with the `-bench`
flag:
go test -bench .
For more detailed info about the Go track see the [help
page](http://exercism.io/languages/go).
## Source
Inspired by the Bank OCR kata [http://codingdojo.org/cgi-bin/wiki.pl?KataBankOCR](http://codingdojo.org/cgi-bin/wiki.pl?KataBankOCR)
## Submitting Incomplete Problems
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

65
go/ocr-numbers/ocr.go Normal file
View File

@ -0,0 +1,65 @@
package ocr
import "strings"
// recognizeDigit takes a 3x4 grid of pipes, underscores, and spaces
// and determines the digit represented.
func recognizeDigit(in string) string {
switch in {
case "\n _ \n| |\n|_|\n ":
return "0"
case "\n \n |\n |\n ":
return "1"
case "\n _ \n _|\n|_ \n ":
return "2"
case "\n _ \n _|\n _|\n ":
return "3"
case "\n \n|_|\n |\n ":
return "4"
case "\n _ \n|_ \n _|\n ":
return "5"
case "\n _ \n|_ \n|_|\n ":
return "6"
case "\n _ \n |\n |\n ":
return "7"
case "\n _ \n|_|\n|_|\n ":
return "8"
case "\n _ \n|_|\n _|\n ":
return "9"
}
return "?"
}
// parseChar takes 3 lines and a number and returns
// the string value of that character
func parseChar(lines []string, num int) string {
startIdx := 3 * num
lenNeed := startIdx + 3
if len(lines[0]) < lenNeed || len(lines[1]) < lenNeed {
return ""
}
char := "\n" + lines[0][(startIdx+0):(startIdx+3)]
char += "\n" + lines[1][(startIdx+0):(startIdx+3)]
char += "\n" + lines[2][(startIdx+0):(startIdx+3)]
char += "\n" + lines[3][(startIdx+0):(startIdx+3)]
return recognizeDigit(char)
}
// Recognize takes a string, splits it up by \n and
// then sends 4 line chunks and calls parseChar on it
func Recognize(in string) []string {
var ret []string
lines := strings.Split(in, "\n")
numRet := len(lines) / 4
for i := 0; i < numRet; i++ {
var retString string
startIdx := (i * 4) + 1
procLines := lines[startIdx : startIdx+4]
numChars := len(lines[startIdx]) / 3
for j := 0; j < numChars; j++ {
retString += parseChar(procLines, j)
}
ret = append(ret, retString)
}
return ret
}

View File

@ -0,0 +1,130 @@
// Go requirements:
//
// Define a function recognizeDigit as README Step 1 except make it recognize
// all ten digits 0 to 9. Pick what you like for parameters and return values
// but make it useful as a subroutine for README step 2.
//
// For README Step 2 define,
//
// func Recognize(string) []string
//
// and implement it using recognizeDigit.
//
// Input strings tested here have a \n at the beginning of each line and
// no trailing \n on the last line. (This makes for readable raw string
// literals.)
//
// For bonus points, gracefully handle misformatted data. What should you
// do with a partial cell? Discard it? Pad with spaces? Report it with a
// "?" character? What should you do if the first character is not \n?
package ocr
import (
"reflect"
"testing"
)
var tests = []struct {
in string
out []string
}{
{`
_
| |
|_|
`, []string{"0"}},
{`
|
|
`, []string{"1"}},
{`
_
_|
|_
`, []string{"2"}},
{`
_
_|
_|
`, []string{"3"}},
{`
|_|
|
`, []string{"4"}},
{`
_
|_
_|
`, []string{"5"}},
{`
_
|_
|_|
`, []string{"6"}},
{`
_
|
|
`, []string{"7"}},
{`
_
|_|
|_|
`, []string{"8"}},
{`
_
|_|
_|
`, []string{"9"}},
{`
_
|| |
||_|
`, []string{"10"}},
{`
| |
| |
`, []string{"?"}},
{`
_ _ _ _
| || | || | | || || |
| ||_| ||_| | ||_||_|
`, []string{"110101100"}},
{`
_ _ _
| || | || | || || |
| | _| ||_| | ||_||_|
`, []string{"11?10?1?0"}},
{`
_ _ _ _ _ _ _ _
| _| _||_||_ |_ ||_||_|| |
||_ _| | _||_| ||_| _||_|
`, []string{"1234567890"}},
{`
_ _
| _| _|
||_ _|
_ _
|_||_ |_
| _||_|
_ _ _
||_||_|
||_| _|
`, []string{"123", "456", "789"}},
}
var _ = recognizeDigit // step 1.
func TestRecognize(t *testing.T) {
for _, test := range tests {
if res := Recognize(test.in); !reflect.DeepEqual(res, test.out) {
t.Fatalf("Recognize(`%s`) = %q, want %q.", test.in, res, test.out)
}
}
}

59
go/octal/README.md Normal file
View File

@ -0,0 +1,59 @@
# Octal
Write a program that will convert a octal number, represented as a string (e.g. '1735263'), to its decimal equivalent using first principles (i.e. no, you may not use built-in or external libraries to accomplish the conversion).
Implement octal to decimal conversion. Given an octal input
string, your program should produce a decimal output.
## Note
- Implement the conversion yourself.
Do not use something else to perform the conversion for you.
- Treat invalid input as octal 0.
## About Octal (Base-8)
Decimal is a base-10 system.
A number 233 in base 10 notation can be understood
as a linear combination of powers of 10:
- The rightmost digit gets multiplied by 10^0 = 1
- The next number gets multiplied by 10^1 = 10
- ...
- The *n*th number gets multiplied by 10^*(n-1)*.
- All these values are summed.
So:
```
233 # decimal
= 2*10^2 + 3*10^1 + 3*10^0
= 2*100 + 3*10 + 3*1
```
Octal is similar, but uses powers of 8 rather than powers of 10.
So:
```
233 # octal
= 2*8^2 + 3*8^1 + 3*8^0
= 2*64 + 3*8 + 3*1
= 128 + 24 + 3
= 155
```
To run the tests simply run the command `go test` in the exercise directory.
If the test suite contains benchmarks, you can run these with the `-bench`
flag:
go test -bench .
For more detailed info about the Go track see the [help
page](http://exercism.io/languages/go).
## Source
All of Computer Science [http://www.wolframalpha.com/input/?i=base+8](http://www.wolframalpha.com/input/?i=base+8)
## Submitting Incomplete Problems
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

24
go/octal/octal.go Normal file
View File

@ -0,0 +1,24 @@
package octal
import (
"errors"
"math"
)
// ParseOctal takes a string representation of an octal number
// and returns the decimal value of that number, or an error if it
// was unparseable as an octal number
func ParseOctal(v string) (int64, error) {
var ret float64
octLen := float64(len(v))
for i := range v {
octLen--
switch {
case v[i] > 47 && v[i] < 56:
ret = ret + float64(v[i]-48)*math.Pow(8, octLen)
default:
return 0, errors.New("Unparseable as octal")
}
}
return int64(ret), nil
}

50
go/octal/octal_test.go Normal file
View File

@ -0,0 +1,50 @@
package octal
import (
"testing"
)
var testCases = []struct {
input string
expectedNum int64
expectErr bool
}{
{"1", 1, false},
{"10", 8, false},
{"1234567", 342391, false},
{"carrot", 0, true},
{"35682", 0, true},
}
func TestParseOctal(t *testing.T) {
for _, test := range testCases {
actualNum, actualErr := ParseOctal(test.input)
if actualNum != test.expectedNum {
t.Fatalf("ParseOctal(%s): expected[%d], actual [%d]",
test.input, test.expectedNum, actualNum)
}
// if we expect an error and there isn't one
if test.expectErr && actualErr == nil {
t.Errorf("ParseOctal(%s): expected an error, but error is nil", test.input)
}
// if we don't expect an error and there is one
if !test.expectErr && actualErr != nil {
t.Errorf("ParseOctal(%s): expected no error, but error is: %s", test.input, actualErr)
}
}
}
func BenchmarkParseOctal(b *testing.B) {
b.StopTimer()
for _, test := range testCases {
b.StartTimer()
for i := 0; i < b.N; i++ {
ParseOctal(test.input)
}
b.StopTimer()
}
}

89
go/wordy/README.md Normal file
View File

@ -0,0 +1,89 @@
# Wordy
Write a program that takes a word problem and returns the answer as an integer.
## Step 1
E.g.
> What is 5 plus 13?
The program should handle large numbers and negative numbers.
Remember, that these are verbal word problems, not treated as you
normally would treat a written problem. This means that you calculate
as you move forward each step. In other words, you should ignore order
of operations. 3 + 2 * 3 = 15, not 9.
Use the tests to drive your solution by deleting the `skip` in one test
at a time.
## Step 2
E.g.
> What is 5 plus 13?
> What is 7 minus 5?
> What is 6 multiplied by 4?
> What is 25 divided by 5?
## Step 3
E.g.
> What is 5 plus 13 plus 6?
> What is 7 minus 5 minus 1?
> What is 9 minus 3 plus 5?
> What is 3 plus 5 minus 8?
## Step 4
E.g.
> What is 5 plus 13?
> What is 7 minus 5?
> What is 6 times 4?
> What is 25 divided by 5?
> What is 78 plus 5 minus 3?
> What is 18 times 3 plus 16?
> What is 4 times 3 divided by 6?
> What is 4 plus 3 times 2?
## Extensions
Implement questions of the type:
> What is 2 raised to the 5th power?
Remember to write failing tests for this code.
To run the tests simply run the command `go test` in the exercise directory.
If the test suite contains benchmarks, you can run these with the `-bench`
flag:
go test -bench .
For more detailed info about the Go track see the [help
page](http://exercism.io/languages/go).
## Source
Inspired by one of the generated questions in the Extreme Startup game. [https://github.com/rchatley/extreme_startup](https://github.com/rchatley/extreme_startup)
## Submitting Incomplete Problems
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

50
go/wordy/wordy_test.go Normal file
View File

@ -0,0 +1,50 @@
package wordy
import "testing"
var tests = []struct {
q string
a int
ok bool
}{
{"What is 1 plus 1?", 2, true},
{"What is 53 plus 2?", 55, true},
{"What is -1 plus -10?", -11, true},
{"What is 123 plus 45678?", 45801, true},
{"What is 4 minus -12?", 16, true},
{"What is -3 multiplied by 25?", -75, true},
{"What is 33 divided by -3?", -11, true},
{"What is 1 plus 1 plus 1?", 3, true},
{"What is 1 plus 5 minus -2?", 8, true},
{"What is 20 minus 4 minus 13?", 3, true},
{"What is 17 minus 6 plus 3?", 14, true},
{"What is 2 multiplied by -2 multiplied by 3?", -12, true},
{"What is -3 plus 7 multiplied by -2?", -8, true},
{"What is -12 divided by 2 divided by -3?", 2, true},
{"What is 53 cubed?", 0, false},
{"Who is the president of the United States?", 0, false},
}
func TestAnswer(t *testing.T) {
for _, test := range tests {
switch a, ok := Answer(test.q); {
case !ok:
if test.ok {
t.Errorf("Answer(%q) returned ok = false, expecting true.", test.q)
}
case !test.ok:
t.Errorf("Answer(%q) = %d, %t, expecting ok = false.", test.q, a, ok)
case a != test.a:
t.Errorf("Answer(%q) = %d, want %d.", test.q, a, test.a)
}
}
}
// Benchmark combined time to answer all questions.
func BenchmarkAnswer(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range tests {
Answer(test.q)
}
}
}