diff --git a/go/hello-world/README.md b/go/hello-world/README.md new file mode 100644 index 0000000000000000000000000000000000000000..13dd5c878ba6ec33ec5973b01a67da3c4fb9ccba --- /dev/null +++ b/go/hello-world/README.md @@ -0,0 +1,44 @@ +# Hello World + +The classical introductory exercise. Just say "Hello, World!". + +["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is +the traditional first program for beginning programming in a new language +or environment. + +The objectives are simple: + +- Write a function that returns the string "Hello, World!". +- Run the test suite and make sure that it succeeds. +- Submit your solution and check it at the website. + +If everything goes well, you will be ready to fetch your first real exercise. + +## Coding the solution + +Look for a stub file having the name hello_world.go +and place your solution code in that file. + +## 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. + +## Further information + +For more detailed information about the Go track, including how to get help if +you're having trouble, please visit the exercism.io [Go language page](http://exercism.io/languages/go/resources). + +## Source + +This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/go/hello-world/go.mod b/go/hello-world/go.mod new file mode 100644 index 0000000000000000000000000000000000000000..5bfa5f67dd59d121636f3996f0273e3d43a8d562 --- /dev/null +++ b/go/hello-world/go.mod @@ -0,0 +1,3 @@ +module greeting + +go 1.13 diff --git a/go/hello-world/hello_world.go b/go/hello-world/hello_world.go new file mode 100644 index 0000000000000000000000000000000000000000..b9b4eb19ad49530bd793d8f4106864c70058b94f --- /dev/null +++ b/go/hello-world/hello_world.go @@ -0,0 +1,8 @@ +// Provides the string of Hello, World! +// +package greeting + +// HelloWorld returns the greeting string. +func HelloWorld() string { + return "Hello, World!" +} diff --git a/go/hello-world/hello_world_test.go b/go/hello-world/hello_world_test.go new file mode 100644 index 0000000000000000000000000000000000000000..bf6cb90455e91fa5d3fe14fd2eaa3d0380781d6c --- /dev/null +++ b/go/hello-world/hello_world_test.go @@ -0,0 +1,37 @@ +package greeting + +import "testing" + +// Define a function named HelloWorld that takes no arguments, +// and returns a string. +// In other words, define a function with the following signature: +// HelloWorld() string + +func TestHelloWorld(t *testing.T) { + expected := "Hello, World!" + if observed := HelloWorld(); observed != expected { + t.Fatalf("HelloWorld() = %v, want %v", observed, expected) + } +} + +// BenchmarkHelloWorld() is a benchmarking function. These functions follow the +// form `func BenchmarkXxx(*testing.B)` and can be used to test the performance +// of your implementation. They may not be present in every exercise, but when +// they are you can run them by including the `-bench` flag with the `go test` +// command, like so: `go test -v --bench . --benchmem` +// +// You will see output similar to the following: +// +// BenchmarkHelloWorld 2000000000 0.46 ns/op +// +// This means that the loop ran 2000000000 times at a speed of 0.46 ns per loop. +// +// While benchmarking can be useful to compare different iterations of the same +// exercise, keep in mind that others will run the same benchmarks on different +// machines, with different specs, so the results from these benchmark tests may +// vary. +func BenchmarkHelloWorld(b *testing.B) { + for i := 0; i < b.N; i++ { + HelloWorld() + } +} diff --git a/go/leap/README.md b/go/leap/README.md new file mode 100644 index 0000000000000000000000000000000000000000..84ba77428ca093a054e70045b5d020522ac07d5c --- /dev/null +++ b/go/leap/README.md @@ -0,0 +1,69 @@ +# Leap + +Given a year, report if it is a leap year. + +The tricky thing here is that a leap year in the Gregorian calendar occurs: + +```text +on every year that is evenly divisible by 4 + except every year that is evenly divisible by 100 + unless the year is also evenly divisible by 400 +``` + +For example, 1997 is not a leap year, but 1996 is. 1900 is not a leap +year, but 2000 is. + +## Notes + +Though our exercise adopts some very simple rules, there is more to +learn! + +For a delightful, four minute explanation of the whole leap year +phenomenon, go watch [this youtube video][video]. + +[video]: http://www.youtube.com/watch?v=xX96xng7sAE + +You will see a `cases_test.go` file in this exercise. This holds the test +cases used in the `leap_test.go`. You can mostly ignore this file. + +However, if you are interested... we sometimes generate the test data from a +[cross language repository][problem-specifications-leap]. In that repo +exercises may have a [.json file][problem-specifications-leap-json] that +contains common test data. Some of our local exercises have an +[intermediary program][local-leap-gen] that takes the problem specification +JSON and turns in into Go structs that are fed into the `<exercise>_test.go` +file. The Go specific transformation of that data lives in the `cases_test.go` file. + +[problem-specifications-leap]: https://github.com/exercism/problem-specifications/tree/master/exercises/leap +[problem-specifications-leap-json]: https://github.com/exercism/problem-specifications/blob/master/exercises/leap/canonical-data.json +[local-leap-gen]: https://github.com/exercism/go/blob/master/exercises/leap/.meta/gen.go + + +## Coding the solution + +Look for a stub file having the name leap.go +and place your solution code in that file. + +## 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. + +## Further information + +For more detailed information about the Go track, including how to get help if +you're having trouble, please visit the exercism.io [Go language page](http://exercism.io/languages/go/resources). + +## Source + +JavaRanch Cattle Drive, exercise 3 [http://www.javaranch.com/leap.jsp](http://www.javaranch.com/leap.jsp) + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/go/leap/cases_test.go b/go/leap/cases_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f9e8c04b3e84eb6651f7c78ec62d9916669e53ce --- /dev/null +++ b/go/leap/cases_test.go @@ -0,0 +1,18 @@ +package leap + +// Source: exercism/problem-specifications +// Commit: 18875ec Leap: Improve the specification so that code generation is more readable - … (#1468) +// Problem Specifications Version: 1.5.1 + +var testCases = []struct { + year int + expected bool + description string +}{ + {2015, false, "year not divisible by 4 in common year"}, + {1970, false, "year divisible by 2, not divisible by 4 in common year"}, + {1996, true, "year divisible by 4, not divisible by 100 in leap year"}, + {2100, false, "year divisible by 100, not divisible by 400 in common year"}, + {2000, true, "year divisible by 400 in leap year"}, + {1800, false, "year divisible by 200, not divisible by 400 in common year"}, +} diff --git a/go/leap/go.mod b/go/leap/go.mod new file mode 100644 index 0000000000000000000000000000000000000000..bdbf06a932faef149b406aa1dd61da1ba89de74d --- /dev/null +++ b/go/leap/go.mod @@ -0,0 +1,3 @@ +module leap + +go 1.13 diff --git a/go/leap/leap.go b/go/leap/leap.go new file mode 100644 index 0000000000000000000000000000000000000000..fab698bf9eb0f911ecd30ecad8f9210e4cc3c5d9 --- /dev/null +++ b/go/leap/leap.go @@ -0,0 +1,7 @@ +//Package leap calculates leap years. +package leap + +//IsLeapYear takes in a year and returns its leap status. +func IsLeapYear(year int) bool { + return (year%4 == 0) && (year%100 > 0 || year%400 == 0) +} diff --git a/go/leap/leap_test.go b/go/leap/leap_test.go new file mode 100644 index 0000000000000000000000000000000000000000..eabd1f2c3b9a8b44578fd33f6c7df8f3f046198e --- /dev/null +++ b/go/leap/leap_test.go @@ -0,0 +1,22 @@ +package leap + +import "testing" + +func TestLeapYears(t *testing.T) { + for _, test := range testCases { + observed := IsLeapYear(test.year) + if observed != test.expected { + t.Fatalf("IsLeapYear(%d) = %t, want %t (%s)", + test.year, observed, test.expected, test.description) + } + } +} + +// Benchmark 400 year interval to get fair weighting of different years. +func Benchmark400(b *testing.B) { + for i := 0; i < b.N; i++ { + for y := 1600; y < 2000; y++ { + IsLeapYear(y) + } + } +} diff --git a/go/proverb/README.md b/go/proverb/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8248182a9b1172a763910fb59606ae5f9e5774b8 --- /dev/null +++ b/go/proverb/README.md @@ -0,0 +1,46 @@ +# Proverb + +For want of a horseshoe nail, a kingdom was lost, or so the saying goes. + +Given a list of inputs, generate the relevant proverb. For example, given the list `["nail", "shoe", "horse", "rider", "message", "battle", "kingdom"]`, you will output the full text of this proverbial rhyme: + +```text +For want of a nail the shoe was lost. +For want of a shoe the horse was lost. +For want of a horse the rider was lost. +For want of a rider the message was lost. +For want of a message the battle was lost. +For want of a battle the kingdom was lost. +And all for the want of a nail. +``` + +Note that the list of inputs may vary; your solution should be able to handle lists of arbitrary length and content. No line of the output text should be a static, unchanging string; all should vary according to the input given. + +## Coding the solution + +Look for a stub file having the name proverb.go +and place your solution code in that file. + +## 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. + +## Further information + +For more detailed information about the Go track, including how to get help if +you're having trouble, please visit the exercism.io [Go language page](http://exercism.io/languages/go/resources). + +## Source + +Wikipedia [http://en.wikipedia.org/wiki/For_Want_of_a_Nail](http://en.wikipedia.org/wiki/For_Want_of_a_Nail) + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/go/proverb/cases_test.go b/go/proverb/cases_test.go new file mode 100644 index 0000000000000000000000000000000000000000..53e2fb512ff60964737df101418193118ee801bb --- /dev/null +++ b/go/proverb/cases_test.go @@ -0,0 +1,44 @@ +package proverb + +// Source: exercism/problem-specifications +// Commit: e86e97a proverb: apply "input" policy +// Problem Specifications Version: 1.1.0 + +type proverbTest struct { + description string + input []string + expected []string +} + +var stringTestCases = []proverbTest{ + { + description: "zero pieces", + input: []string{}, + expected: []string{}, + }, + { + description: "one piece", + input: []string{"nail"}, + expected: []string{"And all for the want of a nail."}, + }, + { + description: "two pieces", + input: []string{"nail", "shoe"}, + expected: []string{"For want of a nail the shoe was lost.", "And all for the want of a nail."}, + }, + { + description: "three pieces", + input: []string{"nail", "shoe", "horse"}, + expected: []string{"For want of a nail the shoe was lost.", "For want of a shoe the horse was lost.", "And all for the want of a nail."}, + }, + { + description: "full proverb", + input: []string{"nail", "shoe", "horse", "rider", "message", "battle", "kingdom"}, + expected: []string{"For want of a nail the shoe was lost.", "For want of a shoe the horse was lost.", "For want of a horse the rider was lost.", "For want of a rider the message was lost.", "For want of a message the battle was lost.", "For want of a battle the kingdom was lost.", "And all for the want of a nail."}, + }, + { + description: "four pieces modernized", + input: []string{"pin", "gun", "soldier", "battle"}, + expected: []string{"For want of a pin the gun was lost.", "For want of a gun the soldier was lost.", "For want of a soldier the battle was lost.", "And all for the want of a pin."}, + }, +} diff --git a/go/proverb/go.mod b/go/proverb/go.mod new file mode 100644 index 0000000000000000000000000000000000000000..c3f938fe7cb4f20346c487403ce9e747ab9e9afa --- /dev/null +++ b/go/proverb/go.mod @@ -0,0 +1,3 @@ +module proverb + +go 1.13 diff --git a/go/proverb/proverb.go b/go/proverb/proverb.go new file mode 100644 index 0000000000000000000000000000000000000000..8af59ff7c8f4385761ede1c23ebc8271c9c6ae9c --- /dev/null +++ b/go/proverb/proverb.go @@ -0,0 +1,23 @@ +//Package proverb pens proverb rhyme. +package proverb + +import "fmt" + +//Proverb returns the string for the proverb. +func Proverb(rhyme []string) []string { + if len(rhyme) == 0 { + return []string{} + } + + var lastStr = fmt.Sprintf("And all for the want of a %s.", rhyme[0]) + retVal := []string{} + + if len(rhyme) > 1 { + for i := 0; i+1 < len(rhyme); i++ { + s := fmt.Sprintf("For want of a %s the %s was lost.", rhyme[i], rhyme[i+1]) + retVal = append(retVal, s) + } + } + retVal = append(retVal, lastStr) + return retVal +} diff --git a/go/proverb/proverb_test.go b/go/proverb/proverb_test.go new file mode 100644 index 0000000000000000000000000000000000000000..46b9dcc9ee1b734a7a2dc23bacb60043d4515c83 --- /dev/null +++ b/go/proverb/proverb_test.go @@ -0,0 +1,25 @@ +package proverb + +import ( + "fmt" + "testing" +) + +func TestProverb(t *testing.T) { + for _, test := range stringTestCases { + actual := Proverb(test.input) + if fmt.Sprintf("%q", actual) != fmt.Sprintf("%q", test.expected) { + t.Fatalf("FAIL %s - Proverb test [%s]\n\texpected: [%s],\n\tactual: [%s]", + test.description, test.input, test.expected, actual) + } + t.Logf("PASS %s", test.description) + } +} + +func BenchmarkProverb(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, test := range stringTestCases { + Proverb(test.input) + } + } +} diff --git a/go/space-age/README.md b/go/space-age/README.md new file mode 100644 index 0000000000000000000000000000000000000000..0ebf7a59a4b6655f9cb974f1cb25f33889272a21 --- /dev/null +++ b/go/space-age/README.md @@ -0,0 +1,64 @@ +# Space Age + +Given an age in seconds, calculate how old someone would be on: + + - Mercury: orbital period 0.2408467 Earth years + - Venus: orbital period 0.61519726 Earth years + - Earth: orbital period 1.0 Earth years, 365.25 Earth days, or 31557600 seconds + - Mars: orbital period 1.8808158 Earth years + - Jupiter: orbital period 11.862615 Earth years + - Saturn: orbital period 29.447498 Earth years + - Uranus: orbital period 84.016846 Earth years + - Neptune: orbital period 164.79132 Earth years + +So if you were told someone were 1,000,000,000 seconds old, you should +be able to say that they're 31.69 Earth-years old. + +If you're wondering why Pluto didn't make the cut, go watch [this +youtube video](http://www.youtube.com/watch?v=Z_2gbGXzFbs). + +## Simple Stub + +The space_age.go "stub file" contains only one line with the correct +package name and nothing more. This will be the usual pattern for future +exercises. You will need to figure out the function signature(s). + +One way to figure out the function signature(s) is to look +at the corresponding \*\_test.go file. It will show the package level +functions(s) that the test will use to verify the solution. + +## Planet Type + +The test cases make use of a custom `Planet` type that is sent to your function. +You will need to implement this custom type yourself. +Implementing this new custom type as a string should suffice. + + +## Coding the solution + +Look for a stub file having the name space_age.go +and place your solution code in that file. + +## 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. + +## Further information + +For more detailed information about the Go track, including how to get help if +you're having trouble, please visit the exercism.io [Go language page](http://exercism.io/languages/go/resources). + +## Source + +Partially inspired by Chapter 1 in Chris Pine's online Learn to Program tutorial. [http://pine.fm/LearnToProgram/?Chapter=01](http://pine.fm/LearnToProgram/?Chapter=01) + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/go/space-age/cases_test.go b/go/space-age/cases_test.go new file mode 100644 index 0000000000000000000000000000000000000000..5280b07a30dd29eac55f0658e90404c77e9055c9 --- /dev/null +++ b/go/space-age/cases_test.go @@ -0,0 +1,61 @@ +package space + +// Source: exercism/problem-specifications +// Commit: 28b3dac0 space-age: restrict seconds to fit within 32-bit int range +// Problem Specifications Version: 1.2.0 + +var testCases = []struct { + description string + planet Planet + seconds float64 + expected float64 +}{ + { + description: "age on Earth", + planet: "Earth", + seconds: 1000000000, + expected: 31.69, + }, + { + description: "age on Mercury", + planet: "Mercury", + seconds: 2134835688, + expected: 280.88, + }, + { + description: "age on Venus", + planet: "Venus", + seconds: 189839836, + expected: 9.78, + }, + { + description: "age on Mars", + planet: "Mars", + seconds: 2129871239, + expected: 35.88, + }, + { + description: "age on Jupiter", + planet: "Jupiter", + seconds: 901876382, + expected: 2.41, + }, + { + description: "age on Saturn", + planet: "Saturn", + seconds: 2000000000, + expected: 2.15, + }, + { + description: "age on Uranus", + planet: "Uranus", + seconds: 1210123456, + expected: 0.46, + }, + { + description: "age on Neptune", + planet: "Neptune", + seconds: 1821023456, + expected: 0.35, + }, +} diff --git a/go/space-age/go.mod b/go/space-age/go.mod new file mode 100644 index 0000000000000000000000000000000000000000..1847ac20dc57f1f4c09d047b4359f77e68d39f32 --- /dev/null +++ b/go/space-age/go.mod @@ -0,0 +1,3 @@ +module space + +go 1.13 diff --git a/go/space-age/space_age.go b/go/space-age/space_age.go new file mode 100644 index 0000000000000000000000000000000000000000..e947e8c2315a66bd9245feb3b3c56529713cd044 --- /dev/null +++ b/go/space-age/space_age.go @@ -0,0 +1,22 @@ +package space + +/*Planet type represents the name of a planet.*/ +type Planet string + +var earthSeconds = 31557600.0 +var n = map[string]float64{ + "Mercury": 0.2408467, + "Venus": 0.61519726, + "Earth": 1.0, + "Mars": 1.8808158, + "Jupiter": 11.862615, + "Saturn": 29.447498, + "Uranus": 84.016846, + "Neptune": 164.79132, +} + +/*Age returns earth years relative to planet and age seconds.*/ +func Age(seconds float64, planet Planet) float64 { + earthYears := seconds / earthSeconds + return earthYears / n[string(planet)] +} diff --git a/go/space-age/space_age_test.go b/go/space-age/space_age_test.go new file mode 100644 index 0000000000000000000000000000000000000000..71f73597a4e447ab14898def10002df5b5cd095c --- /dev/null +++ b/go/space-age/space_age_test.go @@ -0,0 +1,25 @@ +package space + +import ( + "math" + "testing" +) + +func TestAge(t *testing.T) { + const precision = 0.01 + for _, tc := range testCases { + actual := Age(tc.seconds, tc.planet) + if math.IsNaN(actual) || math.Abs(actual-tc.expected) > precision { + t.Fatalf("FAIL: %s\nExpected: %#v\nActual: %#v", tc.description, tc.expected, actual) + } + t.Logf("PASS: %s", tc.description) + } +} + +func BenchmarkAge(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, tc := range testCases { + Age(tc.seconds, tc.planet) + } + } +} diff --git a/go/triangle/README.md b/go/triangle/README.md new file mode 100644 index 0000000000000000000000000000000000000000..04491f7799384ad88b21fb7378c46a83bdd6159f --- /dev/null +++ b/go/triangle/README.md @@ -0,0 +1,64 @@ +# Triangle + +Determine if a triangle is equilateral, isosceles, or scalene. + +An _equilateral_ triangle has all three sides the same length. + +An _isosceles_ triangle has at least two sides the same length. (It is sometimes +specified as having exactly two sides the same length, but for the purposes of +this exercise we'll say at least two.) + +A _scalene_ triangle has all sides of different lengths. + +## Note + +For a shape to be a triangle at all, all sides have to be of length > 0, and +the sum of the lengths of any two sides must be greater than or equal to the +length of the third side. See [Triangle Inequality](https://en.wikipedia.org/wiki/Triangle_inequality). + +## Dig Deeper + +The case where the sum of the lengths of two sides _equals_ that of the +third is known as a _degenerate_ triangle - it has zero area and looks like +a single line. Feel free to add your own code/tests to check for degenerate triangles. + +## Constant Declarations + +In this exercise you are asked to declare a series of constants used to identify +different types of triangles. Pick the data type you think works best for this +and get the tests passing. + +Afterwards, it may be worth reading about Go's +predeclared identifier [iota](https://golang.org/ref/spec#Iota). There's an +excellent write up about it +[here](https://splice.com/blog/iota-elegant-constants-golang/). + + +## Coding the solution + +Look for a stub file having the name triangle.go +and place your solution code in that file. + +## 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. + +## Further information + +For more detailed information about the Go track, including how to get help if +you're having trouble, please visit the exercism.io [Go language page](http://exercism.io/languages/go/resources). + +## Source + +The Ruby Koans triangle project, parts 1 & 2 [http://rubykoans.com](http://rubykoans.com) + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/go/triangle/go.mod b/go/triangle/go.mod new file mode 100644 index 0000000000000000000000000000000000000000..9c0e6aa393b24602728ccd3ee7777fb11d25ca0a --- /dev/null +++ b/go/triangle/go.mod @@ -0,0 +1,3 @@ +module triangle + +go 1.13 diff --git a/go/triangle/triangle.go b/go/triangle/triangle.go new file mode 100644 index 0000000000000000000000000000000000000000..8b8b9633c8b8f02a468178205307151cecc92b8c --- /dev/null +++ b/go/triangle/triangle.go @@ -0,0 +1,37 @@ +//Package triangle classifies triangles by type. +package triangle + +import "math" + +//Kind represents the category of triangle. +type Kind uint + +//These are the categories. +const ( + NaT Kind = 0 // Not a Triangle + Equ Kind = 1 // equilateral + Iso Kind = 2 // isosceles + Sca Kind = 3 // scalene +) + +//KindFromSides returns the type of triangle based on the sides. +func KindFromSides(a, b, c float64) Kind { + var k Kind = NaT + + if math.IsInf(a+b+c, 0) { + k = NaT + } else if math.IsNaN(a + b + c) { + k = NaT + } else if (a+b < c) || (a+c < b) || (b+c < a) { + k = NaT + } else if a <= 0 || b <= 0 || c <= 0 { + k = NaT + } else if a == b && b == c { + k = Equ + } else if a == b || a == c || b == c { + k = Iso + } else if a != b && a != c && b != c { + k = Sca + } + return k +} diff --git a/go/triangle/triangle_test.go b/go/triangle/triangle_test.go new file mode 100644 index 0000000000000000000000000000000000000000..749df6f13f55921f510856d72f7c45ec9409deff --- /dev/null +++ b/go/triangle/triangle_test.go @@ -0,0 +1,93 @@ +package triangle + +import ( + "math" + "testing" +) + +type testCase struct { + want Kind + a, b, c float64 +} + +// basic test cases +var testData = []testCase{ + {Equ, 2, 2, 2}, // same length + {Equ, 10, 10, 10}, // a little bigger + {Iso, 3, 4, 4}, // last two sides equal + {Iso, 4, 3, 4}, // first and last sides equal + {Iso, 4, 4, 3}, // first two sides equal + {Iso, 10, 10, 2}, // again + {Iso, 2, 4, 2}, // a "triangle" that is just a line is still OK + {Sca, 3, 4, 5}, // no sides equal + {Sca, 10, 11, 12}, // again + {Sca, 5, 4, 2}, // descending order + {Sca, .4, .6, .3}, // small sides + {Sca, 1, 4, 3}, // a "triangle" that is just a line is still OK + {Sca, 5, 4, 6}, // 2a == b+c looks like equilateral, but isn't always. + {Sca, 6, 4, 5}, // 2a == b+c looks like equilateral, but isn't always. + {NaT, 0, 0, 0}, // zero length + {NaT, 3, 4, -5}, // negative length + {NaT, 1, 1, 3}, // fails triangle inequality + {NaT, 2, 5, 2}, // another + {NaT, 7, 3, 2}, // another +} + +// generate cases with NaN and Infs, append to basic cases +func init() { + nan := math.NaN() + pinf := math.Inf(1) + ninf := math.Inf(-1) + nf := make([]testCase, 4*4*4) + i := 0 + for _, a := range []float64{3, nan, pinf, ninf} { + for _, b := range []float64{4, nan, pinf, ninf} { + for _, c := range []float64{5, nan, pinf, ninf} { + nf[i] = testCase{NaT, a, b, c} + i++ + } + } + } + testData = append(testData, nf[1:]...) +} + +// Test that the kinds are not equal to each other. +// If they are equal, then TestKind will return false positives. +func TestKindsNotEqual(t *testing.T) { + kindsAndNames := []struct { + kind Kind + name string + }{ + {Equ, "Equ"}, + {Iso, "Iso"}, + {Sca, "Sca"}, + {NaT, "NaT"}, + } + + for i, pair1 := range kindsAndNames { + for j := i + 1; j < len(kindsAndNames); j++ { + pair2 := kindsAndNames[j] + if pair1.kind == pair2.kind { + t.Fatalf("%s should not be equal to %s", pair1.name, pair2.name) + } + } + } +} + +func TestKind(t *testing.T) { + for _, test := range testData { + got := KindFromSides(test.a, test.b, test.c) + if got != test.want { + t.Fatalf("Triangle with sides, %g, %g, %g = %v, want %v", + test.a, test.b, test.c, got, test.want) + } + } +} + +func BenchmarkKind(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, test := range testData { + KindFromSides(test.a, test.b, test.c) + } + } +} diff --git a/go/two-fer/README.md b/go/two-fer/README.md new file mode 100644 index 0000000000000000000000000000000000000000..4fd3018c768b5fd74039859418970cc6eb43b131 --- /dev/null +++ b/go/two-fer/README.md @@ -0,0 +1,55 @@ +# Two Fer + +`Two-fer` or `2-fer` is short for two for one. One for you and one for me. + +Given a name, return a string with the message: + +```text +One for X, one for me. +``` + +Where X is the given name. + +However, if the name is missing, return the string: + +```text +One for you, one for me. +``` + +Here are some examples: + +|Name |String to return +|:-------|:------------------ +|Alice |One for Alice, one for me. +|Bob |One for Bob, one for me. +| |One for you, one for me. +|Zaphod |One for Zaphod, one for me. + +## Coding the solution + +Look for a stub file having the name two_fer.go +and place your solution code in that file. + +## 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. + +## Further information + +For more detailed information about the Go track, including how to get help if +you're having trouble, please visit the exercism.io [Go language page](http://exercism.io/languages/go/resources). + +## Source + +[https://github.com/exercism/problem-specifications/issues/757](https://github.com/exercism/problem-specifications/issues/757) + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/go/two-fer/example_two_fer_test.go b/go/two-fer/example_two_fer_test.go new file mode 100644 index 0000000000000000000000000000000000000000..fe0f02397582ebb992914515954465f727f234a5 --- /dev/null +++ b/go/two-fer/example_two_fer_test.go @@ -0,0 +1,20 @@ +package twofer + +import "fmt" + +// ExampleShareWith() is an Example function. Examples are testable snippets of +// Go code that are used for documenting and verifying the package API. +// They may be present in some exercises to demonstrate the expected use of the +// exercise API and can be run as part of a package's test suite. +// +// When an Example test is run the data that is written to standard output is +// compared to the data that comes after the "Output: " comment. +// +// Below the result of ShareWith() is passed to standard output +// using fmt.Println, and this is compared against the expected output. +// If they are equal, the test passes. +func ExampleShareWith() { + h := ShareWith("") + fmt.Println(h) + // Output: One for you, one for me. +} diff --git a/go/two-fer/go.mod b/go/two-fer/go.mod new file mode 100644 index 0000000000000000000000000000000000000000..7a696c8a362b5d818bdd5420d983b95c56a7e12c --- /dev/null +++ b/go/two-fer/go.mod @@ -0,0 +1,16 @@ +module twofer + +go 1.13 + +require ( + github.com/heptio/velero v1.2.0 // indirect + golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6 // indirect + golang.org/x/lint v0.0.0-20200130185559-910be7a94367 // indirect + golang.org/x/mod v0.2.0 // indirect + golang.org/x/net v0.0.0-20200202094626-16171245cfb2 // indirect + golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect + golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4 // indirect + golang.org/x/text v0.3.2 // indirect + golang.org/x/tools v0.0.0-20200214201135-548b770e2dfa // indirect + golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect +) diff --git a/go/two-fer/go.sum b/go/two-fer/go.sum new file mode 100644 index 0000000000000000000000000000000000000000..f4a47e9775c836971f165cc0ab2a98ee9113cff9 --- /dev/null +++ b/go/two-fer/go.sum @@ -0,0 +1,27 @@ +github.com/heptio/velero v1.2.0 h1:jqE0YnKsZIbOiFeWHrGlqvIJdMkBAz4HPU8ePbUGbOU= +github.com/heptio/velero v1.2.0/go.mod h1:Q8aj4N9pmvDNp2hWmqWJ1Z1ybUjEI+iQOP3C9hx2njQ= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367 h1:0IiAsCRByjO2QjX7ZPkw5oU9x+n1YqRL802rjC0c3Aw= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200214201135-548b770e2dfa h1:BmyblL6HF4UvCacG8vRH/IPhx3pIS4LMNkeqP6+vEwc= +golang.org/x/tools v0.0.0-20200214201135-548b770e2dfa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/go/two-fer/two_fer.go b/go/two-fer/two_fer.go new file mode 100644 index 0000000000000000000000000000000000000000..89fb2c0d57073dbe749068e112d86f1071287762 --- /dev/null +++ b/go/two-fer/two_fer.go @@ -0,0 +1,12 @@ +// Package twofer provides exercise to output a string. +package twofer + +import "fmt" + +//ShareWith provides the string filling in for whom. +func ShareWith(name string) string { + if name == "" { + name = "you" + } + return fmt.Sprintf("One for %s, one for me.", name) +} diff --git a/go/two-fer/two_fer_test.go b/go/two-fer/two_fer_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f4ce1587382fa24f70e0afc3aac57ac520a5fa44 --- /dev/null +++ b/go/two-fer/two_fer_test.go @@ -0,0 +1,31 @@ +package twofer + +import "testing" + +// Define a function ShareWith(string) string. + +var tests = []struct { + name, expected string +}{ + {"", "One for you, one for me."}, + {"Alice", "One for Alice, one for me."}, + {"Bob", "One for Bob, one for me."}, +} + +func TestShareWith(t *testing.T) { + for _, test := range tests { + if observed := ShareWith(test.name); observed != test.expected { + t.Fatalf("ShareWith(%s) = \"%v\", want \"%v\"", test.name, observed, test.expected) + } + } +} + +func BenchmarkShareWith(b *testing.B) { + for i := 0; i < b.N; i++ { + + for _, test := range tests { + ShareWith(test.name) + } + + } +}