Merge Go Work
This commit is contained in:
parent
b8814259b5
commit
9e58d17c5c
46
go/atbash-cipher/README.md
Normal file
46
go/atbash-cipher/README.md
Normal file
@ -0,0 +1,46 @@
|
||||
# Atbash Cipher
|
||||
|
||||
Create an implementation of the atbash cipher, an ancient encryption system created in the Middle East.
|
||||
|
||||
The Atbash cipher is a simple substitution cipher that relies on
|
||||
transposing all the letters in the alphabet such that the resulting
|
||||
alphabet is backwards. The first letter is replaced with the last
|
||||
letter, the second with the second-last, and so on.
|
||||
|
||||
An Atbash cipher for the Latin alphabet would be as follows:
|
||||
|
||||
```plain
|
||||
Plain: abcdefghijklmnopqrstuvwxyz
|
||||
Cipher: zyxwvutsrqponmlkjihgfedcba
|
||||
```
|
||||
|
||||
It is a very weak cipher because it only has one possible key, and it is
|
||||
a simple monoalphabetic substitution cipher. However, this may not have
|
||||
been an issue in the cipher's time.
|
||||
|
||||
Ciphertext is written out in groups of fixed length, the traditional group size
|
||||
being 5 letters, and punctuation is excluded. This is to make it harder to guess
|
||||
things based on word boundaries.
|
||||
|
||||
## Examples
|
||||
- Encoding `test` gives `gvhg`
|
||||
- Decoding `gvhg` gives `test`
|
||||
- Decoding `gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt` gives `The quick brown fox jumps over the lazy dog.`
|
||||
|
||||
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 [http://en.wikipedia.org/wiki/Atbash](http://en.wikipedia.org/wiki/Atbash)
|
||||
|
||||
## Submitting Incomplete Problems
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
36
go/atbash-cipher/atbash.go
Normal file
36
go/atbash-cipher/atbash.go
Normal file
@ -0,0 +1,36 @@
|
||||
package atbash
|
||||
|
||||
import "strings"
|
||||
|
||||
func Atbash(s string) string {
|
||||
s = strings.ToLower(s)
|
||||
var v []byte
|
||||
var b, iter int
|
||||
for i := range s {
|
||||
sv := int(s[i])
|
||||
switch {
|
||||
case sv < 48:
|
||||
continue
|
||||
case sv >= 48 && sv <= 57:
|
||||
b = sv
|
||||
case sv < 109:
|
||||
b = 110 + (109 - sv)
|
||||
case sv == 109:
|
||||
b = 110
|
||||
case sv == 110:
|
||||
b = 109
|
||||
case sv > 110:
|
||||
b = 109 - (sv - 110)
|
||||
}
|
||||
v = append(v, byte(b))
|
||||
iter++
|
||||
if iter == 5 {
|
||||
v = append(v, ' ')
|
||||
iter = 0
|
||||
}
|
||||
}
|
||||
if iter == 0 {
|
||||
return string(v)[:len(string(v))-1]
|
||||
}
|
||||
return string(v)
|
||||
}
|
40
go/atbash-cipher/atbash_cipher_test.go
Normal file
40
go/atbash-cipher/atbash_cipher_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
package atbash
|
||||
|
||||
import "testing"
|
||||
|
||||
var tests = []struct {
|
||||
expected string
|
||||
s string
|
||||
}{
|
||||
{"ml", "no"},
|
||||
{"ml", "no"},
|
||||
{"bvh", "yes"},
|
||||
{"lnt", "OMG"},
|
||||
{"lnt", "O M G"},
|
||||
{"nrmwy oldrm tob", "mindblowingly"},
|
||||
{"gvhgr mt123 gvhgr mt", "Testing, 1 2 3, testing."},
|
||||
{"gifgs rhurx grlm", "Truth is fiction."},
|
||||
{"gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt", "The quick brown fox jumps over the lazy dog."},
|
||||
}
|
||||
|
||||
func TestAtbash(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
actual := Atbash(test.s)
|
||||
if actual != test.expected {
|
||||
t.Errorf("Atbash(%s): expected %s, actual %s", test.s, test.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAtbash(b *testing.B) {
|
||||
b.StopTimer()
|
||||
for _, test := range tests {
|
||||
b.StartTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
Atbash(test.s)
|
||||
}
|
||||
|
||||
b.StopTimer()
|
||||
}
|
||||
}
|
BIN
go/atbash-cipher/cmd/cmd
Executable file
BIN
go/atbash-cipher/cmd/cmd
Executable file
Binary file not shown.
11
go/atbash-cipher/cmd/main.go
Normal file
11
go/atbash-cipher/cmd/main.go
Normal file
@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"../../atbash-cipher"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println(atbash.Atbash("mindblowingly"))
|
||||
}
|
@ -1 +1 @@
|
||||
custom-set
|
||||
prime-factors
|
Binary file not shown.
@ -11,9 +11,9 @@ func main() {
|
||||
s1 := stringset.NewFromSlice([]string{"a"})
|
||||
addAndOutput(s1, "b")
|
||||
addAndOutput(s1, "d")
|
||||
addAndOutput(s1, "c")
|
||||
s1.PrettyPrint()
|
||||
return
|
||||
addAndOutput(s1, "c")
|
||||
addAndOutput(s1, "0")
|
||||
addAndOutput(s1, "aa")
|
||||
addAndOutput(s1, "aaa")
|
||||
|
@ -27,7 +27,6 @@ package stringset
|
||||
// Format the empty set as {}.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"strconv"
|
||||
@ -167,17 +166,13 @@ func TestEqual(t *testing.T) {
|
||||
// helper for testing Add, Delete
|
||||
func testEleOp(name string, op func(Set, string), cases []eleOpCase, t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
fmt.Print("Running Test Case: ")
|
||||
fmt.Println(tc)
|
||||
s := NewFromSlice(tc.set)
|
||||
op(s, tc.ele)
|
||||
want := NewFromSlice(tc.want)
|
||||
if !Equal(s, want) {
|
||||
fmt.Println(s.String())
|
||||
t.Fatalf("%v %s %q = %v, want %v",
|
||||
NewFromSlice(tc.set), name, tc.ele, s, want)
|
||||
}
|
||||
fmt.Println("=== Done ===")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ package stringset
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -45,20 +44,12 @@ func (s Set) Add(v string) {
|
||||
return
|
||||
}
|
||||
if !s.Has(v) {
|
||||
bef := "Current Top Node: " + s.top.value + ";L:" + s.top.getLeftValue() + ";R:" + s.top.getRightValue()
|
||||
newNode := s.top.Add(&Node{value: v})
|
||||
fmt.Println(bef)
|
||||
fmt.Println("Current New Node: " + newNode.value + ";L:" + newNode.getLeftValue() + ";R:" + newNode.getRightValue())
|
||||
fmt.Printf("newNode.left: %v (%v)\n", &newNode.left, newNode.left)
|
||||
|
||||
s.top.value = newNode.value
|
||||
s.top.left = newNode.left
|
||||
s.top.right = newNode.right
|
||||
fmt.Println("Current Top Node: " + s.top.value + ";L:" + s.top.getLeftValue() + ";R:" + s.top.getRightValue())
|
||||
fmt.Printf("s.top.left: %v (%v)\n", &s.top.left, s.top.left)
|
||||
fmt.Println("Add Done")
|
||||
|
||||
//s.top = s.top.Add(newNode)
|
||||
//fmt.Println("Current Top Node: " + s.top.value + ";L:" + s.top.getLeftValue() + ";R:" + s.top.getRightValue())
|
||||
}
|
||||
}
|
||||
|
||||
@ -274,63 +265,43 @@ func (sv *Node) findHome(v *Node) {
|
||||
}
|
||||
|
||||
func (sv *Node) Add(n *Node) *Node {
|
||||
fmt.Println("1 Adding at Node " + sv.value)
|
||||
cmp := strings.Compare(n.value, sv.value)
|
||||
if cmp < 0 {
|
||||
fmt.Println("2 checking to left")
|
||||
if sv.left == nil {
|
||||
fmt.Println("3 left is nil, add it")
|
||||
sv.left = n
|
||||
} else {
|
||||
fmt.Println("--> 4 recurse left")
|
||||
sv.left = sv.left.Add(n)
|
||||
fmt.Println("<-- 5 added to left")
|
||||
}
|
||||
} else {
|
||||
fmt.Println("6 checking to right")
|
||||
if sv.right == nil {
|
||||
fmt.Println("7 right is nil, add it")
|
||||
sv.right = n
|
||||
} else {
|
||||
fmt.Println("--> 8 recurse right")
|
||||
sv.right = sv.right.Add(n)
|
||||
fmt.Println("<-- 9 added to right")
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("10 let's balance now (sv: " + sv.value + ")")
|
||||
newVal := sv
|
||||
/* TODO: Fix the tree balancing
|
||||
balance := GetBalance(sv)
|
||||
// left left unbalance
|
||||
fmt.Println("11 balance: " + strconv.Itoa(balance))
|
||||
newVal := sv
|
||||
if balance > 1 && strings.Compare(n.value, sv.getLeftValue()) < 0 { // < sv.left.value {
|
||||
fmt.Println("12 Left Left")
|
||||
if balance > 1 && strings.Compare(n.value, sv.getLeftValue()) < 0 {
|
||||
newVal = RightRotate(sv)
|
||||
fmt.Println("13")
|
||||
}
|
||||
// right right unbalance
|
||||
if balance < -1 && strings.Compare(n.value, sv.getRightValue()) > 0 { //n.value > sv.right.value {
|
||||
fmt.Println("14 Right Right")
|
||||
if balance < -1 && strings.Compare(n.value, sv.getRightValue()) > 0 {
|
||||
newVal = LeftRotate(sv)
|
||||
fmt.Println("15")
|
||||
}
|
||||
// left right unbalance
|
||||
if balance > 1 && strings.Compare(n.value, sv.getLeftValue()) > 0 { //n.value > sv.left.value {
|
||||
fmt.Println("16 Left Right")
|
||||
if balance > 1 && strings.Compare(n.value, sv.getLeftValue()) > 0 {
|
||||
sv.left = LeftRotate(sv.left)
|
||||
fmt.Println("17")
|
||||
newVal = RightRotate(sv)
|
||||
fmt.Println("18")
|
||||
}
|
||||
// right left unbalance
|
||||
if balance < -1 && strings.Compare(n.value, sv.getRightValue()) < 0 { //n.value < sv.right.value {
|
||||
fmt.Println("19 Right Left")
|
||||
if balance < -1 && strings.Compare(n.value, sv.getRightValue()) < 0 {
|
||||
sv.right = RightRotate(sv.right)
|
||||
fmt.Println("20")
|
||||
newVal = LeftRotate(sv)
|
||||
fmt.Println("21")
|
||||
}
|
||||
fmt.Println("22 end add")
|
||||
*/
|
||||
return newVal
|
||||
}
|
||||
|
||||
@ -476,9 +447,6 @@ func RightRotate(y *Node) *Node {
|
||||
// Perform rotation
|
||||
x.right = y
|
||||
y.left = t2
|
||||
fmt.Println("RightRotate: return=" + x.value + "; L:" + x.left.value + "; R:" + x.right.value)
|
||||
fmt.Println("RightRotate: leftNode=" + x.getLeftValue() + "; L:" + x.left.getLeftValue() + "; R:" + x.left.getRightValue())
|
||||
fmt.Println("RightRotate: rightNode=" + x.getRightValue() + "; L:" + x.right.getLeftValue() + "; R:" + x.right.getRightValue())
|
||||
// Return new root
|
||||
return x
|
||||
}
|
||||
@ -490,9 +458,6 @@ func LeftRotate(x *Node) *Node {
|
||||
y.left = x
|
||||
x.right = t2
|
||||
// Return new root
|
||||
fmt.Println("LeftRotate: return=" + y.value + "; L:" + y.left.value + "; R:" + y.right.value)
|
||||
fmt.Println("LeftRotate: leftNode=" + y.getLeftValue() + "; L:" + y.left.getLeftValue() + "; R:" + y.left.getRightValue())
|
||||
fmt.Println("LeftRotate: rightNode=" + y.getRightValue() + "; L:" + y.right.getLeftValue() + "; R:" + y.right.getRightValue())
|
||||
return y
|
||||
}
|
||||
|
||||
|
58
go/hello-world/README.md
Normal file
58
go/hello-world/README.md
Normal file
@ -0,0 +1,58 @@
|
||||
# Hello World
|
||||
|
||||
Write a function that greets the user by name, or by saying "Hello, World!" if no name is given.
|
||||
|
||||
["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is the traditional first program for beginning programming in a new language.
|
||||
|
||||
**Note:** You can skip this exercise by running:
|
||||
|
||||
exercism skip $LANGUAGE hello-world
|
||||
|
||||
## Specification
|
||||
|
||||
Write a `Hello World!` function that can greet someone given their name.
|
||||
The function should return the appropriate greeting.
|
||||
|
||||
For an input of "Alice", the response should be "Hello, Alice!".
|
||||
|
||||
If a name is not given, the response should be "Hello, World!"
|
||||
|
||||
## Test-Driven Development
|
||||
|
||||
As programmers mature, they eventually want to test their code.
|
||||
|
||||
Here at Exercism we simulate [Test-Driven Development](http://en.wikipedia.org/wiki/Test-driven_development) (TDD), where you write your tests before writing any functionality. The simulation comes in the form of a pre-written test suite, which will signal that you have solved the problem.
|
||||
|
||||
It will also provide you with a safety net to explore other solutions without breaking the functionality.
|
||||
|
||||
### A typical TDD workflow on Exercism:
|
||||
|
||||
1. Run the test file and pick one test that's failing.
|
||||
2. Write some code to fix the test you picked.
|
||||
3. Re-run the tests to confirm the test is now passing.
|
||||
4. Repeat from step 1.
|
||||
5. Submit your solution (`exercism submit /path/to/file`)
|
||||
|
||||
## Instructions
|
||||
|
||||
Submissions are encouraged to be general, within reason. Having said that, it's also important not to over-engineer a solution.
|
||||
|
||||
It's important to remember that the goal is to make code as expressive and readable as we can. However, solutions to the hello-world exercise will not be reviewed by a person, but by rikki- the robot, who will offer an encouraging word.
|
||||
|
||||
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
|
||||
|
||||
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||
|
||||
## Submitting Incomplete Problems
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
29
go/hello-world/hello_test.go
Normal file
29
go/hello-world/hello_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package hello
|
||||
|
||||
import "testing"
|
||||
|
||||
// Define a function HelloWorld(string) string.
|
||||
//
|
||||
// Also define a testVersion with a value that matches
|
||||
// the targetTestVersion here.
|
||||
|
||||
const targetTestVersion = 2
|
||||
|
||||
func TestHelloWorld(t *testing.T) {
|
||||
tests := []struct {
|
||||
name, expected string
|
||||
}{
|
||||
{"", "Hello, World!"},
|
||||
{"Gopher", "Hello, Gopher!"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
observed := HelloWorld(test.name)
|
||||
if observed != test.expected {
|
||||
t.Fatalf("HelloWorld(%s) = %v, want %v", test.name, observed, test.expected)
|
||||
}
|
||||
}
|
||||
|
||||
if testVersion != targetTestVersion {
|
||||
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
||||
}
|
||||
}
|
11
go/hello-world/hello_world.go
Normal file
11
go/hello-world/hello_world.go
Normal file
@ -0,0 +1,11 @@
|
||||
package hello
|
||||
|
||||
const testVersion = 2
|
||||
|
||||
// HelloWorld takes a string (optionally empty) and says hello to it!
|
||||
func HelloWorld(s string) string {
|
||||
if s == "" {
|
||||
s = "World"
|
||||
}
|
||||
return "Hello, " + s + "!"
|
||||
}
|
38
go/phone-number/README.md
Normal file
38
go/phone-number/README.md
Normal file
@ -0,0 +1,38 @@
|
||||
# Phone Number
|
||||
|
||||
Write a program that cleans up user-entered phone numbers so that they can be sent SMS messages.
|
||||
|
||||
The rules are as follows:
|
||||
|
||||
- If the phone number is less than 10 digits assume that it is bad
|
||||
number
|
||||
- If the phone number is 10 digits assume that it is good
|
||||
- If the phone number is 11 digits and the first number is 1, trim the 1
|
||||
and use the last 10 digits
|
||||
- If the phone number is 11 digits and the first number is not 1, then
|
||||
it is a bad number
|
||||
- If the phone number is more than 11 digits assume that it is a bad
|
||||
number
|
||||
|
||||
We've provided tests, now make them pass.
|
||||
|
||||
Hint: Only make one test pass at a time. Disable the others, then flip
|
||||
each on in turn after you get the current failing one to pass.
|
||||
|
||||
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
|
||||
|
||||
Event Manager by JumpstartLab [http://tutorials.jumpstartlab.com/projects/eventmanager.html](http://tutorials.jumpstartlab.com/projects/eventmanager.html)
|
||||
|
||||
## Submitting Incomplete Problems
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
118
go/phone-number/phone_number_test.go
Normal file
118
go/phone-number/phone_number_test.go
Normal file
@ -0,0 +1,118 @@
|
||||
package phonenumber
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testCase struct {
|
||||
input string
|
||||
expected string
|
||||
expectErr bool
|
||||
}
|
||||
|
||||
var numberTests = []testCase{
|
||||
{"(123) 456-7890", "1234567890", false},
|
||||
{"123.456.7890", "1234567890", false},
|
||||
{"1234567890", "1234567890", false},
|
||||
{"12345678901234567", "", true},
|
||||
{"21234567890", "", true},
|
||||
{"123456789", "", true},
|
||||
}
|
||||
|
||||
func TestNumber(t *testing.T) {
|
||||
for _, test := range numberTests {
|
||||
actual, actualErr := Number(test.input)
|
||||
if actual != test.expected {
|
||||
t.Errorf("Number(%s): expected [%s], actual: [%s]", test.input, test.expected, actual)
|
||||
}
|
||||
// if we expect an error and there isn't one
|
||||
if test.expectErr && actualErr == nil {
|
||||
t.Errorf("Number(%s): expected an error, but error is nil", test.input)
|
||||
}
|
||||
// if we don't expect an error and there is one
|
||||
if !test.expectErr && actualErr != nil {
|
||||
t.Errorf("Number(%s): expected no error, but error is: %s", test.input, actualErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkNumber(b *testing.B) {
|
||||
b.StopTimer()
|
||||
for _, test := range numberTests {
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Number(test.input)
|
||||
}
|
||||
b.StopTimer()
|
||||
}
|
||||
}
|
||||
|
||||
var areaCodeTests = []testCase{
|
||||
{"1234567890", "123", false},
|
||||
{"213.456.7890", "213", false},
|
||||
{"213.456.7890.2345", "", true},
|
||||
{"213.456", "", true},
|
||||
}
|
||||
|
||||
func TestAreaCode(t *testing.T) {
|
||||
for _, test := range areaCodeTests {
|
||||
actual, actualErr := AreaCode(test.input)
|
||||
if actual != test.expected {
|
||||
t.Errorf("AreaCode(%s): expected [%s], actual: [%s]", test.input, test.expected, actual)
|
||||
}
|
||||
// if we expect an error and there isn't one
|
||||
if test.expectErr && actualErr == nil {
|
||||
t.Errorf("AreaCode(%s): expected an error, but error is nil", test.input)
|
||||
}
|
||||
// if we don't expect an error and there is one
|
||||
if !test.expectErr && actualErr != nil {
|
||||
t.Errorf("AreaCode(%s): expected no error, but error is: %s", test.input, actualErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAreaCode(b *testing.B) {
|
||||
b.StopTimer()
|
||||
for _, test := range areaCodeTests {
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
AreaCode(test.input)
|
||||
}
|
||||
b.StopTimer()
|
||||
}
|
||||
}
|
||||
|
||||
var formatTests = []testCase{
|
||||
{"1234567890", "(123) 456-7890", false},
|
||||
{"11234567890", "(123) 456-7890", false},
|
||||
{"112345", "", true},
|
||||
{"11234590870986", "", true},
|
||||
}
|
||||
|
||||
func TestFormat(t *testing.T) {
|
||||
for _, test := range formatTests {
|
||||
actual, actualErr := Format(test.input)
|
||||
if actual != test.expected {
|
||||
t.Errorf("Format(%s): expected [%s], actual: [%s]", test.input, test.expected, actual)
|
||||
}
|
||||
// if we expect an error and there isn't one
|
||||
if test.expectErr && actualErr == nil {
|
||||
t.Errorf("Format(%s): expected an error, but error is nil", test.input)
|
||||
}
|
||||
// if we don't expect an error and there is one
|
||||
if !test.expectErr && actualErr != nil {
|
||||
t.Errorf("Format(%s): expected no error, but error is: %s", test.input, actualErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFormat(b *testing.B) {
|
||||
b.StopTimer()
|
||||
for _, test := range areaCodeTests {
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
Format(test.input)
|
||||
}
|
||||
b.StopTimer()
|
||||
}
|
||||
}
|
44
go/phone-number/phonenumber.go
Normal file
44
go/phone-number/phonenumber.go
Normal file
@ -0,0 +1,44 @@
|
||||
package phonenumber
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Number takes a number and validates it
|
||||
func Number(num string) (string, error) {
|
||||
num = strings.Map(func(r rune) rune {
|
||||
if r >= '0' && r <= '9' {
|
||||
return r
|
||||
}
|
||||
return -1
|
||||
}, num)
|
||||
// A number can be 11 digits long, if it starts with a 1
|
||||
// but ignore that one.
|
||||
if len(num) == 11 && num[0] == '1' {
|
||||
num = num[1:]
|
||||
}
|
||||
if len(num) != 10 {
|
||||
return "", errors.New("Invalid Number")
|
||||
}
|
||||
return num, nil
|
||||
}
|
||||
|
||||
// AreaCode takes a number, validates it, and returns the area code
|
||||
func AreaCode(num string) (string, error) {
|
||||
num, err := Number(num)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return num[:3], nil
|
||||
}
|
||||
|
||||
// Format takes a number, validates it and returns it in the format
|
||||
// (nnn) nnn-nnnn
|
||||
func Format(num string) (string, error) {
|
||||
num, err := Number(num)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "(" + num[:3] + ") " + num[3:6] + "-" + num[6:], nil
|
||||
}
|
36
go/pig-latin/README.md
Normal file
36
go/pig-latin/README.md
Normal file
@ -0,0 +1,36 @@
|
||||
# Pig Latin
|
||||
|
||||
Implement a program that translates from English to Pig Latin
|
||||
|
||||
Pig Latin is a made-up children's language that's intended to be
|
||||
confusing. It obeys a few simple rules (below), but when it's spoken
|
||||
quickly it's really difficult for non-children (and non-native speakers)
|
||||
to understand.
|
||||
|
||||
- **Rule 1**: If a word begins with a vowel sound, add an "ay" sound to
|
||||
the end of the word.
|
||||
- **Rule 2**: If a word begins with a consonant sound, move it to the
|
||||
end of the word, and then add an "ay" sound to the end of the word.
|
||||
|
||||
There are a few more rules for edge cases, and there are regional
|
||||
variants too.
|
||||
|
||||
See <http://en.wikipedia.org/wiki/Pig_latin> for more details.
|
||||
|
||||
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 Pig Latin exercise at Test First Teaching by Ultrasaurus [https://github.com/ultrasaurus/test-first-teaching/blob/master/learn_ruby/pig_latin/](https://github.com/ultrasaurus/test-first-teaching/blob/master/learn_ruby/pig_latin/)
|
||||
|
||||
## Submitting Incomplete Problems
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
41
go/pig-latin/igpay.go
Normal file
41
go/pig-latin/igpay.go
Normal file
@ -0,0 +1,41 @@
|
||||
package igpay
|
||||
|
||||
import "strings"
|
||||
|
||||
// PigLatin takes some words and converts them to pig latin
|
||||
// 1) Move starting consonant sounds to the end of the word
|
||||
// 2) add 'ay'
|
||||
func PigLatin(in string) string {
|
||||
var ret string
|
||||
words := strings.Split(in, " ")
|
||||
for i := range words {
|
||||
ret += pigLatinWord(words[i])
|
||||
if i < len(words)-1 {
|
||||
ret += " "
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// pigLatinWord actually does the heavy lifting
|
||||
func pigLatinWord(in string) string {
|
||||
var ret string
|
||||
// First move all consonant sounds to the end
|
||||
for i := 0; i < len(in); i++ {
|
||||
// Edge consonant sound cases
|
||||
if in[0] == 'q' && in[1] == 'u' {
|
||||
in = in[2:] + string(in[0]) + string(in[1])
|
||||
}
|
||||
|
||||
vowelPos := strings.IndexAny(in, "aeiou")
|
||||
|
||||
// If we have a y and another vowel, then y is a consonant
|
||||
// also, x
|
||||
if vowelPos == 0 || (vowelPos > 1 && (in[0] == 'y' || in[0] == 'x')) {
|
||||
return in + "ay"
|
||||
}
|
||||
in = in[1:] + string(in[0])
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
29
go/pig-latin/pig_latin_test.go
Normal file
29
go/pig-latin/pig_latin_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package igpay
|
||||
|
||||
import "testing"
|
||||
|
||||
var tests = []struct{ pl, in string }{
|
||||
{"appleay", "apple"},
|
||||
{"earay", "ear"},
|
||||
{"igpay", "pig"},
|
||||
{"oalakay", "koala"},
|
||||
{"airchay", "chair"},
|
||||
{"eenquay", "queen"},
|
||||
{"aresquay", "square"},
|
||||
{"erapythay", "therapy"},
|
||||
{"ushthray", "thrush"},
|
||||
{"oolschay", "school"},
|
||||
{"ickquay astfay unray", "quick fast run"},
|
||||
{"ellowyay", "yellow"},
|
||||
{"yttriaay", "yttria"},
|
||||
{"enonxay", "xenon"},
|
||||
{"xrayay", "xray"},
|
||||
}
|
||||
|
||||
func TestPigLatin(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
if pl := PigLatin(test.in); pl != test.pl {
|
||||
t.Fatalf("PigLatin(%q) = %q, want %q.", test.in, pl, test.pl)
|
||||
}
|
||||
}
|
||||
}
|
48
go/prime-factors/README.md
Normal file
48
go/prime-factors/README.md
Normal file
@ -0,0 +1,48 @@
|
||||
# Prime Factors
|
||||
|
||||
Compute the prime factors of a given natural number.
|
||||
|
||||
A prime number is only evenly divisible by itself and 1.
|
||||
|
||||
Note that 1 is not a prime number.
|
||||
|
||||
## Example
|
||||
|
||||
What are the prime factors of 60?
|
||||
|
||||
- Our first divisor is 2. 2 goes into 60, leaving 30.
|
||||
- 2 goes into 30, leaving 15.
|
||||
- 2 doesn't go cleanly into 15. So let's move on to our next divisor, 3.
|
||||
- 3 goes cleanly into 15, leaving 5.
|
||||
- 3 does not go cleanly into 5. The next possible factor is 4.
|
||||
- 4 does not go cleanly into 5. The next possible factor is 5.
|
||||
- 5 does go cleanly into 5.
|
||||
- We're left only with 1, so now, we're done.
|
||||
|
||||
Our successful divisors in that computation represent the list of prime
|
||||
factors of 60: 2, 2, 3, and 5.
|
||||
|
||||
You can check this yourself:
|
||||
|
||||
- 2 * 2 * 3 * 5
|
||||
- = 4 * 15
|
||||
- = 60
|
||||
- Success!
|
||||
|
||||
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 Prime Factors Kata by Uncle Bob [http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata](http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata)
|
||||
|
||||
## Submitting Incomplete Problems
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
21
go/prime-factors/prime.go
Normal file
21
go/prime-factors/prime.go
Normal file
@ -0,0 +1,21 @@
|
||||
package prime
|
||||
|
||||
const testVersion = 2
|
||||
|
||||
func Factors(fnd int64) []int64 {
|
||||
var ret []int64
|
||||
var i int64
|
||||
foundFactor := true
|
||||
for i = 2; i < fnd; i++ {
|
||||
for j := range ret {
|
||||
if i%ret[j] == 0 {
|
||||
// Already covered this case, move on
|
||||
foundFactor = false
|
||||
}
|
||||
if !foundFactor {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
48
go/prime-factors/primefactors_test.go
Normal file
48
go/prime-factors/primefactors_test.go
Normal file
@ -0,0 +1,48 @@
|
||||
package prime
|
||||
|
||||
// Return prime factors in increasing order
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const targetTestVersion = 2
|
||||
|
||||
var tests = []struct {
|
||||
input int64
|
||||
expected []int64
|
||||
}{
|
||||
{1, []int64{}},
|
||||
{2, []int64{2}},
|
||||
{3, []int64{3}},
|
||||
{4, []int64{2, 2}},
|
||||
{6, []int64{2, 3}},
|
||||
{8, []int64{2, 2, 2}},
|
||||
{9, []int64{3, 3}},
|
||||
{27, []int64{3, 3, 3}},
|
||||
{625, []int64{5, 5, 5, 5}},
|
||||
{901255, []int64{5, 17, 23, 461}},
|
||||
{93819012551, []int64{11, 9539, 894119}},
|
||||
}
|
||||
|
||||
func TestPrimeFactors(t *testing.T) {
|
||||
if testVersion != targetTestVersion {
|
||||
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
||||
}
|
||||
for _, test := range tests {
|
||||
actual := Factors(test.input)
|
||||
if !reflect.DeepEqual(actual, test.expected) {
|
||||
t.Errorf("prime.Factors(%d) = %v; expected %v",
|
||||
test.input, actual, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkPrimeFactors(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, test := range tests {
|
||||
Factors(test.input)
|
||||
}
|
||||
}
|
||||
}
|
53
go/strain/README.md
Normal file
53
go/strain/README.md
Normal file
@ -0,0 +1,53 @@
|
||||
# Strain
|
||||
|
||||
Implement the `keep` and `discard` operation on collections. Given a collection and a predicate on the collection's elements, `keep` returns a new collection containing those elements where the predicate is true, while `discard` returns a new collection containing those elements where the predicate is false.
|
||||
|
||||
Write two functions that each take a function and a list. One of them will
|
||||
return the list of items for which the passed in function is true, and the
|
||||
other will return the items for which it is false.
|
||||
|
||||
For example, given the collection of numbers:
|
||||
|
||||
- 1, 2, 3, 4, 5
|
||||
|
||||
And the predicate:
|
||||
|
||||
- is the number even?
|
||||
|
||||
Then your keep operation should produce:
|
||||
|
||||
- 2, 4
|
||||
|
||||
While your discard operation should produce:
|
||||
|
||||
- 1, 3, 5
|
||||
|
||||
Note that the union of keep and discard is all the elements.
|
||||
|
||||
The functions may be called `keep` and `discard`, or they may need different
|
||||
names in order to not clash with existing functions or concepts in your
|
||||
language.
|
||||
|
||||
## Restrictions
|
||||
|
||||
Keep your hands off that filter/reject/whatchamacallit functionality
|
||||
provided by your standard library! Solve this one yourself using other
|
||||
basic tools instead.
|
||||
|
||||
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
|
||||
|
||||
Conversation with James Edward Gray II [https://twitter.com/jeg2](https://twitter.com/jeg2)
|
||||
|
||||
## Submitting Incomplete Problems
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
54
go/strain/strain.go
Normal file
54
go/strain/strain.go
Normal file
@ -0,0 +1,54 @@
|
||||
package strain
|
||||
|
||||
// Ints is a slice of int
|
||||
type Ints []int
|
||||
|
||||
// Lists is a slice of int slices
|
||||
type Lists [][]int
|
||||
|
||||
// Strings is a slice of strings
|
||||
type Strings []string
|
||||
|
||||
// Keep runs the Ints through a function and returns the ones that succeed
|
||||
func (i Ints) Keep(kf func(int) bool) Ints {
|
||||
var ret Ints
|
||||
for idx := range i {
|
||||
if kf(i[idx]) {
|
||||
ret = append(ret, i[idx])
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Discard runs the Ints through a function and returns the ones that fail
|
||||
func (i Ints) Discard(df func(int) bool) Ints {
|
||||
var ret Ints
|
||||
for idx := range i {
|
||||
if !df(i[idx]) {
|
||||
ret = append(ret, i[idx])
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Keep runs the Lists through a function and returns the ones that succeed
|
||||
func (l Lists) Keep(kf func([]int) bool) Lists {
|
||||
var ret Lists
|
||||
for idx := range l {
|
||||
if kf(l[idx]) {
|
||||
ret = append(ret, l[idx])
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Keep runs the Strings through a function and returns the ones that succeed
|
||||
func (s Strings) Keep(kf func(string) bool) Strings {
|
||||
var ret Strings
|
||||
for idx := range s {
|
||||
if kf(s[idx]) {
|
||||
ret = append(ret, s[idx])
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
170
go/strain/strain_test.go
Normal file
170
go/strain/strain_test.go
Normal file
@ -0,0 +1,170 @@
|
||||
// Collections, hm? For this exercise in Go you'll work with slices as
|
||||
// collections. Define the following in your solution:
|
||||
//
|
||||
// type Ints []int
|
||||
// type Lists [][]int
|
||||
// type Strings []string
|
||||
//
|
||||
// Then complete the exercise by implementing these methods:
|
||||
//
|
||||
// (Ints) Keep(func(int) bool) Ints
|
||||
// (Ints) Discard(func(int) bool) Ints
|
||||
// (Lists) Keep(func([]int) bool) Lists
|
||||
// (Strings) Keep(func(string) bool) Strings
|
||||
|
||||
package strain
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func lt10(x int) bool { return x < 10 }
|
||||
func gt10(x int) bool { return x > 10 }
|
||||
func odd(x int) bool { return x&1 == 1 }
|
||||
func even(x int) bool { return x&1 == 0 }
|
||||
|
||||
var keepTests = []struct {
|
||||
pred func(int) bool
|
||||
list Ints
|
||||
want Ints
|
||||
}{
|
||||
{lt10,
|
||||
nil,
|
||||
nil},
|
||||
{lt10,
|
||||
Ints{1, 2, 3},
|
||||
Ints{1, 2, 3}},
|
||||
{odd,
|
||||
Ints{1, 2, 3},
|
||||
Ints{1, 3}},
|
||||
{even,
|
||||
Ints{1, 2, 3, 4, 5},
|
||||
Ints{2, 4}},
|
||||
}
|
||||
|
||||
func TestKeepInts(t *testing.T) {
|
||||
for _, test := range keepTests {
|
||||
// setup here copies test.list, preserving the nil value if it is nil
|
||||
// and making a fresh copy of the underlying array otherwise.
|
||||
cp := test.list
|
||||
if cp != nil {
|
||||
cp = append(Ints{}, cp...)
|
||||
}
|
||||
switch res := cp.Keep(test.pred); {
|
||||
case !reflect.DeepEqual(cp, test.list):
|
||||
t.Fatalf("Ints%v.Keep() should not modify its reciever. "+
|
||||
"Found %v, reciever should stay %v",
|
||||
test.list, cp, test.list)
|
||||
case !reflect.DeepEqual(res, test.want):
|
||||
t.Fatalf("Ints%v.Keep() = %v, want %v",
|
||||
test.list, res, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var discardTests = []struct {
|
||||
pred func(int) bool
|
||||
list Ints
|
||||
want Ints
|
||||
}{
|
||||
{lt10,
|
||||
nil,
|
||||
nil},
|
||||
{gt10,
|
||||
Ints{1, 2, 3},
|
||||
Ints{1, 2, 3}},
|
||||
{odd,
|
||||
Ints{1, 2, 3},
|
||||
Ints{2}},
|
||||
{even,
|
||||
Ints{1, 2, 3, 4, 5},
|
||||
Ints{1, 3, 5}},
|
||||
}
|
||||
|
||||
func TestDiscardInts(t *testing.T) {
|
||||
for _, test := range discardTests {
|
||||
cp := test.list
|
||||
if cp != nil {
|
||||
cp = append(Ints{}, cp...) // dup underlying array
|
||||
}
|
||||
switch res := cp.Discard(test.pred); {
|
||||
case !reflect.DeepEqual(cp, test.list):
|
||||
t.Fatalf("Ints%v.Discard() should not modify its reciever. "+
|
||||
"Found %v, reciever should stay %v",
|
||||
test.list, cp, test.list)
|
||||
case !reflect.DeepEqual(res, test.want):
|
||||
t.Fatalf("Ints%v.Discard() = %v, want %v",
|
||||
test.list, res, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeepStrings(t *testing.T) {
|
||||
zword := func(s string) bool { return len(s) > 0 && s[0] == 'z' }
|
||||
list := Strings{"apple", "zebra", "banana", "zombies", "cherimoya", "zelot"}
|
||||
want := Strings{"zebra", "zombies", "zelot"}
|
||||
|
||||
cp := append(Strings{}, list...) // make copy, as with TestInts
|
||||
switch res := cp.Keep(zword); {
|
||||
case !reflect.DeepEqual(cp, list):
|
||||
t.Fatalf("Strings%v.Keep() should not modify its reciever. "+
|
||||
"Found %v, reciever should stay %v",
|
||||
list, cp, list)
|
||||
case !reflect.DeepEqual(res, want):
|
||||
t.Fatalf("Strings%v.Keep() = %v, want %v",
|
||||
list, res, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeepLists(t *testing.T) {
|
||||
has5 := func(l []int) bool {
|
||||
for _, e := range l {
|
||||
if e == 5 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
list := Lists{
|
||||
{1, 2, 3},
|
||||
{5, 5, 5},
|
||||
{5, 1, 2},
|
||||
{2, 1, 2},
|
||||
{1, 5, 2},
|
||||
{2, 2, 1},
|
||||
{1, 2, 5},
|
||||
}
|
||||
want := Lists{
|
||||
{5, 5, 5},
|
||||
{5, 1, 2},
|
||||
{1, 5, 2},
|
||||
{1, 2, 5},
|
||||
}
|
||||
cp := append(Lists{}, list...)
|
||||
switch res := cp.Keep(has5); {
|
||||
case !reflect.DeepEqual(cp, list):
|
||||
t.Fatalf("Lists%v.Keep() should not modify its reciever. "+
|
||||
"Found %v, reciever should stay %v",
|
||||
list, cp, list)
|
||||
case !reflect.DeepEqual(res, want):
|
||||
t.Fatalf("Lists%v.Keep() = %v, want %v",
|
||||
list, res, want)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkKeepInts(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, test := range keepTests {
|
||||
test.list.Keep(test.pred)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDiscardInts(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, test := range discardTests {
|
||||
test.list.Discard(test.pred)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user