This commit is contained in:
Brian Buller 2016-11-29 21:28:40 -06:00
parent 4e2f6c22b4
commit 549ba5084e
14 changed files with 877 additions and 0 deletions

75
go/diamond/README.md Normal file
View File

@ -0,0 +1,75 @@
# Diamond
Given a letter, print a diamond starting with 'A' with the supplied letter at the widest point.
## Diamond kata
The diamond kata takes as its input a letter, and outputs it in a diamond
shape. Given a letter, it prints a diamond starting with 'A', with the
supplied letter at the widest point.
## Requirements
* The first row contains one 'A'.
* The last row contains one 'A'.
* All rows, except the first and last, have exactly two identical letters.
* All rows have as many trailing spaces as leading spaces. (This might be 0).
* The diamond is horizontally symmetric.
* The diamond is vertically symmetric.
* The diamond has a square shape (width equals height).
* The letters form a diamond shape.
* The top half has the letters in ascending order.
* The bottom half has the letters in descending order.
* The four corners (containing the spaces) are triangles.
## Examples
In the following examples, spaces are indicated by `·` characters.
Diamond for letter 'A':
```plain
A
```
Diamond for letter 'C':
```plain
··A··
·B·B·
C···C
·B·B·
··A··
```
Diamond for letter 'E':
```plain
····A····
···B·B···
··C···C··
·D·····D·
E·······E
·D·····D·
··C···C··
···B·B···
····A····
```
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
Seb Rose [http://claysnow.co.uk/recycling-tests-in-tdd/](http://claysnow.co.uk/recycling-tests-in-tdd/)
## Submitting Incomplete Problems
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

36
go/diamond/diamond.go Normal file
View File

@ -0,0 +1,36 @@
package diamond
import (
"errors"
"strings"
)
const testVersion = 1
func Gen(c byte) (string, error) {
if c > 'Z' || c < 'A' {
return "", errors.New("Out of Range")
}
d := rune(strings.ToUpper(string(c))[0])
var ret string
for i := 'A'; i <= d; i++ {
ret += PrintRow(i, d) + "\n"
}
for i := d - 1; i >= 'A'; i-- {
ret += PrintRow(i, d) + "\n"
}
return ret, nil
}
func PrintRow(rowChar rune, genChar rune) string {
var ret string
ret += strings.Repeat(" ", int(genChar-rowChar))
ret += string(rowChar)
if rowChar > 'A' {
ret += strings.Repeat(" ", (2*int(rowChar-'A') - 1))
ret += string(rowChar)
}
ret += strings.Repeat(" ", int(genChar-rowChar))
return ret
}

227
go/diamond/diamond_test.go Normal file
View File

@ -0,0 +1,227 @@
package diamond
import (
"math/rand"
"reflect"
"strings"
"testing"
"testing/quick"
"time"
)
var config = &quick.Config{Rand: rand.New(rand.NewSource(time.Now().UnixNano()))}
type correctChar byte
func (c correctChar) Generate(rand *rand.Rand, _ int) reflect.Value {
return reflect.ValueOf(correctChar('A' + rand.Intn('Z'-'A'+1)))
}
func checkCorrect(requirement func(byte, []string) bool, keepSeparator bool, t *testing.T) {
assertion := func(char correctChar) bool {
d, err := Gen(byte(char))
if err != nil {
return false
}
separator := strings.Split
if keepSeparator {
separator = strings.SplitAfter
}
rows := separator(d, "\n")
if len(rows) < 2 {
return false
}
return requirement(byte(char), rows[:len(rows)-1])
}
if err := quick.Check(assertion, config); err != nil {
t.Error(err)
}
}
func TestFirstRowContainsOneA(t *testing.T) {
requirement := func(char byte, rows []string) bool {
return len(rows) > 0 && strings.Count(rows[0], "A") == 1
}
checkCorrect(requirement, false, t)
}
func TestLastRowContainsOneA(t *testing.T) {
requirement := func(char byte, rows []string) bool {
return len(rows) > 0 && strings.Count(rows[len(rows)-1], "A") == 1
}
checkCorrect(requirement, false, t)
}
func TestAllRowsIdenticalLettersExceptFirstAndLast(t *testing.T) {
requirement := func(char byte, rows []string) bool {
for i, row := range rows {
r := strings.TrimSpace(row)
if r[0] != r[len(r)-1] {
return false
}
if len(r) < 2 && i != 0 && i != len(rows)-1 {
return false
}
}
return true
}
checkCorrect(requirement, false, t)
}
func TestAllRowsHaveSameTrailingSpaces(t *testing.T) {
requirement := func(char byte, rows []string) bool {
for _, row := range rows {
if len(row) == 0 {
return false
}
for i, j := 0, len(row)-1; i < j && row[i] == ' '; i, j = i+1, j-1 {
if row[j] != ' ' {
return false
}
}
}
return true
}
checkCorrect(requirement, false, t)
}
func TestDiamondIsHorizontallySymmetric(t *testing.T) {
requirement := func(char byte, rows []string) bool {
for _, row := range rows {
l := len(row)
for i := l/2 - 1; i >= 0; i-- {
if row[i] != row[l-1-i] {
return false
}
}
}
return true
}
checkCorrect(requirement, false, t)
}
func TestDiamondIsVerticallySymmetric(t *testing.T) {
requirement := func(char byte, rows []string) bool {
for i, j := 0, len(rows)-1; i < j; i, j = i+1, j-1 {
if rows[i] != rows[j] {
return false
}
}
return true
}
checkCorrect(requirement, true, t)
}
func TestDiamondIsSquare(t *testing.T) {
requirement := func(char byte, rows []string) bool {
if int(char-'A')*2+1 != len(rows) {
return false
}
for _, row := range rows {
if len(row) != len(rows) {
return false
}
}
return true
}
checkCorrect(requirement, false, t)
}
func TestDiamondHasItsShape(t *testing.T) {
requirement := func(char byte, rows []string) bool {
var n int
for i, row := range rows {
s := len(strings.TrimSpace(row))
if i > len(rows)/2 && n <= s {
return false
} else if i <= len(rows)/2 && n >= s {
return false
}
n = s
}
return true
}
checkCorrect(requirement, false, t)
}
func TestTopHalfHasAscendingLetters(t *testing.T) {
requirement := func(char byte, rows []string) bool {
var start byte = 'A' - 1
for i := 0; i <= len(rows)/2; i++ {
s := strings.TrimLeft(rows[i], " ")
if s == "" || s[0] <= start {
return false
}
start = s[0]
}
return true
}
checkCorrect(requirement, false, t)
}
func TestBottomHalfHasDescendingLetters(t *testing.T) {
requirement := func(char byte, rows []string) bool {
var start byte = 'A' - 1
for i := len(rows) - 1; i > len(rows)/2; i-- {
s := strings.TrimLeft(rows[i], " ")
if s == "" || s[0] <= start {
return false
}
start = s[0]
}
return true
}
checkCorrect(requirement, false, t)
}
func TestDiamondFourCornersAreTriangle(t *testing.T) {
requirement := func(char byte, rows []string) bool {
notSpace := func(r rune) bool { return r <= 'Z' && r >= 'A' }
var n int
for i, row := range rows {
s := strings.IndexFunc(row, notSpace)
e := len(row) - strings.LastIndexFunc(row, notSpace) - 1
if s != e {
return false
} else if i == 0 {
n = s
} else {
if i > len(rows)/2 && n >= s {
return false
} else if i <= len(rows)/2 && n <= s {
return false
}
n = s
}
}
return true
}
checkCorrect(requirement, false, t)
}
type wrongChar byte
func (c wrongChar) Generate(rand *rand.Rand, _ int) reflect.Value {
b := rand.Intn(256)
for ; b >= 'A' && b <= 'Z'; b = rand.Intn(256) {
}
return reflect.ValueOf(wrongChar(b))
}
func TestCharOutOfRangeShouldGiveError(t *testing.T) {
assertion := func(char wrongChar) bool {
_, err := Gen(byte(char))
return err != nil
}
if err := quick.Check(assertion, config); err != nil {
t.Error(err)
}
}
const targetTestVersion = 1
func TestTestVersion(t *testing.T) {
if testVersion != targetTestVersion {
t.Errorf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
}
}

31
go/isogram/README.md Normal file
View File

@ -0,0 +1,31 @@
# Isogram
Determine if a word or phrase is an isogram.
An isogram (also known as a "nonpattern word") is a word or phrase without a repeating letter.
Examples of isograms:
- lumberjacks
- background
- downstream
The word *isograms*, however, is not an isogram, because the s repeats.
To run the tests simply run the command `go test` in the exercise directory.
If the test suite contains benchmarks, you can run these with the `-bench`
flag:
go test -bench .
For more detailed info about the Go track see the [help
page](http://exercism.io/languages/go).
## Source
Wikipedia [https://en.wikipedia.org/wiki/Isogram](https://en.wikipedia.org/wiki/Isogram)
## Submitting Incomplete Problems
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

23
go/isogram/isogram.go Normal file
View File

@ -0,0 +1,23 @@
package isogram
import "strings"
const testVersion = 1
func IsIsogram(inp string) bool {
used := make(map[rune]int)
inp = strings.ToLower(inp)
for _, l := range inp {
switch l {
case '-':
continue
case ' ':
continue
}
if used[l] > 0 {
return false
}
used[l] = used[l] + 1
}
return true
}

View File

@ -0,0 +1,50 @@
package isogram
import "testing"
var testCases = []struct {
word string
expected bool
}{
{"duplicates", true},
{"eleven", false},
{"subdermatoglyphic", true},
{"Alphabet", false},
{"thumbscrew-japingly", true},
{"Hjelmqvist-Gryb-Zock-Pfund-Wax", true},
{"Heizölrückstoßabdämpfung", true},
{"the quick brown fox", false},
{"Emily Jung Schwartzkopf", true},
{"éléphant", false},
}
func TestIsIsogram(t *testing.T) {
for _, c := range testCases {
if IsIsogram(c.word) != c.expected {
t.Fatalf("FAIL: Word %q, expected %v, got %v", c.word, c.expected, !c.expected)
}
t.Logf("PASS: Word %q", c.word)
}
}
func BenchmarkIsIsogram(b *testing.B) {
b.StopTimer()
for _, c := range testCases {
b.StartTimer()
for i := 0; i < b.N; i++ {
IsIsogram(c.word)
}
b.StopTimer()
}
}
const targetTestVersion = 1
func TestTestVersion(t *testing.T) {
if testVersion != targetTestVersion {
t.Errorf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
}
}

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

@ -0,0 +1,26 @@
package paasio
const testVersion = 3
func NewWriteCounter() WriteCounter {
w := new(WriteCounter)
return w
}
func (w *WriteCounter) WriteCount() (int64, int) {
return 0, 0
}
func NewReadCounter() ReadCounter {
r := new(ReadCounter)
return r
}
func (r *ReadCounter) ReadCount() (int64, int) {
return 0, 0
}
func NewReadWriteCounter() *ReadWriteCounter {
r := new(ReadWriteCounter)
return r
}

View File

@ -0,0 +1,42 @@
# Perfect Numbers
The Greek mathematician Nicomachus devised a classification scheme for natural numbers.
The Greek mathematican Nicomachus devised a classification scheme for
natural numbers, identifying each as belonging uniquely to the
categories of _abundant_, _perfect_, or _deficient_. A perfect number
equals the sum of its positive divisors — the pairs of numbers whose
product yields the target number, excluding the number itself.
- Perfect: Sum of factors = number
- Abundant: Sum of factors > number
- Deficient: Sum of factors < number
The Aliquot sum is defined as the sum of the factors of a number not
including the number itself.
## Examples
- 6 is a perfect number because its divisors are 1, 2, 3 and 6 = 1 + 2 +
3.
- 28 is perfect number because 28 = 1 + 2 + 4 + 7 + 14.
- Prime numbers 7, 13, etc are Deficient by the Nicomachus
classification.
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
Taken from Chapter 2 of Functional Thinking by Neal Ford. [http://shop.oreilly.com/product/0636920029687.do](http://shop.oreilly.com/product/0636920029687.do)
## Submitting Incomplete Problems
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

View File

@ -0,0 +1,40 @@
package perfect
import "errors"
type Classification int
const (
ClassificationPerfect = iota
ClassificationDeficient
ClassificationAbundant
)
const testVersion = 1
var ErrOnlyPositive error
func Classify(inp uint64) (Classification, error) {
ErrOnlyPositive = errors.New("Only Positive Allowed")
if inp <= 0 {
return 0, ErrOnlyPositive
}
factors := GetFactorSum(inp)
if factors > inp {
return ClassificationAbundant, nil
}
if factors < inp {
return ClassificationDeficient, nil
}
return ClassificationPerfect, nil
}
func GetFactorSum(inp uint64) uint64 {
var ret uint64
for i := uint64(1); i < inp; i++ {
if inp%i == 0 {
ret += i
}
}
return ret
}

View File

@ -0,0 +1,41 @@
package perfect
import "testing"
var _ error = ErrOnlyPositive
func TestGivesPositiveRequiredError(t *testing.T) {
if _, err := Classify(0); err != ErrOnlyPositive {
t.Errorf("Expected error %q but got %q", ErrOnlyPositive, err)
}
}
func TestClassifiesCorrectly(t *testing.T) {
cases := []struct {
input uint64
expected Classification
}{
{1, ClassificationDeficient},
{13, ClassificationDeficient},
{12, ClassificationAbundant},
{6, ClassificationPerfect},
{28, ClassificationPerfect},
{496, ClassificationPerfect},
{8128, ClassificationPerfect},
}
for _, c := range cases {
if cat, err := Classify(c.input); err != nil {
t.Errorf("%d: Expected no error but got %s", c.input, err)
} else if cat != c.expected {
t.Errorf("%d: Expected %q, got %q", c.input, c.expected, cat)
}
}
}
const targetTestVersion = 1
func TestTestVersion(t *testing.T) {
if testVersion != targetTestVersion {
t.Errorf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
}
}

View File

@ -0,0 +1,60 @@
# Protein Translation
Write a program that will translate RNA sequences into proteins.
Lets write a program that will translate RNA sequences into proteins. [general ref](http://en.wikipedia.org/wiki/Translation_(biology)
RNA can be broken into three nucleotide sequences called codons, and then translated to a polypeptide like so:
RNA: `"AUGUUUUCU"` => translates to
Codons: `"AUG", "UUU", "UCU"`
=> which become a polypeptide with the following sequence =>
Protein: `"Methionine", "Phenylalanine", "Serine"`
There are 64 codons which in turn correspond to 20 amino acids; however, all of the codon sequences and resulting amino acids are not important in this exercise. If it works for one codon, the program should work for all of them.
However, feel free to expand the list in the test suite to include them all.
There are also four terminating codons (also known as 'STOP' codons); if any of these codons are encountered (by the ribosome), all translation ends and the protein is terminated.
All subsequent codons after are ignored, like this:
RNA: `"AUGUUUUCUUAAAUG"` =>
Codons: `"AUG", "UUU", "UCU", "UAG", "AUG"` =>
Protein: `"Methionine", "Phenylalanine", "Serine"`
Note the stop codon terminates the translation and the final methionine is not translated into the protein sequence.
Below are the codons and resulting Amino Acids needed for the exercise.
Codon | Protein
:--- | :---
AUG | Methionine
UUU, UUC | Phenylalanine
UUA, UUG | Leucine
UCU, UCC, UCA, UCG | Serine
UAU, UAC | Tyrosine
UGU, UGC | Cysteine
UGG | Tryptophan
UAA, UAG, UGA | STOP
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
Tyler Long
## Submitting Incomplete Problems
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

View File

@ -0,0 +1,62 @@
package protein
const testVersion = 1
func FromRNA(inp string) []string {
var ret []string
for i := 0; i < len(inp); i = i + 3 {
cdn := FromCodon(inp[i : i+3])
if cdn == "STOP" {
break
}
ret = append(ret, cdn)
}
return ret
}
func FromCodon(inp string) string {
switch inp {
case "AUG":
return "Methionine"
case "UUU":
return "Phenylalanine"
case "UUC":
return "Phenylalanine"
case "UUA":
return "Leucine"
case "UUG":
return "Leucine"
case "UCU":
return "Serine"
case "UCC":
return "Serine"
case "UCA":
return "Serine"
case "UCG":
return "Serine"
case "UAU":
return "Tyrosine"
case "UAC":
return "Tyrosine"
case "UGU":
return "Cysteine"
case "UGC":
return "Cysteine"
case "UGG":
return "Tryptophan"
}
return "STOP"
}
/*
Codon | Protein
:--- | :---
AUG | Methionine
UUU, UUC | Phenylalanine
UUA, UUG | Leucine
UCU, UCC, UCA, UCG | Serine
UAU, UAC | Tyrosine
UGU, UGC | Cysteine
UGG | Tryptophan
UAA, UAG, UGA | STOP
*/

View File

@ -0,0 +1,69 @@
package protein
import (
"reflect"
"testing"
)
const targetTestVersion = 1
type codonCase struct {
input string
expected string
}
var codonTestCases = []codonCase{
{"AUG", "Methionine"},
{"UUU", "Phenylalanine"},
{"UUC", "Phenylalanine"},
{"UUA", "Leucine"},
{"UUG", "Leucine"},
{"UCU", "Serine"},
{"UCC", "Serine"},
{"UCA", "Serine"},
{"UCG", "Serine"},
{"UAU", "Tyrosine"},
{"UAC", "Tyrosine"},
{"UGU", "Cysteine"},
{"UGC", "Cysteine"},
{"UGG", "Tryptophan"},
{"UAA", "STOP"},
{"UAG", "STOP"},
{"UGA", "STOP"},
}
type rnaCase struct {
input string
expected []string
}
var proteinTestCases = []rnaCase{
{"AUGUUUUCUUAAAUG", []string{"Methionine", "Phenylalanine", "Serine"}},
{"AUGUUUUGG", []string{"Methionine", "Phenylalanine", "Tryptophan"}},
{"AUGUUUUAA", []string{"Methionine", "Phenylalanine"}},
{"UGGUGUUAUUAAUGGUUU", []string{"Tryptophan", "Cysteine", "Tyrosine"}},
}
func TestCodon(t *testing.T) {
for _, test := range codonTestCases {
actual := FromCodon(test.input)
if actual != test.expected {
t.Errorf("Protein Translation test [%s], expected [%s], actual [%s]", test.input, test.expected, actual)
}
}
}
func TestProtein(t *testing.T) {
for _, test := range proteinTestCases {
actual := FromRNA(test.input)
if !reflect.DeepEqual(actual, test.expected) {
t.Errorf("Protein Translation test [%s], expected %q, actual %q", test.input, test.expected, actual)
}
}
}
func TestTestVersion(t *testing.T) {
if testVersion != targetTestVersion {
t.Errorf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
}
}

View File

@ -0,0 +1,95 @@
package twelve
const testVersion = 1
func Song() string {
var ret string
for i := 1; i <= 12; i++ {
ret += Verse(i) + "\n"
}
return ret
}
func Verse(i int) string {
ret := "On the " + intToOrd(i) + " day of Christmas my true love gave to me, "
if i >= 12 {
ret += "twelve Drummers Drumming, "
}
if i >= 11 {
ret += "eleven Pipers Piping, "
}
if i >= 10 {
ret += "ten Lords-a-Leaping, "
}
if i >= 9 {
ret += "nine Ladies Dancing, "
}
if i >= 8 {
ret += "eight Maids-a-Milking, "
}
if i >= 7 {
ret += "seven Swans-a-Swimming, "
}
if i >= 6 {
ret += "six Geese-a-Laying, "
}
if i >= 5 {
ret += "five Gold Rings, "
}
if i >= 4 {
ret += "four Calling Birds, "
}
if i >= 3 {
ret += "three French Hens, "
}
if i >= 2 {
ret += "two Turtle Doves, and "
}
return ret + "a Partridge in a Pear Tree."
}
func intToOrd(i int) string {
switch i {
case 1:
return "first"
case 2:
return "second"
case 3:
return "third"
case 4:
return "fourth"
case 5:
return "fifth"
case 6:
return "sixth"
case 7:
return "seventh"
case 8:
return "eighth"
case 9:
return "ninth"
case 10:
return "tenth"
case 11:
return "eleventh"
case 12:
return "twelfth"
}
return ""
}
/*
{1, "On the first day of Christmas my true love gave to me, a Partridge in a Pear Tree."},
{2, "On the second day of Christmas my true love gave to me, two Turtle Doves, and a Partridge in a Pear Tree."},
{3, "On the third day of Christmas my true love gave to me, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree."},
{4, "On the fourth day of Christmas my true love gave to me, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree."},
{5, "On the fifth day of Christmas my true love gave to me, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree."},
{6, "On the sixth day of Christmas my true love gave to me, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree."},
{7, "On the seventh day of Christmas my true love gave to me, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree."},
{8, "On the eighth day of Christmas my true love gave to me, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree."},
{9, "On the ninth day of Christmas my true love gave to me, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree."},
{10, "On the tenth day of Christmas my true love gave to me, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree."},
{11, "On the eleventh day of Christmas my true love gave to me, eleven Pipers Piping, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree."},
{12, "On the twelfth day of Christmas my true love gave to me, twelve Drummers Drumming, eleven Pipers Piping, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree."},
*/