Initialise
This commit is contained in:
parent
3ff7f9b0b9
commit
0941f68e91
700 changed files with 27489 additions and 0 deletions
43
acronym/.exercism/config.json
Normal file
43
acronym/.exercism/config.json
Normal file
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"blurb": "Convert a long phrase to its acronym",
|
||||
"authors": [
|
||||
"Akasurde"
|
||||
],
|
||||
"contributors": [
|
||||
"alebaffa",
|
||||
"antimatter96",
|
||||
"bitfield",
|
||||
"colinking",
|
||||
"da-edra",
|
||||
"ekingery",
|
||||
"felixbuenemann",
|
||||
"ferhatelmas",
|
||||
"hilary",
|
||||
"ilmanzo",
|
||||
"kytrinyx",
|
||||
"leenipper",
|
||||
"mattcbaker",
|
||||
"petertseng",
|
||||
"robphoenix",
|
||||
"sebito91",
|
||||
"strangeman",
|
||||
"tleen",
|
||||
"usmanismail"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"acronym.go"
|
||||
],
|
||||
"test": [
|
||||
"acronym_test.go"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.go"
|
||||
],
|
||||
"editor": [
|
||||
"cases_test.go"
|
||||
]
|
||||
},
|
||||
"source": "Julien Vanier",
|
||||
"source_url": "https://github.com/monkbroc"
|
||||
}
|
1
acronym/.exercism/metadata.json
Normal file
1
acronym/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"go","exercise":"acronym","id":"5a79933a6c1442b69e3f9b0402b81063","url":"https://exercism.org/tracks/go/exercises/acronym","handle":"snowyforest","is_requester":true,"auto_approve":false}
|
41
acronym/HELP.md
Normal file
41
acronym/HELP.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
|
||||
flags:
|
||||
|
||||
go test -v --bench . --benchmem
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit acronym.go` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
|
||||
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, you can use one of the following resources:
|
||||
|
||||
- [How to Write Go Code](https://golang.org/doc/code.html)
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
- [Go Resources](http://golang.org/help)
|
||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
|
45
acronym/README.md
Normal file
45
acronym/README.md
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Acronym
|
||||
|
||||
Welcome to Acronym on Exercism's Go Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
Convert a phrase to its acronym.
|
||||
|
||||
Techies love their TLA (Three Letter Acronyms)!
|
||||
|
||||
Help generate some jargon by writing a program that converts a long name
|
||||
like Portable Network Graphics to its acronym (PNG).
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @Akasurde
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @alebaffa
|
||||
- @antimatter96
|
||||
- @bitfield
|
||||
- @colinking
|
||||
- @da-edra
|
||||
- @ekingery
|
||||
- @felixbuenemann
|
||||
- @ferhatelmas
|
||||
- @hilary
|
||||
- @ilmanzo
|
||||
- @kytrinyx
|
||||
- @leenipper
|
||||
- @mattcbaker
|
||||
- @petertseng
|
||||
- @robphoenix
|
||||
- @sebito91
|
||||
- @strangeman
|
||||
- @tleen
|
||||
- @usmanismail
|
||||
|
||||
### Based on
|
||||
|
||||
Julien Vanier - https://github.com/monkbroc
|
15
acronym/acronym.go
Normal file
15
acronym/acronym.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
// This is a "stub" file. It's a little start on your solution.
|
||||
// It's not a complete solution though; you have to write some code.
|
||||
|
||||
// Package acronym should have a package comment that summarizes what it's about.
|
||||
// https://golang.org/doc/effective_go.html#commentary
|
||||
package acronym
|
||||
|
||||
// Abbreviate should have a comment documenting it.
|
||||
func Abbreviate(s string) string {
|
||||
// Write some code here to pass the test suite.
|
||||
// Then remove all the stock comments.
|
||||
// They're here to help you get started but they only clutter a finished solution.
|
||||
// If you leave them in, reviewers may protest!
|
||||
return ""
|
||||
}
|
25
acronym/acronym_test.go
Normal file
25
acronym/acronym_test.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
package acronym
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAcronym(t *testing.T) {
|
||||
for _, test := range stringTestCases {
|
||||
actual := Abbreviate(test.input)
|
||||
if actual != test.expected {
|
||||
t.Errorf("Acronym test [%s], expected [%s], actual [%s]", test.input, test.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAcronym(b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, test := range stringTestCases {
|
||||
Abbreviate(test.input)
|
||||
}
|
||||
}
|
||||
}
|
49
acronym/cases_test.go
Normal file
49
acronym/cases_test.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package acronym
|
||||
|
||||
// Source: exercism/problem-specifications
|
||||
// Commit: cacf1f1 Acronym: add underscore test case (#1436)
|
||||
// Problem Specifications Version: 1.7.0
|
||||
|
||||
type acronymTest struct {
|
||||
input string
|
||||
expected string
|
||||
}
|
||||
|
||||
var stringTestCases = []acronymTest{
|
||||
{
|
||||
input: "Portable Network Graphics",
|
||||
expected: "PNG",
|
||||
},
|
||||
{
|
||||
input: "Ruby on Rails",
|
||||
expected: "ROR",
|
||||
},
|
||||
{
|
||||
input: "First In, First Out",
|
||||
expected: "FIFO",
|
||||
},
|
||||
{
|
||||
input: "GNU Image Manipulation Program",
|
||||
expected: "GIMP",
|
||||
},
|
||||
{
|
||||
input: "Complementary metal-oxide semiconductor",
|
||||
expected: "CMOS",
|
||||
},
|
||||
{
|
||||
input: "Rolling On The Floor Laughing So Hard That My Dogs Came Over And Licked Me",
|
||||
expected: "ROTFLSHTMDCOALM",
|
||||
},
|
||||
{
|
||||
input: "Something - I made up from thin air",
|
||||
expected: "SIMUFTA",
|
||||
},
|
||||
{
|
||||
input: "Halley's Comet",
|
||||
expected: "HC",
|
||||
},
|
||||
{
|
||||
input: "The Road _Not_ Taken",
|
||||
expected: "TRNT",
|
||||
},
|
||||
}
|
3
acronym/go.mod
Normal file
3
acronym/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module acronym
|
||||
|
||||
go 1.16
|
33
all-your-base/.exercism/config.json
Normal file
33
all-your-base/.exercism/config.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"blurb": "Convert a number, represented as a sequence of digits in one base, to any other base.",
|
||||
"authors": [
|
||||
"erizocosmico"
|
||||
],
|
||||
"contributors": [
|
||||
"alebaffa",
|
||||
"bitfield",
|
||||
"ekingery",
|
||||
"ferhatelmas",
|
||||
"hilary",
|
||||
"leenipper",
|
||||
"ngochai94",
|
||||
"petertseng",
|
||||
"robphoenix",
|
||||
"sebito91",
|
||||
"tleen"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"all_your_base.go"
|
||||
],
|
||||
"test": [
|
||||
"all_your_base_test.go"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.go"
|
||||
],
|
||||
"editor": [
|
||||
"cases_test.go"
|
||||
]
|
||||
}
|
||||
}
|
1
all-your-base/.exercism/metadata.json
Normal file
1
all-your-base/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"go","exercise":"all-your-base","id":"57966a5b188f41a7850b201d6599541e","url":"https://exercism.org/tracks/go/exercises/all-your-base","handle":"snowyforest","is_requester":true,"auto_approve":false}
|
41
all-your-base/HELP.md
Normal file
41
all-your-base/HELP.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
|
||||
flags:
|
||||
|
||||
go test -v --bench . --benchmem
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit all_your_base.go` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
|
||||
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, you can use one of the following resources:
|
||||
|
||||
- [How to Write Go Code](https://golang.org/doc/code.html)
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
- [Go Resources](http://golang.org/help)
|
||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
|
69
all-your-base/README.md
Normal file
69
all-your-base/README.md
Normal file
|
@ -0,0 +1,69 @@
|
|||
# All Your Base
|
||||
|
||||
Welcome to All Your Base on Exercism's Go Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
Convert a number, represented as a sequence of digits in one base, to any other base.
|
||||
|
||||
Implement general base conversion. Given a number in base **a**,
|
||||
represented as a sequence of digits, convert it to base **b**.
|
||||
|
||||
## Note
|
||||
|
||||
- Try to implement the conversion yourself.
|
||||
Do not use something else to perform the conversion for you.
|
||||
|
||||
## About [Positional Notation](https://en.wikipedia.org/wiki/Positional_notation)
|
||||
|
||||
In positional notation, a number in base **b** can be understood as a linear
|
||||
combination of powers of **b**.
|
||||
|
||||
The number 42, *in base 10*, means:
|
||||
|
||||
(4 \* 10^1) + (2 \* 10^0)
|
||||
|
||||
The number 101010, *in base 2*, means:
|
||||
|
||||
(1 \* 2^5) + (0 \* 2^4) + (1 \* 2^3) + (0 \* 2^2) + (1 \* 2^1) + (0 \* 2^0)
|
||||
|
||||
The number 1120, *in base 3*, means:
|
||||
|
||||
(1 \* 3^3) + (1 \* 3^2) + (2 \* 3^1) + (0 \* 3^0)
|
||||
|
||||
I think you got the idea!
|
||||
|
||||
*Yes. Those three numbers above are exactly the same. Congratulations!*
|
||||
|
||||
Assumptions:
|
||||
1. Zero is always represented in outputs as [0] instead of [].
|
||||
2. In no other instances are leading zeroes present in any outputs.
|
||||
3. Leading zeroes are accepted in inputs.
|
||||
4. An empty sequence of input digits is considered zero, rather than an error.
|
||||
|
||||
Handle problem cases by returning an error whose Error() method
|
||||
returns one of following messages:
|
||||
* input base must be >= 2
|
||||
* output base must be >= 2
|
||||
* all digits must satisfy 0 <= d < input base
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @erizocosmico
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @alebaffa
|
||||
- @bitfield
|
||||
- @ekingery
|
||||
- @ferhatelmas
|
||||
- @hilary
|
||||
- @leenipper
|
||||
- @ngochai94
|
||||
- @petertseng
|
||||
- @robphoenix
|
||||
- @sebito91
|
||||
- @tleen
|
5
all-your-base/all_your_base.go
Normal file
5
all-your-base/all_your_base.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
package allyourbase
|
||||
|
||||
func ConvertToBase(inputBase int, inputDigits []int, outputBase int) ([]int, error) {
|
||||
panic("Please implement the ConvertToBase function")
|
||||
}
|
27
all-your-base/all_your_base_test.go
Normal file
27
all-your-base/all_your_base_test.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package allyourbase
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConvertToBase(t *testing.T) {
|
||||
for _, c := range testCases {
|
||||
output, err := ConvertToBase(c.inputBase, c.inputDigits, c.outputBase)
|
||||
if c.err != "" {
|
||||
if err == nil || c.err != err.Error() {
|
||||
t.Fatalf(`FAIL: %s
|
||||
Expected error: %s
|
||||
Got: %v`, c.description, c.err, err)
|
||||
}
|
||||
} else if !reflect.DeepEqual(c.expected, output) {
|
||||
t.Fatalf(`FAIL: %s
|
||||
Input base: %d
|
||||
Input digits: %#v
|
||||
Output base: %d
|
||||
Expected output digits: %#v
|
||||
Got: %#v`, c.description, c.inputBase, c.inputDigits, c.outputBase, c.expected, output)
|
||||
}
|
||||
t.Logf("PASS: %s", c.description)
|
||||
}
|
||||
}
|
183
all-your-base/cases_test.go
Normal file
183
all-your-base/cases_test.go
Normal file
|
@ -0,0 +1,183 @@
|
|||
package allyourbase
|
||||
|
||||
// Source: exercism/problem-specifications
|
||||
// Commit: c21ffd7 all-your-base: improve "input base is one" test
|
||||
// Problem Specifications Version: 2.3.0
|
||||
|
||||
var testCases = []struct {
|
||||
description string
|
||||
inputBase int
|
||||
inputDigits []int
|
||||
outputBase int
|
||||
expected []int
|
||||
err string
|
||||
}{
|
||||
{
|
||||
description: "single bit one to decimal",
|
||||
inputBase: 2,
|
||||
inputDigits: []int{1},
|
||||
outputBase: 10,
|
||||
expected: []int{1},
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "binary to single decimal",
|
||||
inputBase: 2,
|
||||
inputDigits: []int{1, 0, 1},
|
||||
outputBase: 10,
|
||||
expected: []int{5},
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "single decimal to binary",
|
||||
inputBase: 10,
|
||||
inputDigits: []int{5},
|
||||
outputBase: 2,
|
||||
expected: []int{1, 0, 1},
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "binary to multiple decimal",
|
||||
inputBase: 2,
|
||||
inputDigits: []int{1, 0, 1, 0, 1, 0},
|
||||
outputBase: 10,
|
||||
expected: []int{4, 2},
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "decimal to binary",
|
||||
inputBase: 10,
|
||||
inputDigits: []int{4, 2},
|
||||
outputBase: 2,
|
||||
expected: []int{1, 0, 1, 0, 1, 0},
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "trinary to hexadecimal",
|
||||
inputBase: 3,
|
||||
inputDigits: []int{1, 1, 2, 0},
|
||||
outputBase: 16,
|
||||
expected: []int{2, 10},
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "hexadecimal to trinary",
|
||||
inputBase: 16,
|
||||
inputDigits: []int{2, 10},
|
||||
outputBase: 3,
|
||||
expected: []int{1, 1, 2, 0},
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "15-bit integer",
|
||||
inputBase: 97,
|
||||
inputDigits: []int{3, 46, 60},
|
||||
outputBase: 73,
|
||||
expected: []int{6, 10, 45},
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "empty list",
|
||||
inputBase: 2,
|
||||
inputDigits: []int{},
|
||||
outputBase: 10,
|
||||
expected: []int{0},
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "single zero",
|
||||
inputBase: 10,
|
||||
inputDigits: []int{0},
|
||||
outputBase: 2,
|
||||
expected: []int{0},
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "multiple zeros",
|
||||
inputBase: 10,
|
||||
inputDigits: []int{0, 0, 0},
|
||||
outputBase: 2,
|
||||
expected: []int{0},
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "leading zeros",
|
||||
inputBase: 7,
|
||||
inputDigits: []int{0, 6, 0},
|
||||
outputBase: 10,
|
||||
expected: []int{4, 2},
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "input base is one",
|
||||
inputBase: 1,
|
||||
inputDigits: []int{0},
|
||||
outputBase: 10,
|
||||
expected: []int(nil),
|
||||
err: "input base must be >= 2",
|
||||
},
|
||||
{
|
||||
description: "input base is zero",
|
||||
inputBase: 0,
|
||||
inputDigits: []int{},
|
||||
outputBase: 10,
|
||||
expected: []int(nil),
|
||||
err: "input base must be >= 2",
|
||||
},
|
||||
{
|
||||
description: "input base is negative",
|
||||
inputBase: -2,
|
||||
inputDigits: []int{1},
|
||||
outputBase: 10,
|
||||
expected: []int(nil),
|
||||
err: "input base must be >= 2",
|
||||
},
|
||||
{
|
||||
description: "negative digit",
|
||||
inputBase: 2,
|
||||
inputDigits: []int{1, -1, 1, 0, 1, 0},
|
||||
outputBase: 10,
|
||||
expected: []int(nil),
|
||||
err: "all digits must satisfy 0 <= d < input base",
|
||||
},
|
||||
{
|
||||
description: "invalid positive digit",
|
||||
inputBase: 2,
|
||||
inputDigits: []int{1, 2, 1, 0, 1, 0},
|
||||
outputBase: 10,
|
||||
expected: []int(nil),
|
||||
err: "all digits must satisfy 0 <= d < input base",
|
||||
},
|
||||
{
|
||||
description: "output base is one",
|
||||
inputBase: 2,
|
||||
inputDigits: []int{1, 0, 1, 0, 1, 0},
|
||||
outputBase: 1,
|
||||
expected: []int(nil),
|
||||
err: "output base must be >= 2",
|
||||
},
|
||||
{
|
||||
description: "output base is zero",
|
||||
inputBase: 10,
|
||||
inputDigits: []int{7},
|
||||
outputBase: 0,
|
||||
expected: []int(nil),
|
||||
err: "output base must be >= 2",
|
||||
},
|
||||
{
|
||||
description: "output base is negative",
|
||||
inputBase: 2,
|
||||
inputDigits: []int{1},
|
||||
outputBase: -7,
|
||||
expected: []int(nil),
|
||||
err: "output base must be >= 2",
|
||||
},
|
||||
{
|
||||
description: "both bases are negative",
|
||||
inputBase: -2,
|
||||
inputDigits: []int{1},
|
||||
outputBase: -7,
|
||||
expected: []int(nil),
|
||||
err: "input base must be >= 2",
|
||||
},
|
||||
}
|
3
all-your-base/go.mod
Normal file
3
all-your-base/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module allyourbase
|
||||
|
||||
go 1.16
|
39
allergies/.exercism/config.json
Normal file
39
allergies/.exercism/config.json
Normal file
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"blurb": "Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies.",
|
||||
"authors": [
|
||||
"zilkey"
|
||||
],
|
||||
"contributors": [
|
||||
"aarti",
|
||||
"alebaffa",
|
||||
"bitfield",
|
||||
"ekingery",
|
||||
"ferhatelmas",
|
||||
"hilary",
|
||||
"kytrinyx",
|
||||
"leenipper",
|
||||
"mkoppmann",
|
||||
"petertseng",
|
||||
"robphoenix",
|
||||
"sebito91",
|
||||
"strangeman",
|
||||
"tleen",
|
||||
"tompao"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"allergies.go"
|
||||
],
|
||||
"test": [
|
||||
"allergies_test.go"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.go"
|
||||
],
|
||||
"editor": [
|
||||
"cases_test.go"
|
||||
]
|
||||
},
|
||||
"source": "Jumpstart Lab Warm-up",
|
||||
"source_url": "http://jumpstartlab.com"
|
||||
}
|
1
allergies/.exercism/metadata.json
Normal file
1
allergies/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"go","exercise":"allergies","id":"348afc34e7dc4d0abf44316d6a081fd0","url":"https://exercism.org/tracks/go/exercises/allergies","handle":"snowyforest","is_requester":true,"auto_approve":false}
|
41
allergies/HELP.md
Normal file
41
allergies/HELP.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
|
||||
flags:
|
||||
|
||||
go test -v --bench . --benchmem
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit allergies.go` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
|
||||
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, you can use one of the following resources:
|
||||
|
||||
- [How to Write Go Code](https://golang.org/doc/code.html)
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
- [Go Resources](http://golang.org/help)
|
||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
|
63
allergies/README.md
Normal file
63
allergies/README.md
Normal file
|
@ -0,0 +1,63 @@
|
|||
# Allergies
|
||||
|
||||
Welcome to Allergies on Exercism's Go Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
Given a person's allergy score, determine 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.
|
||||
|
||||
Note: a given score may include allergens **not** listed above (i.e.
|
||||
allergens that score 256, 512, 1024, etc.). Your program should
|
||||
ignore those components of the score. For example, if the allergy
|
||||
score is 257, your program should only report the eggs (1) allergy.
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @zilkey
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @aarti
|
||||
- @alebaffa
|
||||
- @bitfield
|
||||
- @ekingery
|
||||
- @ferhatelmas
|
||||
- @hilary
|
||||
- @kytrinyx
|
||||
- @leenipper
|
||||
- @mkoppmann
|
||||
- @petertseng
|
||||
- @robphoenix
|
||||
- @sebito91
|
||||
- @strangeman
|
||||
- @tleen
|
||||
- @tompao
|
||||
|
||||
### Based on
|
||||
|
||||
Jumpstart Lab Warm-up - http://jumpstartlab.com
|
9
allergies/allergies.go
Normal file
9
allergies/allergies.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
package allergies
|
||||
|
||||
func Allergies(allergies uint) []string {
|
||||
panic("Please implement the Allergies function")
|
||||
}
|
||||
|
||||
func AllergicTo(allergies uint, allergen string) bool {
|
||||
panic("Please implement the AllergicTo function")
|
||||
}
|
79
allergies/allergies_test.go
Normal file
79
allergies/allergies_test.go
Normal file
|
@ -0,0 +1,79 @@
|
|||
package allergies
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAllergies(t *testing.T) {
|
||||
for _, test := range listTests {
|
||||
if actual := Allergies(test.score); !sameSliceElements(actual, test.expected) {
|
||||
t.Fatalf("FAIL: Allergies(%d): expected %#v, actual %#v", test.score, test.expected, actual)
|
||||
} else {
|
||||
t.Logf("PASS: Allergic to %#v", test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAllergies(b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
||||
for _, test := range allergicToTests {
|
||||
Allergies(test.score)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllergicTo(t *testing.T) {
|
||||
for _, test := range allergicToTests {
|
||||
for _, response := range test.expected {
|
||||
actual := AllergicTo(test.score, response.substance)
|
||||
if actual != response.result {
|
||||
t.Fatalf("FAIL: AllergicTo(%d, %s): expected %t, actual %t", test.score, response.substance, response.result, actual)
|
||||
} else {
|
||||
t.Logf("PASS: AllergicTo(%d, %s) %t", test.score, response.substance, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAllergicTo(b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, test := range allergicToTests {
|
||||
|
||||
for _, response := range test.expected {
|
||||
AllergicTo(test.score, response.substance)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stringSet is a set of strings
|
||||
type stringSet map[string]bool
|
||||
|
||||
// sameSliceElements checks if the slices have the same number of elements
|
||||
// regardless of their order
|
||||
func sameSliceElements(a, b []string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
|
||||
return reflect.DeepEqual(sliceSet(a), sliceSet(b))
|
||||
}
|
||||
|
||||
// sliceSet creates a new stringSet from a slice of strings
|
||||
func sliceSet(list []string) stringSet {
|
||||
set := make(stringSet)
|
||||
|
||||
for _, elem := range list {
|
||||
set[elem] = true
|
||||
}
|
||||
|
||||
return set
|
||||
}
|
70
allergies/cases_test.go
Normal file
70
allergies/cases_test.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
package allergies
|
||||
|
||||
// Source: exercism/problem-specifications
|
||||
// Commit: 17a2ab2 added allergies test case (#1275)
|
||||
// Problem Specifications Version: 1.2.0
|
||||
|
||||
// allergicTo
|
||||
type allergicResult struct {
|
||||
substance string
|
||||
result bool
|
||||
}
|
||||
|
||||
var allergicToTests = []struct {
|
||||
description string
|
||||
score uint
|
||||
expected []allergicResult
|
||||
}{
|
||||
{
|
||||
description: "no allergies means not allergic",
|
||||
score: 0,
|
||||
expected: []allergicResult{
|
||||
{"peanuts", false},
|
||||
{"cats", false},
|
||||
{"strawberries", false},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "is allergic to eggs",
|
||||
score: 1,
|
||||
expected: []allergicResult{
|
||||
{"eggs", true},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "allergic to eggs in addition to other stuff",
|
||||
score: 5,
|
||||
expected: []allergicResult{
|
||||
{"eggs", true},
|
||||
{"shellfish", true},
|
||||
{"strawberries", false},
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "allergic to strawberries but not peanuts",
|
||||
score: 9,
|
||||
expected: []allergicResult{
|
||||
{"eggs", true},
|
||||
{"peanuts", false},
|
||||
{"shellfish", false},
|
||||
{"strawberries", true},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// list
|
||||
var listTests = []struct {
|
||||
description string
|
||||
score uint
|
||||
expected []string
|
||||
}{
|
||||
{"no allergies at all", 0, []string{}},
|
||||
{"allergic to just eggs", 1, []string{"eggs"}},
|
||||
{"allergic to just peanuts", 2, []string{"peanuts"}},
|
||||
{"allergic to just strawberries", 8, []string{"strawberries"}},
|
||||
{"allergic to eggs and peanuts", 3, []string{"eggs", "peanuts"}},
|
||||
{"allergic to more than eggs but not peanuts", 5, []string{"eggs", "shellfish"}},
|
||||
{"allergic to lots of stuff", 248, []string{"strawberries", "tomatoes", "chocolate", "pollen", "cats"}},
|
||||
{"allergic to everything", 255, []string{"eggs", "peanuts", "shellfish", "strawberries", "tomatoes", "chocolate", "pollen", "cats"}},
|
||||
{"ignore non allergen score parts", 509, []string{"eggs", "shellfish", "strawberries", "tomatoes", "chocolate", "pollen", "cats"}},
|
||||
}
|
3
allergies/go.mod
Normal file
3
allergies/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module allergies
|
||||
|
||||
go 1.16
|
41
anagram/.exercism/config.json
Normal file
41
anagram/.exercism/config.json
Normal file
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"blurb": "Given a word and a list of possible anagrams, select the correct sublist.",
|
||||
"authors": [
|
||||
"mikegehard"
|
||||
],
|
||||
"contributors": [
|
||||
"alebaffa",
|
||||
"bitfield",
|
||||
"ekingery",
|
||||
"ferhatelmas",
|
||||
"henrik",
|
||||
"hilary",
|
||||
"ilmanzo",
|
||||
"kf8a",
|
||||
"kytrinyx",
|
||||
"leenipper",
|
||||
"markijbema",
|
||||
"petertseng",
|
||||
"robphoenix",
|
||||
"sebito91",
|
||||
"strangeman",
|
||||
"tleen",
|
||||
"tompao"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"anagram.go"
|
||||
],
|
||||
"test": [
|
||||
"anagram_test.go"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.go"
|
||||
],
|
||||
"editor": [
|
||||
"cases_test.go"
|
||||
]
|
||||
},
|
||||
"source": "Inspired by the Extreme Startup game",
|
||||
"source_url": "https://github.com/rchatley/extreme_startup"
|
||||
}
|
1
anagram/.exercism/metadata.json
Normal file
1
anagram/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"go","exercise":"anagram","id":"984fe85be7224a63a97367cb9680f24f","url":"https://exercism.org/tracks/go/exercises/anagram","handle":"snowyforest","is_requester":true,"auto_approve":false}
|
41
anagram/HELP.md
Normal file
41
anagram/HELP.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
|
||||
flags:
|
||||
|
||||
go test -v --bench . --benchmem
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit anagram.go` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
|
||||
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, you can use one of the following resources:
|
||||
|
||||
- [How to Write Go Code](https://golang.org/doc/code.html)
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
- [Go Resources](http://golang.org/help)
|
||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
|
43
anagram/README.md
Normal file
43
anagram/README.md
Normal file
|
@ -0,0 +1,43 @@
|
|||
# Anagram
|
||||
|
||||
Welcome to Anagram on Exercism's Go Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
An anagram is a rearrangement of letters to form a new word.
|
||||
Given a word and a list of candidates, select the sublist of anagrams of the given word.
|
||||
|
||||
Given `"listen"` and a list of candidates like `"enlists" "google"
|
||||
"inlets" "banana"` the program should return a list containing
|
||||
`"inlets"`.
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @mikegehard
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @alebaffa
|
||||
- @bitfield
|
||||
- @ekingery
|
||||
- @ferhatelmas
|
||||
- @henrik
|
||||
- @hilary
|
||||
- @ilmanzo
|
||||
- @kf8a
|
||||
- @kytrinyx
|
||||
- @leenipper
|
||||
- @markijbema
|
||||
- @petertseng
|
||||
- @robphoenix
|
||||
- @sebito91
|
||||
- @strangeman
|
||||
- @tleen
|
||||
- @tompao
|
||||
|
||||
### Based on
|
||||
|
||||
Inspired by the Extreme Startup game - https://github.com/rchatley/extreme_startup
|
5
anagram/anagram.go
Normal file
5
anagram/anagram.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
package anagram
|
||||
|
||||
func Detect(subject string, candidates []string) []string {
|
||||
panic("Please implement the Detect function")
|
||||
}
|
45
anagram/anagram_test.go
Normal file
45
anagram/anagram_test.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
package anagram
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func equal(a, 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 %q
|
||||
Expected %q
|
||||
Got %q
|
||||
`
|
||||
t.Fatalf(msg, tt.description, tt.subject, tt.candidates, tt.expected, actual)
|
||||
} else {
|
||||
t.Logf("PASS: %s", tt.description)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDetectAnagrams(b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, tt := range testCases {
|
||||
Detect(tt.subject, tt.candidates)
|
||||
}
|
||||
}
|
||||
}
|
128
anagram/cases_test.go
Normal file
128
anagram/cases_test.go
Normal file
|
@ -0,0 +1,128 @@
|
|||
package anagram
|
||||
|
||||
// Source: exercism/problem-specifications
|
||||
// Commit: baaf092 anagram: words are not anagrams of themselves
|
||||
// Problem Specifications Version: 1.4.0
|
||||
|
||||
var testCases = []struct {
|
||||
description string
|
||||
subject string
|
||||
candidates []string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
description: "no matches",
|
||||
subject: "diaper",
|
||||
candidates: []string{
|
||||
"hello",
|
||||
"world",
|
||||
"zombies",
|
||||
"pants"},
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
description: "detects two anagrams",
|
||||
subject: "master",
|
||||
candidates: []string{
|
||||
"stream",
|
||||
"pigeon",
|
||||
"maters"},
|
||||
expected: []string{
|
||||
"stream",
|
||||
"maters"},
|
||||
},
|
||||
{
|
||||
description: "does not detect anagram subsets",
|
||||
subject: "good",
|
||||
candidates: []string{
|
||||
"dog",
|
||||
"goody"},
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
description: "detects anagram",
|
||||
subject: "listen",
|
||||
candidates: []string{
|
||||
"enlists",
|
||||
"google",
|
||||
"inlets",
|
||||
"banana"},
|
||||
expected: []string{
|
||||
"inlets"},
|
||||
},
|
||||
{
|
||||
description: "detects three anagrams",
|
||||
subject: "allergy",
|
||||
candidates: []string{
|
||||
"gallery",
|
||||
"ballerina",
|
||||
"regally",
|
||||
"clergy",
|
||||
"largely",
|
||||
"leading"},
|
||||
expected: []string{
|
||||
"gallery",
|
||||
"regally",
|
||||
"largely"},
|
||||
},
|
||||
{
|
||||
description: "does not detect non-anagrams with identical checksum",
|
||||
subject: "mass",
|
||||
candidates: []string{
|
||||
"last"},
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
description: "detects anagrams case-insensitively",
|
||||
subject: "Orchestra",
|
||||
candidates: []string{
|
||||
"cashregister",
|
||||
"Carthorse",
|
||||
"radishes"},
|
||||
expected: []string{
|
||||
"Carthorse"},
|
||||
},
|
||||
{
|
||||
description: "detects anagrams using case-insensitive subject",
|
||||
subject: "Orchestra",
|
||||
candidates: []string{
|
||||
"cashregister",
|
||||
"carthorse",
|
||||
"radishes"},
|
||||
expected: []string{
|
||||
"carthorse"},
|
||||
},
|
||||
{
|
||||
description: "detects anagrams using case-insensitive possible matches",
|
||||
subject: "orchestra",
|
||||
candidates: []string{
|
||||
"cashregister",
|
||||
"Carthorse",
|
||||
"radishes"},
|
||||
expected: []string{
|
||||
"Carthorse"},
|
||||
},
|
||||
{
|
||||
description: "does not detect a anagram if the original word is repeated",
|
||||
subject: "go",
|
||||
candidates: []string{
|
||||
"go Go GO"},
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
description: "anagrams must use all letters exactly once",
|
||||
subject: "tapper",
|
||||
candidates: []string{
|
||||
"patter"},
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
description: "words are not anagrams of themselves (case-insensitive)",
|
||||
subject: "BANANA",
|
||||
candidates: []string{
|
||||
"BANANA",
|
||||
"Banana",
|
||||
"banana"},
|
||||
expected: []string{},
|
||||
},
|
||||
}
|
3
anagram/go.mod
Normal file
3
anagram/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module anagram
|
||||
|
||||
go 1.16
|
33
armstrong-numbers/.exercism/config.json
Normal file
33
armstrong-numbers/.exercism/config.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"blurb": "Determine if a number is an Armstrong number",
|
||||
"authors": [
|
||||
"ilmanzo"
|
||||
],
|
||||
"contributors": [
|
||||
"bitfield",
|
||||
"da-edra",
|
||||
"Daveed9",
|
||||
"ekingery",
|
||||
"ferhatelmas",
|
||||
"hilary",
|
||||
"kytrinyx",
|
||||
"leenipper",
|
||||
"sebito91"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"armstrong_numbers.go"
|
||||
],
|
||||
"test": [
|
||||
"armstrong_numbers_test.go"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.go"
|
||||
],
|
||||
"editor": [
|
||||
"cases_test.go"
|
||||
]
|
||||
},
|
||||
"source": "Wikipedia",
|
||||
"source_url": "https://en.wikipedia.org/wiki/Narcissistic_number"
|
||||
}
|
1
armstrong-numbers/.exercism/metadata.json
Normal file
1
armstrong-numbers/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"go","exercise":"armstrong-numbers","id":"e257645217454209b478764ad41df2ef","url":"https://exercism.org/tracks/go/exercises/armstrong-numbers","handle":"snowyforest","is_requester":true,"auto_approve":false}
|
41
armstrong-numbers/HELP.md
Normal file
41
armstrong-numbers/HELP.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
|
||||
flags:
|
||||
|
||||
go test -v --bench . --benchmem
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit armstrong_numbers.go` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
|
||||
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, you can use one of the following resources:
|
||||
|
||||
- [How to Write Go Code](https://golang.org/doc/code.html)
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
- [Go Resources](http://golang.org/help)
|
||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
|
39
armstrong-numbers/README.md
Normal file
39
armstrong-numbers/README.md
Normal file
|
@ -0,0 +1,39 @@
|
|||
# Armstrong Numbers
|
||||
|
||||
Welcome to Armstrong Numbers on Exercism's Go Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
An [Armstrong number](https://en.wikipedia.org/wiki/Narcissistic_number) is a number that is the sum of its own digits each raised to the power of the number of digits.
|
||||
|
||||
For example:
|
||||
|
||||
- 9 is an Armstrong number, because `9 = 9^1 = 9`
|
||||
- 10 is *not* an Armstrong number, because `10 != 1^2 + 0^2 = 1`
|
||||
- 153 is an Armstrong number, because: `153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153`
|
||||
- 154 is *not* an Armstrong number, because: `154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190`
|
||||
|
||||
Write some code to determine whether a number is an Armstrong number.
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @ilmanzo
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @bitfield
|
||||
- @da-edra
|
||||
- @Daveed9
|
||||
- @ekingery
|
||||
- @ferhatelmas
|
||||
- @hilary
|
||||
- @kytrinyx
|
||||
- @leenipper
|
||||
- @sebito91
|
||||
|
||||
### Based on
|
||||
|
||||
Wikipedia - https://en.wikipedia.org/wiki/Narcissistic_number
|
5
armstrong-numbers/armstrong_numbers.go
Normal file
5
armstrong-numbers/armstrong_numbers.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
package armstrong
|
||||
|
||||
func IsNumber(n int) bool {
|
||||
panic("Please implement the IsNumber function")
|
||||
}
|
28
armstrong-numbers/armstrong_numbers_test.go
Normal file
28
armstrong-numbers/armstrong_numbers_test.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package armstrong
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestArmstrong(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
if actual := IsNumber(tc.input); actual != tc.expected {
|
||||
t.Fatalf("FAIL: %s\nExpected: %v\nActual: %v", tc.description, tc.expected, actual)
|
||||
}
|
||||
t.Logf("PASS: %s", tc.description)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIsNumber(b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
b.Run(fmt.Sprintf("%d", tc.input), func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
IsNumber(tc.input)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
57
armstrong-numbers/cases_test.go
Normal file
57
armstrong-numbers/cases_test.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
package armstrong
|
||||
|
||||
// Source: exercism/problem-specifications
|
||||
// Commit: b3c2522 armstrong-numbers: Zero is an Armstrong number and requires specific testing (#1505)
|
||||
// Problem Specifications Version: 1.1.0
|
||||
|
||||
var testCases = []struct {
|
||||
description string
|
||||
input int
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
description: "Zero is an Armstrong number",
|
||||
input: 0,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
description: "Single digit numbers are Armstrong numbers",
|
||||
input: 5,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
description: "There are no 2 digit Armstrong numbers",
|
||||
input: 10,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
description: "Three digit number that is an Armstrong number",
|
||||
input: 153,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
description: "Three digit number that is not an Armstrong number",
|
||||
input: 100,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
description: "Four digit number that is an Armstrong number",
|
||||
input: 9474,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
description: "Four digit number that is not an Armstrong number",
|
||||
input: 9475,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
description: "Seven digit number that is an Armstrong number",
|
||||
input: 9926315,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
description: "Seven digit number that is not an Armstrong number",
|
||||
input: 9926314,
|
||||
expected: false,
|
||||
},
|
||||
}
|
3
armstrong-numbers/go.mod
Normal file
3
armstrong-numbers/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module armstrong
|
||||
|
||||
go 1.16
|
37
atbash-cipher/.exercism/config.json
Normal file
37
atbash-cipher/.exercism/config.json
Normal file
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"blurb": "Create an implementation of the atbash cipher, an ancient encryption system created in the Middle East.",
|
||||
"authors": [
|
||||
"zilkey"
|
||||
],
|
||||
"contributors": [
|
||||
"alebaffa",
|
||||
"bitfield",
|
||||
"ekingery",
|
||||
"ferhatelmas",
|
||||
"hilary",
|
||||
"kytrinyx",
|
||||
"leenipper",
|
||||
"petertseng",
|
||||
"robphoenix",
|
||||
"sebito91",
|
||||
"strangeman",
|
||||
"tleen",
|
||||
"tompao"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"atbash_cipher.go"
|
||||
],
|
||||
"test": [
|
||||
"atbash_cipher_test.go"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.go"
|
||||
],
|
||||
"editor": [
|
||||
"cases_test.go"
|
||||
]
|
||||
},
|
||||
"source": "Wikipedia",
|
||||
"source_url": "http://en.wikipedia.org/wiki/Atbash"
|
||||
}
|
1
atbash-cipher/.exercism/metadata.json
Normal file
1
atbash-cipher/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"go","exercise":"atbash-cipher","id":"7ab13ce7aca04d1e868f8547d6c7fec9","url":"https://exercism.org/tracks/go/exercises/atbash-cipher","handle":"snowyforest","is_requester":true,"auto_approve":false}
|
41
atbash-cipher/HELP.md
Normal file
41
atbash-cipher/HELP.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
|
||||
flags:
|
||||
|
||||
go test -v --bench . --benchmem
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit atbash_cipher.go` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
|
||||
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, you can use one of the following resources:
|
||||
|
||||
- [How to Write Go Code](https://golang.org/doc/code.html)
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
- [Go Resources](http://golang.org/help)
|
||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
|
60
atbash-cipher/README.md
Normal file
60
atbash-cipher/README.md
Normal file
|
@ -0,0 +1,60 @@
|
|||
# Atbash Cipher
|
||||
|
||||
Welcome to Atbash Cipher on Exercism's Go Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
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:
|
||||
|
||||
```text
|
||||
Plain: abcdefghijklmnopqrstuvwxyz
|
||||
Cipher: zyxwvutsrqponmlkjihgfedcba
|
||||
```
|
||||
|
||||
It is a very weak cipher because it only has one possible key, and it is
|
||||
a simple mono-alphabetic 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 `thequickbrownfoxjumpsoverthelazydog`
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @zilkey
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @alebaffa
|
||||
- @bitfield
|
||||
- @ekingery
|
||||
- @ferhatelmas
|
||||
- @hilary
|
||||
- @kytrinyx
|
||||
- @leenipper
|
||||
- @petertseng
|
||||
- @robphoenix
|
||||
- @sebito91
|
||||
- @strangeman
|
||||
- @tleen
|
||||
- @tompao
|
||||
|
||||
### Based on
|
||||
|
||||
Wikipedia - http://en.wikipedia.org/wiki/Atbash
|
5
atbash-cipher/atbash_cipher.go
Normal file
5
atbash-cipher/atbash_cipher.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
package atbash
|
||||
|
||||
func Atbash(s string) string {
|
||||
panic("Please implement the Atbash function")
|
||||
}
|
25
atbash-cipher/atbash_cipher_test.go
Normal file
25
atbash-cipher/atbash_cipher_test.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
package atbash
|
||||
|
||||
import "testing"
|
||||
|
||||
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) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
||||
for _, test := range tests {
|
||||
Atbash(test.s)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
61
atbash-cipher/cases_test.go
Normal file
61
atbash-cipher/cases_test.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
package atbash
|
||||
|
||||
// Source: exercism/problem-specifications
|
||||
// Commit: dda678b atbash-cipher: Apply new "input" policy
|
||||
// Problem Specifications Version: 1.1.0
|
||||
|
||||
type atbashTest struct {
|
||||
s string
|
||||
expected string
|
||||
}
|
||||
|
||||
var tests = []atbashTest{
|
||||
{
|
||||
s: "yes",
|
||||
expected: "bvh",
|
||||
},
|
||||
{
|
||||
s: "no",
|
||||
expected: "ml",
|
||||
},
|
||||
{
|
||||
s: "OMG",
|
||||
expected: "lnt",
|
||||
},
|
||||
{
|
||||
s: "O M G",
|
||||
expected: "lnt",
|
||||
},
|
||||
{
|
||||
s: "mindblowingly",
|
||||
expected: "nrmwy oldrm tob",
|
||||
},
|
||||
{
|
||||
s: "Testing,1 2 3, testing.",
|
||||
expected: "gvhgr mt123 gvhgr mt",
|
||||
},
|
||||
{
|
||||
s: "Truth is fiction.",
|
||||
expected: "gifgs rhurx grlm",
|
||||
},
|
||||
{
|
||||
s: "The quick brown fox jumps over the lazy dog.",
|
||||
expected: "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt",
|
||||
},
|
||||
{
|
||||
s: "exercism",
|
||||
expected: "vcvix rhn",
|
||||
},
|
||||
{
|
||||
s: "anobstacleisoftenasteppingstone",
|
||||
expected: "zmlyh gzxov rhlug vmzhg vkkrm thglm v",
|
||||
},
|
||||
{
|
||||
s: "testing123testing",
|
||||
expected: "gvhgr mt123 gvhgr mt",
|
||||
},
|
||||
{
|
||||
s: "thequickbrownfoxjumpsoverthelazydog",
|
||||
expected: "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt",
|
||||
},
|
||||
}
|
3
atbash-cipher/go.mod
Normal file
3
atbash-cipher/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module atbash
|
||||
|
||||
go 1.16
|
34
bank-account/.exercism/config.json
Normal file
34
bank-account/.exercism/config.json
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"blurb": "Simulate a bank account supporting opening/closing, withdraws, and deposits of money. Watch out for concurrent transactions!",
|
||||
"authors": [
|
||||
"soniakeys"
|
||||
],
|
||||
"contributors": [
|
||||
"alebaffa",
|
||||
"bitfield",
|
||||
"ekingery",
|
||||
"ferhatelmas",
|
||||
"hilary",
|
||||
"homelinen",
|
||||
"JensChrG",
|
||||
"juergenhoetzel",
|
||||
"kytrinyx",
|
||||
"leenipper",
|
||||
"parroty",
|
||||
"petertseng",
|
||||
"robphoenix",
|
||||
"sebito91",
|
||||
"tleen"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"bank_account.go"
|
||||
],
|
||||
"test": [
|
||||
"bank_account_test.go"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.go"
|
||||
]
|
||||
}
|
||||
}
|
1
bank-account/.exercism/metadata.json
Normal file
1
bank-account/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"go","exercise":"bank-account","id":"144a1c0f54a6427297f78eb8112d5bf8","url":"https://exercism.org/tracks/go/exercises/bank-account","handle":"snowyforest","is_requester":true,"auto_approve":false}
|
41
bank-account/HELP.md
Normal file
41
bank-account/HELP.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
|
||||
flags:
|
||||
|
||||
go test -v --bench . --benchmem
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit bank_account.go` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
|
||||
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, you can use one of the following resources:
|
||||
|
||||
- [How to Write Go Code](https://golang.org/doc/code.html)
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
- [Go Resources](http://golang.org/help)
|
||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
|
77
bank-account/README.md
Normal file
77
bank-account/README.md
Normal file
|
@ -0,0 +1,77 @@
|
|||
# Bank Account
|
||||
|
||||
Welcome to Bank Account on Exercism's Go Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
Simulate a bank account supporting opening/closing, withdrawals, and deposits
|
||||
of money. Watch out for concurrent transactions!
|
||||
|
||||
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!
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
If Open is given a negative initial deposit, it must return nil.
|
||||
Deposit must handle a negative amount as a withdrawal. Withdrawals must
|
||||
not succeed if they result in a negative balance.
|
||||
If any Account method is called on an closed account, it must not modify
|
||||
the account and must return ok = false.
|
||||
|
||||
The tests will execute some operations concurrently. You should strive
|
||||
to ensure that operations on the Account leave it in a consistent state.
|
||||
For example: multiple goroutines may be depositing and withdrawing money
|
||||
simultaneously, two withdrawals occurring concurrently should not be able
|
||||
to bring the balance into the negative.
|
||||
|
||||
If you are new to concurrent operations in Go it will be worth looking
|
||||
at the sync package, specifically Mutexes:
|
||||
|
||||
https://golang.org/pkg/sync/
|
||||
https://tour.golang.org/concurrency/9
|
||||
https://gobyexample.com/mutexes
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @soniakeys
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @alebaffa
|
||||
- @bitfield
|
||||
- @ekingery
|
||||
- @ferhatelmas
|
||||
- @hilary
|
||||
- @homelinen
|
||||
- @JensChrG
|
||||
- @juergenhoetzel
|
||||
- @kytrinyx
|
||||
- @leenipper
|
||||
- @parroty
|
||||
- @petertseng
|
||||
- @robphoenix
|
||||
- @sebito91
|
||||
- @tleen
|
19
bank-account/bank_account.go
Normal file
19
bank-account/bank_account.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
package account
|
||||
|
||||
// Define the Account type here.
|
||||
|
||||
func Open(amount int64) *Account {
|
||||
panic("Please implement the Open function")
|
||||
}
|
||||
|
||||
func (a *Account) Balance() (int64, bool) {
|
||||
panic("Please implement the Balance function")
|
||||
}
|
||||
|
||||
func (a *Account) Deposit(amount int64) (int64, bool) {
|
||||
panic("Please implement the Deposit function")
|
||||
}
|
||||
|
||||
func (a *Account) Close() (int64, bool) {
|
||||
panic("Please implement the Close function")
|
||||
}
|
334
bank-account/bank_account_test.go
Normal file
334
bank-account/bank_account_test.go
Normal file
|
@ -0,0 +1,334 @@
|
|||
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)
|
||||
}
|
||||
|
||||
// verify closing balance is 0
|
||||
if b, _ := a.Balance(); b != 0 {
|
||||
t.Log("Balance after close is non-zero.")
|
||||
t.Fatalf("After a.Close() balance is %d and not 0", b)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// The benchmark operations are here to encourage you to try different
|
||||
// implementations to see which ones perform better. These are worth
|
||||
// exploring after the tests pass.
|
||||
//
|
||||
// There is a basic benchmark and a parallelized version of the same
|
||||
// benchmark. You run the benchmark using:
|
||||
// go test --bench=.
|
||||
//
|
||||
// The output will look something like this:
|
||||
// goos: linux
|
||||
// goarch: amd64
|
||||
// BenchmarkAccountOperations-8 10000000 130 ns/op
|
||||
// BenchmarkAccountOperationsParallel-8 3000000 488 ns/op
|
||||
// PASS
|
||||
//
|
||||
// You will notice that parallelism does not increase speed in this case, in
|
||||
// fact it makes things slower! This is because none of the operations in our
|
||||
// Account benefit from parallel processing. We are specifically protecting
|
||||
// the account balance internals from being accessed by multiple processes
|
||||
// simultaneously. Your protections will make the parallel processing slower
|
||||
// because there is some overhead in managing the processes and protections.
|
||||
//
|
||||
// The interesting thing to try here is to experiment with the protections
|
||||
// and see how their implementation changes the results of the parallel
|
||||
// benchmark.
|
||||
func BenchmarkAccountOperations(b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
a := Open(0)
|
||||
defer a.Close()
|
||||
for n := 0; n < b.N; n++ {
|
||||
a.Deposit(10)
|
||||
a.Deposit(-10)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAccountOperationsParallel(b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
a := Open(0)
|
||||
defer a.Close()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
a.Deposit(10)
|
||||
a.Deposit(-10)
|
||||
}
|
||||
})
|
||||
}
|
3
bank-account/go.mod
Normal file
3
bank-account/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module account
|
||||
|
||||
go 1.16
|
35
binary-search-tree/.exercism/config.json
Normal file
35
binary-search-tree/.exercism/config.json
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"blurb": "Insert and search for numbers in a binary tree.",
|
||||
"authors": [
|
||||
"zilkey"
|
||||
],
|
||||
"contributors": [
|
||||
"alebaffa",
|
||||
"bitfield",
|
||||
"ekingery",
|
||||
"ferhatelmas",
|
||||
"hilary",
|
||||
"jcbwlkr",
|
||||
"kytrinyx",
|
||||
"leenipper",
|
||||
"petertseng",
|
||||
"robphoenix",
|
||||
"sebito91",
|
||||
"sjakobi",
|
||||
"tapank",
|
||||
"tleen"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"binary_search_tree.go"
|
||||
],
|
||||
"test": [
|
||||
"binary_search_tree_test.go"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.go"
|
||||
]
|
||||
},
|
||||
"source": "Josh Cheek",
|
||||
"source_url": "https://twitter.com/josh_cheek"
|
||||
}
|
1
binary-search-tree/.exercism/metadata.json
Normal file
1
binary-search-tree/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"go","exercise":"binary-search-tree","id":"d27006c8034b45b484a392abb1b5adc8","url":"https://exercism.org/tracks/go/exercises/binary-search-tree","handle":"snowyforest","is_requester":true,"auto_approve":false}
|
41
binary-search-tree/HELP.md
Normal file
41
binary-search-tree/HELP.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
|
||||
flags:
|
||||
|
||||
go test -v --bench . --benchmem
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit binary_search_tree.go` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
|
||||
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, you can use one of the following resources:
|
||||
|
||||
- [How to Write Go Code](https://golang.org/doc/code.html)
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
- [Go Resources](http://golang.org/help)
|
||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
|
86
binary-search-tree/README.md
Normal file
86
binary-search-tree/README.md
Normal file
|
@ -0,0 +1,86 @@
|
|||
# Binary Search Tree
|
||||
|
||||
Welcome to Binary Search Tree on Exercism's Go Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
Insert and search for numbers in a binary tree.
|
||||
|
||||
When we need to represent sorted data, an array does not make a good
|
||||
data structure.
|
||||
|
||||
Say we have the array `[1, 3, 4, 5]`, and we add 2 to it so it becomes
|
||||
`[1, 3, 4, 5, 2]` now we must sort the entire array again! We can
|
||||
improve on this by realizing that we only need to make space for the new
|
||||
item `[1, nil, 3, 4, 5]`, and then adding the item in the space we
|
||||
added. But this still requires us to shift many elements down by one.
|
||||
|
||||
Binary Search Trees, however, can operate on sorted data much more
|
||||
efficiently.
|
||||
|
||||
A binary search tree consists of a series of connected nodes. Each node
|
||||
contains a piece of data (e.g. the number 3), a variable named `left`,
|
||||
and a variable named `right`. The `left` and `right` variables point at
|
||||
`nil`, or other nodes. Since these other nodes in turn have other nodes
|
||||
beneath them, we say that the left and right variables are pointing at
|
||||
subtrees. All data in the left subtree is less than or equal to the
|
||||
current node's data, and all data in the right subtree is greater than
|
||||
the current node's data.
|
||||
|
||||
For example, if we had a node containing the data 4, and we added the
|
||||
data 2, our tree would look like this:
|
||||
|
||||
4
|
||||
/
|
||||
2
|
||||
|
||||
If we then added 6, it would look like this:
|
||||
|
||||
4
|
||||
/ \
|
||||
2 6
|
||||
|
||||
If we then added 3, it would look like this
|
||||
|
||||
4
|
||||
/ \
|
||||
2 6
|
||||
\
|
||||
3
|
||||
|
||||
And if we then added 1, 5, and 7, it would look like this
|
||||
|
||||
4
|
||||
/ \
|
||||
/ \
|
||||
2 6
|
||||
/ \ / \
|
||||
1 3 5 7
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @zilkey
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @alebaffa
|
||||
- @bitfield
|
||||
- @ekingery
|
||||
- @ferhatelmas
|
||||
- @hilary
|
||||
- @jcbwlkr
|
||||
- @kytrinyx
|
||||
- @leenipper
|
||||
- @petertseng
|
||||
- @robphoenix
|
||||
- @sebito91
|
||||
- @sjakobi
|
||||
- @tapank
|
||||
- @tleen
|
||||
|
||||
### Based on
|
||||
|
||||
Josh Cheek - https://twitter.com/josh_cheek
|
54
binary-search-tree/binary_search_tree.go
Normal file
54
binary-search-tree/binary_search_tree.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
// This is a "stub" file. It's a little start on your solution.
|
||||
// It's not a complete solution though; you have to write some code.
|
||||
|
||||
// Package binarysearchtree should have a package comment that summarizes what it's about.
|
||||
// https://golang.org/doc/effective_go.html#commentary
|
||||
package binarysearchtree
|
||||
|
||||
type SearchTreeData struct {
|
||||
left *SearchTreeData
|
||||
data int
|
||||
right *SearchTreeData
|
||||
}
|
||||
|
||||
// NewBst creates and returns a new SearchTreeData.
|
||||
func NewBst(i int) SearchTreeData {
|
||||
// Write some code here to pass the test suite.
|
||||
// Then remove all the stock comments.
|
||||
// They're here to help you get started but they only clutter a finished solution.
|
||||
// If you leave them in, reviewers may protest!
|
||||
return SearchTreeData{}
|
||||
}
|
||||
|
||||
// Insert inserts an int into the SearchTreeData.
|
||||
// Inserts happen based on the rules of a BinarySearchTree
|
||||
func (std *SearchTreeData) Insert(i int) {
|
||||
// Write some code here to pass the test suite.
|
||||
// Then remove all the stock comments.
|
||||
// They're here to help you get started but they only clutter a finished solution.
|
||||
// If you leave them in, reviewers may protest!
|
||||
}
|
||||
|
||||
// MapString returns the ordered contents of SearchTreeData as a []string.
|
||||
// The values are in increasing order starting with the lowest int value.
|
||||
// SearchTreeData that has the numbers [1,3,7,5] added will return the
|
||||
// []string ["1", "3", "5", "7"].
|
||||
func (std *SearchTreeData) MapString(func(int) string) (result []string) {
|
||||
// Write some code here to pass the test suite.
|
||||
// Then remove all the stock comments.
|
||||
// They're here to help you get started but they only clutter a finished solution.
|
||||
// If you leave them in, reviewers may protest!
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// MapInt returns the ordered contents of SearchTreeData as an []int.
|
||||
// The values are in increasing order starting with the lowest int value.
|
||||
// SearchTreeData that has the numbers [1,3,7,5] added will return the
|
||||
// []int [1,3,5,7].
|
||||
func (std *SearchTreeData) MapInt(func(int) int) (result []int) {
|
||||
// Write some code here to pass the test suite.
|
||||
// Then remove all the stock comments.
|
||||
// They're here to help you get started but they only clutter a finished solution.
|
||||
// If you leave them in, reviewers may protest!
|
||||
return []int{}
|
||||
}
|
226
binary-search-tree/binary_search_tree_test.go
Normal file
226
binary-search-tree/binary_search_tree_test.go
Normal file
|
@ -0,0 +1,226 @@
|
|||
// API:
|
||||
//
|
||||
// type SearchTreeData struct {
|
||||
// left *SearchTreeData
|
||||
// data int
|
||||
// right *SearchTreeData
|
||||
// }
|
||||
//
|
||||
// func NewBst(int) *SearchTreeData
|
||||
// func (*SearchTreeData) Insert(int)
|
||||
// func (*SearchTreeData) MapString(func(int) string) []string
|
||||
// func (*SearchTreeData) MapInt(func(int) int) []int
|
||||
|
||||
package binarysearchtree
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDataIsRetained(t *testing.T) {
|
||||
actual := NewBst(4).data
|
||||
expected := 4
|
||||
if actual != expected {
|
||||
t.Errorf("NewBst(4).data: %d, want %d.", actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsertingLess(t *testing.T) {
|
||||
bst := SearchTreeData{data: 4}
|
||||
bst.Insert(2)
|
||||
|
||||
actual := bst.data
|
||||
expected := 4
|
||||
if actual != expected {
|
||||
t.Errorf("bst.data: %d, want %d.", actual, expected)
|
||||
}
|
||||
|
||||
expected = 2
|
||||
if bst.left == nil {
|
||||
t.Fatalf("bst.left: nil, want %d.", expected)
|
||||
}
|
||||
actual = bst.left.data
|
||||
if actual != expected {
|
||||
t.Errorf("bst.left.data: %d, want %d.", actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsertingSame(t *testing.T) {
|
||||
bst := SearchTreeData{data: 4}
|
||||
bst.Insert(4)
|
||||
|
||||
actual := bst.data
|
||||
expected := 4
|
||||
if actual != expected {
|
||||
t.Errorf("bst.data: %d, want %d.", actual, expected)
|
||||
}
|
||||
|
||||
expected = 4
|
||||
if bst.left == nil {
|
||||
t.Fatalf("bst.left: nil, want %d.", expected)
|
||||
}
|
||||
actual = bst.left.data
|
||||
if actual != expected {
|
||||
t.Errorf("bst.left.data: %d, want %d.", actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsertingMore(t *testing.T) {
|
||||
bst := SearchTreeData{data: 4}
|
||||
bst.Insert(5)
|
||||
|
||||
actual := bst.data
|
||||
expected := 4
|
||||
if actual != expected {
|
||||
t.Errorf("bst.data: %d, want %d.", actual, expected)
|
||||
}
|
||||
|
||||
expected = 5
|
||||
if bst.right == nil {
|
||||
t.Fatalf("bst.right: nil, want %d.", expected)
|
||||
}
|
||||
actual = bst.right.data
|
||||
if actual != expected {
|
||||
t.Errorf("bst.data: %d, want %d.", actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestComplexTree(t *testing.T) {
|
||||
bst := SearchTreeData{data: 4}
|
||||
bst.Insert(2)
|
||||
bst.Insert(6)
|
||||
bst.Insert(1)
|
||||
bst.Insert(3)
|
||||
bst.Insert(7)
|
||||
bst.Insert(5)
|
||||
|
||||
actual := bst.data
|
||||
expected := 4
|
||||
if actual != expected {
|
||||
t.Errorf("bst.data: %d, want %d.", actual, expected)
|
||||
}
|
||||
|
||||
expected = 2
|
||||
if bst.left == nil {
|
||||
t.Fatalf("bst.left: nil, want %d.", expected)
|
||||
}
|
||||
actual = bst.left.data
|
||||
if actual != expected {
|
||||
t.Errorf("bst.left.data: %d, want %d.", actual, expected)
|
||||
}
|
||||
|
||||
expected = 1
|
||||
if bst.left.left == nil {
|
||||
t.Fatalf("bst.left.left: nil, want %d.", expected)
|
||||
}
|
||||
actual = bst.left.left.data
|
||||
if actual != expected {
|
||||
t.Errorf("bst.left.left.data: %d, want %d.", actual, expected)
|
||||
}
|
||||
|
||||
expected = 3
|
||||
if bst.left.right == nil {
|
||||
t.Fatalf("bst.left.right: nil, want %d.", expected)
|
||||
}
|
||||
actual = bst.left.right.data
|
||||
if actual != expected {
|
||||
t.Errorf("bst.left.right.data: %d, want %d.", actual, expected)
|
||||
}
|
||||
|
||||
expected = 6
|
||||
if bst.right == nil {
|
||||
t.Fatalf("bst.right: nil, want %d.", expected)
|
||||
}
|
||||
actual = bst.right.data
|
||||
if actual != expected {
|
||||
t.Errorf("bst.right.data: %d, want %d", actual, expected)
|
||||
}
|
||||
|
||||
expected = 5
|
||||
if bst.right.left == nil {
|
||||
t.Fatalf("bst.right.left: nil, want %d.", expected)
|
||||
}
|
||||
actual = bst.right.left.data
|
||||
if actual != expected {
|
||||
t.Errorf("bst.right.left.data: %d, want %d", actual, expected)
|
||||
}
|
||||
|
||||
expected = 7
|
||||
if bst.right.right == nil {
|
||||
t.Fatalf("bst.right.right: nil, want %d.", expected)
|
||||
}
|
||||
actual = bst.right.right.data
|
||||
if actual != expected {
|
||||
t.Errorf("bst.right.right.data: %d, want %d", actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapStringWithOneElement(t *testing.T) {
|
||||
bst := SearchTreeData{data: 4}
|
||||
|
||||
actual := bst.MapString(strconv.Itoa)
|
||||
expected := []string{"4"}
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Errorf("bst.MapString(): %q, want %q.", actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapStringWithSmallElement(t *testing.T) {
|
||||
bst := SearchTreeData{data: 4}
|
||||
bst.Insert(2)
|
||||
|
||||
actual := bst.MapString(strconv.Itoa)
|
||||
expected := []string{"2", "4"}
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Errorf("bst.MapString(): %q, want %q.", actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapStringWithLargeElement(t *testing.T) {
|
||||
bst := SearchTreeData{data: 4}
|
||||
bst.Insert(5)
|
||||
|
||||
actual := bst.MapString(strconv.Itoa)
|
||||
expected := []string{"4", "5"}
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Errorf("bst.MapString(): %q, want %q.", actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapStringWithComplexStructure(t *testing.T) {
|
||||
bst := SearchTreeData{data: 4}
|
||||
bst.Insert(2)
|
||||
bst.Insert(1)
|
||||
bst.Insert(3)
|
||||
bst.Insert(6)
|
||||
bst.Insert(7)
|
||||
bst.Insert(5)
|
||||
|
||||
actual := bst.MapString(strconv.Itoa)
|
||||
expected := []string{"1", "2", "3", "4", "5", "6", "7"}
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Errorf("bst.MapString(): %q, want %q.", actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapIntWithComplexStructure(t *testing.T) {
|
||||
bst := SearchTreeData{data: 4}
|
||||
bst.Insert(2)
|
||||
bst.Insert(1)
|
||||
bst.Insert(3)
|
||||
bst.Insert(6)
|
||||
bst.Insert(7)
|
||||
bst.Insert(5)
|
||||
|
||||
f := func(i int) int {
|
||||
return i
|
||||
}
|
||||
|
||||
actual := bst.MapInt(f)
|
||||
expected := []int{1, 2, 3, 4, 5, 6, 7}
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Errorf("bst.MapInt(): %v, want %v.", actual, expected)
|
||||
}
|
||||
}
|
3
binary-search-tree/go.mod
Normal file
3
binary-search-tree/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module binarysearchtree
|
||||
|
||||
go 1.16
|
35
binary-search/.exercism/config.json
Normal file
35
binary-search/.exercism/config.json
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"blurb": "Implement a binary search algorithm.",
|
||||
"authors": [],
|
||||
"contributors": [
|
||||
"alebaffa",
|
||||
"bitfield",
|
||||
"da-edra",
|
||||
"ekingery",
|
||||
"ferhatelmas",
|
||||
"hilary",
|
||||
"ilmanzo",
|
||||
"kytrinyx",
|
||||
"leenipper",
|
||||
"petertseng",
|
||||
"robphoenix",
|
||||
"sebito91",
|
||||
"tleen"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"binary_search.go"
|
||||
],
|
||||
"test": [
|
||||
"binary_search_test.go"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.go"
|
||||
],
|
||||
"editor": [
|
||||
"cases_test.go"
|
||||
]
|
||||
},
|
||||
"source": "Wikipedia",
|
||||
"source_url": "http://en.wikipedia.org/wiki/Binary_search_algorithm"
|
||||
}
|
1
binary-search/.exercism/metadata.json
Normal file
1
binary-search/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"go","exercise":"binary-search","id":"447c79640e994a07b5ea1461b2672ce2","url":"https://exercism.org/tracks/go/exercises/binary-search","handle":"snowyforest","is_requester":true,"auto_approve":false}
|
41
binary-search/HELP.md
Normal file
41
binary-search/HELP.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
|
||||
flags:
|
||||
|
||||
go test -v --bench . --benchmem
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit binary_search.go` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
|
||||
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, you can use one of the following resources:
|
||||
|
||||
- [How to Write Go Code](https://golang.org/doc/code.html)
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
- [Go Resources](http://golang.org/help)
|
||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
|
62
binary-search/README.md
Normal file
62
binary-search/README.md
Normal file
|
@ -0,0 +1,62 @@
|
|||
# Binary Search
|
||||
|
||||
Welcome to Binary Search on Exercism's Go Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
Implement a binary search algorithm.
|
||||
|
||||
Searching a sorted collection is a common task. A dictionary is a sorted
|
||||
list of word definitions. Given a word, one can find its definition. A
|
||||
telephone book is a sorted list of people's names, addresses, and
|
||||
telephone numbers. Knowing someone's name allows one to quickly find
|
||||
their telephone number and address.
|
||||
|
||||
If the list to be searched contains more than a few items (a dozen, say)
|
||||
a binary search will require far fewer comparisons than a linear search,
|
||||
but it imposes the requirement that the list be sorted.
|
||||
|
||||
In computer science, a binary search or half-interval search algorithm
|
||||
finds the position of a specified input value (the search "key") within
|
||||
an array sorted by key value.
|
||||
|
||||
In each step, the algorithm compares the search key value with the key
|
||||
value of the middle element of the array.
|
||||
|
||||
If the keys match, then a matching element has been found and its index,
|
||||
or position, is returned.
|
||||
|
||||
Otherwise, if the search key is less than the middle element's key, then
|
||||
the algorithm repeats its action on the sub-array to the left of the
|
||||
middle element or, if the search key is greater, on the sub-array to the
|
||||
right.
|
||||
|
||||
If the remaining array to be searched is empty, then the key cannot be
|
||||
found in the array and a special "not found" indication is returned.
|
||||
|
||||
A binary search halves the number of items to check with each iteration,
|
||||
so locating an item (or determining its absence) takes logarithmic time.
|
||||
A binary search is a dichotomic divide and conquer search algorithm.
|
||||
|
||||
## Source
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @alebaffa
|
||||
- @bitfield
|
||||
- @da-edra
|
||||
- @ekingery
|
||||
- @ferhatelmas
|
||||
- @hilary
|
||||
- @ilmanzo
|
||||
- @kytrinyx
|
||||
- @leenipper
|
||||
- @petertseng
|
||||
- @robphoenix
|
||||
- @sebito91
|
||||
- @tleen
|
||||
|
||||
### Based on
|
||||
|
||||
Wikipedia - http://en.wikipedia.org/wiki/Binary_search_algorithm
|
5
binary-search/binary_search.go
Normal file
5
binary-search/binary_search.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
package binarysearch
|
||||
|
||||
func SearchInts(list []int, key int) int {
|
||||
panic("Please implement the SearchInts function")
|
||||
}
|
55
binary-search/binary_search_test.go
Normal file
55
binary-search/binary_search_test.go
Normal file
|
@ -0,0 +1,55 @@
|
|||
package binarysearch
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSearchInts(t *testing.T) {
|
||||
for _, test := range testCases {
|
||||
if x := SearchInts(test.slice, test.key); x != test.x {
|
||||
t.Fatalf("FAIL: %s\nSearchInts(%#v, %d) = %d, want %d",
|
||||
test.description, test.slice, test.key, x, test.x)
|
||||
}
|
||||
t.Logf("SUCCESS: %s", test.description)
|
||||
}
|
||||
}
|
||||
|
||||
// Benchmarks also test searching larger random slices
|
||||
|
||||
type query struct {
|
||||
slice []int
|
||||
x int
|
||||
}
|
||||
|
||||
func newQuery(n int) (query, error) {
|
||||
q := query{slice: make([]int, n)}
|
||||
for i := 0; i < n; i++ {
|
||||
q.slice[i] = i
|
||||
}
|
||||
q.x = rand.Intn(n)
|
||||
if res := SearchInts(q.slice, q.x); res != q.x {
|
||||
return q, fmt.Errorf("Search of %d values gave different answer", n)
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func runBenchmark(n int, b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
q, err := newQuery(n)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
SearchInts(q.slice, q.x)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark1e2(b *testing.B) { runBenchmark(1e2, b) }
|
||||
func Benchmark1e4(b *testing.B) { runBenchmark(1e4, b) }
|
||||
func Benchmark1e6(b *testing.B) { runBenchmark(1e6, b) }
|
||||
func Benchmark1e8(b *testing.B) { runBenchmark(1e8, b) }
|
91
binary-search/cases_test.go
Normal file
91
binary-search/cases_test.go
Normal file
|
@ -0,0 +1,91 @@
|
|||
package binarysearch
|
||||
|
||||
// Source: exercism/problem-specifications
|
||||
// Commit: bfb218f binary-search: test description tweak
|
||||
// Problem Specifications Version: 1.3.0
|
||||
|
||||
var testCases = []struct {
|
||||
description string
|
||||
slice []int
|
||||
key int
|
||||
x int
|
||||
err string
|
||||
}{
|
||||
{
|
||||
description: "finds a value in an array with one element",
|
||||
slice: []int{6},
|
||||
key: 6,
|
||||
x: 0,
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "finds a value in the middle of an array",
|
||||
slice: []int{1, 3, 4, 6, 8, 9, 11},
|
||||
key: 6,
|
||||
x: 3,
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "finds a value at the beginning of an array",
|
||||
slice: []int{1, 3, 4, 6, 8, 9, 11},
|
||||
key: 1,
|
||||
x: 0,
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "finds a value at the end of an array",
|
||||
slice: []int{1, 3, 4, 6, 8, 9, 11},
|
||||
key: 11,
|
||||
x: 6,
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "finds a value in an array of odd length",
|
||||
slice: []int{1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 634},
|
||||
key: 144,
|
||||
x: 9,
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "finds a value in an array of even length",
|
||||
slice: []int{1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377},
|
||||
key: 21,
|
||||
x: 5,
|
||||
err: "",
|
||||
},
|
||||
{
|
||||
description: "identifies that a value is not included in the array",
|
||||
slice: []int{1, 3, 4, 6, 8, 9, 11},
|
||||
key: 7,
|
||||
x: -1,
|
||||
err: "value not in array",
|
||||
},
|
||||
{
|
||||
description: "a value smaller than the array's smallest value is not found",
|
||||
slice: []int{1, 3, 4, 6, 8, 9, 11},
|
||||
key: 0,
|
||||
x: -1,
|
||||
err: "value not in array",
|
||||
},
|
||||
{
|
||||
description: "a value larger than the array's largest value is not found",
|
||||
slice: []int{1, 3, 4, 6, 8, 9, 11},
|
||||
key: 13,
|
||||
x: -1,
|
||||
err: "value not in array",
|
||||
},
|
||||
{
|
||||
description: "nothing is found in an empty array",
|
||||
slice: []int{},
|
||||
key: 1,
|
||||
x: -1,
|
||||
err: "value not in array",
|
||||
},
|
||||
{
|
||||
description: "nothing is found when the left and right bounds cross",
|
||||
slice: []int{1, 2},
|
||||
key: 0,
|
||||
x: -1,
|
||||
err: "value not in array",
|
||||
},
|
||||
}
|
3
binary-search/go.mod
Normal file
3
binary-search/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module binarysearch
|
||||
|
||||
go 1.16
|
40
bob/.exercism/config.json
Normal file
40
bob/.exercism/config.json
Normal file
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"blurb": "Bob is a lackadaisical teenager. In conversation, his responses are very limited.",
|
||||
"authors": [
|
||||
"kytrinyx"
|
||||
],
|
||||
"contributors": [
|
||||
"alebaffa",
|
||||
"austinlyons",
|
||||
"bitfield",
|
||||
"ekingery",
|
||||
"ferhatelmas",
|
||||
"hilary",
|
||||
"leenipper",
|
||||
"levicook",
|
||||
"petertseng",
|
||||
"robphoenix",
|
||||
"sebito91",
|
||||
"soniakeys",
|
||||
"strangeman",
|
||||
"tleen",
|
||||
"tompao",
|
||||
"Tonkpils"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"bob.go"
|
||||
],
|
||||
"test": [
|
||||
"bob_test.go"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.go"
|
||||
],
|
||||
"editor": [
|
||||
"cases_test.go"
|
||||
]
|
||||
},
|
||||
"source": "Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial.",
|
||||
"source_url": "http://pine.fm/LearnToProgram/?Chapter=06"
|
||||
}
|
1
bob/.exercism/metadata.json
Normal file
1
bob/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"go","exercise":"bob","id":"194f002cb95349529fea94519879a3cb","url":"https://exercism.org/tracks/go/exercises/bob","handle":"snowyforest","is_requester":true,"auto_approve":false}
|
41
bob/HELP.md
Normal file
41
bob/HELP.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
|
||||
flags:
|
||||
|
||||
go test -v --bench . --benchmem
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit bob.go` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
|
||||
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, you can use one of the following resources:
|
||||
|
||||
- [How to Write Go Code](https://golang.org/doc/code.html)
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
- [Go Resources](http://golang.org/help)
|
||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
|
50
bob/README.md
Normal file
50
bob/README.md
Normal file
|
@ -0,0 +1,50 @@
|
|||
# Bob
|
||||
|
||||
Welcome to Bob on Exercism's Go Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
|
||||
|
||||
Bob answers 'Sure.' if you ask him a question, such as "How are you?".
|
||||
|
||||
He answers 'Whoa, chill out!' if you YELL AT HIM (in all capitals).
|
||||
|
||||
He answers 'Calm down, I know what I'm doing!' if you yell a question at him.
|
||||
|
||||
He says 'Fine. Be that way!' if you address him without actually saying
|
||||
anything.
|
||||
|
||||
He answers 'Whatever.' to anything else.
|
||||
|
||||
Bob's conversational partner is a purist when it comes to written communication and always follows normal rules regarding sentence punctuation in English.
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @kytrinyx
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @alebaffa
|
||||
- @austinlyons
|
||||
- @bitfield
|
||||
- @ekingery
|
||||
- @ferhatelmas
|
||||
- @hilary
|
||||
- @leenipper
|
||||
- @levicook
|
||||
- @petertseng
|
||||
- @robphoenix
|
||||
- @sebito91
|
||||
- @soniakeys
|
||||
- @strangeman
|
||||
- @tleen
|
||||
- @tompao
|
||||
- @Tonkpils
|
||||
|
||||
### Based on
|
||||
|
||||
Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. - http://pine.fm/LearnToProgram/?Chapter=06
|
15
bob/bob.go
Normal file
15
bob/bob.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
// This is a "stub" file. It's a little start on your solution.
|
||||
// It's not a complete solution though; you have to write some code.
|
||||
|
||||
// Package bob should have a package comment that summarizes what it's about.
|
||||
// https://golang.org/doc/effective_go.html#commentary
|
||||
package bob
|
||||
|
||||
// Hey should have a comment documenting it.
|
||||
func Hey(remark string) string {
|
||||
// Write some code here to pass the test suite.
|
||||
// Then remove all the stock comments.
|
||||
// They're here to help you get started but they only clutter a finished solution.
|
||||
// If you leave them in, reviewers may protest!
|
||||
return ""
|
||||
}
|
28
bob/bob_test.go
Normal file
28
bob/bob_test.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package bob
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestHey(t *testing.T) {
|
||||
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 BenchmarkHey(b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, tt := range testCases {
|
||||
Hey(tt.input)
|
||||
}
|
||||
}
|
||||
}
|
137
bob/cases_test.go
Normal file
137
bob/cases_test.go
Normal file
|
@ -0,0 +1,137 @@
|
|||
package bob
|
||||
|
||||
// Source: exercism/problem-specifications
|
||||
// Commit: 1904e91 Bob: Cleans up language on a couple of test cases
|
||||
// Problem Specifications Version: 1.5.0
|
||||
|
||||
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",
|
||||
"Hi there!",
|
||||
"Whatever.",
|
||||
},
|
||||
{
|
||||
"using acronyms in regular speech",
|
||||
"It's OK if you don't want to go to the DMV.",
|
||||
"Whatever.",
|
||||
},
|
||||
{
|
||||
"forceful question",
|
||||
"WHAT'S GOING ON?",
|
||||
"Calm down, I know what I'm doing!",
|
||||
},
|
||||
{
|
||||
"shouting numbers",
|
||||
"1, 2, 3 GO!",
|
||||
"Whoa, chill out!",
|
||||
},
|
||||
{
|
||||
"no letters",
|
||||
"1, 2, 3",
|
||||
"Whatever.",
|
||||
},
|
||||
{
|
||||
"question with no letters",
|
||||
"4?",
|
||||
"Sure.",
|
||||
},
|
||||
{
|
||||
"shouting with special characters",
|
||||
"ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!",
|
||||
"Whoa, chill out!",
|
||||
},
|
||||
{
|
||||
"shouting with no exclamation mark",
|
||||
"I HATE THE DMV",
|
||||
"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",
|
||||
"Fine. Be that way!",
|
||||
},
|
||||
{
|
||||
"non-question ending with whitespace",
|
||||
"This is a statement ending with whitespace ",
|
||||
"Whatever.",
|
||||
},
|
||||
}
|
3
bob/go.mod
Normal file
3
bob/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module bob
|
||||
|
||||
go 1.16
|
22
bottle-song/.exercism/config.json
Normal file
22
bottle-song/.exercism/config.json
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"authors": [
|
||||
"PakkuDon"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"bottle_song.go"
|
||||
],
|
||||
"test": [
|
||||
"bottle_song_test.go"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.go"
|
||||
],
|
||||
"invalidator": [
|
||||
"go.mod"
|
||||
]
|
||||
},
|
||||
"blurb": "Produce the lyrics to the popular children's repetitive song: Ten Green Bottles.",
|
||||
"source": "Wikipedia",
|
||||
"source_url": "https://en.wikipedia.org/wiki/Ten_Green_Bottles"
|
||||
}
|
1
bottle-song/.exercism/metadata.json
Normal file
1
bottle-song/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"go","exercise":"bottle-song","id":"6f3ee5c29c9449c48f06d291e3d23ce4","url":"https://exercism.org/tracks/go/exercises/bottle-song","handle":"snowyforest","is_requester":true,"auto_approve":false}
|
41
bottle-song/HELP.md
Normal file
41
bottle-song/HELP.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
|
||||
flags:
|
||||
|
||||
go test -v --bench . --benchmem
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit bottle_song.go` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
|
||||
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, you can use one of the following resources:
|
||||
|
||||
- [How to Write Go Code](https://golang.org/doc/code.html)
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
- [Go Resources](http://golang.org/help)
|
||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
|
72
bottle-song/README.md
Normal file
72
bottle-song/README.md
Normal file
|
@ -0,0 +1,72 @@
|
|||
# Bottle Song
|
||||
|
||||
Welcome to Bottle Song on Exercism's Go Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
Recite the lyrics to that popular children's repetitive song: Ten Green Bottles.
|
||||
|
||||
Note that not all verses are identical.
|
||||
|
||||
```text
|
||||
Ten green bottles hanging on the wall,
|
||||
Ten green bottles hanging on the wall,
|
||||
And if one green bottle should accidentally fall,
|
||||
There'll be nine green bottles hanging on the wall.
|
||||
|
||||
Nine green bottles hanging on the wall,
|
||||
Nine green bottles hanging on the wall,
|
||||
And if one green bottle should accidentally fall,
|
||||
There'll be eight green bottles hanging on the wall.
|
||||
|
||||
Eight green bottles hanging on the wall,
|
||||
Eight green bottles hanging on the wall,
|
||||
And if one green bottle should accidentally fall,
|
||||
There'll be seven green bottles hanging on the wall.
|
||||
|
||||
Seven green bottles hanging on the wall,
|
||||
Seven green bottles hanging on the wall,
|
||||
And if one green bottle should accidentally fall,
|
||||
There'll be six green bottles hanging on the wall.
|
||||
|
||||
Six green bottles hanging on the wall,
|
||||
Six green bottles hanging on the wall,
|
||||
And if one green bottle should accidentally fall,
|
||||
There'll be five green bottles hanging on the wall.
|
||||
|
||||
Five green bottles hanging on the wall,
|
||||
Five green bottles hanging on the wall,
|
||||
And if one green bottle should accidentally fall,
|
||||
There'll be four green bottles hanging on the wall.
|
||||
|
||||
Four green bottles hanging on the wall,
|
||||
Four green bottles hanging on the wall,
|
||||
And if one green bottle should accidentally fall,
|
||||
There'll be three green bottles hanging on the wall.
|
||||
|
||||
Three green bottles hanging on the wall,
|
||||
Three green bottles hanging on the wall,
|
||||
And if one green bottle should accidentally fall,
|
||||
There'll be two green bottles hanging on the wall.
|
||||
|
||||
Two green bottles hanging on the wall,
|
||||
Two green bottles hanging on the wall,
|
||||
And if one green bottle should accidentally fall,
|
||||
There'll be one green bottle hanging on the wall.
|
||||
|
||||
One green bottle hanging on the wall,
|
||||
One green bottle hanging on the wall,
|
||||
And if one green bottle should accidentally fall,
|
||||
There'll be no green bottles hanging on the wall.
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @PakkuDon
|
||||
|
||||
### Based on
|
||||
|
||||
Wikipedia - https://en.wikipedia.org/wiki/Ten_Green_Bottles
|
5
bottle-song/bottle_song.go
Normal file
5
bottle-song/bottle_song.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
package bottlesong
|
||||
|
||||
func Recite(startBottles, takeDown int) []string {
|
||||
panic("Please implement the Recite function")
|
||||
}
|
78
bottle-song/bottle_song_test.go
Normal file
78
bottle-song/bottle_song_test.go
Normal file
|
@ -0,0 +1,78 @@
|
|||
package bottlesong
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
func TestRecite(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
actual := Recite(tc.input.startBottles, tc.input.takeDown)
|
||||
if !equal(actual, tc.expected) {
|
||||
t.Errorf("Recite(%d, %d) = %q, want: %q", tc.input.startBottles, tc.input.takeDown, actual, tc.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func equal(a, b []string) bool {
|
||||
if len(b) != len(a) {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(a) == 0 && len(b) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%v", a) == fmt.Sprintf("%v", b)
|
||||
}
|
||||
|
||||
// Title is a copy of strings.Title function of the stdlib.
|
||||
// The copy is here because strings.Title is deprecated but we still
|
||||
// want to use this function as the alternative would require us to support
|
||||
// external dependencies which we don't yet (tracking issue https://github.com/exercism/go/issues/2379).
|
||||
// Students should still be able to use strings.Title if they want.
|
||||
// Since this exercise is currently deprecated, this shouldn't matter too much.
|
||||
func Title(s string) string {
|
||||
// Use a closure here to remember state.
|
||||
// Hackish but effective. Depends on Map scanning in order and calling
|
||||
// the closure once per rune.
|
||||
prev := ' '
|
||||
return strings.Map(
|
||||
func(r rune) rune {
|
||||
if isSeparator(prev) {
|
||||
prev = r
|
||||
return unicode.ToTitle(r)
|
||||
}
|
||||
prev = r
|
||||
return r
|
||||
},
|
||||
s)
|
||||
}
|
||||
|
||||
// Copy of strings.isSeparator function of the stdlib.
|
||||
func isSeparator(r rune) bool {
|
||||
// ASCII alphanumerics and underscore are not separators
|
||||
if r <= 0x7F {
|
||||
switch {
|
||||
case '0' <= r && r <= '9':
|
||||
return false
|
||||
case 'a' <= r && r <= 'z':
|
||||
return false
|
||||
case 'A' <= r && r <= 'Z':
|
||||
return false
|
||||
case r == '_':
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
// Letters and digits are not separators
|
||||
if unicode.IsLetter(r) || unicode.IsDigit(r) {
|
||||
return false
|
||||
}
|
||||
// Otherwise, all we can do for now is treat spaces as separators.
|
||||
return unicode.IsSpace(r)
|
||||
}
|
75
bottle-song/cases_test.go
Normal file
75
bottle-song/cases_test.go
Normal file
|
@ -0,0 +1,75 @@
|
|||
package bottlesong
|
||||
|
||||
// This is an auto-generated file. Do not change it manually. Run the generator to update the file.
|
||||
// See https://github.com/exercism/go#synchronizing-tests-and-instructions
|
||||
// Source: exercism/problem-specifications
|
||||
// Commit: 472204b bottle-song: Reimplement test cases checking for "One green bottles" (#2102)
|
||||
|
||||
type bottleSongInput struct {
|
||||
startBottles int
|
||||
takeDown int
|
||||
}
|
||||
|
||||
var testCases = []struct {
|
||||
description string
|
||||
input bottleSongInput
|
||||
expected []string
|
||||
}{
|
||||
|
||||
{
|
||||
description: "first generic verse",
|
||||
input: bottleSongInput{
|
||||
startBottles: 10,
|
||||
takeDown: 1,
|
||||
},
|
||||
expected: []string{"Ten green bottles hanging on the wall,", "Ten green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be nine green bottles hanging on the wall."},
|
||||
},
|
||||
{
|
||||
description: "last generic verse",
|
||||
input: bottleSongInput{
|
||||
startBottles: 3,
|
||||
takeDown: 1,
|
||||
},
|
||||
expected: []string{"Three green bottles hanging on the wall,", "Three green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be two green bottles hanging on the wall."},
|
||||
},
|
||||
{
|
||||
description: "verse with 2 bottles",
|
||||
input: bottleSongInput{
|
||||
startBottles: 2,
|
||||
takeDown: 1,
|
||||
},
|
||||
expected: []string{"Two green bottles hanging on the wall,", "Two green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be one green bottle hanging on the wall."},
|
||||
},
|
||||
{
|
||||
description: "verse with 1 bottle",
|
||||
input: bottleSongInput{
|
||||
startBottles: 1,
|
||||
takeDown: 1,
|
||||
},
|
||||
expected: []string{"One green bottle hanging on the wall,", "One green bottle hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be no green bottles hanging on the wall."},
|
||||
},
|
||||
{
|
||||
description: "first two verses",
|
||||
input: bottleSongInput{
|
||||
startBottles: 10,
|
||||
takeDown: 2,
|
||||
},
|
||||
expected: []string{"Ten green bottles hanging on the wall,", "Ten green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be nine green bottles hanging on the wall.", "", "Nine green bottles hanging on the wall,", "Nine green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be eight green bottles hanging on the wall."},
|
||||
},
|
||||
{
|
||||
description: "last three verses",
|
||||
input: bottleSongInput{
|
||||
startBottles: 3,
|
||||
takeDown: 3,
|
||||
},
|
||||
expected: []string{"Three green bottles hanging on the wall,", "Three green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be two green bottles hanging on the wall.", "", "Two green bottles hanging on the wall,", "Two green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be one green bottle hanging on the wall.", "", "One green bottle hanging on the wall,", "One green bottle hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be no green bottles hanging on the wall."},
|
||||
},
|
||||
{
|
||||
description: "all verses",
|
||||
input: bottleSongInput{
|
||||
startBottles: 10,
|
||||
takeDown: 10,
|
||||
},
|
||||
expected: []string{"Ten green bottles hanging on the wall,", "Ten green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be nine green bottles hanging on the wall.", "", "Nine green bottles hanging on the wall,", "Nine green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be eight green bottles hanging on the wall.", "", "Eight green bottles hanging on the wall,", "Eight green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be seven green bottles hanging on the wall.", "", "Seven green bottles hanging on the wall,", "Seven green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be six green bottles hanging on the wall.", "", "Six green bottles hanging on the wall,", "Six green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be five green bottles hanging on the wall.", "", "Five green bottles hanging on the wall,", "Five green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be four green bottles hanging on the wall.", "", "Four green bottles hanging on the wall,", "Four green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be three green bottles hanging on the wall.", "", "Three green bottles hanging on the wall,", "Three green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be two green bottles hanging on the wall.", "", "Two green bottles hanging on the wall,", "Two green bottles hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be one green bottle hanging on the wall.", "", "One green bottle hanging on the wall,", "One green bottle hanging on the wall,", "And if one green bottle should accidentally fall,", "There'll be no green bottles hanging on the wall."},
|
||||
},
|
||||
}
|
3
bottle-song/go.mod
Normal file
3
bottle-song/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module bottlesong
|
||||
|
||||
go 1.18
|
34
circular-buffer/.exercism/config.json
Normal file
34
circular-buffer/.exercism/config.json
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"blurb": "A data structure that uses a single, fixed-size buffer as if it were connected end-to-end.",
|
||||
"authors": [
|
||||
"soniakeys"
|
||||
],
|
||||
"contributors": [
|
||||
"alebaffa",
|
||||
"bitfield",
|
||||
"dchapes",
|
||||
"ekingery",
|
||||
"ferhatelmas",
|
||||
"hilary",
|
||||
"kytrinyx",
|
||||
"leenipper",
|
||||
"manavo",
|
||||
"petertseng",
|
||||
"robphoenix",
|
||||
"sebito91",
|
||||
"tleen"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"circular_buffer.go"
|
||||
],
|
||||
"test": [
|
||||
"circular_buffer_test.go"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.go"
|
||||
]
|
||||
},
|
||||
"source": "Wikipedia",
|
||||
"source_url": "http://en.wikipedia.org/wiki/Circular_buffer"
|
||||
}
|
1
circular-buffer/.exercism/metadata.json
Normal file
1
circular-buffer/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"go","exercise":"circular-buffer","id":"76c656cd7d2640dd9702cc8d798d0741","url":"https://exercism.org/tracks/go/exercises/circular-buffer","handle":"snowyforest","is_requester":true,"auto_approve":false}
|
41
circular-buffer/HELP.md
Normal file
41
circular-buffer/HELP.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
|
||||
flags:
|
||||
|
||||
go test -v --bench . --benchmem
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit circular_buffer.go` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
|
||||
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, you can use one of the following resources:
|
||||
|
||||
- [How to Write Go Code](https://golang.org/doc/code.html)
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
- [Go Resources](http://golang.org/help)
|
||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
|
82
circular-buffer/README.md
Normal file
82
circular-buffer/README.md
Normal file
|
@ -0,0 +1,82 @@
|
|||
# Circular Buffer
|
||||
|
||||
Welcome to Circular Buffer on Exercism's Go Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
A circular buffer, cyclic buffer or ring buffer is a data structure that
|
||||
uses a single, fixed-size buffer as if it were connected end-to-end.
|
||||
|
||||
A circular buffer first starts empty and of some predefined length. For
|
||||
example, this is a 7-element buffer:
|
||||
<!-- prettier-ignore -->
|
||||
[ ][ ][ ][ ][ ][ ][ ]
|
||||
|
||||
Assume that a 1 is written into the middle of the buffer (exact starting
|
||||
location does not matter in a circular buffer):
|
||||
<!-- prettier-ignore -->
|
||||
[ ][ ][ ][1][ ][ ][ ]
|
||||
|
||||
Then assume that two more elements are added — 2 & 3 — which get
|
||||
appended after the 1:
|
||||
<!-- prettier-ignore -->
|
||||
[ ][ ][ ][1][2][3][ ]
|
||||
|
||||
If two elements are then removed from the buffer, the oldest values
|
||||
inside the buffer are removed. The two elements removed, in this case,
|
||||
are 1 & 2, leaving the buffer with just a 3:
|
||||
<!-- prettier-ignore -->
|
||||
[ ][ ][ ][ ][ ][3][ ]
|
||||
|
||||
If the buffer has 7 elements then it is completely full:
|
||||
<!-- prettier-ignore -->
|
||||
[5][6][7][8][9][3][4]
|
||||
|
||||
When the buffer is full an error will be raised, alerting the client
|
||||
that further writes are blocked until a slot becomes free.
|
||||
|
||||
When the buffer is full, the client can opt to overwrite the oldest
|
||||
data with a forced write. In this case, two more elements — A & B —
|
||||
are added and they overwrite the 3 & 4:
|
||||
<!-- prettier-ignore -->
|
||||
[5][6][7][8][9][A][B]
|
||||
|
||||
3 & 4 have been replaced by A & B making 5 now the oldest data in the
|
||||
buffer. Finally, if two elements are removed then what would be
|
||||
returned is 5 & 6 yielding the buffer:
|
||||
<!-- prettier-ignore -->
|
||||
[ ][ ][7][8][9][A][B]
|
||||
|
||||
Because there is space available, if the client again uses overwrite
|
||||
to store C & D then the space where 5 & 6 were stored previously will
|
||||
be used not the location of 7 & 8. 7 is still the oldest element and
|
||||
the buffer is once again full.
|
||||
<!-- prettier-ignore -->
|
||||
[C][D][7][8][9][A][B]
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @soniakeys
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @alebaffa
|
||||
- @bitfield
|
||||
- @dchapes
|
||||
- @ekingery
|
||||
- @ferhatelmas
|
||||
- @hilary
|
||||
- @kytrinyx
|
||||
- @leenipper
|
||||
- @manavo
|
||||
- @petertseng
|
||||
- @robphoenix
|
||||
- @sebito91
|
||||
- @tleen
|
||||
|
||||
### Based on
|
||||
|
||||
Wikipedia - http://en.wikipedia.org/wiki/Circular_buffer
|
30
circular-buffer/circular_buffer.go
Normal file
30
circular-buffer/circular_buffer.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package circular
|
||||
|
||||
// Implement a circular buffer of bytes supporting both overflow-checked writes
|
||||
// and unconditional, possibly overwriting, writes.
|
||||
//
|
||||
// We chose the provided API so that Buffer implements io.ByteReader
|
||||
// and io.ByteWriter and can be used (size permitting) as a drop in
|
||||
// replacement for anything using that interface.
|
||||
|
||||
// Define the Buffer type here.
|
||||
|
||||
func NewBuffer(size int) *Buffer {
|
||||
panic("Please implement the NewBuffer function")
|
||||
}
|
||||
|
||||
func (b *Buffer) ReadByte() (byte, error) {
|
||||
panic("Please implement the ReadByte function")
|
||||
}
|
||||
|
||||
func (b *Buffer) WriteByte(c byte) error {
|
||||
panic("Please implement the WriteByte function")
|
||||
}
|
||||
|
||||
func (b *Buffer) Overwrite(c byte) {
|
||||
panic("Please implement the Overwrite function")
|
||||
}
|
||||
|
||||
func (b *Buffer) Reset() {
|
||||
panic("Please implement the Reset function")
|
||||
}
|
199
circular-buffer/circular_buffer_test.go
Normal file
199
circular-buffer/circular_buffer_test.go
Normal file
|
@ -0,0 +1,199 @@
|
|||
package circular
|
||||
|
||||
import (
|
||||
"io"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Here is one way you can have a test case verify that the expected
|
||||
// interfaces are implemented.
|
||||
|
||||
var _ io.ByteReader = new(Buffer)
|
||||
var _ io.ByteWriter = new(Buffer)
|
||||
|
||||
// testBuffer and methods support the tests, providing log and fail messages.
|
||||
|
||||
type testBuffer struct {
|
||||
*testing.T
|
||||
b *Buffer
|
||||
}
|
||||
|
||||
func nb(size int, t *testing.T) testBuffer {
|
||||
t.Logf("NewBuffer(%d)", size)
|
||||
return testBuffer{t, NewBuffer(size)}
|
||||
}
|
||||
|
||||
func (tb testBuffer) read(want byte) {
|
||||
switch c, err := tb.b.ReadByte(); {
|
||||
case err != nil:
|
||||
var _ error = err
|
||||
tb.Fatalf("ReadByte() failed unexpectedly: %v", err)
|
||||
case c != want:
|
||||
tb.Fatalf("ReadByte() = %c, want %c.", c, want)
|
||||
}
|
||||
tb.Logf("ReadByte %c", want)
|
||||
}
|
||||
|
||||
func (tb testBuffer) readFail() {
|
||||
c, err := tb.b.ReadByte()
|
||||
if err == nil {
|
||||
tb.Fatalf("ReadByte() = %c, expected a failure", c)
|
||||
}
|
||||
var _ error = err
|
||||
tb.Log("ReadByte() fails as expected")
|
||||
}
|
||||
|
||||
func (tb testBuffer) write(c byte) {
|
||||
if err := tb.b.WriteByte(c); err != nil {
|
||||
var _ error = err
|
||||
tb.Fatalf("WriteByte(%c) failed unexpectedly: %v", c, err)
|
||||
}
|
||||
tb.Logf("WriteByte(%c)", c)
|
||||
}
|
||||
|
||||
func (tb testBuffer) writeFail(c byte) {
|
||||
err := tb.b.WriteByte(c)
|
||||
if err == nil {
|
||||
tb.Fatalf("WriteByte(%c) succeeded, expected a failure", c)
|
||||
}
|
||||
var _ error = err
|
||||
tb.Logf("WriteByte(%c) fails as expected", c)
|
||||
}
|
||||
|
||||
func (tb testBuffer) reset() {
|
||||
tb.b.Reset()
|
||||
tb.Log("Reset()")
|
||||
}
|
||||
|
||||
func (tb testBuffer) overwrite(c byte) {
|
||||
tb.b.Overwrite(c)
|
||||
tb.Logf("Overwrite(%c)", c)
|
||||
}
|
||||
|
||||
// tests. separate functions so log will have descriptive test name.
|
||||
|
||||
func TestReadEmptyBuffer(t *testing.T) {
|
||||
tb := nb(1, t)
|
||||
tb.readFail()
|
||||
}
|
||||
|
||||
func TestWriteAndReadOneItem(t *testing.T) {
|
||||
tb := nb(1, t)
|
||||
tb.write('1')
|
||||
tb.read('1')
|
||||
tb.readFail()
|
||||
}
|
||||
|
||||
func TestWriteAndReadMultipleItems(t *testing.T) {
|
||||
tb := nb(2, t)
|
||||
tb.write('1')
|
||||
tb.write('2')
|
||||
tb.read('1')
|
||||
tb.read('2')
|
||||
tb.readFail()
|
||||
}
|
||||
|
||||
func TestReset(t *testing.T) {
|
||||
tb := nb(3, t)
|
||||
tb.write('1')
|
||||
tb.write('2')
|
||||
tb.write('3')
|
||||
tb.reset()
|
||||
tb.write('1')
|
||||
tb.write('3')
|
||||
tb.read('1')
|
||||
tb.write('4')
|
||||
tb.read('3')
|
||||
}
|
||||
|
||||
func TestAlternateWriteAndRead(t *testing.T) {
|
||||
tb := nb(2, t)
|
||||
tb.write('1')
|
||||
tb.read('1')
|
||||
tb.write('2')
|
||||
tb.read('2')
|
||||
}
|
||||
|
||||
func TestReadOldestItem(t *testing.T) {
|
||||
tb := nb(3, t)
|
||||
tb.write('1')
|
||||
tb.write('2')
|
||||
tb.read('1')
|
||||
tb.write('3')
|
||||
tb.read('2')
|
||||
tb.read('3')
|
||||
}
|
||||
|
||||
func TestWriteFullBuffer(t *testing.T) {
|
||||
tb := nb(2, t)
|
||||
tb.write('1')
|
||||
tb.write('2')
|
||||
tb.writeFail('A')
|
||||
}
|
||||
|
||||
func TestOverwriteFull(t *testing.T) {
|
||||
tb := nb(2, t)
|
||||
tb.write('1')
|
||||
tb.write('2')
|
||||
tb.overwrite('A')
|
||||
tb.read('2')
|
||||
tb.read('A')
|
||||
tb.readFail()
|
||||
}
|
||||
|
||||
func TestOverwriteNonFull(t *testing.T) {
|
||||
tb := nb(2, t)
|
||||
tb.write('1')
|
||||
tb.overwrite('2')
|
||||
tb.read('1')
|
||||
tb.read('2')
|
||||
tb.readFail()
|
||||
}
|
||||
|
||||
func TestAlternateReadAndOverwrite(t *testing.T) {
|
||||
tb := nb(5, t)
|
||||
tb.write('1')
|
||||
tb.write('2')
|
||||
tb.write('3')
|
||||
tb.read('1')
|
||||
tb.read('2')
|
||||
tb.write('4')
|
||||
tb.read('3')
|
||||
tb.write('5')
|
||||
tb.write('6')
|
||||
tb.write('7')
|
||||
tb.write('8')
|
||||
tb.overwrite('A')
|
||||
tb.overwrite('B')
|
||||
tb.read('6')
|
||||
tb.read('7')
|
||||
tb.read('8')
|
||||
tb.read('A')
|
||||
tb.read('B')
|
||||
tb.readFail()
|
||||
}
|
||||
|
||||
func BenchmarkOverwrite(b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
c := NewBuffer(100)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.Overwrite(0)
|
||||
}
|
||||
b.SetBytes(int64(b.N))
|
||||
}
|
||||
|
||||
func BenchmarkWriteRead(b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
c := NewBuffer(100)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.WriteByte(0)
|
||||
c.ReadByte()
|
||||
}
|
||||
b.SetBytes(int64(b.N))
|
||||
}
|
3
circular-buffer/go.mod
Normal file
3
circular-buffer/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module standard
|
||||
|
||||
go 1.16
|
41
clock/.exercism/config.json
Normal file
41
clock/.exercism/config.json
Normal file
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"blurb": "Implement a clock that handles times without dates.",
|
||||
"authors": [
|
||||
"soniakeys"
|
||||
],
|
||||
"contributors": [
|
||||
"alebaffa",
|
||||
"bitfield",
|
||||
"cwithmichael",
|
||||
"da-edra",
|
||||
"dmgawel",
|
||||
"ekingery",
|
||||
"ferhatelmas",
|
||||
"hilary",
|
||||
"kytrinyx",
|
||||
"leenipper",
|
||||
"nywilken",
|
||||
"petertseng",
|
||||
"pminten",
|
||||
"robphoenix",
|
||||
"sebito91",
|
||||
"thenickcox",
|
||||
"tleen"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"clock.go"
|
||||
],
|
||||
"test": [
|
||||
"clock_test.go"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.go"
|
||||
],
|
||||
"editor": [
|
||||
"cases_test.go"
|
||||
]
|
||||
},
|
||||
"source": "Pairing session with Erin Drummond",
|
||||
"source_url": "https://twitter.com/ebdrummond"
|
||||
}
|
1
clock/.exercism/metadata.json
Normal file
1
clock/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"track":"go","exercise":"clock","id":"8e3ecc7d2fc64c52b15e61434cd99094","url":"https://exercism.org/tracks/go/exercises/clock","handle":"snowyforest","is_requester":true,"auto_approve":false}
|
41
clock/HELP.md
Normal file
41
clock/HELP.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
|
||||
flags:
|
||||
|
||||
go test -v --bench . --benchmem
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit clock.go` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
|
||||
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, you can use one of the following resources:
|
||||
|
||||
- [How to Write Go Code](https://golang.org/doc/code.html)
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
- [Go Resources](http://golang.org/help)
|
||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
|
58
clock/README.md
Normal file
58
clock/README.md
Normal file
|
@ -0,0 +1,58 @@
|
|||
# Clock
|
||||
|
||||
Welcome to Clock on Exercism's Go Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
Implement a clock that handles times without dates.
|
||||
|
||||
You should be able to add and subtract minutes to it.
|
||||
|
||||
Two clocks that represent the same time should be equal to each other.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
To satisfy the requirement in the instructions about clocks being equal, values of
|
||||
your Clock type need to work with the == operator. This means that if your
|
||||
New function returns a pointer rather than a value, your clocks will
|
||||
probably not work with ==.
|
||||
|
||||
While the time.Time type in the standard library (https://golang.org/pkg/time/#Time)
|
||||
doesn't necessarily need to be used as a basis for your Clock type, it might
|
||||
help to look at how constructors there (Date and Now) return values rather
|
||||
than pointers. Note also how most time.Time methods have value receivers
|
||||
rather than pointer receivers.
|
||||
|
||||
For some useful guidelines on when to use a value receiver or a pointer
|
||||
receiver see: https://github.com/golang/go/wiki/CodeReviewComments#receiver-type
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @soniakeys
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @alebaffa
|
||||
- @bitfield
|
||||
- @cwithmichael
|
||||
- @da-edra
|
||||
- @dmgawel
|
||||
- @ekingery
|
||||
- @ferhatelmas
|
||||
- @hilary
|
||||
- @kytrinyx
|
||||
- @leenipper
|
||||
- @nywilken
|
||||
- @petertseng
|
||||
- @pminten
|
||||
- @robphoenix
|
||||
- @sebito91
|
||||
- @thenickcox
|
||||
- @tleen
|
||||
|
||||
### Based on
|
||||
|
||||
Pairing session with Erin Drummond - https://twitter.com/ebdrummond
|
167
clock/cases_test.go
Normal file
167
clock/cases_test.go
Normal file
|
@ -0,0 +1,167 @@
|
|||
package clock
|
||||
|
||||
// Source: exercism/problem-specifications
|
||||
// Commit: b344762 clock: Add test case for exactly negative sixty minutes.
|
||||
// Problem Specifications Version: 2.4.0
|
||||
|
||||
// Create a new clock with an initial time
|
||||
var timeTests = []struct {
|
||||
h, m int
|
||||
want string
|
||||
}{
|
||||
{8, 0, "08:00"}, // on the hour
|
||||
{11, 9, "11:09"}, // past the hour
|
||||
{24, 0, "00:00"}, // midnight is zero hours
|
||||
{25, 0, "01:00"}, // hour rolls over
|
||||
{100, 0, "04:00"}, // hour rolls over continuously
|
||||
{1, 60, "02:00"}, // sixty minutes is next hour
|
||||
{0, 160, "02:40"}, // minutes roll over
|
||||
{0, 1723, "04:43"}, // minutes roll over continuously
|
||||
{25, 160, "03:40"}, // hour and minutes roll over
|
||||
{201, 3001, "11:01"}, // hour and minutes roll over continuously
|
||||
{72, 8640, "00:00"}, // hour and minutes roll over to exactly midnight
|
||||
{-1, 15, "23:15"}, // negative hour
|
||||
{-25, 0, "23:00"}, // negative hour rolls over
|
||||
{-91, 0, "05:00"}, // negative hour rolls over continuously
|
||||
{1, -40, "00:20"}, // negative minutes
|
||||
{1, -160, "22:20"}, // negative minutes roll over
|
||||
{1, -4820, "16:40"}, // negative minutes roll over continuously
|
||||
{2, -60, "01:00"}, // negative sixty minutes is previous hour
|
||||
{-25, -160, "20:20"}, // negative hour and minutes both roll over
|
||||
{-121, -5810, "22:10"}, // negative hour and minutes both roll over continuously
|
||||
}
|
||||
|
||||
// Add minutes
|
||||
var addTests = []struct {
|
||||
h, m, a int
|
||||
want string
|
||||
}{
|
||||
{10, 0, 3, "10:03"}, // add minutes
|
||||
{6, 41, 0, "06:41"}, // add no minutes
|
||||
{0, 45, 40, "01:25"}, // add to next hour
|
||||
{10, 0, 61, "11:01"}, // add more than one hour
|
||||
{0, 45, 160, "03:25"}, // add more than two hours with carry
|
||||
{23, 59, 2, "00:01"}, // add across midnight
|
||||
{5, 32, 1500, "06:32"}, // add more than one day (1500 min = 25 hrs)
|
||||
{1, 1, 3500, "11:21"}, // add more than two days
|
||||
}
|
||||
|
||||
// Subtract minutes
|
||||
var subtractTests = []struct {
|
||||
h, m, a int
|
||||
want string
|
||||
}{
|
||||
{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
|
||||
{6, 15, 160, "03:35"}, // subtract more than two hours with borrow
|
||||
{5, 32, 1500, "04:32"}, // subtract more than one day (1500 min = 25 hrs)
|
||||
{2, 20, 3000, "00:20"}, // subtract more than two days
|
||||
}
|
||||
|
||||
// Compare two clocks for equality
|
||||
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 with hour overflow
|
||||
{
|
||||
hm{10, 37},
|
||||
hm{34, 37},
|
||||
true,
|
||||
},
|
||||
// clocks with hour overflow by several days
|
||||
{
|
||||
hm{3, 11},
|
||||
hm{99, 11},
|
||||
true,
|
||||
},
|
||||
// clocks with negative hour
|
||||
{
|
||||
hm{22, 40},
|
||||
hm{-2, 40},
|
||||
true,
|
||||
},
|
||||
// clocks with negative hour that wraps
|
||||
{
|
||||
hm{17, 3},
|
||||
hm{-31, 3},
|
||||
true,
|
||||
},
|
||||
// clocks with negative hour that wraps multiple times
|
||||
{
|
||||
hm{13, 49},
|
||||
hm{-83, 49},
|
||||
true,
|
||||
},
|
||||
// clocks with minute overflow
|
||||
{
|
||||
hm{0, 1},
|
||||
hm{0, 1441},
|
||||
true,
|
||||
},
|
||||
// clocks with minute overflow by several days
|
||||
{
|
||||
hm{2, 2},
|
||||
hm{2, 4322},
|
||||
true,
|
||||
},
|
||||
// clocks with negative minute
|
||||
{
|
||||
hm{2, 40},
|
||||
hm{3, -20},
|
||||
true,
|
||||
},
|
||||
// clocks with negative minute that wraps
|
||||
{
|
||||
hm{4, 10},
|
||||
hm{5, -1490},
|
||||
true,
|
||||
},
|
||||
// clocks with negative minute that wraps multiple times
|
||||
{
|
||||
hm{6, 15},
|
||||
hm{6, -4305},
|
||||
true,
|
||||
},
|
||||
// clocks with negative hours and minutes
|
||||
{
|
||||
hm{7, 32},
|
||||
hm{-12, -268},
|
||||
true,
|
||||
},
|
||||
// clocks with negative hours and minutes that wrap
|
||||
{
|
||||
hm{18, 7},
|
||||
hm{-54, -11513},
|
||||
true,
|
||||
},
|
||||
// full clock and zeroed clock
|
||||
{
|
||||
hm{24, 0},
|
||||
hm{0, 0},
|
||||
true,
|
||||
},
|
||||
}
|
19
clock/clock.go
Normal file
19
clock/clock.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
package clock
|
||||
|
||||
// Define the Clock type here.
|
||||
|
||||
func New(h, m int) Clock {
|
||||
panic("Please implement the New function")
|
||||
}
|
||||
|
||||
func (c Clock) Add(m int) Clock {
|
||||
panic("Please implement the Add function")
|
||||
}
|
||||
|
||||
func (c Clock) Subtract(m int) Clock {
|
||||
panic("Please implement the Subtract function")
|
||||
}
|
||||
|
||||
func (c Clock) String() string {
|
||||
panic("Please implement the String function")
|
||||
}
|
146
clock/clock_test.go
Normal file
146
clock/clock_test.go
Normal file
|
@ -0,0 +1,146 @@
|
|||
package clock
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCreateClock(t *testing.T) {
|
||||
for _, n := range timeTests {
|
||||
if got := New(n.h, n.m); got.String() != n.want {
|
||||
t.Fatalf("New(%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 := New(a.h, a.m).Add(a.a); got.String() != a.want {
|
||||
t.Fatalf("New(%d, %d).Add(%d) = %q, want %q",
|
||||
a.h, a.m, a.a, got, a.want)
|
||||
}
|
||||
}
|
||||
t.Log(len(addTests), "test cases")
|
||||
}
|
||||
|
||||
func TestSubtractMinutes(t *testing.T) {
|
||||
for _, a := range subtractTests {
|
||||
if got := New(a.h, a.m).Subtract(a.a); got.String() != a.want {
|
||||
t.Fatalf("New(%d, %d).Subtract(%d) = %q, want %q",
|
||||
a.h, a.m, a.a, got, a.want)
|
||||
}
|
||||
}
|
||||
t.Log(len(subtractTests), "test cases")
|
||||
}
|
||||
|
||||
func TestAddMinutesStringless(t *testing.T) {
|
||||
for _, a := range addTests {
|
||||
var wantHour, wantMin int
|
||||
split := strings.SplitN(a.want, ":", 2)
|
||||
if len(split) > 0 {
|
||||
wantHour, _ = strconv.Atoi(split[0])
|
||||
}
|
||||
if len(split) > 1 {
|
||||
wantMin, _ = strconv.Atoi(split[1])
|
||||
}
|
||||
want := New(wantHour, wantMin)
|
||||
if got := New(a.h, a.m).Add(a.a); !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("New(%d, %d).Add(%d) = %v, want %v",
|
||||
a.h, a.m, a.a, got, want)
|
||||
}
|
||||
}
|
||||
t.Log(len(addTests), "test cases")
|
||||
}
|
||||
|
||||
func TestSubtractMinutesStringless(t *testing.T) {
|
||||
for _, a := range subtractTests {
|
||||
var wantHour, wantMin int
|
||||
split := strings.SplitN(a.want, ":", 2)
|
||||
if len(split) > 0 {
|
||||
wantHour, _ = strconv.Atoi(split[0])
|
||||
}
|
||||
if len(split) > 1 {
|
||||
wantMin, _ = strconv.Atoi(split[1])
|
||||
}
|
||||
want := New(wantHour, wantMin)
|
||||
if got := New(a.h, a.m).Subtract(a.a); !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("New(%d, %d).Subtract(%d) = %v, want %v",
|
||||
a.h, a.m, a.a, got, want)
|
||||
}
|
||||
}
|
||||
t.Log(len(subtractTests), "test cases")
|
||||
}
|
||||
|
||||
func TestCompareClocks(t *testing.T) {
|
||||
for _, e := range eqTests {
|
||||
clock1 := New(e.c1.h, e.c1.m)
|
||||
clock2 := New(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")
|
||||
}
|
||||
|
||||
func TestAddAndCompare(t *testing.T) {
|
||||
clock1 := New(15, 45).Add(16)
|
||||
clock2 := New(16, 1)
|
||||
if !reflect.DeepEqual(clock1, clock2) {
|
||||
t.Errorf("clock.New(15,45).Add(16) differs from clock.New(16,1)")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubtractAndCompare(t *testing.T) {
|
||||
clock1 := New(16, 1).Subtract(16)
|
||||
clock2 := New(15, 45)
|
||||
if !reflect.DeepEqual(clock1, clock2) {
|
||||
t.Errorf("clock.New(16,1).Subtract(16) differs from clock.New(15,45)")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAddMinutes(b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
c := New(12, 0)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, a := range addTests {
|
||||
c.Add(a.a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSubtractMinutes(b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
c := New(12, 0)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, a := range subtractTests {
|
||||
c.Subtract(a.a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCreateClocks(b *testing.B) {
|
||||
if testing.Short() {
|
||||
b.Skip("skipping benchmark in short mode.")
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, n := range timeTests {
|
||||
New(n.h, n.m)
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue