Initial Commit

This commit is contained in:
2016-08-13 18:20:14 -05:00
commit 50f4a86fd8
408 changed files with 15301 additions and 0 deletions

39
go/allergies/README.md Normal file
View File

@@ -0,0 +1,39 @@
# Allergies
Write a program that, given a person's allergy score, can tell them whether or not they're allergic to a given item, and their full list of allergies.
An allergy test produces a single numeric score which contains the
information about all the allergies the person has (that they were
tested for).
The list of items (and their value) that were tested are:
* eggs (1)
* peanuts (2)
* shellfish (4)
* strawberries (8)
* tomatoes (16)
* chocolate (32)
* pollen (64)
* cats (128)
So if Tom is allergic to peanuts and chocolate, he gets a score of 34.
Now, given just that score of 34, your program should be able to say:
- Whether Tom is allergic to any one of those allergens listed above.
- All the allergens Tom is allergic to.
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
Jumpstart Lab Warm-up [view source](http://jumpstartlab.com)

44
go/allergies/allergies.go Normal file
View File

@@ -0,0 +1,44 @@
package allergies
// Allergies takes a score and returns all of the
// things that the score is allergic to.
func Allergies(score int) []string {
var ret []string
for _, v := range getAllAllergens() {
if AllergicTo(score, v) {
ret = append(ret, v)
}
}
return ret
}
// AllergicTo takes a score and an allergen and returns if
// That score is allergic to that thing.
func AllergicTo(score int, tst string) bool {
return score&getScoreForAllergen(tst) == getScoreForAllergen(tst)
}
func getAllAllergens() []string {
return []string{
"eggs",
"peanuts",
"shellfish",
"strawberries",
"tomatoes",
"chocolate",
"pollen",
"cats",
}
}
func getScoreForAllergen(tst string) int {
ret := 1
for _, v := range getAllAllergens() {
if tst == v {
return ret
}
ret *= 2
}
return -1
}

View File

@@ -0,0 +1,79 @@
package allergies
import (
"fmt"
"testing"
)
var allergiesTests = []struct {
expected []string
input int
}{
{[]string{}, 0},
{[]string{"eggs"}, 1},
{[]string{"peanuts"}, 2},
{[]string{"strawberries"}, 8},
{[]string{"eggs", "peanuts"}, 3},
{[]string{"eggs", "shellfish"}, 5},
{[]string{"strawberries", "tomatoes", "chocolate", "pollen", "cats"}, 248},
{[]string{"eggs", "peanuts", "shellfish", "strawberries", "tomatoes", "chocolate", "pollen", "cats"}, 255},
{[]string{"eggs", "shellfish", "strawberries", "tomatoes", "chocolate", "pollen", "cats"}, 509},
}
func TestAllergies(t *testing.T) {
for _, test := range allergiesTests {
actual := Allergies(test.input)
if fmt.Sprintf("%s", actual) != fmt.Sprintf("%s", test.expected) {
t.Fatalf("FAIL: Allergies(%d): expected %s, actual %s", test.input, test.expected, actual)
} else {
t.Logf("PASS: Allergic to %v", test.expected)
}
}
}
func BenchmarkAllergies(b *testing.B) {
b.StopTimer()
for _, test := range allergicToTests {
b.StartTimer()
for i := 0; i < b.N; i++ {
Allergies(test.i)
}
b.StopTimer()
}
}
var allergicToTests = []struct {
expected bool
i int
allergen string
}{
{false, 0, "peanuts"},
{false, 0, "cats"},
{false, 0, "strawberries"},
{true, 1, "eggs"},
{true, 5, "eggs"},
}
func TestAllergicTo(t *testing.T) {
for _, test := range allergicToTests {
actual := AllergicTo(test.i, test.allergen)
if actual != test.expected {
t.Fatalf("FAIL: AllergicTo(%d, %s): expected %t, actual %t", test.i, test.allergen, test.expected, actual)
} else {
t.Logf("PASS: AllergicTo(%d, %s) %t", test.i, test.allergen, actual)
}
}
}
func BenchmarkAllergicTo(b *testing.B) {
b.StopTimer()
for _, test := range allergicToTests {
b.StartTimer()
for i := 0; i < b.N; i++ {
AllergicTo(test.i, test.allergen)
}
b.StopTimer()
}
}

21
go/anagram/README.md Normal file
View File

@@ -0,0 +1,21 @@
# Anagram
Write a program that, given a word and a list of possible anagrams, selects the correct sublist.
Given `"listen"` and a list of candidates like `"enlists" "google"
"inlets" "banana"` the program should return a list containing
`"inlets"`.
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 Extreme Startup game [view source](https://github.com/rchatley/extreme_startup)

28
go/anagram/anagram.go Normal file
View File

@@ -0,0 +1,28 @@
package anagram
import "strings"
// Detect returns all candidates that are anagrams of subject
func Detect(subject string, candidates []string) []string {
var ret []string
for i := range candidates {
if isAnagram(subject, candidates[i]) {
ret = append(ret, strings.ToLower(candidates[i]))
}
}
return ret
}
func isAnagram(s, c string) bool {
s = strings.ToLower(s)
c = strings.ToLower(c)
if s == c || len(s) != len(c) {
return false
}
for _, v := range strings.Split(s, "") {
if strings.Count(s, v) != strings.Count(c, v) {
return false
}
}
return true
}

172
go/anagram/anagram_test.go Normal file
View File

@@ -0,0 +1,172 @@
package anagram
import (
"fmt"
"sort"
"testing"
)
var testCases = []struct {
subject string
candidates []string
expected []string
description string
}{
{
subject: "diaper",
candidates: []string{
"hello",
"world",
"zombies",
"pants",
},
expected: []string{},
description: "no matches",
},
{
subject: "ant",
candidates: []string{
"tan",
"stand",
"at",
},
expected: []string{"tan"},
description: "simple anagram",
},
{
subject: "listen",
candidates: []string{
"enlists",
"google",
"inlets",
"banana",
},
expected: []string{"inlets"},
description: "another simple anagram",
},
{
subject: "master",
candidates: []string{
"stream",
"pigeon",
"maters",
},
expected: []string{"maters", "stream"},
description: "multiple anagrams",
},
{
subject: "allergy",
candidates: []string{
"gallery",
"ballerina",
"regally",
"clergy",
"largely",
"leading",
},
expected: []string{"gallery", "largely", "regally"},
description: "multiple anagrams (again)",
},
{
subject: "galea",
candidates: []string{
"eagle",
},
expected: []string{},
description: "does not confuse different duplicates",
},
{
subject: "corn",
candidates: []string{
"corn",
"dark",
"Corn",
"rank",
"CORN",
"cron",
"park",
},
expected: []string{"cron"},
description: "identical word is not anagram",
},
{
subject: "mass",
candidates: []string{
"last",
},
expected: []string{},
description: "eliminate anagrams with same checksum",
},
{
subject: "good",
candidates: []string{
"dog",
"goody",
},
expected: []string{},
description: "eliminate anagram subsets",
},
{
subject: "Orchestra",
candidates: []string{
"cashregiser",
"carthorse",
"radishes",
},
expected: []string{"carthorse"},
description: "subjects are case insensitive",
},
{
subject: "orchestra",
candidates: []string{
"cashregiser",
"Carthorse",
"radishes",
},
expected: []string{"carthorse"},
description: "candidates are case insensitive",
},
}
func equal(a []string, b []string) bool {
if len(b) != len(a) {
return false
}
sort.Strings(a)
sort.Strings(b)
return fmt.Sprintf("%v", a) == fmt.Sprintf("%v", b)
}
func TestDetectAnagrams(t *testing.T) {
for _, tt := range testCases {
actual := Detect(tt.subject, tt.candidates)
if !equal(tt.expected, actual) {
msg := `FAIL: %s
Subject %s
Candidates %v
Expected %v
Got %v
`
t.Fatalf(msg, tt.description, tt.subject, tt.candidates, tt.expected, actual)
} else {
t.Logf("PASS: %s", tt.description)
}
}
}
func BenchmarkDetectAnagrams(b *testing.B) {
b.StopTimer()
for _, tt := range testCases {
b.StartTimer()
for i := 0; i < b.N; i++ {
Detect(tt.subject, tt.candidates)
}
b.StopTimer()
}
}

40
go/bank-account/README.md Normal file
View File

@@ -0,0 +1,40 @@
# Bank Account
Bank accounts can be accessed in different ways at the same time.
A bank account can be accessed in multiple ways. Clients can make
deposits and withdrawals using the internet, mobile phones, etc. Shops
can charge against the account.
Create an account that can be accessed from multiple threads/processes
(terminology depends on your programming language).
It should be possible to close an account; operations against a closed
account must fail.
## Instructions
Run the test file, and fix each of the errors in turn. When you get the
first test to pass, go to the first pending or skipped test, and make
that pass as well. When all of the tests are passing, feel free to
submit.
Remember that passing code is just the first step. The goal is to work
towards a solution that is as readable and expressive as you can make
it.
Have fun!
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://help.exercism.io/getting-started-with-go.html).
## Source
[view source]()

View File

@@ -0,0 +1,58 @@
package account
import "sync"
// Account just represents a user's account
type Account struct {
sync.RWMutex
balance int
closed bool
}
// Open returns a new account
func Open(amt int) *Account {
a := new(Account)
_, ok := a.Deposit(amt)
if ok {
return a
}
return nil
}
// Close returns the payout amount and an 'ok' flag
func (a *Account) Close() (int, bool) {
a.Lock()
ret := a.balance
if a.closed {
a.Unlock()
return 0, false
}
a.closed = true
a.balance = 0
a.Unlock()
return ret, true
}
// Balance returns the current account balance
// and an 'ok' flag
func (a *Account) Balance() (int, bool) {
if a.closed {
return 0, false
}
return a.balance, true
}
// Deposit takes an amount (can be a withdrawal)
// and returns the new balance and an 'ok' flag
func (a *Account) Deposit(amount int) (int, bool) {
var ret int
var ok bool
a.Lock()
if !a.closed && a.balance+amount >= 0 {
a.balance += amount
ret = a.balance
ok = true
}
a.Unlock()
return ret, ok
}

View File

@@ -0,0 +1,289 @@
// API:
//
// Open(initalDeposit int64) *Account
// (Account) Close() (payout int64, ok bool)
// (Account) Balance() (balance int64, ok bool)
// (Account) Deposit(amount uint64) (newBalance int64, ok bool)
//
// If Open is given a negative initial deposit, it must return nil.
// Deposit must handle a negative amount as a withdrawal.
// If any Account method is called on an closed account, it must not modify
// the account and must return ok = false.
package account
import (
"runtime"
"sync"
"sync/atomic"
"testing"
"time"
)
func TestSeqOpenBalanceClose(t *testing.T) {
// open account
const amt = 10
a := Open(amt)
if a == nil {
t.Fatalf("Open(%d) = nil, want non-nil *Account.", amt)
}
t.Logf("Account 'a' opened with initial balance of %d.", amt)
// verify balance after open
switch b, ok := a.Balance(); {
case !ok:
t.Fatal("a.Balance() returned !ok, want ok.")
case b != amt:
t.Fatalf("a.Balance() = %d, want %d", b, amt)
}
// close account
switch p, ok := a.Close(); {
case !ok:
t.Fatalf("a.Close() returned !ok, want ok.")
case p != amt:
t.Fatalf("a.Close() returned payout = %d, want %d.", p, amt)
}
t.Log("Account 'a' closed.")
// verify balance no longer accessible
if b, ok := a.Balance(); ok {
t.Log("Balance still available on closed account.")
t.Fatalf("a.Balance() = %d, %t. Want ok == false", b, ok)
}
}
func TestSeqOpenDepositClose(t *testing.T) {
// open account
const openAmt = 10
a := Open(openAmt)
if a == nil {
t.Fatalf("Open(%d) = nil, want non-nil *Account.", openAmt)
}
t.Logf("Account 'a' opened with initial balance of %d.", openAmt)
// deposit
const depAmt = 20
const newAmt = openAmt + depAmt
switch b, ok := a.Deposit(depAmt); {
case !ok:
t.Fatalf("a.Deposit(%d) returned !ok, want ok.", depAmt)
case b != openAmt+depAmt:
t.Fatalf("a.Deposit(%d) = %d, want new balance = %d", depAmt, b, newAmt)
}
t.Logf("Deposit of %d accepted to account 'a'", depAmt)
// close account
switch p, ok := a.Close(); {
case !ok:
t.Fatalf("a.Close() returned !ok, want ok.")
case p != newAmt:
t.Fatalf("a.Close() returned payout = %d, want %d.", p, newAmt)
}
t.Log("Account 'a' closed.")
// verify deposits no longer accepted
if b, ok := a.Deposit(1); ok {
t.Log("Deposit accepted on closed account.")
t.Fatalf("a.Deposit(1) = %d, %t. Want ok == false", b, ok)
}
}
func TestMoreSeqCases(t *testing.T) {
// open account 'a' as before
const openAmt = 10
a := Open(openAmt)
if a == nil {
t.Fatalf("Open(%d) = nil, want non-nil *Account.", openAmt)
}
t.Logf("Account 'a' opened with initial balance of %d.", openAmt)
// open account 'z' with zero balance
z := Open(0)
if z == nil {
t.Fatal("Open(0) = nil, want non-nil *Account.")
}
t.Log("Account 'z' opened with initial balance of 0.")
// attempt to open account with negative opening balance
if Open(-10) != nil {
t.Fatal("Open(-10) seemed to work, " +
"want nil result for negative opening balance.")
}
// verify both balances a and z still there
switch b, ok := a.Balance(); {
case !ok:
t.Fatal("a.Balance() returned !ok, want ok.")
case b != openAmt:
t.Fatalf("a.Balance() = %d, want %d", b, openAmt)
}
switch b, ok := z.Balance(); {
case !ok:
t.Fatal("z.Balance() returned !ok, want ok.")
case b != 0:
t.Fatalf("z.Balance() = %d, want 0", b)
}
// withdrawals
const wAmt = 3
const newAmt = openAmt - wAmt
switch b, ok := a.Deposit(-wAmt); {
case !ok:
t.Fatalf("a.Deposit(%d) returned !ok, want ok.", -wAmt)
case b != newAmt:
t.Fatalf("a.Deposit(%d) = %d, want new balance = %d", -wAmt, b, newAmt)
}
t.Logf("Withdrawal of %d accepted from account 'a'", wAmt)
if _, ok := z.Deposit(-1); ok {
t.Fatal("z.Deposit(-1) returned ok, want !ok.")
}
// verify both balances
switch b, ok := a.Balance(); {
case !ok:
t.Fatal("a.Balance() returned !ok, want ok.")
case b != newAmt:
t.Fatalf("a.Balance() = %d, want %d", b, newAmt)
}
switch b, ok := z.Balance(); {
case !ok:
t.Fatal("z.Balance() returned !ok, want ok.")
case b != 0:
t.Fatalf("z.Balance() = %d, want 0", b)
}
// close just z
switch p, ok := z.Close(); {
case !ok:
t.Fatalf("z.Close() returned !ok, want ok.")
case p != 0:
t.Fatalf("z.Close() returned payout = %d, want 0.", p)
}
t.Log("Account 'z' closed.")
// verify 'a' balance one more time
switch b, ok := a.Balance(); {
case !ok:
t.Fatal("a.Balance() returned !ok, want ok.")
case b != newAmt:
t.Fatalf("a.Balance() = %d, want %d", b, newAmt)
}
}
func TestConcClose(t *testing.T) {
if runtime.NumCPU() < 2 {
t.Skip("Multiple CPU cores required for concurrency tests.")
}
if runtime.GOMAXPROCS(0) < 2 {
runtime.GOMAXPROCS(2)
}
// test competing close attempts
for rep := 0; rep < 1000; rep++ {
const openAmt = 10
a := Open(openAmt)
if a == nil {
t.Fatalf("Open(%d) = nil, want non-nil *Account.", openAmt)
}
var start sync.WaitGroup
start.Add(1)
const closeAttempts = 10
res := make(chan string)
for i := 0; i < closeAttempts; i++ {
go func() { // on your mark,
start.Wait() // get set...
switch p, ok := a.Close(); {
case !ok:
if p != 0 {
t.Errorf("a.Close() = %d, %t. "+
"Want payout = 0 for unsuccessful close", p, ok)
res <- "fail"
} else {
res <- "already closed"
}
case p != openAmt:
t.Errorf("a.Close() = %d, %t. "+
"Want payout = %d for successful close", p, ok, openAmt)
res <- "fail"
default:
res <- "close" // exactly one goroutine should reach here
}
}()
}
start.Done() // ...go
var closes, fails int
for i := 0; i < closeAttempts; i++ {
switch <-res {
case "close":
closes++
case "fail":
fails++
}
}
switch {
case fails > 0:
t.FailNow() // error already logged by other goroutine
case closes == 0:
t.Fatal("Concurrent a.Close() attempts all failed. " +
"Want one to succeed.")
case closes > 1:
t.Fatalf("%d concurrent a.Close() attempts succeeded, "+
"each paying out %d!. Want just one to succeed.",
closes, openAmt)
}
}
}
func TestConcDeposit(t *testing.T) {
if runtime.NumCPU() < 2 {
t.Skip("Multiple CPU cores required for concurrency tests.")
}
if runtime.GOMAXPROCS(0) < 2 {
runtime.GOMAXPROCS(2)
}
a := Open(0)
if a == nil {
t.Fatal("Open(0) = nil, want non-nil *Account.")
}
const amt = 10
const c = 1000
var negBal int32
var start, g sync.WaitGroup
start.Add(1)
g.Add(3 * c)
for i := 0; i < c; i++ {
go func() { // deposit
start.Wait()
a.Deposit(amt) // ignore return values
g.Done()
}()
go func() { // withdraw
start.Wait()
for {
if _, ok := a.Deposit(-amt); ok {
break
}
time.Sleep(time.Microsecond) // retry
}
g.Done()
}()
go func() { // watch that balance stays >= 0
start.Wait()
if p, _ := a.Balance(); p < 0 {
atomic.StoreInt32(&negBal, 1)
}
g.Done()
}()
}
start.Done()
g.Wait()
if negBal == 1 {
t.Fatal("Balance went negative with concurrent deposits and " +
"withdrawals. Want balance always >= 0.")
}
if p, ok := a.Balance(); !ok || p != 0 {
t.Fatalf("After equal concurrent deposits and withdrawals, "+
"a.Balance = %d, %t. Want 0, true", p, ok)
}
}

43
go/binary/README.md Normal file
View File

@@ -0,0 +1,43 @@
# Binary
Write a program that will convert a binary number, represented as a string (e.g. '101010'), to its decimal equivalent using first principles
Implement binary to decimal conversion. Given a binary input
string, your program should produce a decimal output. The
program should handle invalid inputs.
## Note
- Implement the conversion yourself.
Do not use something else to perform the conversion for you.
## About Binary (Base-2)
Decimal is a base-10 system.
A number 23 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: `23 => 2*10^1 + 3*10^0 => 2*10 + 3*1 = 23 base 10`
Binary is similar, but uses powers of 2 rather than powers of 10.
So: `101 => 1*2^2 + 0*2^1 + 1*2^0 => 1*4 + 0*2 + 1*1 => 4 + 1 => 5 base 10`.
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 [view source](http://www.wolframalpha.com/input/?i=binary&a=*C.binary-_*MathWorld-)

22
go/binary/binary.go Normal file
View File

@@ -0,0 +1,22 @@
package binary
import "fmt"
// ParseBinary takes a binary string and returns the
// integer representation of it.
func ParseBinary(bin string) (int, error) {
var ret int
currSpot := 1
for len(bin) > 0 {
v := bin[len(bin)-1]
if v != '0' && v != '1' {
return 0, fmt.Errorf("Invalid String")
}
if v == '1' {
ret = ret + currSpot
}
currSpot = currSpot * 2
bin = bin[:len(bin)-1]
}
return ret, nil
}

55
go/binary/binary_test.go Normal file
View File

@@ -0,0 +1,55 @@
package binary
import (
"testing"
)
// You must implement the function,
//
// func ParseBinary(string) (int, error)
//
// It is standard for Go functions to return error values to report error conditions.
// The test cases below are all valid binary numbers however. For this exercise you
// may simply return nil for the error value in all cases.
//
// For bonus points though, what errors might be possible when parsing a number?
// Can you add code to detect error conditions and return appropriate error values?
var testCases = []struct {
binary string
expected int
}{
{"1", 1},
{"10", 2},
{"11", 3},
{"100", 4},
{"1001", 9},
{"11010", 26},
{"10001101000", 1128},
{"0", 0},
}
func TestParseBinary(t *testing.T) {
for _, tt := range testCases {
actual, err := ParseBinary(tt.binary)
// We don't expect errors for any of the test cases.
if err != nil {
t.Fatalf("ParseBinary(%v) returned error %q. Error not expected.",
tt.binary, err)
}
// Well, we don't expect wrong answers either.
if actual != tt.expected {
t.Fatalf("ParseBinary(%v): actual %d, expected %v",
tt.binary, actual, tt.expected)
}
}
}
// Benchmark combined time for all tests
func BenchmarkBinary(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, tt := range testCases {
ParseBinary(tt.binary)
}
}
}

44
go/bob/README.md Normal file
View File

@@ -0,0 +1,44 @@
# Bob
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
Bob answers 'Sure.' if you ask him a question.
He answers 'Whoa, chill out!' if you yell at him.
He says 'Fine. Be that way!' if you address him without actually saying
anything.
He answers 'Whatever.' to anything else.
## Instructions
Run the test file, and fix each of the errors in turn. When you get the
first test to pass, go to the first pending or skipped test, and make
that pass as well. When all of the tests are passing, feel free to
submit.
Remember that passing code is just the first step. The goal is to work
towards a solution that is as readable and expressive as you can make
it.
Please make your solution as general as possible. Good code doesn't just
pass the test suite, it works with any input that fits the
specification.
Have fun!
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 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. [view source](http://pine.fm/LearnToProgram/?Chapter=06)

19
go/bob/bob.go Normal file
View File

@@ -0,0 +1,19 @@
package bob
import "strings"
// TestVersion is an exercism thing
const TestVersion = 1
// Hey provokes a response from Bob
func Hey(inp string) string {
inp = strings.TrimSpace(inp)
if inp == "" {
return "Fine. Be that way!"
} else if inp == strings.ToUpper(inp) && inp != strings.ToLower(inp) {
return "Whoa, chill out!"
} else if strings.HasSuffix(inp, "?") {
return "Sure."
}
return "Whatever."
}

33
go/bob/bob_test.go Normal file
View File

@@ -0,0 +1,33 @@
package bob
import "testing"
const testVersion = 1
// Retired testVersions
// (none) 4a9e144a3c5dc0d9773f4cf641ffe3efe48641d8
func TestHeyBob(t *testing.T) {
if TestVersion != testVersion {
t.Fatalf("Found TestVersion = %v, want %v", TestVersion, testVersion)
}
for _, tt := range testCases {
actual := Hey(tt.input)
if actual != tt.expected {
msg := `
ALICE (%s): %q
BOB: %s
Expected Bob to respond: %s`
t.Fatalf(msg, tt.description, tt.input, actual, tt.expected)
}
}
}
func BenchmarkBob(b *testing.B) {
for _, tt := range testCases {
for i := 0; i < b.N; i++ {
Hey(tt.input)
}
}
}

141
go/bob/cases_test.go Normal file
View File

@@ -0,0 +1,141 @@
package bob
// Source: exercism/x-common
// Commit: 945d08e Merge pull request #50 from soniakeys/master
var testCases = []struct {
description string
input string
expected string
}{
{
"stating something",
"Tom-ay-to, tom-aaaah-to.",
"Whatever.",
},
{
"shouting",
"WATCH OUT!",
"Whoa, chill out!",
},
{
"shouting gibberish",
"FCECDFCAAB",
"Whoa, chill out!",
},
{
"asking a question",
"Does this cryogenic chamber make me look fat?",
"Sure.",
},
{
"asking a numeric question",
"You are, what, like 15?",
"Sure.",
},
{
"asking gibberish",
"fffbbcbeab?",
"Sure.",
},
{
"talking forcefully",
"Let's go make out behind the gym!",
"Whatever.",
},
{
"using acronyms in regular speech",
"It's OK if you don't want to go to the DMV.",
"Whatever.",
},
{
"forceful question",
"WHAT THE HELL WERE YOU THINKING?",
"Whoa, chill out!",
},
{
"shouting numbers",
"1, 2, 3 GO!",
"Whoa, chill out!",
},
{
"only numbers",
"1, 2, 3",
"Whatever.",
},
{
"question with only numbers",
"4?",
"Sure.",
},
{
"shouting with special characters",
"ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!",
"Whoa, chill out!",
},
{
"shouting with umlauts",
"ÜMLÄÜTS!",
"Whoa, chill out!",
},
{
"calmly speaking with umlauts",
"ÜMLäÜTS!",
"Whatever.",
},
{
"shouting with no exclamation mark",
"I HATE YOU",
"Whoa, chill out!",
},
{
"statement containing question mark",
"Ending with ? means a question.",
"Whatever.",
},
{
"non-letters with question",
":) ?",
"Sure.",
},
{
"prattling on",
"Wait! Hang on. Are you going to be OK?",
"Sure.",
},
{
"silence",
"",
"Fine. Be that way!",
},
{
"prolonged silence",
" ",
"Fine. Be that way!",
},
{
"alternate silence",
"\t\t\t\t\t\t\t\t\t\t",
"Fine. Be that way!",
},
{
"multiple line question",
"\nDoes this cryogenic chamber make me look fat?\nno",
"Whatever.",
},
{
"starting with whitespace",
" hmmmmmmm...",
"Whatever.",
},
{
"ending with whitespace",
"Okay if like my spacebar quite a bit? ",
"Sure.",
},
{
"other whitespace",
"\n\r \t\v\u00a0\u2002",
"Fine. Be that way!",
},
}

20
go/bracket-push/README.md Normal file
View File

@@ -0,0 +1,20 @@
# Bracket Push
Make sure the brackets and braces all match.
Ensure that all the brackets and braces are matched correctly,
and nested correctly.
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://help.exercism.io/getting-started-with-go.html).
## Source
Ginna Baker [view source]()

View File

@@ -0,0 +1,26 @@
package bracket_push
// Bracket makes sure that all brackets match
func Bracket(s string) (bool, error) {
// Set up a map of matches that we care about
matches := make(map[byte]byte)
matches['}'] = '{'
matches[')'] = '('
matches[']'] = '['
var pairs []byte
for i := range s {
if v, ok := matches[s[i]]; ok {
// Found a match, it's a closing bracket
if len(pairs) == 0 || pairs[len(pairs)-1] != v {
return false, nil
}
pairs = pairs[:len(pairs)-1]
} else {
pairs = append(pairs, s[i])
}
}
if len(pairs) > 0 {
return false, nil
}
return true, nil
}

View File

@@ -0,0 +1,72 @@
package bracket_push
import (
"testing"
)
var testCases = []struct {
input string
expected bool
}{
{
input: "",
expected: true,
},
{
input: "{}",
expected: true,
},
{
input: "{{",
expected: false,
},
{
input: "}{",
expected: false,
},
{
input: "{}[]",
expected: true,
},
{
input: "{[]}",
expected: true,
},
{
input: "{[}]",
expected: false,
},
{
input: "{[)][]}",
expected: false,
},
{
input: "{[]([()])}",
expected: true,
},
}
func TestBracket(t *testing.T) {
for _, tt := range testCases {
actual, err := Bracket(tt.input)
// We don't expect errors for any of the test cases
if err != nil {
t.Fatalf("Bracket(%q) returned error %q. Error not expected.", tt.input, err)
}
if actual != tt.expected {
t.Fatalf("Bracket(%q) was expected to return %v but returned %v.",
tt.input, tt.expected, actual)
}
}
}
func BenchmarkBracket(b *testing.B) {
b.StopTimer()
for _, tt := range testCases {
b.StartTimer()
for i := 0; i < b.N; i++ {
Bracket(tt.input)
}
b.StopTimer()
}
}

View File

@@ -0,0 +1,77 @@
package brackets
import (
"testing"
)
const testVersion = 2
var testCases = []struct {
input string
expected bool
}{
{
input: "",
expected: true,
},
{
input: "{}",
expected: true,
},
{
input: "{{",
expected: false,
},
{
input: "}{",
expected: false,
},
{
input: "{}[]",
expected: true,
},
{
input: "{[]}",
expected: true,
},
{
input: "{[}]",
expected: false,
},
{
input: "{[)][]}",
expected: false,
},
{
input: "{[]([()])}",
expected: true,
},
}
func TestBracket(t *testing.T) {
for _, tt := range testCases {
actual, err := Bracket(tt.input)
// We don't expect errors for any of the test cases
if err != nil {
t.Fatalf("Bracket(%q) returned error %q. Error not expected.", tt.input, err)
}
if actual != tt.expected {
t.Fatalf("Bracket(%q) was expected to return %v but returned %v.",
tt.input, tt.expected, actual)
}
}
if TestVersion != testVersion {
t.Fatalf("Found TestVersion = %v, want %v.", TestVersion, testVersion)
}
}
func BenchmarkBracket(b *testing.B) {
b.StopTimer()
for _, tt := range testCases {
b.StartTimer()
for i := 0; i < b.N; i++ {
Bracket(tt.input)
}
b.StopTimer()
}
}

23
go/clock/README.md Normal file
View File

@@ -0,0 +1,23 @@
# Clock
Implement a clock that handles times without dates.
Create a clock that is independent of date.
You should be able to add and subtract minutes to it.
Two clocks that represent the same time should be equal to each other.
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://help.exercism.io/getting-started-with-go.html).
## Source
Pairing session with Erin Drummond [view source](https://twitter.com/ebdrummond)

78
go/clock/cases_test.go Normal file
View File

@@ -0,0 +1,78 @@
package clock
// Source: exercism/x-common
// Commit: 269f498 Merge pull request #48 from soniakeys/custom-set-json
// Test creating a new clock with an initial time.
var timeTests = []struct {
h, m int
want string
}{
{8, 0, "08:00"}, // on the hour
{9, 0, "09:00"}, // on the hour
{11, 9, "11:09"}, // past the hour
{11, 19, "11:19"}, // past the hour
{24, 0, "00:00"}, // midnight is zero hours
{25, 0, "01:00"}, // hour rolls over
{1, 60, "02:00"}, // sixty minutes is next hour
{0, 160, "02:40"}, // minutes roll over
{25, 160, "03:40"}, // hour and minutes roll over
{-1, 15, "23:15"}, // negative hour
{-25, 0, "23:00"}, // negative hour rolls over
{1, -40, "00:20"}, // negative minutes
{1, -160, "22:20"}, // negative minutes roll over
{-25, -160, "20:20"}, // negative hour and minutes both roll over
}
// Test adding and subtracting minutes.
var addTests = []struct {
h, m, a int
want string
}{
{10, 0, 3, "10:03"}, // add minutes
{0, 45, 40, "01:25"}, // add to next hour
{10, 0, 61, "11:01"}, // add more than one hour
{23, 59, 2, "00:01"}, // add across midnight
{5, 32, 1500, "06:32"}, // add more than one day (1500 min = 25 hrs)
{0, 45, 160, "03:25"}, // add more than two hours with carry
{10, 3, -3, "10:00"}, // subtract minutes
{10, 3, -30, "09:33"}, // subtract to previous hour
{10, 3, -70, "08:53"}, // subtract more than an hour
{0, 3, -4, "23:59"}, // subtract across midnight
{0, 0, -160, "21:20"}, // subtract more than two hours
{5, 32, -1500, "04:32"}, // subtract more than one day (1500 min = 25 hrs)
{6, 15, -160, "03:35"}, // subtract more than two hours with borrow
}
// Construct two separate clocks, set times, test if they are equal.
type hm struct{ h, m int }
var eqTests = []struct {
c1, c2 hm
want bool
}{
// clocks with same time
{
hm{15, 37},
hm{15, 37},
true,
},
// clocks a minute apart
{
hm{15, 36},
hm{15, 37},
false,
},
// clocks an hour apart
{
hm{14, 37},
hm{15, 37},
false,
},
// clocks set 24 hours apart
{
hm{10, 37},
hm{34, 37},
true,
},
}

34
go/clock/clock.go Normal file
View File

@@ -0,0 +1,34 @@
package clock
import "fmt"
// TestVersion is for exercism
const TestVersion = 2
// Clock is an int representing the time of day
type Clock int
// Time returns a Clock representing the given hour & minute
func Time(hour, minute int) Clock {
return TimeFromMinutes(hour*60 + minute)
}
// String returns a string representation of Clock
func (c Clock) String() string {
return fmt.Sprintf("%02d:%02d", c/60, c%60)
}
// Add adds minutes to the clock
func (c Clock) Add(minutes int) Clock {
return TimeFromMinutes(int(c) + minutes)
}
// TimeFromMinutes takes a minutes integer value and returns a Clock
func TimeFromMinutes(minutes int) Clock {
for minutes < 0 {
// Keep adding 24 hours to the minutes value until it's positive
minutes = minutes + (24 * 60)
}
minutes = minutes % (24 * 60)
return Clock(minutes)
}

69
go/clock/clock_test.go Normal file
View File

@@ -0,0 +1,69 @@
package clock
import (
"reflect"
"testing"
)
// Clock type API:
//
// Time(hour, minute int) Clock // a "constructor"
// (Clock) String() string // a "stringer"
// (Clock) Add(minutes int) Clock
//
// Add should also handle subtraction by accepting negative values.
// To satisfy the readme requirement about clocks being equal, values of
// your Clock type need to work with the == operator.
//
// It might help to study the time.Time type in the standard library
// (https://golang.org/pkg/time/#Time) as a model. See how constructors there
// (Date and Now) return Time values rather than pointers. Note also how
// most time.Time methods have value receivers rather that pointer recievers.
// For more background on this read
// https://github.com/golang/go/wiki/CodeReviewComments#receiver-type.
const testVersion = 2
// Retired testVersions
// (none) 79937f6d58e25ebafe12d1cb4a9f88f4de70cfd6
// 1 8d0cb8b617be2e36b2ca5ad2034e5f80f2372924
func TestCreateClock(t *testing.T) {
if TestVersion != testVersion {
t.Fatalf("Found TestVersion = %v, want %v", TestVersion, testVersion)
}
for _, n := range timeTests {
if got := Time(n.h, n.m); got.String() != n.want {
t.Fatalf("Time(%d, %d) = %q, want %q", n.h, n.m, got, n.want)
}
}
t.Log(len(timeTests), "test cases")
}
func TestAddMinutes(t *testing.T) {
for _, a := range addTests {
if got := Time(a.h, a.m).Add(a.a); got.String() != a.want {
t.Fatalf("Time(%d, %d).Add(%d) = %q, want %q",
a.h, a.m, a.a, got, a.want)
}
}
t.Log(len(addTests), "test cases")
}
func TestCompareClocks(t *testing.T) {
for _, e := range eqTests {
clock1 := Time(e.c1.h, e.c1.m)
clock2 := Time(e.c2.h, e.c2.m)
got := clock1 == clock2
if got != e.want {
t.Log("Clock1:", clock1)
t.Log("Clock2:", clock2)
t.Logf("Clock1 == Clock2 is %t, want %t", got, e.want)
if reflect.DeepEqual(clock1, clock2) {
t.Log("(Hint: see comments in clock_test.go.)")
}
t.FailNow()
}
}
t.Log(len(eqTests), "test cases")
}

View File

@@ -0,0 +1,87 @@
# Crypto Square
Implement the classic method for composing secret messages called a square code.
The input is first normalized: The spaces and punctuation are removed
from the English text and the message is downcased.
Then, the normalized characters are broken into rows. These rows can be
regarded as forming a rectangle when printed with intervening newlines.
For example, the sentence
> If man was meant to stay on the ground god would have given us roots
is 54 characters long.
Broken into 8-character columns, it yields 7 rows.
Those 7 rows produce this rectangle when printed one per line:
```plain
ifmanwas
meanttos
tayonthe
groundgo
dwouldha
vegivenu
sroots
```
The coded message is obtained by reading down the columns going left to
right.
For example, the message above is coded as:
```plain
imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau
```
Write a program that, given an English text, outputs the encoded version
of that text.
The size of the square (number of columns) should be decided by the
length of the message.
If the message is a length that creates a perfect square (e.g. 4, 9, 16,
25, 36, etc), use that number of columns.
If the message doesn't fit neatly into a square, choose the number of
columns that corresponds to the smallest square that is larger than the
number of characters in the message.
For example, a message 4 characters long should use a 2 x 2 square. A
message that is 81 characters long would use a square that is 9 columns
wide.
A message between 5 and 8 characters long should use a rectangle 3
characters wide.
Output the encoded text grouped by column.
For example:
- "Have a nice day. Feed the dog & chill out!"
- Normalizes to: "haveanicedayfeedthedogchillout"
- Which has length: 30
- And splits into 5 6-character rows:
- "havean"
- "iceday"
- "feedth"
- "edogch"
- "illout"
- Which yields a ciphertext beginning: "hifei acedl v…"
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://help.exercism.io/getting-started-with-go.html).
## Source
J Dalbey's Programming Practice problems [view source](http://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html)

View File

@@ -0,0 +1,45 @@
package cryptosquare
import (
"math"
"regexp"
"strings"
)
// TestVersion is an exercism thing
const TestVersion = 1
// Encode implements the classic method for composing
// secret messages called a square code
func Encode(txt string) string {
r := regexp.MustCompile("[^a-zA-Z0-9]+")
nrm := strings.ToLower(r.ReplaceAllString(txt, ""))
// The string should be normalized now (alphanumeric, lower case)
sqrt := int(math.Ceil(math.Sqrt(float64(len(nrm)))))
var square, ret []string
var tmp string
// Build the initial square
for i := 0; i < len(nrm); i++ {
if i%sqrt == 0 && len(tmp) != 0 {
square = append(square, tmp)
tmp = ""
}
tmp += string(nrm[i])
}
square = append(square, tmp)
tmp = ""
// Now rebuild the string by columns
for i := 0; i < len(square[0]); i++ {
for j := 0; j < len(square); j++ {
if i < len(square[j]) {
tmp += string(square[j][i])
}
}
ret = append(ret, tmp)
tmp = ""
}
return strings.Join(ret, " ")
}

View File

@@ -0,0 +1,111 @@
package cryptosquare
import "testing"
const testVersion = 1
// Retired testVersions
// (none) 71ad8ac57fe7d5b777cfa1afd116cd41e1af55ed
var tests = []struct {
pt string // plain text
ct string // cipher text
}{
{
"s#$%^&plunk",
"su pn lk",
},
{
"1, 2, 3 GO!",
"1g 2o 3",
},
{
"1234",
"13 24",
},
{
"123456789",
"147 258 369",
},
{
"123456789abc",
"159 26a 37b 48c",
},
{
"Never vex thine heart with idle woes",
"neewl exhie vtetw ehaho ririe vntds",
},
{
"ZOMG! ZOMBIES!!!",
"zzi ooe mms gb",
},
{
"Time is an illusion. Lunchtime doubly so.",
"tasney inicds miohoo elntu illib suuml",
},
{
"We all know interspecies romance is weird.",
"wneiaw eorene awssci liprer lneoid ktcms",
},
{
"Madness, and then illumination.",
"msemo aanin dnin ndla etlt shui",
},
{
"Vampires are people too!",
"vrel aepe mset paoo irpo",
},
{
"",
"",
},
{
"1",
"1",
},
{
"12",
"1 2",
},
{
"12 3",
"13 2",
},
{
"12345678",
"147 258 36",
},
{
"123456789a",
"159 26a 37 48",
},
{
"If man was meant to stay on the ground god would have given us roots",
"imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau",
},
{
"Have a nice day. Feed the dog & chill out!",
"hifei acedl veeol eddgo aatcu nyhht",
},
}
func TestEncode(t *testing.T) {
if TestVersion != testVersion {
t.Errorf("Found TestVersion = %v, want %v.", TestVersion, testVersion)
}
for _, test := range tests {
if ct := Encode(test.pt); ct != test.ct {
t.Fatalf(`Encode(%q):
got %q
want %q`, test.pt, ct, test.ct)
}
}
}
func BenchmarkEncode(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range tests {
Encode(test.pt)
}
}
}

1
go/current Symbolic link
View File

@@ -0,0 +1 @@
react

View File

@@ -0,0 +1,30 @@
# Difference Of Squares
Find the difference between the sum of the squares and the square of the sums of the first N natural numbers.
The square of the sum of the first ten natural numbers is,
(1 + 2 + ... + 10)**2 = 55**2 = 3025
The sum of the squares of the first ten natural numbers is,
1**2 + 2**2 + ... + 10**2 = 385
Hence the difference between the square of the sum of the first
ten natural numbers and the sum of the squares is 2640:
3025 - 385 = 2640
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://help.exercism.io/getting-started-with-go.html).
## Source
Problem 6 at Project Euler [view source](http://projecteuler.net/problem=6)

View File

@@ -0,0 +1,32 @@
package diffsquares
import "math"
// SquareOfSums calculates the Square of the sums
// of the first 'num' natural numbers
func SquareOfSums(num int) int {
ret := 0
for num > 0 {
ret += num
num--
}
return int(math.Pow(float64(ret), 2))
}
// SumOfSquares calculates the Sum of the Squares
// of the first 'num' natural numbers
func SumOfSquares(num int) int {
ret := 0
for num > 0 {
ret += int(math.Pow(float64(num), 2))
num--
}
return ret
}
// Difference calculates the difference between
// The SquareOfSums and the SumOfSquares for the
// first 'num' natural numbers
func Difference(num int) int {
return SquareOfSums(num) - SumOfSquares(num)
}

View File

@@ -0,0 +1,54 @@
package diffsquares
import "testing"
var tests = []struct{ n, sqOfSums, sumOfSq int }{
{5, 225, 55},
{10, 3025, 385},
{100, 25502500, 338350},
}
func TestSquareOfSums(t *testing.T) {
for _, test := range tests {
if s := SquareOfSums(test.n); s != test.sqOfSums {
t.Fatalf("SquareOfSums(%d) = %d, want %d", test.n, s, test.sqOfSums)
}
}
}
func TestSumOfSquares(t *testing.T) {
for _, test := range tests {
if s := SumOfSquares(test.n); s != test.sumOfSq {
t.Fatalf("SumOfSquares(%d) = %d, want %d", test.n, s, test.sumOfSq)
}
}
}
func TestDifference(t *testing.T) {
for _, test := range tests {
want := test.sqOfSums - test.sumOfSq
if s := Difference(test.n); s != want {
t.Fatalf("Difference(%d) = %d, want %d", test.n, s, want)
}
}
}
// Benchmark functions on just a single number (100, from the original PE problem)
// to avoid overhead of iterating over tests.
func BenchmarkSquareOfSums(b *testing.B) {
for i := 0; i < b.N; i++ {
SquareOfSums(100)
}
}
func BenchmarkSumOfSquares(b *testing.B) {
for i := 0; i < b.N; i++ {
SumOfSquares(100)
}
}
func BenchmarkDifference(b *testing.B) {
for i := 0; i < b.N; i++ {
Difference(100)
}
}

62
go/etl/README.md Normal file
View File

@@ -0,0 +1,62 @@
# Etl
We are going to do the `Transform` step of an Extract-Transform-Load.
### ETL
Extract-Transform-Load (ETL) is a fancy way of saying, "We have some crufty, legacy data over in this system, and now we need it in this shiny new system over here, so
we're going to migrate this."
(Typically, this is followed by, "We're only going to need to run this
once." That's then typically followed by much forehead slapping and
moaning about how stupid we could possibly be.)
### The goal
We're going to extract some scrabble scores from a legacy system.
The old system stored a list of letters per score:
- 1 point: "A", "E", "I", "O", "U", "L", "N", "R", "S", "T",
- 2 points: "D", "G",
- 3 points: "B", "C", "M", "P",
- 4 points: "F", "H", "V", "W", "Y",
- 5 points: "K",
- 8 points: "J", "X",
- 10 points: "Q", "Z",
The shiny new scrabble system instead stores the score per letter, which
makes it much faster and easier to calculate the score for a word. It
also stores the letters in lower-case regardless of the case of the
input letters:
- "a" is worth 1 point.
- "b" is worth 3 points.
- "c" is worth 3 points.
- "d" is worth 2 points.
- Etc.
Your mission, should you choose to accept it, is to write a program that
transforms the legacy data format to the shiny new format.
### Notes
Note that both the old and the new system use strings to represent
letters, even in languages that have a separate data type for
characters.
A final note about scoring, Scrabble is played around the world in a
variety of languages, each with its own unique scoring table. For
example, an "A" is scored at 14 in the Basque-language version of the
game while being scored at 9 in the Latin-language version.
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://help.exercism.io/getting-started-with-go.html).
## Source
The Jumpstart Lab team [view source](http://jumpstartlab.com)

17
go/etl/etl.go Normal file
View File

@@ -0,0 +1,17 @@
package etl
import "strings"
// Transform takes the legacy data structure
// and converts it into the new and improved
// data structure oh man this new system will
// make us so rich you guys.
func Transform(input map[int][]string) map[string]int {
ret := make(map[string]int)
for k, v := range input {
for _, let := range v {
ret[strings.ToLower(let)] = k
}
}
return ret
}

90
go/etl/etl_test.go Normal file
View File

@@ -0,0 +1,90 @@
package etl
import "testing"
type given map[int][]string
type expectation map[string]int
var transformTests = []struct {
input given
output expectation
}{
{
given{1: {"A"}},
expectation{"a": 1},
},
{
given{1: {"A", "E", "I", "O", "U"}},
expectation{"a": 1, "e": 1, "i": 1, "o": 1, "u": 1},
},
{
given{
1: {"A", "E"},
2: {"D", "G"},
},
expectation{
"a": 1,
"e": 1,
"d": 2,
"g": 2,
},
},
{
given{
1: {"A", "E", "I", "O", "U", "L", "N", "R", "S", "T"},
2: {"D", "G"},
3: {"B", "C", "M", "P"},
4: {"F", "H", "V", "W", "Y"},
5: {"K"},
8: {"J", "X"},
10: {"Q", "Z"},
},
expectation{
"a": 1, "e": 1, "i": 1, "o": 1, "u": 1, "l": 1, "n": 1, "r": 1, "s": 1, "t": 1,
"d": 2, "g": 2,
"b": 3, "c": 3, "m": 3, "p": 3,
"f": 4, "h": 4, "v": 4, "w": 4, "y": 4,
"k": 5,
"j": 8, "x": 8,
"q": 10, "z": 10,
},
},
}
func equal(actual map[string]int, expectation map[string]int) bool {
if len(actual) != len(expectation) {
return false
}
for k, actualVal := range actual {
expectationVal, present := expectation[k]
if !present || actualVal != expectationVal {
return false
}
}
return true
}
func TestTranform(t *testing.T) {
for _, tt := range transformTests {
actual := Transform(map[int][]string(tt.input))
if !equal(actual, tt.output) {
t.Fatalf("Transform(%v). Expected [%v], Actual [%v]", tt.input, tt.output, actual)
}
}
}
func BenchmarkTranform(b *testing.B) {
b.StopTimer()
for _, tt := range transformTests {
b.StartTimer()
for i := 0; i < b.N; i++ {
Transform(map[int][]string(tt.input))
}
b.StopTimer()
}
}

80
go/food-chain/README.md Normal file
View File

@@ -0,0 +1,80 @@
# Food Chain
Write a program that generates the lyrics of the song 'I Know an Old Lady Who Swallowed a Fly'
Write a program that generates the lyrics to the song
"I know an old lady who swallowed a fly". While you could
copy/paste the lyrics, or read them from a file, this
problem is much more interesting if you approach it
algorithmically.
This is a [cumulative song](http://en.wikipedia.org/wiki/Cumulative_song) of unknown origin.
This is one of many common variants.
```plain
I know an old lady who swallowed a fly.
I don't know why she swallowed the fly. Perhaps she'll die.
I know an old lady who swallowed a spider.
It wriggled and jiggled and tickled inside her.
She swallowed the spider to catch the fly.
I don't know why she swallowed the fly. Perhaps she'll die.
I know an old lady who swallowed a bird.
How absurd to swallow a bird!
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
She swallowed the spider to catch the fly.
I don't know why she swallowed the fly. Perhaps she'll die.
I know an old lady who swallowed a cat.
Imagine that, to swallow a cat!
She swallowed the cat to catch the bird.
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
She swallowed the spider to catch the fly.
I don't know why she swallowed the fly. Perhaps she'll die.
I know an old lady who swallowed a dog.
What a hog, to swallow a dog!
She swallowed the dog to catch the cat.
She swallowed the cat to catch the bird.
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
She swallowed the spider to catch the fly.
I don't know why she swallowed the fly. Perhaps she'll die.
I know an old lady who swallowed a goat.
Just opened her throat and swallowed a goat!
She swallowed the goat to catch the dog.
She swallowed the dog to catch the cat.
She swallowed the cat to catch the bird.
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
She swallowed the spider to catch the fly.
I don't know why she swallowed the fly. Perhaps she'll die.
I know an old lady who swallowed a cow.
I don't know how she swallowed a cow!
She swallowed the cow to catch the goat.
She swallowed the goat to catch the dog.
She swallowed the dog to catch the cat.
She swallowed the cat to catch the bird.
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
She swallowed the spider to catch the fly.
I don't know why she swallowed the fly. Perhaps she'll die.
I know an old lady who swallowed a horse.
She's dead, of course!
```
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://help.exercism.io/getting-started-with-go.html).
## Source
Wikipedia [view source](http://en.wikipedia.org/wiki/There_Was_an_Old_Lady_Who_Swallowed_a_Fly)

100
go/food-chain/food_chain.go Normal file
View File

@@ -0,0 +1,100 @@
package foodchain
import (
"fmt"
"strings"
)
// TestVersion is an exercism thing
const TestVersion = 1
// An Inedible is something that you probably shouldn't eat.
// At the least, you shouldn't eat it whole/live.
type Inedible struct {
// What it is
Name string
// A quick jab about it
FollowUp string
}
// DoNotEat is a non-exhaustive list of Inedibles. It's recommended
// that you don't eat them. Yet the old lady did.
var DoNotEat = []Inedible{
Inedible{
"fly", "I don't know why she swallowed the fly. Perhaps she'll die.",
},
Inedible{
"spider", "It wriggled and jiggled and tickled inside her.",
},
Inedible{
"bird", "How absurd to swallow a bird!",
},
Inedible{
"cat", "Imagine that, to swallow a cat!",
},
Inedible{
"dog", "What a hog, to swallow a dog!",
},
Inedible{
"goat", "Just opened her throat and swallowed a goat!",
},
Inedible{
"cow", "I don't know how she swallowed a cow!",
},
Inedible{
"horse", "She's dead, of course!",
},
}
// Verse generates the text for a specific verse
func Verse(verseNum int) string {
return strings.Trim(Swallow(verseNum-1, true), "\n")
}
// Verses generates the text for all verses from verse1 to verse2
func Verses(verse1, verse2 int) string {
var ret string
for verse1 <= verse2 {
ret += Verse(verse1) + "\n\n"
verse1++
}
return strings.Trim(ret, "\n")
}
// Song generates all verses
func Song() string {
var ret string
for verseNum := 1; verseNum <= len(DoNotEat); verseNum++ {
ret += Verse(verseNum) + "\n\n"
}
return strings.Trim(ret, "\n")
}
// Swallow generates the text for swallowing something
func Swallow(dneIdx int, first bool) string {
var ret string
if first || dneIdx == len(DoNotEat)-1 {
ret = fmt.Sprintf(
"I know an old lady who swallowed a %s.\n%s\n",
DoNotEat[dneIdx].Name,
DoNotEat[dneIdx].FollowUp,
)
if dneIdx == 0 || dneIdx == len(DoNotEat)-1 {
return ret
}
}
ret += fmt.Sprintf("She swallowed the %s to catch the %s",
DoNotEat[dneIdx].Name,
DoNotEat[dneIdx-1].Name,
)
if DoNotEat[dneIdx-1].Name == "spider" {
ret += " that wriggled and jiggled and tickled inside her.\n"
} else if DoNotEat[dneIdx-1].Name == "fly" {
ret += ".\nI don't know why she swallowed the fly. Perhaps she'll die.\n"
return ret
} else {
ret += ".\n"
}
return ret + Swallow(dneIdx-1, false)
}

View File

@@ -0,0 +1,95 @@
package foodchain
import (
"strings"
"testing"
)
const testVersion = 1
func TestTestVersion(t *testing.T) {
if TestVersion != testVersion {
t.Errorf("Found TestVersion = %v, want %v.", TestVersion, testVersion)
}
}
var ref = []string{``,
`I know an old lady who swallowed a fly.
I don't know why she swallowed the fly. Perhaps she'll die.`,
`I know an old lady who swallowed a spider.
It wriggled and jiggled and tickled inside her.
She swallowed the spider to catch the fly.
I don't know why she swallowed the fly. Perhaps she'll die.`,
`I know an old lady who swallowed a bird.
How absurd to swallow a bird!
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
She swallowed the spider to catch the fly.
I don't know why she swallowed the fly. Perhaps she'll die.`,
`I know an old lady who swallowed a cat.
Imagine that, to swallow a cat!
She swallowed the cat to catch the bird.
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
She swallowed the spider to catch the fly.
I don't know why she swallowed the fly. Perhaps she'll die.`,
`I know an old lady who swallowed a dog.
What a hog, to swallow a dog!
She swallowed the dog to catch the cat.
She swallowed the cat to catch the bird.
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
She swallowed the spider to catch the fly.
I don't know why she swallowed the fly. Perhaps she'll die.`,
`I know an old lady who swallowed a goat.
Just opened her throat and swallowed a goat!
She swallowed the goat to catch the dog.
She swallowed the dog to catch the cat.
She swallowed the cat to catch the bird.
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
She swallowed the spider to catch the fly.
I don't know why she swallowed the fly. Perhaps she'll die.`,
`I know an old lady who swallowed a cow.
I don't know how she swallowed a cow!
She swallowed the cow to catch the goat.
She swallowed the goat to catch the dog.
She swallowed the dog to catch the cat.
She swallowed the cat to catch the bird.
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
She swallowed the spider to catch the fly.
I don't know why she swallowed the fly. Perhaps she'll die.`,
`I know an old lady who swallowed a horse.
She's dead, of course!`,
}
func TestVerse(t *testing.T) {
for v := 1; v <= 8; v++ {
if ret := Verse(v); ret != ref[v] {
t.Fatalf("Verse(%d) =\n%s\n want:\n%s\n", v, ret, ref[v])
}
}
}
func TestVerses(t *testing.T) {
if ret, want := Verses(1, 2), ref[1]+"\n\n"+ref[2]; ret != want {
t.Fatalf("Verses(1, 2) =\n%s\n want:\n%s\n", ret, want)
}
}
func TestSong(t *testing.T) {
if ret, want := Song(), strings.Join(ref[1:], "\n\n"); ret != want {
t.Fatalf("Song() =\n%s\n want:\n%s\n", ret, want)
}
}
func BenchmarkSong(b *testing.B) {
for i := 0; i < b.N; i++ {
Song()
}
}

19
go/gigasecond/README.md Normal file
View File

@@ -0,0 +1,19 @@
# Gigasecond
Write a program that will calculate the date that someone turned or will celebrate their 1 Gs anniversary.
A gigasecond is one billion (10**9) seconds.
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://help.exercism.io/getting-started-with-go.html).
## Source
Chapter 9 in Chris Pine's online Learn to Program tutorial. [view source](http://pine.fm/LearnToProgram/?Chapter=09)

View File

@@ -0,0 +1,31 @@
package gigasecond
// Source: exercism/x-common
// Commit: 1e9e232 Merge pull request #45 from soniakeys/gigasecond-tests
// Add one gigasecond to the input.
var addCases = []struct {
in string
want string
}{
{
"2011-04-25",
"2043-01-01T01:46:40",
},
{
"1977-06-13",
"2009-02-19T01:46:40",
},
{
"1959-07-19",
"1991-03-27T01:46:40",
},
{
"2015-01-24T22:00:00",
"2046-10-02T23:46:40",
},
{
"2015-01-24T23:59:59",
"2046-10-03T01:46:39",
},
}

View File

@@ -0,0 +1,14 @@
package gigasecond
import "time"
// TestVersion
const TestVersion = 2 // find the value in gigasecond_test.go
// AddGigasecond Adds a gigasecond to the time t
func AddGigasecond(t time.Time) time.Time {
return t.Add(time.Second * 1000000000)
}
// Birthday is my fake birthday
var Birthday = time.Date(1979, 4, 23, 10, 2, 0, 0, time.UTC)

View File

@@ -0,0 +1,73 @@
package gigasecond
// Write a function AddGigasecond that works with time.Time.
// Also define a variable Birthday set to your (or someone else's) birthday.
// Run go test -v to see your gigasecond anniversary.
import (
"os"
"testing"
"time"
)
const testVersion = 2
// Retired testVersions
// (none) 98807b314216ff27492378a00df60410cc971d32
// 1 ed0594b6fd6664928d17bbc70b543a56da05a5b8
// date formats used in test data
const (
fmtD = "2006-01-02"
fmtDT = "2006-01-02T15:04:05"
)
func TestAddGigasecond(t *testing.T) {
if TestVersion != testVersion {
t.Fatalf("Found TestVersion = %v, want %v.", TestVersion, testVersion)
}
for _, tc := range addCases {
in := parse(tc.in, t)
want := parse(tc.want, t)
got := AddGigasecond(in)
if !got.Equal(want) {
t.Fatalf(`AddGigasecond(%s)
= %s
want %s`, in, got, want)
}
}
t.Log("Tested", len(addCases), "cases.")
}
func TestYourAnniversary(t *testing.T) {
t.Logf(`
Your birthday: %s
Your gigasecond anniversary: %s`, Birthday, AddGigasecond(Birthday))
}
func parse(s string, t *testing.T) time.Time {
tt, err := time.Parse(fmtDT, s) // try full date time format first
if err != nil {
tt, err = time.Parse(fmtD, s) // also allow just date
}
if err != nil {
// can't run tests if input won't parse. if this seems to be a
// development or ci environment, raise an error. if this condition
// makes it to the solver though, ask for a bug report.
_, statErr := os.Stat("example_gen.go")
if statErr == nil || os.Getenv("TRAVIS_GO_VERSION") > "" {
t.Fatal(err)
} else {
t.Log(err)
t.Skip("(Not your problem. " +
"please file issue at https://github.com/exercism/xgo.)")
}
}
return tt
}
func BenchmarkAddGigasecond(b *testing.B) {
for i := 0; i < b.N; i++ {
AddGigasecond(time.Time{})
}
}

41
go/grains/README.md Normal file
View File

@@ -0,0 +1,41 @@
# Grains
Write a program that calculates the number of grains of wheat on a chessboard given that the number on each square doubles.
There once was a wise servant who saved the life of a prince. The king
promised to pay whatever the servant could dream up. Knowing that the
king loved chess, the servant told the king he would like to have grains
of wheat. One grain on the first square of a chess board. Two grains on
the next. Four on the third, and so on.
There are 64 squares on a chessboard.
Write a program that shows:
- how many grains were on each square, and
- the total number of grains
## 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:
- Optimize for speed.
- Optimize for readability.
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://help.exercism.io/getting-started-with-go.html).
## Source
JavaRanch Cattle Drive, exercise 6 [view source](http://www.javaranch.com/grains.jsp)

30
go/grains/grains.go Normal file
View File

@@ -0,0 +1,30 @@
package grains
import "errors"
// Square just takes 1 * 2^sq
func Square(sq int) (uint64, error) {
if sq > 0 && sq < 65 {
return (1 << uint(sq-1)), nil
}
return 0, errors.New("Invalid Square Requested")
}
// TotalForSquare calculates the total number
// for all squares up to sq (cause why not)
func TotalForSquare(sq int) (uint64, error) {
if sq < 0 || sq > 64 {
return 0, errors.New("Invalid Square Requested")
}
var ret uint64
for i := 0; i <= sq; i++ {
ret = (ret << 1) | 1
}
return ret, nil
}
// Total calculates the total for the entire board
func Total() uint64 {
ret, _ := TotalForSquare(64)
return ret
}

61
go/grains/grains_test.go Normal file
View File

@@ -0,0 +1,61 @@
package grains
import (
"testing"
)
var squareTests = []struct {
input int
expectedVal uint64
expectError bool
}{
{1, 1, false},
{2, 2, false},
{3, 4, false},
{4, 8, false},
{16, 32768, false},
{32, 2147483648, false},
{64, 9223372036854775808, false},
{65, 0, true},
{0, 0, true},
{-1, 0, true},
}
func TestSquare(t *testing.T) {
for _, test := range squareTests {
actualVal, actualErr := Square(test.input)
if actualVal != test.expectedVal {
t.Errorf("Square(%d) expected %d, Actual %d", test.input, test.expectedVal, actualVal)
}
// if we expect an error and there isn't one
if test.expectError && actualErr == nil {
t.Errorf("Square(%d) expected an error, but error is nil", test.input)
}
// if we don't expect an error and there is one
if !test.expectError && actualErr != nil {
t.Errorf("Square(%d) expected no error, but error is: %s", test.input, actualErr)
}
}
}
func TestTotal(t *testing.T) {
var expected uint64 = 18446744073709551615
if actual := Total(); actual != expected {
t.Errorf("Total() expected %d, Actual %d", expected, actual)
}
}
func BenchmarkSquare(b *testing.B) {
b.StopTimer()
for _, test := range squareTests {
b.StartTimer()
for i := 0; i < b.N; i++ {
Square(test.input)
}
b.StopTimer()
}
}

50
go/hamming/README.md Normal file
View File

@@ -0,0 +1,50 @@
# Hamming
Write a program that can calculate the Hamming difference between two DNA strands.
A mutation is simply a mistake that occurs during the creation or
copying of a nucleic acid, in particular DNA. Because nucleic acids are
vital to cellular functions, mutations tend to cause a ripple effect
throughout the cell. Although mutations are technically mistakes, a very
rare mutation may equip the cell with a beneficial attribute. In fact,
the macro effects of evolution are attributable by the accumulated
result of beneficial microscopic mutations over many generations.
The simplest and most common type of nucleic acid mutation is a point
mutation, which replaces one base with another at a single nucleotide.
By counting the number of differences between two homologous DNA strands
taken from different genomes with a common ancestor, we get a measure of
the minimum number of point mutations that could have occurred on the
evolutionary path between the two strands.
This is called the 'Hamming distance'.
It is found by comparing two DNA strands and counting how many of the
nucleotides are different from their equivalent in the other string.
GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
^ ^ ^ ^ ^ ^^
The Hamming distance between these two DNA strands is 7.
# Implementation notes
The Hamming distance is only defined for sequences of equal length. This means
that based on the definition, each language could deal with getting sequences
of equal length differently.
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://help.exercism.io/getting-started-with-go.html).
## Source
The Calculating Point Mutations problem at Rosalind [view source](http://rosalind.info/problems/hamm/)

81
go/hamming/cases_test.go Normal file
View File

@@ -0,0 +1,81 @@
package hamming
// Source: exercism/x-common
// Commit: c84e435 Merge pull request #51 from soniakeys/master
var testCases = []struct {
s1 string
s2 string
want int
}{
{ // identical strands
"A",
"A",
0,
},
{ // long identical strands
"GGACTGA",
"GGACTGA",
0,
},
{ // complete distance in single nucleotide strands
"A",
"G",
1,
},
{ // complete distance in small strands
"AG",
"CT",
2,
},
{ // small distance in small strands
"AT",
"CT",
1,
},
{ // small distance
"GGACG",
"GGTCG",
1,
},
{ // small distance in long strands
"ACCAGGG",
"ACTATGG",
2,
},
{ // non-unique character in first strand
"AGA",
"AGG",
1,
},
{ // non-unique character in second strand
"AGG",
"AGA",
1,
},
{ // large distance
"GATACA",
"GCATAA",
4,
},
{ // large distance in off-by-one strand
"GGACGGATTCTG",
"AGGACGGATTCT",
9,
},
{ // empty strands
"",
"",
0,
},
{ // disallow first strand longer
"AATG",
"AAA",
-1,
},
{ // disallow second strand longer
"ATA",
"AGTG",
-1,
},
}

21
go/hamming/hamming.go Normal file
View File

@@ -0,0 +1,21 @@
package hamming
import "errors"
// TestVersion is an exercism thing
const TestVersion = 2
// Distance measures the hamming distance between two sequences
// and returns the number if different bytes and an error value
func Distance(seq1, seq2 string) (int, error) {
if len(seq1) != len(seq2) {
return -1, errors.New("Strands must be equal length")
}
var ret int
for i := 0; i < len(seq1); i++ {
if seq1[i] != seq2[i] {
ret++
}
}
return ret, nil
}

View File

@@ -0,0 +1,39 @@
package hamming
import "testing"
const testVersion = 2
// Retired testVersions
// (none) df178dc24b57f7d4ccf54d47430192749d56898f
// 1 4f6fe21682f7f2a7845683cb26ff557208153ffe
func TestHamming(t *testing.T) {
if TestVersion != testVersion {
t.Errorf("Found TestVersion = %v, want %v.", TestVersion, testVersion)
}
for _, tc := range testCases {
switch got, err := Distance(tc.s1, tc.s2); {
case err != nil:
if tc.want >= 0 {
t.Fatalf("Distance(%q, %q) returned error: %v",
tc.s1, tc.s2, err)
}
case tc.want < 0:
t.Fatalf("Distance(%q, %q) = %d. Expected error.",
tc.s1, tc.s2, got)
case got != tc.want:
t.Fatalf("Distance(%q, %q) = %d, want %d.",
tc.s1, tc.s2, got, tc.want)
}
}
}
func BenchmarkHamming(b *testing.B) {
// bench combined time to run through all test cases
for i := 0; i < b.N; i++ {
for _, tc := range testCases {
Distance(tc.s1, tc.s2)
}
}
}

121
go/house/README.md Normal file
View File

@@ -0,0 +1,121 @@
# House
Write a program that outputs the nursery rhyme 'This is the House that Jack Built'.
> [The] process of placing a phrase of clause within another phrase of
> clause is called embedding. It is through the processes of recursion
> and embedding that we are able to take a finite number of forms (words
> and phrases) and construct an infinite number of expressions.
> Furthermore, embedding also allows us to construct an infinitely long
> structure, in theory anyway.
- [papyr.com](http://papyr.com/hypertextbooks/grammar/ph_noun.htm)
The nursery rhyme reads as follows:
```plain
This is the house that Jack built.
This is the malt
that lay in the house that Jack built.
This is the rat
that ate the malt
that lay in the house that Jack built.
This is the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the cow with the crumpled horn
that tossed the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the maiden all forlorn
that milked the cow with the crumpled horn
that tossed the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the man all tattered and torn
that kissed the maiden all forlorn
that milked the cow with the crumpled horn
that tossed the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the priest all shaven and shorn
that married the man all tattered and torn
that kissed the maiden all forlorn
that milked the cow with the crumpled horn
that tossed the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the rooster that crowed in the morn
that woke the priest all shaven and shorn
that married the man all tattered and torn
that kissed the maiden all forlorn
that milked the cow with the crumpled horn
that tossed the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the farmer sowing his corn
that kept the rooster that crowed in the morn
that woke the priest all shaven and shorn
that married the man all tattered and torn
that kissed the maiden all forlorn
that milked the cow with the crumpled horn
that tossed the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the horse and the hound and the horn
that belonged to the farmer sowing his corn
that kept the rooster that crowed in the morn
that woke the priest all shaven and shorn
that married the man all tattered and torn
that kissed the maiden all forlorn
that milked the cow with the crumpled horn
that tossed the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
```
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://help.exercism.io/getting-started-with-go.html).
## Source
British nursery rhyme [view source](http://en.wikipedia.org/wiki/This_Is_The_House_That_Jack_Built)

50
go/house/house.go Normal file
View File

@@ -0,0 +1,50 @@
package house
// ASong holds the data we need to generate a song
type ASong struct {
start string
clauses []string
end string
}
// Embed takes two strings and returns a string with the embedded
func Embed(l, p string) string {
return l + " " + p
}
// Verse takes three things and returns a verse
func Verse(start string, clause []string, end string) string {
ret := start + " "
for i := 0; i < len(clause); i++ {
ret += clause[i] + " "
}
ret += end
return ret
}
// Song generates the whole song
func Song() string {
jackSong := ASong{
start: "This is",
clauses: []string{
"the horse and the hound and the horn\nthat belonged to",
"the farmer sowing his corn\nthat kept",
"the rooster that crowed in the morn\nthat woke",
"the priest all shaven and shorn\nthat married",
"the man all tattered and torn\nthat kissed",
"the maiden all forlorn\nthat milked",
"the cow with the crumpled horn\nthat tossed",
"the dog\nthat worried",
"the cat\nthat killed",
"the rat\nthat ate",
"the malt\nthat lay in",
},
end: "the house that Jack built.",
}
var ret string
for i := len(jackSong.clauses); i >= 0; i-- {
ret += Verse(jackSong.start, jackSong.clauses[i:], jackSong.end) + "\n\n"
}
// Trim the trailing "\n\n"
return ret[:len(ret)-2]
}

171
go/house/house_test.go Normal file
View File

@@ -0,0 +1,171 @@
// Embed embeds a noun phrase as the object of relative clause with a
// transitive verb.
//
// Argument relPhrase is a phrase with a relative clause, minus the object
// of the clause. That is, relPhrase consists of a subject, a relative
// pronoun, a transitive verb, possibly a preposition, but then no object.
//
// func Embed(relPhrase, nounPhrase string) string
// Verse generates a verse of a song with relative clauses that have
// a recursive structure.
//
// func Verse(subject string, relPhrases []string, nounPhrase string) string
//
// There are different ways to do this of course, but try using Embed as a
// subroutine and using programmatic recursion that reflects the grammatical
// recursion.
// Song generates the full text of "The House That Jack Built". Oh yes, you
// could just return a string literal, but humor us; use Verse as a subroutine.
//
// func Song() string
package house
import (
"fmt"
"strings"
"testing"
)
var (
s = "This is"
r = []string{
"the cat that broke",
"the vase that was on",
}
p = "the shelf."
last = len(r) - 1
// song copied from readme
song = `This is the house that Jack built.
This is the malt
that lay in the house that Jack built.
This is the rat
that ate the malt
that lay in the house that Jack built.
This is the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the cow with the crumpled horn
that tossed the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the maiden all forlorn
that milked the cow with the crumpled horn
that tossed the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the man all tattered and torn
that kissed the maiden all forlorn
that milked the cow with the crumpled horn
that tossed the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the priest all shaven and shorn
that married the man all tattered and torn
that kissed the maiden all forlorn
that milked the cow with the crumpled horn
that tossed the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the rooster that crowed in the morn
that woke the priest all shaven and shorn
that married the man all tattered and torn
that kissed the maiden all forlorn
that milked the cow with the crumpled horn
that tossed the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the farmer sowing his corn
that kept the rooster that crowed in the morn
that woke the priest all shaven and shorn
that married the man all tattered and torn
that kissed the maiden all forlorn
that milked the cow with the crumpled horn
that tossed the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.
This is the horse and the hound and the horn
that belonged to the farmer sowing his corn
that kept the rooster that crowed in the morn
that woke the priest all shaven and shorn
that married the man all tattered and torn
that kissed the maiden all forlorn
that milked the cow with the crumpled horn
that tossed the dog
that worried the cat
that killed the rat
that ate the malt
that lay in the house that Jack built.`
)
func TestEmbed(t *testing.T) {
l := r[last]
want := l + " " + p
if e := Embed(l, p); e != want {
t.Fatalf("Embed(%q, %q) = %q, want %q.", l, p, e, want)
}
}
func TestVerse(t *testing.T) {
for i := len(r); i >= 0; i-- {
ri := r[i:]
want := s + " " + strings.Join(append(ri, p), " ")
if v := Verse(s, ri, p); v != want {
t.Fatalf("Verse(%q, %q, %q) = %q, want %q.", s, ri, p, v, want)
}
}
}
func TestSong(t *testing.T) {
s := Song()
if s == song {
return
}
fmt.Print(s)
// a little help in locating an error
got := strings.Split(s, "\n")
want := strings.Split(song, "\n")
var g, w string
var i int
for i, w = range want {
if len(got) <= i {
g = ""
break
}
if g = got[i]; g != w {
break
}
}
t.Fatalf("Song() line %d = %q, want %q", i+1, g, w)
}

View File

@@ -0,0 +1,24 @@
# Largest Series Product
Write a program that, when given a string of digits, can calculate the largest product for a series of consecutive digits of length n.
For example, for the input `'0123456789'`, the largest product for a
series of 3 digits is 504 (7 * 8 * 9), and the largest product for a
series of 5 digits is 15120 (5 * 6 * 7 * 8 * 9).
For the input `'73167176531330624919225119674426574742355349194934'`,
the largest product for a series of 6 digits is 23520.
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://help.exercism.io/getting-started-with-go.html).
## Source
A variation on Problem 8 at Project Euler [view source](http://projecteuler.net/problem=8)

View File

@@ -0,0 +1,29 @@
package lsproduct
// Source: exercism/x-common
// Commit: 3764abd Merge pull request #167 from petertseng/largest-series-product-json
var tests = []struct {
digits string
span int
product int64
ok bool
}{
{"0123456789", 2, 72, true},
{"576802143", 2, 48, true},
{"29", 2, 18, true},
{"0123456789", 3, 504, true},
{"1027839564", 3, 270, true},
{"0123456789", 5, 15120, true},
{"73167176531330624919225119674426574742355349194934", 6, 23520, true},
{"52677741234314237566414902593461595376319419139427", 6, 28350, true},
{"7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450", 13, 23514624000, true},
{"0000", 2, 0, true},
{"99099", 3, 0, true},
{"123", 4, -1, false},
{"", 0, 1, true},
{"123", 0, 1, true},
{"", 1, -1, false},
{"1234a5", 2, -1, false},
{"12345", -1, -1, false},
}

View File

@@ -0,0 +1,45 @@
package lsproduct
import "fmt"
// TestVersion defines version testing.
const TestVersion = 1
// LargestSeriesProduct Takes an input string of digits
// and a length for the series. It returns the largest
// series product from that string of that length.
func LargestSeriesProduct(input string, size int) (int, error) {
if size == 0 {
return 1, nil
} else if size > len(input) {
return 0, fmt.Errorf("Invalid Span Size")
}
var high int
for i := 0; i < (len(input) - size + 1); i++ {
try := GetProduct(input[i : i+size])
if try < 0 {
return 0, fmt.Errorf("Invalid input")
}
if try > high {
high = try
}
}
return high, nil
}
// GetProduct takes a string of numbers, splits it up
// and returns the product of them
func GetProduct(input string) int {
if len(input) > 0 {
total := 1
for i := range input {
next := input[i] - 48
if next < 0 || next > 9 {
return -1
}
total = total * int(next)
}
return total
}
return 0
}

View File

@@ -0,0 +1,92 @@
package lsproduct
import "testing"
const testVersion = 1
// Retired testVersions
// (none) ba7a22a355a32901caf46529c799fa53118ded0a
var tests = []struct {
digits string
span int
product int64
ok bool
}{
{"0123456789",
2, 72, true},
{"12",
2, 2, true},
{"19",
2, 9, true},
{"576802143",
2, 48, true},
{"0123456789",
3, 504, true},
{"1027839564",
3, 270, true},
{"0123456789",
5, 15120, true},
{"73167176531330624919225119674426574742355349194934",
6, 23520, true},
{"52677741234314237566414902593461595376319419139427",
6, 28350, true},
{"",
0, 1, true},
{"123",
4, 0, false},
{pe1k, 5, 40824, true}, // original PE problem
{pe1k, 13, 23514624000, true}, // new PE problem
}
const pe1k = "73167176531330624919225119674426574742355349194934" +
"96983520312774506326239578318016984801869478851843" +
"85861560789112949495459501737958331952853208805511" +
"12540698747158523863050715693290963295227443043557" +
"66896648950445244523161731856403098711121722383113" +
"62229893423380308135336276614282806444486645238749" +
"30358907296290491560440772390713810515859307960866" +
"70172427121883998797908792274921901699720888093776" +
"65727333001053367881220235421809751254540594752243" +
"52584907711670556013604839586446706324415722155397" +
"53697817977846174064955149290862569321978468622482" +
"83972241375657056057490261407972968652414535100474" +
"82166370484403199890008895243450658541227588666881" +
"16427171479924442928230863465674813919123162824586" +
"17866458359124566529476545682848912883142607690042" +
"24219022671055626321111109370544217506941658960408" +
"07198403850962455444362981230987879927244284909188" +
"84580156166097919133875499200524063689912560717606" +
"05886116467109405077541002256983155200055935729725" +
"71636269561882670428252483600823257530420752963450"
func TestLargestSeriesProduct(t *testing.T) {
if TestVersion != testVersion {
t.Fatalf("Found TestVersion = %v, want %v", TestVersion, testVersion)
}
for _, test := range tests {
p, err := LargestSeriesProduct(test.digits, test.span)
switch {
case err != nil:
if test.ok {
t.Fatalf("LargestSeriesProduct(%s, %d) returned error %q. "+
"Error not expected.",
test.digits, test.span, err)
}
case !test.ok:
t.Fatalf("LargestSeriesProduct(%s, %d) = %d, %v. Expected error",
test.digits, test.span, p, err)
case int64(p) != test.product:
t.Fatalf("LargestSeriesProduct(%s, %d) = %d, want %d",
test.digits, test.span, p, test.product)
}
}
}
func BenchmarkLargestSeriesProduct(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range tests {
LargestSeriesProduct(test.digits, test.span)
}
}
}

38
go/leap/README.md Normal file
View File

@@ -0,0 +1,38 @@
# Leap
Write a program that will take a year and report if it is a leap year.
The tricky thing here is that a leap year occurs:
```plain
on every year that is evenly divisible by 4
except every year that is evenly divisible by 100
unless the year is also evenly divisible by 400
```
For example, 1997 is not a leap year, but 1996 is. 1900 is not a leap
year, but 2000 is.
If your language provides a method in the standard library that does
this look-up, pretend it doesn't exist and implement it yourself.
## Notes
For a delightful, four minute explanation of the whole leap year
phenomenon, go watch [this youtube video][video].
[video]: http://www.youtube.com/watch?v=xX96xng7sAE
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://help.exercism.io/getting-started-with-go.html).
## Source
JavaRanch Cattle Drive, exercise 3 [view source](http://www.javaranch.com/leap.jsp)

17
go/leap/cases_test.go Normal file
View File

@@ -0,0 +1,17 @@
package leap
// Source: exercism/x-common
// Commit: 945d08e Merge pull request #50 from soniakeys/master
var testCases = []struct {
year int
expected bool
description string
}{
{1996, true, "leap year"},
{1997, false, "non-leap year"},
{1998, false, "non-leap even year"},
{1900, false, "century"},
{2400, true, "fourth century"},
{2000, true, "Y2K"},
}

15
go/leap/leap.go Normal file
View File

@@ -0,0 +1,15 @@
package leap
// TestVersion is an exercism thing.
const TestVersion = 1
// IsLeapYear returns whether the given year is a leap year.
func IsLeapYear(year int) bool {
if year%4 != 0 {
return false
}
if year%400 == 0 {
return true
}
return year%100 != 0
}

34
go/leap/leap_test.go Normal file
View File

@@ -0,0 +1,34 @@
package leap
import "testing"
// Define a function IsLeapYear(int) bool.
//
// Also define an exported TestVersion with a value that matches
// the internal testVersion here.
const testVersion = 1
// Retired testVersions
// (none) 4a9e144a3c5dc0d9773f4cf641ffe3efe48641d8
func TestLeapYears(t *testing.T) {
if TestVersion != testVersion {
t.Fatalf("Found TestVersion = %v, want %v", TestVersion, testVersion)
}
for _, test := range testCases {
observed := IsLeapYear(test.year)
if observed != test.expected {
t.Fatalf("IsLeapYear(%d) = %t, want %t (%s)",
test.year, observed, test.expected, test.description)
}
}
}
func BenchmarkLeapYears(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range testCases {
IsLeapYear(test.year)
}
}
}

71
go/luhn/README.md Normal file
View File

@@ -0,0 +1,71 @@
# Luhn
Write a program that can take a number and determine whether or not it is valid per the Luhn formula.
The Luhn formula is a simple checksum formula used to validate a variety
of identification numbers, such as credit card numbers and Canadian
Social Insurance Numbers.
The formula verifies a number against its included check digit, which is
usually appended to a partial number to generate the full number. This
number must pass the following test:
- Counting from rightmost digit (which is the check digit) and moving
left, double the value of every second digit.
- For any digits that thus become 10 or more, subtract 9 from the
result.
- 1111 becomes 2121.
- 8763 becomes 7733 (from 2×6=12 → 12-9=3 and 2×8=16 → 16-9=7).
- Add all these digits together.
- 1111 becomes 2121 sums as 2+1+2+1 to give a check digit of 6.
- 8763 becomes 7733, and 7+7+3+3 is 20.
If the total ends in 0 (put another way, if the total modulus 10 is
congruent to 0), then the number is valid according to the Luhn formula;
else it is not valid. So, 1111 is not valid (as shown above, it comes
out to 6), while 8763 is valid (as shown above, it comes out to 20).
Write a program that, given a number
- Can check if it is valid per the Luhn formula. This should treat, for
example, "2323 2005 7766 3554" as valid.
- Can return the checksum, or the remainder from using the Luhn method.
- Can add a check digit to make the number valid per the Luhn formula and
return the original number plus that digit. This should give "2323 2005 7766
3554" in response to "2323 2005 7766 355".
## About Checksums
A checksum has to do with error-detection. There are a number of different
ways in which a checksum could be calculated.
When transmitting data, you might also send along a checksum that says how
many bytes of data are being sent. That means that when the data arrives on
the other side, you can count the bytes and compare it to the checksum. If
these are different, then the data has been garbled in transmission.
In the Luhn problem the final digit acts as a sanity check for all the prior
digits. Running those prior digits through a particular algorithm should give
you that final digit.
It doesn't actually tell you if it's a real credit card number, only that it's
a plausible one. It's the same thing with the bytes that get transmitted --
you could have the right number of bytes and still have a garbled message. So
checksums are a simple sanity-check, not a real in-depth verification of the
authenticity of some data. It's often a cheap first pass, and can be used to
quickly discard obviously invalid things.
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://help.exercism.io/getting-started-with-go.html).
## Source
The Luhn Algorithm on Wikipedia [view source](http://en.wikipedia.org/wiki/Luhn_algorithm)

58
go/luhn/luhn.go Normal file
View File

@@ -0,0 +1,58 @@
package luhn
import (
"fmt"
"regexp"
"strconv"
)
// Valid takes a numeric string and returns whether
// it's Luhn valid.
func Valid(toCheck string) bool {
return GetRemainder(toCheck) == 0
}
// GetRemainder returns the leftover from
// running a number through the Luhn checker
func GetRemainder(toCheck string) int {
// Remove any non-numeric characters
r := regexp.MustCompile("[^0-9]+")
toCheck = r.ReplaceAllString(toCheck, "")
if len(toCheck) == 0 {
return -1
}
var total int
var double bool
for i := range toCheck {
var add int
var err error
idx := (len(toCheck) - 1) - i
if add, err = strconv.Atoi(string(toCheck[idx])); err != nil {
return -1
}
if double {
add = add * 2
if add >= 10 {
add = add - 9
}
}
double = !double
total += add
}
return total % 10
}
// AddCheck takes a number and returns the appropriate
// number with an added digit that makes it valid
func AddCheck(toCheck string) string {
if GetRemainder(toCheck) != 0 {
for i := 0; i <= 9; i++ {
tst := fmt.Sprintf("%s%d", toCheck, i)
if GetRemainder(tst) == 0 {
return tst
}
}
}
return toCheck
}

54
go/luhn/luhn_test.go Normal file
View File

@@ -0,0 +1,54 @@
package luhn
import "testing"
var validTests = []struct {
n string
ok bool
}{
{"738", false},
{"8739567", true},
{"1111", false},
{"8763", true},
{" ", false},
{"", false},
{"2323 2005 7766 3554", true},
}
var addTests = []struct{ raw, luhn string }{
{"123", "1230"},
{"873956", "8739567"},
{"837263756", "8372637564"},
{"2323 2005 7766 355", "2323 2005 7766 3554"},
// bonus Unicode cases
// {"2323·2005·7766·355", "2323·2005·7766·3554"},
// {"", ""},
}
func TestValid(t *testing.T) {
for _, test := range validTests {
if ok := Valid(test.n); ok != test.ok {
t.Fatalf("Valid(%s) = %t, want %t.", test.n, ok, test.ok)
}
}
}
func TestAddCheck(t *testing.T) {
for _, test := range addTests {
if luhn := AddCheck(test.raw); luhn != test.luhn {
t.Fatalf("AddCheck(%s) = %s, want %s.", test.raw, luhn, test.luhn)
}
}
}
func BenchmarkValid(b *testing.B) {
for i := 0; i < b.N; i++ {
Valid("2323 2005 7766 3554")
}
}
func BenchmarkAddCheck(b *testing.B) {
for i := 0; i < b.N; i++ {
AddCheck("2323 2005 7766 355")
}
}

View File

@@ -0,0 +1,20 @@
# Palindrome Products
Write a program that can detect palindrome products in a given range.
A palindromic number reads the same both ways. The largest palindrome
made from the product of two 2-digit numbers is 9009 = 91 x 99.
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://help.exercism.io/getting-started-with-go.html).
## Source
Problem 4 at Project Euler [view source](http://projecteuler.net/problem=4)

View File

@@ -0,0 +1,91 @@
package palindrome
import (
"fmt"
"strconv"
)
// Product is a palindromic product and all of its
// factorizations
type Product struct {
Product int
Factorizations [][2]int
}
func createProduct(fac1, fac2 int) *Product {
p := Product{Product: (fac1 * fac2)}
p.addFactors(fac1, fac2)
return &p
}
func (p *Product) hasFactors(fac1, fac2 int) bool {
for i := 0; i < len(p.Factorizations); i++ {
if p.Factorizations[i][0] == fac1 && p.Factorizations[i][1] == fac2 {
return true
}
if p.Factorizations[i][1] == fac1 && p.Factorizations[i][0] == fac2 {
return true
}
}
return false
}
func (p *Product) addFactors(fac1, fac2 int) {
if (fac1 * fac2) == p.Product {
if !p.hasFactors(fac1, fac2) {
p.Factorizations = append(p.Factorizations, [2]int{fac1, fac2})
}
}
}
// Products takes a min and a max and finds
func Products(fmin, fmax int) (Product, Product, error) {
if fmin > fmax {
return Product{}, Product{}, fmt.Errorf("fmin > fmax")
}
var pMin, pMax Product
var err error
var allProducts []Product
for i := fmin; i <= fmax; i++ {
for j := fmin; j <= fmax; j++ {
if isPalindrome(strconv.Itoa(i * j)) {
var found bool
for k := 0; k < len(allProducts); k++ {
if allProducts[k].Product == (i * j) {
allProducts[k].addFactors(i, j)
found = true
break
}
}
if !found {
allProducts = append(allProducts, *createProduct(i, j))
}
}
}
}
for i := range allProducts {
if allProducts[i].Product > pMax.Product {
// is the old pMax the new pMin?
if len(pMin.Factorizations) == 0 {
pMin = pMax
}
pMax = allProducts[i]
} else {
if allProducts[i].Product < pMin.Product {
pMin = allProducts[i]
}
}
}
fmt.Println(allProducts)
return pMin, pMax, err
}
func isPalindrome(s string) bool {
for i := 0; i < (len(s) / 2); i++ {
if s[i] != s[len(s)-1-i] {
return false
}
}
return true
}

View File

@@ -0,0 +1,92 @@
package palindrome
import (
"fmt"
"strconv"
)
// Product is a palindromic product and all of its
// factorizations
type Product struct {
Product int
Factorizations [][2]int
}
func createProduct(fac1, fac2 int) *Product {
p := Product{Product: (fac1 * fac2)}
p.addFactors(fac1, fac2)
return &p
}
func (p *Product) hasFactors(fac1, fac2 int) bool {
for i := 0; i < len(p.Factorizations); i++ {
if p.Factorizations[i][0] == fac1 && p.Factorizations[i][1] == fac2 {
return true
}
if p.Factorizations[i][1] == fac1 && p.Factorizations[i][0] == fac2 {
return true
}
}
return false
}
func (p *Product) addFactors(fac1, fac2 int) {
if (fac1 * fac2) == p.Product {
if !p.hasFactors(fac1, fac2) {
p.Factorizations = append(p.Factorizations, [2]int{fac1, fac2})
}
}
}
// Products takes a min and a max and finds
func Products(fmin, fmax int) (Product, Product, error) {
if fmin > fmax {
return Product{}, Product{}, fmt.Errorf("fmin > fmax")
}
var pMin, pMax Product
var allProducts []Product
for i := fmin; i <= fmax; i++ {
for j := fmin; j <= fmax; j++ {
if isPalindrome(strconv.Itoa(i * j)) {
var found bool
for k := 0; k < len(allProducts); k++ {
if allProducts[k].Product == (i * j) {
allProducts[k].addFactors(i, j)
found = true
break
}
}
if !found {
allProducts = append(allProducts, *createProduct(i, j))
}
}
}
}
for i := range allProducts {
if allProducts[i].Product > pMax.Product {
// is the old pMax the new pMin?
if len(pMin.Factorizations) == 0 {
pMin = pMax
}
pMax = allProducts[i]
} else {
if allProducts[i].Product < pMin.Product {
pMin = allProducts[i]
}
}
}
if len(allProducts) == 0 {
return pMin, pMax, fmt.Errorf("No palindromes")
}
return pMin, pMax, nil
}
func isPalindrome(s string) bool {
for i := 0; i < (len(s) / 2); i++ {
if s[i] != s[len(s)-1-i] {
return false
}
}
return true
}

View File

@@ -0,0 +1,98 @@
package palindrome
import (
"fmt"
"reflect"
"strings"
"testing"
)
// API to impliment:
// type Product struct {
// Product int // palindromic, of course
// // list of all possible two-factor factorizations of Product, within
// // given limits, in order
// Factorizations [][2]int
// }
// func Products(fmin, fmax int) (pmin, pmax Product, error)
var testData = []struct {
// input to Products(): range limits for factors of the palindrome
fmin, fmax int
// output from Products():
pmin, pmax Product // min and max palandromic products
errPrefix string // start of text if there is an error, "" otherwise
}{
{1, 9,
Product{}, // zero value means don't bother to test it
Product{9, [][2]int{{1, 9}, {3, 3}}},
""},
{10, 99,
Product{121, [][2]int{{11, 11}}},
Product{9009, [][2]int{{91, 99}}},
""},
{100, 999,
Product{10201, [][2]int{{101, 101}}},
Product{906609, [][2]int{{913, 993}}},
""},
{4, 10, Product{}, Product{}, "No palindromes"},
{10, 4, Product{}, Product{}, "fmin > fmax"},
/* bonus curiosities. (can a negative number be a palindrome?
// most say no
{-99, -10, Product{}, Product{}, "Negative limits"},
// but you can still get non-negative products from negative factors.
{-99, -10,
Product{121, [][2]int{{-11, -11}}},
Product{9009, [][2]int{{-99, -91}}},
""},
{-2, 2,
Product{0, [][2]int{{-2, 0}, {-1, 0}, {0, 0}, {0, 1}, {0, 2}}},
Product{4, [][2]int{{-2, -2}, {2, 2}}},
""},
// or you could reverse the *digits*, keeping the minus sign in place.
{-2, 2,
Product{-4, [][2]int{{-2, 2}}},
Product{4, [][2]int{{-2, -2}, {2, 2}}},
""},
{
{0, (^uint(0))>>1, Product{}, Product{}, "This one's gonna overflow"},
*/
}
func TestPalindromeProducts(t *testing.T) {
for _, test := range testData {
// common preamble for test failures
ret := fmt.Sprintf("Products(%d, %d) returned",
test.fmin, test.fmax)
// test
pmin, pmax, err := Products(test.fmin, test.fmax)
switch {
case err == nil:
if test.errPrefix > "" {
t.Fatalf(ret+" err = nil, want %q", test.errPrefix+"...")
}
case test.errPrefix == "":
t.Fatalf(ret+" err = %q, want nil", err)
case !strings.HasPrefix(err.Error(), test.errPrefix):
t.Fatalf(ret+" err = %q, want %q", err, test.errPrefix+"...")
default:
continue // correct error, no further tests for this test case
}
matchProd := func(ww string, rp, wp Product) {
if len(wp.Factorizations) > 0 && // option to skip test
!reflect.DeepEqual(rp, wp) {
t.Fatal(ret, ww, "=", rp, "want", wp)
}
}
matchProd("pmin", pmin, test.pmin)
matchProd("pmax", pmax, test.pmax)
}
}
func BenchmarkPalindromeProducts(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range testData {
Products(test.fmin, test.fmax)
}
}
}

View File

@@ -0,0 +1,22 @@
# Parallel Letter Frequency
Write a program that counts the frequency of letters in texts using parallel computation.
Parallelism is about doing things in parallel that can also be done
sequentially. A common example is counting the frequency of letters.
Create a function that returns the total frequency of each letter in a
list of texts and that employs parallelism.
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://help.exercism.io/getting-started-with-go.html).
## Source
[view source]()

View File

@@ -0,0 +1,27 @@
package letter
import "time"
// ConcurrentFrequency concurrently calls Frequency
// and returns the final Frequency Map
func ConcurrentFrequency(input []string) FreqMap {
var procCnt = len(input)
var toMerge []FreqMap
for _, chunk := range input {
go func(chunk string) {
toMerge = append(toMerge, Frequency(chunk))
procCnt--
}(chunk)
}
for procCnt > 0 {
time.Sleep(time.Millisecond)
}
// We should have all FreqMaps now... merge them
ret := make(map[rune]int)
for _, aResult := range toMerge {
for k, v := range aResult {
ret[k] += v
}
}
return ret
}

View File

@@ -0,0 +1,11 @@
package letter
type FreqMap map[rune]int
func Frequency(s string) FreqMap {
m := FreqMap{}
for _, r := range s {
m[r]++
}
return m
}

View File

@@ -0,0 +1,30 @@
package letter
import (
"sync"
"time"
)
// MyConcurrentFrequency ...
func MyConcurrentFrequency(input []string) FreqMap {
var ProcMap = struct {
sync.RWMutex
m map[rune]int
}{m: make(map[rune]int)}
var procCnt = len(input)
for _, chunk := range input {
go func(chunk string) {
for _, rn := range chunk {
ProcMap.Lock()
ProcMap.m[rn]++
ProcMap.Unlock()
}
procCnt--
}(chunk)
}
for procCnt > 0 {
time.Sleep(time.Millisecond)
}
return ProcMap.m
}

View File

@@ -0,0 +1,72 @@
package letter
import (
"reflect"
"testing"
)
// In the separate file frequency.go, you are given a function, Frequency(),
// to sequentially count letter frequencies in a single text.
// Perform this exercise on parallelism using Go concurrency features.
// Make concurrent calls to Frequency and combine results to obtain the answer.
func TestConcurrentFrequency(t *testing.T) {
seq := Frequency(euro + dutch + us)
con := ConcurrentFrequency([]string{euro, dutch, us})
if !reflect.DeepEqual(con, seq) {
t.Fatal("ConcurrentFrequency wrong result")
}
}
var (
euro = `Freude schöner Götterfunken
Tochter aus Elysium,
Wir betreten feuertrunken,
Himmlische, dein Heiligtum!
Deine Zauber binden wieder
Was die Mode streng geteilt;
Alle Menschen werden Brüder,
Wo dein sanfter Flügel weilt.`
dutch = `Wilhelmus van Nassouwe
ben ik, van Duitsen bloed,
den vaderland getrouwe
blijf ik tot in den dood.
Een Prinse van Oranje
ben ik, vrij, onverveerd,
den Koning van Hispanje
heb ik altijd geëerd.`
us = `O say can you see by the dawn's early light,
What so proudly we hailed at the twilight's last gleaming,
Whose broad stripes and bright stars through the perilous fight,
O'er the ramparts we watched, were so gallantly streaming?
And the rockets' red glare, the bombs bursting in air,
Gave proof through the night that our flag was still there;
O say does that star-spangled banner yet wave,
O'er the land of the free and the home of the brave?`
)
func BenchmarkConcurrentFrequency(b *testing.B) {
b.StopTimer()
var bTest []string
for i := 0; i < 5; i++ {
bTest = append(bTest, euro)
bTest = append(bTest, dutch)
bTest = append(bTest, us)
}
b.StartTimer()
ConcurrentFrequency(bTest)
b.StopTimer()
}
func BenchmarkMyConcurrentFrequency(b *testing.B) {
b.StopTimer()
var bTest []string
for i := 0; i < 5; i++ {
bTest = append(bTest, euro)
bTest = append(bTest, dutch)
bTest = append(bTest, us)
}
b.StartTimer()
MyConcurrentFrequency(bTest)
b.StopTimer()
}

View File

@@ -0,0 +1,29 @@
# Pascals Triangle
Write a program that computes Pascal's triangle up to a given number of rows.
In Pascal's Triangle each number is computed by adding the numbers to
the right and left of the current position in the previous row.
```plain
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
# ... etc
```
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://help.exercism.io/getting-started-with-go.html).
## Source
Pascal's Triangle at Wolfram Math World [view source](http://mathworld.wolfram.com/PascalsTriangle.html)

View File

@@ -0,0 +1,26 @@
package pascal
// Triangle returns pascals triangle up to depth
func Triangle(depth int) [][]int {
var ret [][]int
for currDepth := 0; currDepth < depth; currDepth++ {
var newRow, prevRow []int
// Each row is currDepth+1 long
rowLength := currDepth + 1
// Rows start with a 1
newRow = append(newRow, 1)
if currDepth > 0 {
prevRow = ret[currDepth-1]
}
for i := 1; i < rowLength; i++ {
if i == rowLength-1 {
// Rows end with a 1 also
newRow = append(newRow, 1)
break
}
newRow = append(newRow, prevRow[i-1]+prevRow[i])
}
ret = append(ret, newRow)
}
return ret
}

Binary file not shown.

View File

@@ -0,0 +1,22 @@
package main
import (
"fmt"
"os"
"strconv"
"gogs.bullercodeworks.com/brian/pascal"
)
func main() {
if len(os.Args) == 2 {
if num, err := strconv.Atoi(os.Args[1]); err == nil {
ret := pascal.Triangle(num)
for i := range ret {
fmt.Println(ret[i])
}
return
}
}
fmt.Println("Usage: ./pascal_printer <depth>")
}

View File

@@ -0,0 +1,49 @@
package pascal
import (
"fmt"
"reflect"
"testing"
)
var t20 = [][]int{
{1},
{1, 1},
{1, 2, 1},
{1, 3, 3, 1},
{1, 4, 6, 4, 1},
{1, 5, 10, 10, 5, 1},
{1, 6, 15, 20, 15, 6, 1},
{1, 7, 21, 35, 35, 21, 7, 1},
{1, 8, 28, 56, 70, 56, 28, 8, 1},
{1, 9, 36, 84, 126, 126, 84, 36, 9, 1},
{1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1},
{1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1},
{1, 12, 66, 220, 495, 792, 924, 792, 495, 220, 66, 12, 1},
{1, 13, 78, 286, 715, 1287, 1716, 1716, 1287, 715, 286, 78, 13, 1},
{1, 14, 91, 364, 1001, 2002, 3003, 3432, 3003, 2002, 1001, 364, 91, 14, 1},
{1, 15, 105, 455, 1365, 3003, 5005, 6435, 6435, 5005, 3003, 1365, 455, 105, 15, 1},
{1, 16, 120, 560, 1820, 4368, 8008, 11440, 12870, 11440, 8008, 4368, 1820, 560, 120, 16, 1},
{1, 17, 136, 680, 2380, 6188, 12376, 19448, 24310, 24310, 19448, 12376, 6188, 2380, 680, 136, 17, 1},
{1, 18, 153, 816, 3060, 8568, 18564, 31824, 43758, 48620, 43758, 31824, 18564, 8568, 3060, 816, 153, 18, 1},
{1, 19, 171, 969, 3876, 11628, 27132, 50388, 75582, 92378, 92378, 75582, 50388, 27132, 11628, 3876, 969, 171, 19, 1},
}
func TestTriangle(t *testing.T) {
for n := 1; n <= 20; n++ {
res := Triangle(n)
want := t20[:n]
if !reflect.DeepEqual(res, want) {
t.Fatalf("Triangle(%d) = %s,\nwant:%s\n",
n, format(res), format(want))
}
}
t.Log(format(Triangle(20)))
}
func format(t [][]int) (s string) {
for _, r := range t {
s = fmt.Sprintf("%s\n%v", s, r)
}
return
}

View File

@@ -0,0 +1,30 @@
# Pythagorean Triplet
There exists exactly one Pythagorean triplet for which a + b + c = 1000. Find the product a * b * c.
A Pythagorean triplet is a set of three natural numbers, {a, b, c}, for
which,
```
a**2 + b**2 = c**2
```
For example,
```
3**2 + 4**2 = 9 + 16 = 25 = 5**2.
```
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://help.exercism.io/getting-started-with-go.html).
## Source
Problem 9 at Project Euler [view source](http://projecteuler.net/problem=9)

View File

@@ -0,0 +1,44 @@
package pythagorean
import "math"
// Triplet just holds three ints
type Triplet struct {
a, b, c int
}
// Range finds all pythagorean triplets
// from min to max
func Range(min, max int) []Triplet {
var ret []Triplet
for a := min; a <= max; a++ {
for b := a + 1; b <= max; b++ {
cSq := float64(a*a + b*b)
c := int(math.Sqrt(cSq))
if c >= min && c <= max && isTriplet(a, b, c) {
ret = append(ret, Triplet{a, b, c})
}
}
}
return ret
}
// Sum finds all triplets that sum up to total
func Sum(total int) []Triplet {
var ret []Triplet
// No side of a triangle can be over 1/2 of the total
for a := 1; a <= (total / 2); a++ {
for b := a; b <= (total / 2); b++ {
c := total - a - b
if isTriplet(a, b, c) {
ret = append(ret, Triplet{a, b, c})
}
}
}
return ret
}
func isTriplet(a, b, c int) bool {
return (a*a + b*b) == c*c
}

View File

@@ -0,0 +1,73 @@
package pythagorean
// Use this type definition,
//
// type Triplet [3]int
//
// and implement two functions,
//
// Range(min, max int) []Triplet
// Sum(p int) []Triplet
//
// Range returns a list of all Pythagorean triplets with sides in the
// range min to max inclusive.
//
// Sum returns a list of all Pythagorean triplets where the sum a+b+c
// (the perimeter) is equal to p.
//
// The three elements of each returned triplet must be in order,
// t[0] <= t[1] <= t[2], and the list of triplets must be in lexicographic
// order.
import (
"reflect"
"testing"
)
var rangeTests = []struct {
min, max int
ts []Triplet
}{
{1, 10, []Triplet{{3, 4, 5}, {6, 8, 10}}},
{11, 20, []Triplet{{12, 16, 20}}},
}
func TestRange(t *testing.T) {
for _, test := range rangeTests {
ts := Range(test.min, test.max)
if !reflect.DeepEqual(ts, test.ts) {
t.Fatalf("Range(%d, %d) = %v, want %v",
test.min, test.max, ts, test.ts)
}
}
}
var sumTests = []struct {
sum int
ts []Triplet
}{
{180, []Triplet{{18, 80, 82}, {30, 72, 78}, {45, 60, 75}}},
{1000, []Triplet{{200, 375, 425}}},
}
func TestSum(t *testing.T) {
for _, test := range sumTests {
ts := Sum(test.sum)
if !reflect.DeepEqual(ts, test.ts) {
t.Fatalf("Sum(%d) = %v, want %v",
test.sum, ts, test.ts)
}
}
}
func BenchmarkRange(b *testing.B) {
for i := 0; i < b.N; i++ {
Range(1, 100)
}
}
func BenchmarkSum(b *testing.B) {
for i := 0; i < b.N; i++ {
Sum(1000)
}
}

40
go/queen-attack/README.md Normal file
View File

@@ -0,0 +1,40 @@
# Queen Attack
Write a program that positions two queens on a chess board and indicates whether or not they are positioned so that they can attack each other.
In the game of chess, a queen can attack pieces which are on the same
row, column, or diagonal.
A chessboard can be represented by an 8 by 8 array.
So if you're told the white queen is at (2, 3) and the black queen at
(5, 6), then you'd know you've got a set-up like so:
```plain
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ W _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ B _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
```
You'd also be able to answer whether the queens can attack each other.
In this case, that answer would be yes, they can, because both pieces
share a diagonal.
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://help.exercism.io/getting-started-with-go.html).
## Source
J Dalbey's Programming Practice problems [view source](http://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html)

View File

@@ -0,0 +1,29 @@
package queenattack
import (
"errors"
"math"
)
// CanQueenAttack takes two positions one for a
// white queen (wq) and one for a black queen (bq)
// it returns a boolean value: if an attack can
// be made, and an error
func CanQueenAttack(wq, bq string) (bool, error) {
if len(wq) != 2 || len(bq) != 2 ||
wq[0] < 'a' || wq[0] > 'z' ||
wq[1] < '0' || wq[1] > '8' ||
bq[0] < 'a' || bq[0] > 'z' ||
bq[1] < '0' || bq[1] > '8' ||
wq == bq {
return false, errors.New("Invalid pieces/placement")
}
wx, wy := float64(int8(wq[0])), float64(int8(wq[1]))
bx, by := float64(int8(bq[0])), float64(int8(bq[1]))
if wx == bx || wy == by ||
math.Abs(wx-bx) == math.Abs(wy-by) {
return true, nil
}
return false, nil
}

View File

@@ -0,0 +1,53 @@
package queenattack
import "testing"
// Arguments to CanQueenAttack are in algebraic notation.
// See http://en.wikipedia.org/wiki/Algebraic_notation_(chess)
var tests = []struct {
w, b string
attack bool
ok bool
}{
{"b4", "b4", false, false}, // same square
{"a8", "b9", false, false}, // off board
{"here", "there", false, false}, // invalid
{"", "", false, false},
{"b3", "d7", false, true}, // no attack
{"b4", "b7", true, true}, // same file
{"e4", "b4", true, true}, // same rank
{"a1", "f6", true, true}, // common diagonals
{"a6", "b7", true, true},
{"d1", "f3", true, true},
{"f1", "a6", true, true},
}
func TestCanQueenAttack(t *testing.T) {
for _, test := range tests {
switch attack, err := CanQueenAttack(test.w, test.b); {
case err != nil:
if test.ok {
t.Fatalf("CanQueenAttack(%s, %s) returned error %q. "+
"Error not expected.",
test.w, test.b, err)
}
case !test.ok:
t.Fatalf("CanQueenAttack(%s, %s) = %t, %v. Expected error.",
test.w, test.b, attack, err)
case attack != test.attack:
t.Fatalf("CanQueenAttack(%s, %s) = %t, want %t.",
test.w, test.b, attack, test.attack)
}
}
}
// Benchmark combined time for all test cases
func BenchmarkCanQueenAttack(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range tests {
CanQueenAttack(test.w, test.b)
}
}
}

33
go/raindrops/README.md Normal file
View File

@@ -0,0 +1,33 @@
# Raindrops
Write a program that converts a number to a string, the contents of which depends on the number's prime factors.
- If the number contains 3 as a prime factor, output 'Pling'.
- If the number contains 5 as a prime factor, output 'Plang'.
- If the number contains 7 as a prime factor, output 'Plong'.
- If the number does not contain 3, 5, or 7 as a prime factor,
just pass the number's digits straight through.
## Examples
- 28's prime-factorization is 2, 2, 7.
- In raindrop-speak, this would be a simple "Plong".
- 1755 prime-factorization is 3, 3, 3, 5, 13.
- In raindrop-speak, this would be a "PlingPlang".
- The prime factors of 34 are 2 and 17.
- Raindrop-speak doesn't know what to make of that,
so it just goes with the straightforward "34".
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://help.exercism.io/getting-started-with-go.html).
## Source
A variation on a famous interview question intended to weed out potential candidates. [view source](http://jumpstartlab.com)

View File

@@ -0,0 +1,25 @@
package raindrops
// Source: exercism/x-common
// Commit: 3b07e53 Merge pull request #117 from mikeyjcat/add-raindrops-json
var tests = []struct {
input int
expected string
}{
{1, "1"},
{3, "Pling"},
{5, "Plang"},
{7, "Plong"},
{6, "Pling"},
{9, "Pling"},
{10, "Plang"},
{14, "Plong"},
{15, "PlingPlang"},
{21, "PlingPlong"},
{25, "Plang"},
{35, "PlangPlong"},
{49, "Plong"},
{52, "52"},
{105, "PlingPlangPlong"},
}

26
go/raindrops/raindrops.go Normal file
View File

@@ -0,0 +1,26 @@
package raindrops
import "fmt"
// TestVersion
const TestVersion = 1
// Convert takes a number and returns Raindrop-speak
func Convert(i int) string {
var ret string
if i%3 == 0 {
ret += "Pling"
}
if i%5 == 0 {
ret += "Plang"
}
if i%7 == 0 {
ret += "Plong"
}
if ret != "" {
return ret
}
return fmt.Sprintf("%d", i)
}
// The test program has a benchmark too. How fast does your Convert convert?

View File

@@ -0,0 +1,28 @@
package raindrops
import "testing"
const testVersion = 1
// Retired testVersions
// (none) 52fb31c169bc1b540109028f33f4f61b5f429753
func TestConvert(t *testing.T) {
if TestVersion != testVersion {
t.Fatalf("Found TestVersion = %v, want %v", TestVersion, testVersion)
}
for _, test := range tests {
if actual := Convert(test.input); actual != test.expected {
t.Errorf("Convert(%d) = %q, expected %q.",
test.input, actual, test.expected)
}
}
}
func BenchmarkConvert(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range tests {
Convert(test.input)
}
}
}

32
go/react/README.md Normal file
View File

@@ -0,0 +1,32 @@
# React
Implement a basic reactive system.
Reactive programming is a programming paradigm that focuses on how values
are computed in terms of each other to allow a change to one value to
automatically propagate to other values, like in a spreadsheet.
Implement a basic reactive system with cells with settable values ("input"
cells) and cells with values computed in terms of other cells ("compute"
cells). Implement updates so that when an input value is changed, values
propagate to reach a new stable system state.
In addition, compute cells should allow for registering change notification
callbacks. Call a cells callbacks when the cells value in a new stable
state has changed from the previous stable state.
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).
## Submitting Incomplete Problems
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

49
go/react/interfaces.go Normal file
View File

@@ -0,0 +1,49 @@
package react
// A Reactor manages linked cells.
type Reactor interface {
// CreateInput creates an input cell linked into the reactor
// with the given initial value.
CreateInput(int) InputCell
// CreateCompute1 creates a compute cell which computes its value
// based on one other cell. The compute function will only be called
// if the value of the passed cell changes.
CreateCompute1(Cell, func(int) int) ComputeCell
// CreateCompute2 is like CreateCompute1, but depending on two cells.
// The compute function will only be called if the value of any of the
// passed cells changes.
CreateCompute2(Cell, Cell, func(int, int) int) ComputeCell
}
// A Cell is conceptually a holder of a value.
type Cell interface {
// Value returns the current value of the cell.
Value() int
}
// An InputCell has a changeable value, changing the value triggers updates to
// other cells.
type InputCell interface {
Cell
// SetValue sets the value of the cell.
SetValue(int)
}
// A ComputeCell always computes its value based on other cells and can
// call callbacks upon changes.
type ComputeCell interface {
Cell
// AddCallback adds a callback which will be called when the value changes.
// It returns a callback handle which can be used to remove the callback.
AddCallback(func(int)) CallbackHandle
// RemoveCallback removes a previously added callback, if it exists.
RemoveCallback(CallbackHandle)
}
// A CallbackHandle is used to remove previously added callbacks, see ComputeCell.
type CallbackHandle interface{}

94
go/react/react.go Normal file
View File

@@ -0,0 +1,94 @@
package react
import (
"fmt"
"strconv"
)
const testVersion = 4
// MyReactor implements Reactor
type MyReactor struct {
lastId int
cells []Cell
}
// New creates a new Reactor
func New() *MyReactor {
r := &MyReactor{}
//r.callbacks = make(map[Cell][]func(int))
return r
}
// CreateInput builds an input cell and adds it to the reactor
func (r *MyReactor) CreateInput(i int) InputCell {
r.lastId++
ic := MyCell{val: i, id: r.lastId}
return &ic
}
// CreateCompute1 Takes a cell and a function and returns a compute cell
// which has a value based on running the function on the cells value.
func (r *MyReactor) CreateCompute1(c Cell, f func(int) int) ComputeCell {
r.lastId++
cc := &MyCell{id: r.lastId, isComputed: true}
cc.compVal = func() int { return f(c.Value()) }
return cc
}
// CreateCompute2 Takes two cells and a function and returns a compute cell
// which has a value based on running the function on the cells values.
func (r *MyReactor) CreateCompute2(c1, c2 Cell, f func(int, int) int) ComputeCell {
r.lastId++
cc := &MyCell{id: r.lastId, isComputed: true}
cc.compVal = func() int { return f(c1.Value(), c2.Value()) }
return cc
}
// MyCell implements the all Cell interfaces
type MyCell struct {
id int
isComputed bool
val int
compVal func() int
lastCallbackId int
callbacks map[int]func(int)
}
// Value returns the value of the cell
func (c MyCell) Value() int {
if c.isComputed {
return c.compVal()
}
return c.val
}
// SetValue sets the value on the cell
func (c *MyCell) SetValue(i int) {
if i == c.val || c.isComputed {
// No change or this is a computed cell, just return
return
}
c.val = i
// Hit all callbacks
for _, v := range c.callbacks {
fmt.Println("Hitting a callback: " + strconv.Itoa(i))
v(i)
}
}
func (c *MyCell) AddCallback(cb func(int)) CallbackHandle {
if c.lastCallbackId == 0 {
fmt.Println("Initializing Callback Map (Cell " + strconv.Itoa(c.id) + ")")
c.callbacks = make(map[int]func(int))
}
fmt.Println("Adding a Callback to " + strconv.Itoa(c.id))
c.lastCallbackId++
c.callbacks[c.lastCallbackId] = cb
fmt.Println("Number of Callbacks: " + strconv.Itoa(c.lastCallbackId))
return c.lastCallbackId
}
func (c *MyCell) RemoveCallback(cbh CallbackHandle) {
delete(c.callbacks, cbh.(int))
}

278
go/react/react_test.go Normal file
View File

@@ -0,0 +1,278 @@
package react
import (
"runtime"
"testing"
)
// Define a function New() Reactor and the stuff that follows from
// implementing Reactor.
//
// Also define a testVersion with a value that matches
// the targetTestVersion here.
const targetTestVersion = 4
// This is a compile time check to see if you've properly implemented New().
var _ Reactor = New()
// If this test fails and you've proprly defined testVersion the requirements
// of the tests have changed since you wrote your submission.
func TestTestVersion(t *testing.T) {
if testVersion != targetTestVersion {
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
}
}
func assertCellValue(t *testing.T, c Cell, expected int, explanation string) {
observed := c.Value()
_, _, line, _ := runtime.Caller(1)
if observed != expected {
t.Fatalf("(from line %d) %s: expected %d, got %d", line, explanation, expected, observed)
}
}
// Setting the value of an input cell changes the observable Value()
func TestSetInput(t *testing.T) {
r := New()
i := r.CreateInput(1)
assertCellValue(t, i, 1, "i.Value() doesn't match initial value")
i.SetValue(2)
assertCellValue(t, i, 2, "i.Value() doesn't match changed value")
}
// The value of a compute 1 cell is determined by the value of the dependencies.
func TestBasicCompute1(t *testing.T) {
r := New()
i := r.CreateInput(1)
c := r.CreateCompute1(i, func(v int) int { return v + 1 })
assertCellValue(t, c, 2, "c.Value() isn't properly computed based on initial input cell value")
i.SetValue(2)
assertCellValue(t, c, 3, "c.Value() isn't properly computed based on changed input cell value")
}
// The value of a compute 2 cell is determined by the value of the dependencies.
func TestBasicCompute2(t *testing.T) {
r := New()
i1 := r.CreateInput(1)
i2 := r.CreateInput(2)
c := r.CreateCompute2(i1, i2, func(v1, v2 int) int { return v1 | v2 })
assertCellValue(t, c, 3, "c.Value() isn't properly computed based on initial input cell values")
i1.SetValue(4)
assertCellValue(t, c, 6, "c.Value() isn't properly computed when first input cell value changes")
i2.SetValue(8)
assertCellValue(t, c, 12, "c.Value() isn't properly computed when second input cell value changes")
}
// Compute 2 cells can depend on compute 1 cells.
func TestCompute2Diamond(t *testing.T) {
r := New()
i := r.CreateInput(1)
c1 := r.CreateCompute1(i, func(v int) int { return v + 1 })
c2 := r.CreateCompute1(i, func(v int) int { return v - 1 })
c3 := r.CreateCompute2(c1, c2, func(v1, v2 int) int { return v1 * v2 })
assertCellValue(t, c3, 0, "c3.Value() isn't properly computed based on initial input cell value")
i.SetValue(3)
assertCellValue(t, c3, 8, "c3.Value() isn't properly computed based on changed input cell value")
}
// Compute 1 cells can depend on other compute 1 cells.
func TestCompute1Chain(t *testing.T) {
r := New()
inp := r.CreateInput(1)
var c Cell = inp
for i := 2; i <= 8; i++ {
// must save current value of loop variable i for correct behavior.
// compute function has to use digitToAdd not i.
digitToAdd := i
c = r.CreateCompute1(c, func(v int) int { return v*10 + digitToAdd })
}
assertCellValue(t, c, 12345678, "c.Value() isn't properly computed based on initial input cell value")
inp.SetValue(9)
assertCellValue(t, c, 92345678, "c.Value() isn't properly computed based on changed input cell value")
}
// Compute 2 cells can depend on other compute 2 cells.
func TestCompute2Tree(t *testing.T) {
r := New()
ins := make([]InputCell, 3)
for i, v := range []int{1, 10, 100} {
ins[i] = r.CreateInput(v)
}
add := func(v1, v2 int) int { return v1 + v2 }
firstLevel := make([]ComputeCell, 2)
for i := 0; i < 2; i++ {
firstLevel[i] = r.CreateCompute2(ins[i], ins[i+1], add)
}
output := r.CreateCompute2(firstLevel[0], firstLevel[1], add)
assertCellValue(t, output, 121, "output.Value() isn't properly computed based on initial input cell values")
for i := 0; i < 3; i++ {
ins[i].SetValue(ins[i].Value() * 2)
}
assertCellValue(t, output, 242, "output.Value() isn't properly computed based on changed input cell values")
}
// Compute cells can have callbacks.
func TestBasicCallback(t *testing.T) {
r := New()
i := r.CreateInput(1)
c := r.CreateCompute1(i, func(v int) int { return v + 1 })
var observed []int
c.AddCallback(func(v int) {
observed = append(observed, v)
})
if len(observed) != 0 {
t.Fatalf("callback called before changes were made")
}
i.SetValue(2)
if len(observed) != 1 {
t.Fatalf("callback not called when changes were made")
}
if observed[0] != 3 {
t.Fatalf("callback not called with proper value")
}
}
// Callbacks and only trigger on change.
func TestOnlyCallOnChanges(t *testing.T) {
r := New()
i := r.CreateInput(1)
c := r.CreateCompute1(i, func(v int) int {
if v > 3 {
return v + 1
}
return 2
})
var observedCalled int
c.AddCallback(func(int) {
observedCalled++
})
i.SetValue(1)
if observedCalled != 0 {
t.Fatalf("observe function called even though input didn't change")
}
i.SetValue(2)
if observedCalled != 0 {
t.Fatalf("observe function called even though computed value didn't change")
}
}
// Callbacks can be added and removed.
func TestCallbackAddRemove(t *testing.T) {
r := New()
i := r.CreateInput(1)
c := r.CreateCompute1(i, func(v int) int { return v + 1 })
var observed1 []int
cb1 := c.AddCallback(func(v int) {
observed1 = append(observed1, v)
})
var observed2 []int
c.AddCallback(func(v int) {
observed2 = append(observed2, v)
})
i.SetValue(2)
if len(observed1) != 1 || observed1[0] != 3 {
t.Fatalf("observed1 not properly called")
}
if len(observed2) != 1 || observed2[0] != 3 {
t.Fatalf("observed2 not properly called")
}
c.RemoveCallback(cb1)
i.SetValue(3)
if len(observed1) != 1 {
t.Fatalf("observed1 called after removal")
}
if len(observed2) != 2 || observed2[1] != 4 {
t.Fatalf("observed2 not properly called after first callback removal")
}
}
func TestMultipleCallbackRemoval(t *testing.T) {
r := New()
inp := r.CreateInput(1)
c := r.CreateCompute1(inp, func(v int) int { return v + 1 })
numCallbacks := 5
calls := make([]int, numCallbacks)
handles := make([]CallbackHandle, numCallbacks)
for i := 0; i < numCallbacks; i++ {
// Rebind i, otherwise all callbacks will use i = numCallbacks
i := i
handles[i] = c.AddCallback(func(v int) { calls[i]++ })
}
inp.SetValue(2)
for i := 0; i < numCallbacks; i++ {
if calls[i] != 1 {
t.Fatalf("callback %d/%d should be called 1 time, was called %d times", i+1, numCallbacks, calls[i])
}
c.RemoveCallback(handles[i])
}
inp.SetValue(3)
for i := 0; i < numCallbacks; i++ {
if calls[i] != 1 {
t.Fatalf("callback %d/%d was called after it was removed", i+1, numCallbacks)
}
}
}
func TestRemoveIdempotence(t *testing.T) {
r := New()
inp := r.CreateInput(1)
output := r.CreateCompute1(inp, func(v int) int { return v + 1 })
timesCalled := 0
cb1 := output.AddCallback(func(int) {})
output.AddCallback(func(int) { timesCalled++ })
for i := 0; i < 10; i++ {
output.RemoveCallback(cb1)
}
inp.SetValue(2)
if timesCalled != 1 {
t.Fatalf("remaining callback function was not called")
}
}
// Callbacks should only be called once even though
// multiple dependencies have changed.
func TestOnlyCallOnceOnMultipleDepChanges(t *testing.T) {
r := New()
i := r.CreateInput(1)
c1 := r.CreateCompute1(i, func(v int) int { return v + 1 })
c2 := r.CreateCompute1(i, func(v int) int { return v - 1 })
c3 := r.CreateCompute1(c2, func(v int) int { return v - 1 })
c4 := r.CreateCompute2(c1, c3, func(v1, v3 int) int { return v1 * v3 })
changed4 := 0
c4.AddCallback(func(int) { changed4++ })
i.SetValue(3)
if changed4 < 1 {
t.Fatalf("callback function was not called")
} else if changed4 > 1 {
t.Fatalf("callback function was called too often")
}
}
// Callbacks should not be called if dependencies change in such a way
// that the final value of the compute cell does not change.
func TestNoCallOnDepChangesResultingInNoChange(t *testing.T) {
r := New()
inp := r.CreateInput(0)
plus1 := r.CreateCompute1(inp, func(v int) int { return v + 1 })
minus1 := r.CreateCompute1(inp, func(v int) int { return v - 1 })
// The output's value is always 2, no matter what the input is.
output := r.CreateCompute2(plus1, minus1, func(v1, v2 int) int { return v1 - v2 })
timesCalled := 0
output.AddCallback(func(int) { timesCalled++ })
inp.SetValue(5)
if timesCalled != 0 {
t.Fatalf("callback function called even though computed value didn't change")
}
}

View File

@@ -0,0 +1,33 @@
# Rna Transcription
Write a program that, given a DNA strand, returns its RNA complement (per RNA transcription).
Both DNA and RNA strands are a sequence of nucleotides.
The four nucleotides found in DNA are adenine (**A**), cytosine (**C**),
guanine (**G**) and thymine (**T**).
The four nucleotides found in RNA are adenine (**A**), cytosine (**C**),
guanine (**G**) and uracil (**U**).
Given a DNA strand, its transcribed RNA strand is formed by replacing
each nucleotide with its complement:
* `G` -> `C`
* `C` -> `G`
* `T` -> `A`
* `A` -> `U`
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
Rosalind [view source](http://rosalind.info/problems/rna)

View File

@@ -0,0 +1,24 @@
package strand
// Source: exercism/x-common
// Commit: 6985644 Merge pull request #121 from mikeyjcat/add-roman-numerals-test-definition
var rnaTests = []struct {
input string
expected string
}{
// rna complement of cytosine is guanine
{"C", "G"},
// rna complement of guanine is cytosine
{"G", "C"},
// rna complement of thymine is adenine
{"T", "A"},
// rna complement of adenine is uracil
{"A", "U"},
// rna complement
{"ACGTGGTCTTAA", "UGCACCAGAAUU"},
}

View File

@@ -0,0 +1,25 @@
package strand
import "testing"
const testVersion = 2
func TestRNATranscription(t *testing.T) {
if TestVersion != testVersion {
t.Fatalf("Found TestVersion = %v, want %v", TestVersion, testVersion)
}
for _, test := range rnaTests {
if actual := ToRNA(test.input); actual != test.expected {
t.Errorf("ToRNA(%s): %s, expected %s",
test.input, actual, test.expected)
}
}
}
func BenchmarkRNATranscription(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range rnaTests {
ToRNA(test.input)
}
}
}

View File

@@ -0,0 +1,57 @@
# Roman Numerals
Write a function to convert from normal numbers to Roman Numerals: e.g.
The Romans were a clever bunch. They conquered most of Europe and ruled
it for hundreds of years. They invented concrete and straight roads and
even bikinis. One thing they never discovered though was the number
zero. This made writing and dating extensive histories of their exploits
slightly more challenging, but the system of numbers they came up with
is still in use today. For example the BBC uses Roman numerals to date
their programmes.
The Romans wrote numbers using letters - I, V, X, L, C, D, M. (notice
these letters have lots of straight lines and are hence easy to hack
into stone tablets).
```
1 => I
10 => X
7 => VII
```
There is no need to be able to convert numbers larger than about 3000.
(The Romans themselves didn't tend to go any higher)
Wikipedia says: Modern Roman numerals ... are written by expressing each
digit separately starting with the left most digit and skipping any
digit with a value of zero.
To see this in practice, consider the example of 1990.
In Roman numerals 1990 is MCMXC:
1000=M
900=CM
90=XC
2008 is written as MMVIII:
2000=MM
8=VIII
See also: http://www.novaroma.org/via_romana/numbers.html
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
The Roman Numeral Kata [view source](http://codingdojo.org/cgi-bin/wiki.pl?KataRomanNumerals)

View File

@@ -0,0 +1,31 @@
package romannumerals
// Source: exercism/x-common
// Commit: 6985644 Merge pull request #121 from mikeyjcat/add-roman-numerals-test-definition
type romanNumeralTest struct {
arabic int
roman string
hasError bool
}
var romanNumeralTests = []romanNumeralTest{
{1, "I", false},
{2, "II", false},
{3, "III", false},
{4, "IV", false},
{5, "V", false},
{6, "VI", false},
{9, "IX", false},
{27, "XXVII", false},
{48, "XLVIII", false},
{59, "LIX", false},
{93, "XCIII", false},
{141, "CXLI", false},
{163, "CLXIII", false},
{402, "CDII", false},
{575, "DLXXV", false},
{911, "CMXI", false},
{1024, "MXXIV", false},
{3000, "MMM", false},
}

BIN
go/roman-numerals/cmd/cmd Executable file

Binary file not shown.

View File

@@ -0,0 +1,22 @@
package main
import (
"fmt"
"strconv"
"../../roman-numerals"
)
func main() {
arabic := []int{0, -1, 4000, 3999, 1, 2, 3, 4, 5, 6, 9, 27, 48, 59, 93, 141, 163, 402, 575, 911, 1024, 3000}
for i := range arabic {
fmt.Println(strconv.Itoa(arabic[i]) + ": ")
if v, err := romannumerals.ToRomanNumeral(arabic[i]); err == nil {
fmt.Print("-->")
fmt.Println(v)
} else {
fmt.Print("-->")
fmt.Println(err.Error())
}
}
}

View File

@@ -0,0 +1,39 @@
package romannumerals
import "testing"
const testVersion = 1
func TestRomanNumerals(t *testing.T) {
if TestVersion != testVersion {
t.Fatalf("Found TestVersion = %v, want %v", TestVersion, testVersion)
}
tc := append(romanNumeralTests, []romanNumeralTest{
{0, "", true},
{-1, "", true},
{4000, "", true},
{3999, "MMMCMXCIX", false},
}...)
for _, test := range tc {
actual, err := ToRomanNumeral(test.arabic)
if err == nil && test.hasError {
t.Errorf("ToRomanNumeral(%d) should return an error.", test.arabic)
continue
}
if err != nil && !test.hasError {
t.Errorf("ToRomanNumeral(%d) should not return an error.", test.arabic)
continue
}
if actual != test.roman {
t.Errorf("ToRomanNumeral(%d): %s, expected %s", test.arabic, actual, test.roman)
}
}
}
func BenchmarkRomanNumerals(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, test := range romanNumeralTests {
ToRomanNumeral(test.arabic)
}
}
}

View File

@@ -0,0 +1,72 @@
package romannumerals
import (
"errors"
"strings"
)
// TestVersion tells exercism which tests to use
const TestVersion = 1
// ToRomanNumeral takes an int and returns it's roman numberal string value
// Or an error if it can't be done.
func ToRomanNumeral(arabic int) (string, error) {
if arabic <= 0 || arabic > 3999 {
return "", errors.New("Invalid number given")
}
var ret string
var err error
var care int
place := 1
for ; arabic > 0; arabic = (arabic - care) / 10 {
care = arabic % 10
ret = getRomanChar(care, place) + ret
place *= 10
}
if strings.Contains(ret, "?") {
err = errors.New("Invalid number given")
}
return ret, err
}
func getRomanChar(dg, pl int) string {
switch {
case dg <= 0:
return ""
case dg < 4:
return strings.Repeat(getOnesPlaceChar(pl), dg)
case dg == 4:
return getOnesPlaceChar(pl) + getFivesPlaceChar(pl)
case dg < 9:
return getFivesPlaceChar(pl) + getRomanChar(dg-5, pl)
case dg == 9:
return getOnesPlaceChar(pl) + getOnesPlaceChar(pl*10)
}
return "?"
}
func getOnesPlaceChar(pl int) string {
switch pl {
case 1:
return "I"
case 10:
return "X"
case 100:
return "C"
case 1000:
return "M"
}
return "?"
}
func getFivesPlaceChar(pl int) string {
switch pl {
case 1:
return "V"
case 10:
return "L"
case 100:
return "D"
}
return "?"
}

77
go/say/README.md Normal file
View File

@@ -0,0 +1,77 @@
# Say
Write a program that will take a number from 0 to 999,999,999,999 and spell out that number in English.
## Step 1
Handle the basic case of 0 through 99.
If the input to the program is `22`, then the output should be
`'twenty-two'`.
Your program should complain loudly if given a number outside the
blessed range.
Some good test cases for this program are:
- 0
- 14
- 50
- 98
- -1
- 100
### Extension
If you're on a Mac, shell out to Mac OS X's `say` program to talk out
loud.
## Step 2
Implement breaking a number up into chunks of thousands.
So `1234567890` should yield a list like 1, 234, 567, and 890, while the
far simpler `1000` should yield just 1 and 0.
The program must also report any values that are out of range.
## Step 3
Now handle inserting the appropriate scale word between those chunks.
So `1234567890` should yield `'1 billion 234 million 567 thousand 890'`
The program must also report any values that are out of range. It's
fine to stop at "trillion".
## Step 4
Put it all together to get nothing but plain English.
`12345` should give `twelve thousand three hundred forty-five`.
The program must also report any values that are out of range.
### Extensions
Use _and_ (correctly) when spelling out the number in English:
- 14 becomes "fourteen".
- 100 becomes "one hundred".
- 120 becomes "one hundred and twenty".
- 1002 becomes "one thousand and two".
- 1323 becomes "one thousand three hundred and twenty-three".
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
A variation on JavaRanch CattleDrive, exercise 4a [http://www.javaranch.com/say.jsp](http://www.javaranch.com/say.jsp)

Some files were not shown because too many files have changed in this diff Show More