From 549ba5084e3a77320295d7f820b18dd22c038be2 Mon Sep 17 00:00:00 2001 From: Brian Buller Date: Tue, 29 Nov 2016 21:28:40 -0600 Subject: [PATCH] Update --- go/diamond/README.md | 75 ++++++ go/diamond/diamond.go | 36 +++ go/diamond/diamond_test.go | 227 ++++++++++++++++++ go/isogram/README.md | 31 +++ go/isogram/isogram.go | 23 ++ go/isogram/isogram_test.go | 50 ++++ go/paasio/paasio.go | 26 ++ go/perfect-numbers/README.md | 42 ++++ go/perfect-numbers/perfect_numbers.go | 40 +++ go/perfect-numbers/perfect_numbers_test.go | 41 ++++ go/protein-translation/README.md | 60 +++++ go/protein-translation/protein.go | 62 +++++ .../protein_translation_test.go | 69 ++++++ go/twelve-days/twelve_days.go | 95 ++++++++ 14 files changed, 877 insertions(+) create mode 100644 go/diamond/README.md create mode 100644 go/diamond/diamond.go create mode 100644 go/diamond/diamond_test.go create mode 100644 go/isogram/README.md create mode 100644 go/isogram/isogram.go create mode 100644 go/isogram/isogram_test.go create mode 100644 go/paasio/paasio.go create mode 100644 go/perfect-numbers/README.md create mode 100644 go/perfect-numbers/perfect_numbers.go create mode 100644 go/perfect-numbers/perfect_numbers_test.go create mode 100644 go/protein-translation/README.md create mode 100644 go/protein-translation/protein.go create mode 100644 go/protein-translation/protein_translation_test.go create mode 100644 go/twelve-days/twelve_days.go diff --git a/go/diamond/README.md b/go/diamond/README.md new file mode 100644 index 0000000..4b9ae44 --- /dev/null +++ b/go/diamond/README.md @@ -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. + diff --git a/go/diamond/diamond.go b/go/diamond/diamond.go new file mode 100644 index 0000000..d6136a8 --- /dev/null +++ b/go/diamond/diamond.go @@ -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 +} diff --git a/go/diamond/diamond_test.go b/go/diamond/diamond_test.go new file mode 100644 index 0000000..6372878 --- /dev/null +++ b/go/diamond/diamond_test.go @@ -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) + } +} diff --git a/go/isogram/README.md b/go/isogram/README.md new file mode 100644 index 0000000..83a7439 --- /dev/null +++ b/go/isogram/README.md @@ -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. + diff --git a/go/isogram/isogram.go b/go/isogram/isogram.go new file mode 100644 index 0000000..a5cfcf7 --- /dev/null +++ b/go/isogram/isogram.go @@ -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 +} diff --git a/go/isogram/isogram_test.go b/go/isogram/isogram_test.go new file mode 100644 index 0000000..ba8d35f --- /dev/null +++ b/go/isogram/isogram_test.go @@ -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) + } +} diff --git a/go/paasio/paasio.go b/go/paasio/paasio.go new file mode 100644 index 0000000..7c0dadb --- /dev/null +++ b/go/paasio/paasio.go @@ -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 +} diff --git a/go/perfect-numbers/README.md b/go/perfect-numbers/README.md new file mode 100644 index 0000000..c46560a --- /dev/null +++ b/go/perfect-numbers/README.md @@ -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. + diff --git a/go/perfect-numbers/perfect_numbers.go b/go/perfect-numbers/perfect_numbers.go new file mode 100644 index 0000000..7b785ae --- /dev/null +++ b/go/perfect-numbers/perfect_numbers.go @@ -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 +} diff --git a/go/perfect-numbers/perfect_numbers_test.go b/go/perfect-numbers/perfect_numbers_test.go new file mode 100644 index 0000000..346aa08 --- /dev/null +++ b/go/perfect-numbers/perfect_numbers_test.go @@ -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) + } +} diff --git a/go/protein-translation/README.md b/go/protein-translation/README.md new file mode 100644 index 0000000..3ec47f2 --- /dev/null +++ b/go/protein-translation/README.md @@ -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. + diff --git a/go/protein-translation/protein.go b/go/protein-translation/protein.go new file mode 100644 index 0000000..5f29804 --- /dev/null +++ b/go/protein-translation/protein.go @@ -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 +*/ diff --git a/go/protein-translation/protein_translation_test.go b/go/protein-translation/protein_translation_test.go new file mode 100644 index 0000000..c45f6c3 --- /dev/null +++ b/go/protein-translation/protein_translation_test.go @@ -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) + } +} diff --git a/go/twelve-days/twelve_days.go b/go/twelve-days/twelve_days.go new file mode 100644 index 0000000..fc869ab --- /dev/null +++ b/go/twelve-days/twelve_days.go @@ -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."}, +*/