Just a commit
This commit is contained in:
parent
0ef5df860d
commit
ec4ec16ac2
5
clojure/hello-world/src/hello_world.clj
Normal file
5
clojure/hello-world/src/hello_world.clj
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
(ns hello-world)
|
||||||
|
|
||||||
|
(defn hello [] ;; <- arglist goes here
|
||||||
|
;; your code goes here
|
||||||
|
)
|
1
crystal/current
Symbolic link
1
crystal/current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
hello-world
|
10
crystal/hello-world/GETTING_STARTED.md
Normal file
10
crystal/hello-world/GETTING_STARTED.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Welcome to Crystal!
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
*Note: Currently, Crystal only supports Linux and OSX.*
|
||||||
|
|
||||||
|
Use one of the [installation guides](http://crystal-lang.org/docs/installation/index.html) for instructions on installing Crystal.
|
||||||
|
|
||||||
|
## Running Tests
|
||||||
|
`crystal spec hello_world_spec.cr`
|
70
crystal/hello-world/README.md
Normal file
70
crystal/hello-world/README.md
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# Hello World
|
||||||
|
|
||||||
|
Write a function that greets the user by name, or by saying "Hello, World!" if no name is given.
|
||||||
|
|
||||||
|
["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is the traditional first program for beginning programming in a new language.
|
||||||
|
|
||||||
|
**Note:** You can skip this exercise by running:
|
||||||
|
|
||||||
|
exercism skip $LANGUAGE hello-world
|
||||||
|
|
||||||
|
## Specification
|
||||||
|
|
||||||
|
Write a `Hello World!` function that can greet someone given their name.
|
||||||
|
The function should return the appropriate greeting.
|
||||||
|
|
||||||
|
For an input of "Alice", the response should be "Hello, Alice!".
|
||||||
|
|
||||||
|
If a name is not given, the response should be "Hello, World!"
|
||||||
|
|
||||||
|
## Test-Driven Development
|
||||||
|
|
||||||
|
As programmers mature, they eventually want to test their code.
|
||||||
|
|
||||||
|
Here at Exercism we simulate [Test-Driven Development](http://en.wikipedia.org/wiki/Test-driven_development) (TDD), where you write your tests before writing any functionality. The simulation comes in the form of a pre-written test suite, which will signal that you have solved the problem.
|
||||||
|
|
||||||
|
It will also provide you with a safety net to explore other solutions without breaking the functionality.
|
||||||
|
|
||||||
|
### A typical TDD workflow on Exercism:
|
||||||
|
|
||||||
|
1. Run the test file and pick one test that's failing.
|
||||||
|
2. Write some code to fix the test you picked.
|
||||||
|
3. Re-run the tests to confirm the test is now passing.
|
||||||
|
4. Repeat from step 1.
|
||||||
|
5. Submit your solution (`exercism submit /path/to/file`)
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Submissions are encouraged to be general, within reason. Having said that, it's also important not to over-engineer a solution.
|
||||||
|
|
||||||
|
It's important to remember that the goal is to make code as expressive and readable as we can. However, solutions to the hello-world exercise will not be reviewed by a person, but by rikki- the robot, who will offer an encouraging word.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Follow the setup instructions for Crystal here:
|
||||||
|
|
||||||
|
http://exercism.io/languages/crystal
|
||||||
|
|
||||||
|
More help installing can be found here:
|
||||||
|
|
||||||
|
http://crystal-lang.org/docs/installation/index.html
|
||||||
|
|
||||||
|
## Making the Test Suit Pass
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ crystal spec test_spec.cr
|
||||||
|
```
|
||||||
|
|
||||||
|
In each test suite all but the first test have been skipped.
|
||||||
|
|
||||||
|
Once you get a test passing, you can unskip the next one by changing `pending` to `it`.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||||
|
|
||||||
|
## Submitting Incomplete Problems
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
18
crystal/hello-world/hello_world_spec.cr
Normal file
18
crystal/hello-world/hello_world_spec.cr
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
require "spec"
|
||||||
|
require "./hello_world"
|
||||||
|
|
||||||
|
describe "HelloWorld" do
|
||||||
|
describe "#hello" do
|
||||||
|
it "says hello with default 'World'" do
|
||||||
|
HelloWorld.hello.should eq "Hello, World"
|
||||||
|
end
|
||||||
|
|
||||||
|
pending "says hello with one name" do
|
||||||
|
HelloWorld.hello("Max").should eq "Hello, Max"
|
||||||
|
end
|
||||||
|
|
||||||
|
pending "says hello with another name" do
|
||||||
|
HelloWorld.hello("Alice").should eq "Hello, Alice"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
1
dlang/current
Symbolic link
1
dlang/current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
hello-world
|
77
dlang/hello-world/README.md
Normal file
77
dlang/hello-world/README.md
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# Hello World
|
||||||
|
|
||||||
|
Write a function that greets the user by name, or by saying "Hello, World!" if no name is given.
|
||||||
|
|
||||||
|
["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is the traditional first program for beginning programming in a new language.
|
||||||
|
|
||||||
|
**Note:** You can skip this exercise by running:
|
||||||
|
|
||||||
|
exercism skip $LANGUAGE hello-world
|
||||||
|
|
||||||
|
## Specification
|
||||||
|
|
||||||
|
Write a `Hello World!` function that can greet someone given their name.
|
||||||
|
The function should return the appropriate greeting.
|
||||||
|
|
||||||
|
For an input of "Alice", the response should be "Hello, Alice!".
|
||||||
|
|
||||||
|
If a name is not given, the response should be "Hello, World!"
|
||||||
|
|
||||||
|
## Test-Driven Development
|
||||||
|
|
||||||
|
As programmers mature, they eventually want to test their code.
|
||||||
|
|
||||||
|
Here at Exercism we simulate [Test-Driven Development](http://en.wikipedia.org/wiki/Test-driven_development) (TDD), where you write your tests before writing any functionality. The simulation comes in the form of a pre-written test suite, which will signal that you have solved the problem.
|
||||||
|
|
||||||
|
It will also provide you with a safety net to explore other solutions without breaking the functionality.
|
||||||
|
|
||||||
|
### A typical TDD workflow on Exercism:
|
||||||
|
|
||||||
|
1. Run the test file and pick one test that's failing.
|
||||||
|
2. Write some code to fix the test you picked.
|
||||||
|
3. Re-run the tests to confirm the test is now passing.
|
||||||
|
4. Repeat from step 1.
|
||||||
|
5. Submit your solution (`exercism submit /path/to/file`)
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Submissions are encouraged to be general, within reason. Having said that, it's also important not to over-engineer a solution.
|
||||||
|
|
||||||
|
It's important to remember that the goal is to make code as expressive and readable as we can. However, solutions to the hello-world exercise will not be reviewed by a person, but by rikki- the robot, who will offer an encouraging word.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
Make sure you have read [D page](http://exercism.io/languages/dlang) on
|
||||||
|
exercism.io. This covers the basic information on setting up the development
|
||||||
|
environment expected by the exercises.
|
||||||
|
|
||||||
|
## Passing the Tests
|
||||||
|
|
||||||
|
Get the first test compiling, linking and passing by following the [three
|
||||||
|
rules of test-driven development](http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd).
|
||||||
|
Create just enough structure by declaring namespaces, functions, classes,
|
||||||
|
etc., to satisfy any compiler errors and get the test to fail. Then write
|
||||||
|
just enough code to get the test to pass. Once you've done that,
|
||||||
|
uncomment the next test by moving the following line past the next test.
|
||||||
|
|
||||||
|
```D
|
||||||
|
static if (all_tests_enabled)
|
||||||
|
```
|
||||||
|
|
||||||
|
This may result in compile errors as new constructs may be invoked that
|
||||||
|
you haven't yet declared or defined. Again, fix the compile errors minimally
|
||||||
|
to get a failing test, then change the code minimally to pass the test,
|
||||||
|
refactor your implementation for readability and expressiveness and then
|
||||||
|
go on to the next test.
|
||||||
|
|
||||||
|
Try to use standard D facilities in preference to writing your own
|
||||||
|
low-level algorithms or facilities by hand. [DRefLanguage](https://dlang.org/spec/spec.html)
|
||||||
|
and [DReference](https://dlang.org/phobos/index.html) are references to the D language and D standard library.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||||
|
|
||||||
|
## Submitting Incomplete Problems
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
14
dlang/hello-world/hello_test.d
Normal file
14
dlang/hello-world/hello_test.d
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
module helloworld_test;
|
||||||
|
|
||||||
|
import helloworld;
|
||||||
|
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
assert(hello() == "Hello, World!");
|
||||||
|
assert(hello("Alice") == "Hello, Alice!");
|
||||||
|
assert(hello("Bob") == "Hello, Bob!");
|
||||||
|
assert(hello("") == "Hello, !");
|
||||||
|
|
||||||
|
writeln("All tests passed.");
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
hello-world
|
bob
|
1
elm/current
Symbolic link
1
elm/current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
hello-world
|
25
elm/hello-world/HelloWorld.elm
Normal file
25
elm/hello-world/HelloWorld.elm
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{-
|
||||||
|
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.
|
||||||
|
|
||||||
|
The module name is expected by the test program and must match the name of this
|
||||||
|
file. It has to stay just the way it is.
|
||||||
|
-}
|
||||||
|
|
||||||
|
|
||||||
|
module HelloWorld exposing (..)
|
||||||
|
|
||||||
|
-- It's good style to include any types at the top level of your modules.
|
||||||
|
|
||||||
|
|
||||||
|
helloWorld : Maybe String -> String
|
||||||
|
helloWorld name =
|
||||||
|
"replace with your code!"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{-
|
||||||
|
When you have a working solution, 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, nitpickers will protest!
|
||||||
|
-}
|
18
elm/hello-world/HelloWorldTests.elm
Normal file
18
elm/hello-world/HelloWorldTests.elm
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
module Main exposing (..)
|
||||||
|
|
||||||
|
import ElmTest exposing (..)
|
||||||
|
import HelloWorld exposing (helloWorld)
|
||||||
|
|
||||||
|
|
||||||
|
tests : Test
|
||||||
|
tests =
|
||||||
|
suite "Hello, World!"
|
||||||
|
[ test "Hello with no name" (assertEqual "Hello, World!" (helloWorld Nothing))
|
||||||
|
, test "Hello to a sample name" (assertEqual "Hello, Alice!" (helloWorld (Just "Alice")))
|
||||||
|
, test "Hello to another sample name" (assertEqual "Hello, Bob!" (helloWorld (Just "Bob")))
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
main : Program Never
|
||||||
|
main =
|
||||||
|
runSuite tests
|
48
elm/hello-world/README.md
Normal file
48
elm/hello-world/README.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Hello World
|
||||||
|
|
||||||
|
Write a function that greets the user by name, or by saying "Hello, World!" if no name is given.
|
||||||
|
|
||||||
|
["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is the traditional first program for beginning programming in a new language.
|
||||||
|
|
||||||
|
**Note:** You can skip this exercise by running:
|
||||||
|
|
||||||
|
exercism skip $LANGUAGE hello-world
|
||||||
|
|
||||||
|
## Specification
|
||||||
|
|
||||||
|
Write a `Hello World!` function that can greet someone given their name.
|
||||||
|
The function should return the appropriate greeting.
|
||||||
|
|
||||||
|
For an input of "Alice", the response should be "Hello, Alice!".
|
||||||
|
|
||||||
|
If a name is not given, the response should be "Hello, World!"
|
||||||
|
|
||||||
|
## Test-Driven Development
|
||||||
|
|
||||||
|
As programmers mature, they eventually want to test their code.
|
||||||
|
|
||||||
|
Here at Exercism we simulate [Test-Driven Development](http://en.wikipedia.org/wiki/Test-driven_development) (TDD), where you write your tests before writing any functionality. The simulation comes in the form of a pre-written test suite, which will signal that you have solved the problem.
|
||||||
|
|
||||||
|
It will also provide you with a safety net to explore other solutions without breaking the functionality.
|
||||||
|
|
||||||
|
### A typical TDD workflow on Exercism:
|
||||||
|
|
||||||
|
1. Run the test file and pick one test that's failing.
|
||||||
|
2. Write some code to fix the test you picked.
|
||||||
|
3. Re-run the tests to confirm the test is now passing.
|
||||||
|
4. Repeat from step 1.
|
||||||
|
5. Submit your solution (`exercism submit /path/to/file`)
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Submissions are encouraged to be general, within reason. Having said that, it's also important not to over-engineer a solution.
|
||||||
|
|
||||||
|
It's important to remember that the goal is to make code as expressive and readable as we can. However, solutions to the hello-world exercise will not be reviewed by a person, but by rikki- the robot, who will offer an encouraging word.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||||
|
|
||||||
|
## Submitting Incomplete Problems
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
15
elm/hello-world/elm-package.json
Normal file
15
elm/hello-world/elm-package.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"summary": "Exercism problems in Elm.",
|
||||||
|
"repository": "https://github.com/exercism/xelm.git",
|
||||||
|
"license": "BSD3",
|
||||||
|
"source-directories": [
|
||||||
|
"."
|
||||||
|
],
|
||||||
|
"exposed-modules": [],
|
||||||
|
"dependencies": {
|
||||||
|
"elm-community/elm-test": "1.0.0 <= v < 2.0.0",
|
||||||
|
"elm-lang/core": "4.0.0 <= v < 5.0.0"
|
||||||
|
},
|
||||||
|
"elm-version": "0.17.0 <= v < 0.18.0"
|
||||||
|
}
|
4
elm/hello-world/runtests.bat
Normal file
4
elm/hello-world/runtests.bat
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
@echo off
|
||||||
|
for %%f in (*Tests.elm) do (
|
||||||
|
elm-make %%f --yes --output build.js && node build.js
|
||||||
|
)
|
2
elm/hello-world/runtests.sh
Normal file
2
elm/hello-world/runtests.sh
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
elm-make *Tests.elm --yes --output build.js && node build.js
|
@ -1 +1 @@
|
|||||||
sum-of-multiples
|
hello-world
|
19
fsharp/hello-world/HelloWorldTest.fs
Normal file
19
fsharp/hello-world/HelloWorldTest.fs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
module HelloWorldTest
|
||||||
|
|
||||||
|
open NUnit.Framework
|
||||||
|
|
||||||
|
open HelloWorld
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
let ``No name`` () =
|
||||||
|
Assert.That(hello None, Is.EqualTo("Hello, World!"))
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
[<Ignore("Remove to run test")>]
|
||||||
|
let ``Sample name`` () =
|
||||||
|
Assert.That(hello (Some "Alice"), Is.EqualTo("Hello, Alice!"))
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
[<Ignore("Remove to run test")>]
|
||||||
|
let ``Other sample name`` () =
|
||||||
|
Assert.That(hello (Some "Bob"), Is.EqualTo("Hello, Bob!"))
|
48
fsharp/hello-world/README.md
Normal file
48
fsharp/hello-world/README.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Hello World
|
||||||
|
|
||||||
|
Write a function that greets the user by name, or by saying "Hello, World!" if no name is given.
|
||||||
|
|
||||||
|
["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is the traditional first program for beginning programming in a new language.
|
||||||
|
|
||||||
|
**Note:** You can skip this exercise by running:
|
||||||
|
|
||||||
|
exercism skip $LANGUAGE hello-world
|
||||||
|
|
||||||
|
## Specification
|
||||||
|
|
||||||
|
Write a `Hello World!` function that can greet someone given their name.
|
||||||
|
The function should return the appropriate greeting.
|
||||||
|
|
||||||
|
For an input of "Alice", the response should be "Hello, Alice!".
|
||||||
|
|
||||||
|
If a name is not given, the response should be "Hello, World!"
|
||||||
|
|
||||||
|
## Test-Driven Development
|
||||||
|
|
||||||
|
As programmers mature, they eventually want to test their code.
|
||||||
|
|
||||||
|
Here at Exercism we simulate [Test-Driven Development](http://en.wikipedia.org/wiki/Test-driven_development) (TDD), where you write your tests before writing any functionality. The simulation comes in the form of a pre-written test suite, which will signal that you have solved the problem.
|
||||||
|
|
||||||
|
It will also provide you with a safety net to explore other solutions without breaking the functionality.
|
||||||
|
|
||||||
|
### A typical TDD workflow on Exercism:
|
||||||
|
|
||||||
|
1. Run the test file and pick one test that's failing.
|
||||||
|
2. Write some code to fix the test you picked.
|
||||||
|
3. Re-run the tests to confirm the test is now passing.
|
||||||
|
4. Repeat from step 1.
|
||||||
|
5. Submit your solution (`exercism submit /path/to/file`)
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Submissions are encouraged to be general, within reason. Having said that, it's also important not to over-engineer a solution.
|
||||||
|
|
||||||
|
It's important to remember that the goal is to make code as expressive and readable as we can. However, solutions to the hello-world exercise will not be reviewed by a person, but by rikki- the robot, who will offer an encouraging word.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||||
|
|
||||||
|
## Submitting Incomplete Problems
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
@ -1 +1 @@
|
|||||||
react
|
custom-set
|
24
go/custom-set/README.md
Normal file
24
go/custom-set/README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Custom Set
|
||||||
|
|
||||||
|
Create a custom set type.
|
||||||
|
|
||||||
|
Sometimes it is necessary to define a custom data structure of some
|
||||||
|
type, like a set. In this exercise you will define your own set. How it
|
||||||
|
works internally doesn't matter, as long as it behaves like a set of
|
||||||
|
unique elements.
|
||||||
|
|
||||||
|
To run the tests simply run the command `go test` in the exercise directory.
|
||||||
|
|
||||||
|
If the test suite contains benchmarks, you can run these with the `-bench`
|
||||||
|
flag:
|
||||||
|
|
||||||
|
go test -bench .
|
||||||
|
|
||||||
|
For more detailed info about the Go track see the [help
|
||||||
|
page](http://exercism.io/languages/go).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Submitting Incomplete Problems
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
368
go/custom-set/cases_test.go
Normal file
368
go/custom-set/cases_test.go
Normal file
@ -0,0 +1,368 @@
|
|||||||
|
package stringset
|
||||||
|
|
||||||
|
// Source: exercism/x-common
|
||||||
|
// Commit: 269f498 Merge pull request #48 from soniakeys/custom-set-json
|
||||||
|
|
||||||
|
// Test two sets for equality.
|
||||||
|
var eqCases = []binBoolCase{
|
||||||
|
{ // order doesn't matter
|
||||||
|
[]string{"a", "c"},
|
||||||
|
[]string{"c", "a"},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // dupicates don't matter
|
||||||
|
[]string{"a", "a"},
|
||||||
|
[]string{"a"},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // empty sets are equal
|
||||||
|
[]string{},
|
||||||
|
[]string{},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // set with single element is equal to itself
|
||||||
|
[]string{"a"},
|
||||||
|
[]string{"a"},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // different sets are not equal
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
[]string{"c", "d", "e"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{ // empty set is not equal to non-empty set
|
||||||
|
[]string{},
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{ // non-empty set is not equal to empty set
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
[]string{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{ // having most in common is not good enough
|
||||||
|
[]string{"a", "b", "c", "d"},
|
||||||
|
[]string{"b", "c", "d", "e"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an element to a set.
|
||||||
|
var addCases = []eleOpCase{
|
||||||
|
{ // add to empty set
|
||||||
|
[]string{},
|
||||||
|
"c",
|
||||||
|
[]string{"c"},
|
||||||
|
},
|
||||||
|
{ // add to non-empty set
|
||||||
|
[]string{"a", "b", "d"},
|
||||||
|
"c",
|
||||||
|
[]string{"a", "b", "c", "d"},
|
||||||
|
},
|
||||||
|
{ // add existing element
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
"c",
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete an element from a set.
|
||||||
|
var delCases = []eleOpCase{
|
||||||
|
{ // delete an element
|
||||||
|
[]string{"c", "b", "a"},
|
||||||
|
"b",
|
||||||
|
[]string{"a", "c"},
|
||||||
|
},
|
||||||
|
{ // delete an element not in set
|
||||||
|
[]string{"c", "b", "a"},
|
||||||
|
"d",
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test if is a set is empty.
|
||||||
|
var emptyCases = []unaryBoolCase{
|
||||||
|
{ // empty
|
||||||
|
[]string{},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // single element
|
||||||
|
[]string{"a"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{ // a few elements
|
||||||
|
[]string{"a", "b", "c", "b"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the cardinality of a set.
|
||||||
|
var lenCases = []unaryIntCase{
|
||||||
|
{ // empty set
|
||||||
|
[]string{},
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // non-empty set
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
3,
|
||||||
|
},
|
||||||
|
{ // duplicate element
|
||||||
|
[]string{"a", "b", "c", "b"},
|
||||||
|
3,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test if a value is an element of a set.
|
||||||
|
var hasCases = []eleBoolCase{
|
||||||
|
{ // nothing is an element of the empty set
|
||||||
|
[]string{},
|
||||||
|
"a",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{ // 1 is in the set
|
||||||
|
[]string{"a", "b", "c", "b"},
|
||||||
|
"a",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // 2 is in the set
|
||||||
|
[]string{"a", "b", "c", "b"},
|
||||||
|
"b",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // 3 is in the set
|
||||||
|
[]string{"a", "b", "c", "b"},
|
||||||
|
"c",
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // 4 not in the set
|
||||||
|
[]string{"a", "b", "c", "b"},
|
||||||
|
"d",
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test if set1 is a subset of set2.
|
||||||
|
var subsetCases = []binBoolCase{
|
||||||
|
{ // empty set is subset of itself
|
||||||
|
[]string{},
|
||||||
|
[]string{},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // empty set is subset of non-empty set
|
||||||
|
[]string{},
|
||||||
|
[]string{"a"},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // non-empty set is not subset of empty set
|
||||||
|
[]string{"a"},
|
||||||
|
[]string{},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{ // non-empty set is subset of itself
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // proper subset
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
[]string{"d", "a", "b", "c"},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // same number of elements
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
[]string{"d", "a", "c"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{ // superset
|
||||||
|
[]string{"a", "b", "c", "d", "e"},
|
||||||
|
[]string{"b", "c", "d"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{ // fewer elements but not a subset
|
||||||
|
[]string{"a", "b", "c", "k"},
|
||||||
|
[]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test if two sets are disjoint.
|
||||||
|
var disjointCases = []binBoolCase{
|
||||||
|
{ // the empty set is disjoint with itself
|
||||||
|
[]string{},
|
||||||
|
[]string{},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // empty set disjoint with non-empty set
|
||||||
|
[]string{},
|
||||||
|
[]string{"a"},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // non-empty set disjoint with empty set
|
||||||
|
[]string{"a"},
|
||||||
|
[]string{},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{ // one element in common
|
||||||
|
[]string{"a", "b"},
|
||||||
|
[]string{"b", "c"},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{ // no elements in common
|
||||||
|
[]string{"a", "b"},
|
||||||
|
[]string{"c", "d"},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Produce the union of two sets.
|
||||||
|
var unionCases = []binOpCase{
|
||||||
|
{ // union of empty sets
|
||||||
|
[]string{},
|
||||||
|
[]string{},
|
||||||
|
[]string{},
|
||||||
|
},
|
||||||
|
{ // union of empty set with set of one element
|
||||||
|
[]string{},
|
||||||
|
[]string{"b"},
|
||||||
|
[]string{"b"},
|
||||||
|
},
|
||||||
|
{ // union of empty set with non-empty set
|
||||||
|
[]string{},
|
||||||
|
[]string{"c", "b", "e"},
|
||||||
|
[]string{"b", "c", "e"},
|
||||||
|
},
|
||||||
|
{ // union of non-empty set with empty set
|
||||||
|
[]string{"a", "c"},
|
||||||
|
[]string{},
|
||||||
|
[]string{"a", "c"},
|
||||||
|
},
|
||||||
|
{ // union of a set with itself
|
||||||
|
[]string{"a", "c"},
|
||||||
|
[]string{"c", "a"},
|
||||||
|
[]string{"a", "c"},
|
||||||
|
},
|
||||||
|
{ // union with one element
|
||||||
|
[]string{"a", "c"},
|
||||||
|
[]string{"b"},
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
},
|
||||||
|
{ // one element in common, one different
|
||||||
|
[]string{"a", "c"},
|
||||||
|
[]string{"b", "c"},
|
||||||
|
[]string{"c", "b", "a"},
|
||||||
|
},
|
||||||
|
{ // two elements in common
|
||||||
|
[]string{"a", "b", "c", "d"},
|
||||||
|
[]string{"c", "b", "e"},
|
||||||
|
[]string{"a", "b", "c", "d", "e"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intersect two sets.
|
||||||
|
var intersectionCases = []binOpCase{
|
||||||
|
{ // intersect empty sets
|
||||||
|
[]string{},
|
||||||
|
[]string{},
|
||||||
|
[]string{},
|
||||||
|
},
|
||||||
|
{ // intersect empty set with non-empty set
|
||||||
|
[]string{},
|
||||||
|
[]string{"c", "b", "e"},
|
||||||
|
[]string{},
|
||||||
|
},
|
||||||
|
{ // intersect non-empty set with empty set
|
||||||
|
[]string{"a", "b", "c", "d"},
|
||||||
|
[]string{},
|
||||||
|
[]string{},
|
||||||
|
},
|
||||||
|
{ // intersect one element with itself
|
||||||
|
[]string{"c"},
|
||||||
|
[]string{"c"},
|
||||||
|
[]string{"c"},
|
||||||
|
},
|
||||||
|
{ // one element in common, extra elements in both sets
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
[]string{"c", "e", "d"},
|
||||||
|
[]string{"c"},
|
||||||
|
},
|
||||||
|
{ // two elements in common, extras in both sets
|
||||||
|
[]string{"a", "b", "c", "d"},
|
||||||
|
[]string{"c", "b", "e"},
|
||||||
|
[]string{"b", "c"},
|
||||||
|
},
|
||||||
|
{ // intersect with subset
|
||||||
|
[]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"},
|
||||||
|
[]string{"e", "f", "g", "h", "i", "j"},
|
||||||
|
[]string{"e", "f", "g", "h", "i", "j"},
|
||||||
|
},
|
||||||
|
{ // nothing in common
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
[]string{"d", "e", "f"},
|
||||||
|
[]string{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Produce the set difference (set1 - set2)
|
||||||
|
// or more specifically, (set1 ∖ set2)
|
||||||
|
var differenceCases = []binOpCase{
|
||||||
|
{ // difference of two empty sets
|
||||||
|
[]string{},
|
||||||
|
[]string{},
|
||||||
|
[]string{},
|
||||||
|
},
|
||||||
|
{ // difference of empty set and non-empty set
|
||||||
|
[]string{},
|
||||||
|
[]string{"c", "b", "e"},
|
||||||
|
[]string{},
|
||||||
|
},
|
||||||
|
{ // difference of non-empty set and empty set
|
||||||
|
[]string{"a", "b", "c", "d"},
|
||||||
|
[]string{},
|
||||||
|
[]string{"a", "b", "c", "d"},
|
||||||
|
},
|
||||||
|
{ // no elements in common
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
[]string{"d"},
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
},
|
||||||
|
{ // one element in common, one extra
|
||||||
|
[]string{"c", "b", "a"},
|
||||||
|
[]string{"b", "d"},
|
||||||
|
[]string{"a", "c"},
|
||||||
|
},
|
||||||
|
{ // two elements in common, one extra
|
||||||
|
[]string{"a", "b", "c", "d"},
|
||||||
|
[]string{"c", "b", "e"},
|
||||||
|
[]string{"a", "d"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Produce the symmetric difference of two sets. The symmetric
|
||||||
|
// difference consists of elements in one or the other but not both.
|
||||||
|
var symmetricDifferenceCases = []binOpCase{
|
||||||
|
{ // two empty sets
|
||||||
|
[]string{},
|
||||||
|
[]string{},
|
||||||
|
[]string{},
|
||||||
|
},
|
||||||
|
{ // empty set and non-empty set
|
||||||
|
[]string{},
|
||||||
|
[]string{"c", "b", "e"},
|
||||||
|
[]string{"c", "b", "e"},
|
||||||
|
},
|
||||||
|
{ // non-empty set and empty set
|
||||||
|
[]string{"a", "b", "c", "d"},
|
||||||
|
[]string{},
|
||||||
|
[]string{"a", "b", "c", "d"},
|
||||||
|
},
|
||||||
|
{ // no elements in common
|
||||||
|
[]string{"a", "b", "c"},
|
||||||
|
[]string{"d"},
|
||||||
|
[]string{"a", "b", "c", "d"},
|
||||||
|
},
|
||||||
|
{ // one element in common
|
||||||
|
[]string{"c", "b", "a"},
|
||||||
|
[]string{"b", "d"},
|
||||||
|
[]string{"a", "c", "d"},
|
||||||
|
},
|
||||||
|
}
|
BIN
go/custom-set/cmd/cmd
Executable file
BIN
go/custom-set/cmd/cmd
Executable file
Binary file not shown.
49
go/custom-set/cmd/main.go
Normal file
49
go/custom-set/cmd/main.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"../../custom-set"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("Creating Set 1")
|
||||||
|
s1 := stringset.NewFromSlice([]string{"a", "b"})
|
||||||
|
addAndOutput(s1, "A")
|
||||||
|
addAndOutput(s1, "c")
|
||||||
|
addAndOutput(s1, "B")
|
||||||
|
addAndOutput(s1, "B1")
|
||||||
|
addAndOutput(s1, "A1")
|
||||||
|
addAndOutput(s1, "B2")
|
||||||
|
addAndOutput(s1, "A2")
|
||||||
|
addAndOutput(s1, "B3")
|
||||||
|
addAndOutput(s1, "A3")
|
||||||
|
delAndOutput(s1, "a")
|
||||||
|
|
||||||
|
fmt.Println("Creating Set 2")
|
||||||
|
s2 := stringset.NewFromSlice([]string{"A", "c"})
|
||||||
|
addAndOutput(s2, "a")
|
||||||
|
addAndOutput(s2, "b")
|
||||||
|
addAndOutput(s2, "B1")
|
||||||
|
addAndOutput(s2, "A3")
|
||||||
|
addAndOutput(s2, "A2")
|
||||||
|
addAndOutput(s2, "B2")
|
||||||
|
addAndOutput(s2, "A1")
|
||||||
|
addAndOutput(s2, "B3")
|
||||||
|
addAndOutput(s2, "B")
|
||||||
|
s2.PrettyPrint()
|
||||||
|
delAndOutput(s2, "a")
|
||||||
|
s2.PrettyPrint()
|
||||||
|
}
|
||||||
|
|
||||||
|
func addAndOutput(s *stringset.Set, val string) {
|
||||||
|
fmt.Println("Adding " + val)
|
||||||
|
s.Add(val)
|
||||||
|
fmt.Println(s.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func delAndOutput(s *stringset.Set, val string) {
|
||||||
|
fmt.Println("Deleting " + val)
|
||||||
|
s.Delete(val)
|
||||||
|
fmt.Println(s.String())
|
||||||
|
}
|
268
go/custom-set/custom_set_test.go
Normal file
268
go/custom-set/custom_set_test.go
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
package stringset
|
||||||
|
|
||||||
|
// Implement Set as a collection of unique string values.
|
||||||
|
//
|
||||||
|
// API:
|
||||||
|
//
|
||||||
|
// New() Set
|
||||||
|
// NewFromSlice([]string) Set
|
||||||
|
// (s Set) Add(string) // modify s
|
||||||
|
// (s Set) Delete(string) // modify s
|
||||||
|
// (s Set) Has(string) bool
|
||||||
|
// (s Set) IsEmpty() bool
|
||||||
|
// (s Set) Len() int
|
||||||
|
// (s Set) Slice() []string
|
||||||
|
// (s Set) String() string
|
||||||
|
// Equal(s1, s2 Set) bool
|
||||||
|
// Subset(s1, s2 Set) bool // return s1 ⊆ s2
|
||||||
|
// Disjoint(s1, s2 Set) bool
|
||||||
|
// Intersection(s1, s2 Set) Set
|
||||||
|
// Union(s1, s2 Set) Set
|
||||||
|
// Difference(s1, s2 Set) Set // return s1 ∖ s2
|
||||||
|
// SymmetricDifference(s1, s2 Set) Set
|
||||||
|
//
|
||||||
|
// For Set.String, use '{' and '}', output elements as double-quoted strings
|
||||||
|
// safely escaped with Go syntax, and use a comma and a single space between
|
||||||
|
// elements. For example {"a", "b"}.
|
||||||
|
// Format the empty set as {}.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const targetTestVersion = 3
|
||||||
|
|
||||||
|
func TestTestVersion(t *testing.T) {
|
||||||
|
if testVersion != targetTestVersion {
|
||||||
|
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A first set of tests uses Set.String() to judge correctness.
|
||||||
|
|
||||||
|
func TestNew(t *testing.T) {
|
||||||
|
// New must return an empty set.
|
||||||
|
want := "{}"
|
||||||
|
if got := New().String(); got != want {
|
||||||
|
t.Fatalf(`New().String() = %s, want %s.`, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewFromSlice(t *testing.T) {
|
||||||
|
// nil slice should give empty set
|
||||||
|
want := "{}"
|
||||||
|
if got := NewFromSlice(nil).String(); got != want {
|
||||||
|
t.Fatalf(`NewFromSlice(nil) = %s, want %s.`, got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
// slice with one element:
|
||||||
|
want = `{"a"}`
|
||||||
|
if got := NewFromSlice([]string{"a"}).String(); got != want {
|
||||||
|
t.Fatalf(`NewFromSlice([]string{"a"}) = %s, want %s.`, got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
// slice with repeated element:
|
||||||
|
if got := NewFromSlice([]string{"a", "a"}).String(); got != want {
|
||||||
|
t.Fatalf(`NewFromSlice([]string{"a", "a"}) = %s, want %s.`, got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
// slice with two elements:
|
||||||
|
got := NewFromSlice([]string{"a", "b"}).String()
|
||||||
|
want1 := `{"a", "b"}`
|
||||||
|
want2 := `{"b", "a"}`
|
||||||
|
if got != want1 && got != want2 { // order undefined
|
||||||
|
t.Fatalf(`NewFromSlice([]string{"a", "b"}) = %s, want %s or (%s).`,
|
||||||
|
got, want1, want2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlice(t *testing.T) {
|
||||||
|
// empty set should produce empty slice
|
||||||
|
s := New()
|
||||||
|
if l := s.Slice(); len(l) != 0 {
|
||||||
|
t.Fatalf(`s.Slice() = %q, want []`, l)
|
||||||
|
}
|
||||||
|
|
||||||
|
// one element:
|
||||||
|
want := []string{"a"}
|
||||||
|
s = NewFromSlice(want)
|
||||||
|
got := s.Slice()
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Fatalf(`%v Slice = %q, want %q`, s, got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
// two elements:
|
||||||
|
w1 := []string{"a", "b"}
|
||||||
|
w2 := []string{"b", "a"}
|
||||||
|
s = NewFromSlice(w1)
|
||||||
|
got = s.Slice()
|
||||||
|
if !reflect.DeepEqual(got, w1) && !reflect.DeepEqual(got, w2) {
|
||||||
|
t.Fatalf(`%v Slice = %q, want %q`, s, got, w1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trusting NewFromSlice now, remaining tests are table driven, taking data
|
||||||
|
// from cases_test.go and building sets with NewFromSlice.
|
||||||
|
|
||||||
|
// test case types used in cases_test.go
|
||||||
|
type (
|
||||||
|
// binary function, bool result (Equal, Subset, Disjoint)
|
||||||
|
binBoolCase struct {
|
||||||
|
set1 []string
|
||||||
|
set2 []string
|
||||||
|
want bool
|
||||||
|
}
|
||||||
|
// unary function, bool result (IsEmpty)
|
||||||
|
unaryBoolCase struct {
|
||||||
|
set []string
|
||||||
|
want bool
|
||||||
|
}
|
||||||
|
// unary function, int result (Len)
|
||||||
|
unaryIntCase struct {
|
||||||
|
set []string
|
||||||
|
want int
|
||||||
|
}
|
||||||
|
// set-element function, bool result (Has)
|
||||||
|
eleBoolCase struct {
|
||||||
|
set []string
|
||||||
|
ele string
|
||||||
|
want bool
|
||||||
|
}
|
||||||
|
// set-element operator (Add, Delete)
|
||||||
|
eleOpCase struct {
|
||||||
|
set []string
|
||||||
|
ele string
|
||||||
|
want []string
|
||||||
|
}
|
||||||
|
// set-set operator (Union, Intersection, Difference, Symmetric-Difference)
|
||||||
|
binOpCase struct {
|
||||||
|
set1 []string
|
||||||
|
set2 []string
|
||||||
|
want []string
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// helper for testing Equal, Subset, Disjoint
|
||||||
|
func testBinBool(name string, f func(Set, Set) bool, cases []binBoolCase, t *testing.T) {
|
||||||
|
for _, tc := range cases {
|
||||||
|
s1 := NewFromSlice(tc.set1)
|
||||||
|
s2 := NewFromSlice(tc.set2)
|
||||||
|
got := f(s1, s2)
|
||||||
|
if got != tc.want {
|
||||||
|
t.Fatalf("%s(%v, %v) = %t, want %t", name, s1, s2, got, tc.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEqual(t *testing.T) {
|
||||||
|
testBinBool("Equal", Equal, eqCases, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// With Equal tested, remaining tests use it to judge correctness.
|
||||||
|
|
||||||
|
// helper for testing Add, Delete
|
||||||
|
func testEleOp(name string, op func(Set, string), cases []eleOpCase, t *testing.T) {
|
||||||
|
for _, tc := range cases {
|
||||||
|
s := NewFromSlice(tc.set)
|
||||||
|
op(s, tc.ele)
|
||||||
|
want := NewFromSlice(tc.want)
|
||||||
|
if !Equal(s, want) {
|
||||||
|
t.Fatalf("%v %s %q = %v, want %v",
|
||||||
|
NewFromSlice(tc.set), name, tc.ele, s, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAdd(t *testing.T) {
|
||||||
|
testEleOp("Add", Set.Add, addCases, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDelete(t *testing.T) {
|
||||||
|
testEleOp("Delete", Set.Delete, delCases, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHas(t *testing.T) {
|
||||||
|
for _, tc := range hasCases {
|
||||||
|
s := NewFromSlice(tc.set)
|
||||||
|
got := s.Has(tc.ele)
|
||||||
|
if got != tc.want {
|
||||||
|
t.Fatalf("%v Has %q = %t, want %t", s, tc.ele, got, tc.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsEmpty(t *testing.T) {
|
||||||
|
for _, tc := range emptyCases {
|
||||||
|
s := NewFromSlice(tc.set)
|
||||||
|
got := s.IsEmpty()
|
||||||
|
if got != tc.want {
|
||||||
|
t.Fatalf("%v IsEmpty = %t, want %t", s, got, tc.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLen(t *testing.T) {
|
||||||
|
for _, tc := range lenCases {
|
||||||
|
s := NewFromSlice(tc.set)
|
||||||
|
got := s.Len()
|
||||||
|
if got != tc.want {
|
||||||
|
t.Fatalf("%v Len = %d, want %d", s, got, tc.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSubset(t *testing.T) {
|
||||||
|
testBinBool("Subset", Subset, subsetCases, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDisjoint(t *testing.T) {
|
||||||
|
testBinBool("Disjoint", Disjoint, disjointCases, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper for testing Union, Intersection, Difference, SymmetricDifference
|
||||||
|
func testBinOp(name string, f func(Set, Set) Set, cases []binOpCase, t *testing.T) {
|
||||||
|
for _, tc := range cases {
|
||||||
|
s1 := NewFromSlice(tc.set1)
|
||||||
|
s2 := NewFromSlice(tc.set2)
|
||||||
|
want := NewFromSlice(tc.want)
|
||||||
|
got := f(s1, s2)
|
||||||
|
if !Equal(got, want) {
|
||||||
|
t.Fatalf("%s(%v, %v) = %v, want %v", name, s1, s2, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnion(t *testing.T) {
|
||||||
|
testBinOp("Union", Union, unionCases, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIntersection(t *testing.T) {
|
||||||
|
testBinOp("Intersection", Intersection, intersectionCases, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDifference(t *testing.T) {
|
||||||
|
testBinOp("Difference", Difference, differenceCases, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSymmetricDifference(t *testing.T) {
|
||||||
|
testBinOp("SymmetricDifference", SymmetricDifference, symmetricDifferenceCases, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNewFromSlice1e1(b *testing.B) { bench(1e1, b) }
|
||||||
|
func BenchmarkNewFromSlice1e2(b *testing.B) { bench(1e2, b) }
|
||||||
|
func BenchmarkNewFromSlice1e3(b *testing.B) { bench(1e3, b) }
|
||||||
|
func BenchmarkNewFromSlice1e4(b *testing.B) { bench(1e4, b) }
|
||||||
|
|
||||||
|
func bench(nAdd int, b *testing.B) {
|
||||||
|
s := make([]string, nAdd)
|
||||||
|
for i := range s {
|
||||||
|
s[i] = strconv.Itoa(rand.Intn(len(s)))
|
||||||
|
}
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
NewFromSlice(s)
|
||||||
|
}
|
||||||
|
}
|
388
go/custom-set/stringset.go
Normal file
388
go/custom-set/stringset.go
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
package stringset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const testVersion = 3
|
||||||
|
|
||||||
|
// Set is a slice of strings that you can do set operations on.
|
||||||
|
// I decided that I wanted to implement a binary tree for the storage
|
||||||
|
type Set struct {
|
||||||
|
top SetValue
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetValue struct {
|
||||||
|
value string
|
||||||
|
left *SetValue
|
||||||
|
right *SetValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns an empty Set
|
||||||
|
func New() Set {
|
||||||
|
s := new(Set)
|
||||||
|
s.top = SetValue{}
|
||||||
|
return *s
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFromSlice takes a slice of strings and returns a Set
|
||||||
|
func NewFromSlice(s []string) Set {
|
||||||
|
ret := New()
|
||||||
|
for i := range s {
|
||||||
|
ret.Add(s[i])
|
||||||
|
}
|
||||||
|
ret.balance()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds a value to the set
|
||||||
|
func (s Set) Add(v string) {
|
||||||
|
if s.top.value == "" {
|
||||||
|
s.top.value = v
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.top.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Set) PrettyPrint() {
|
||||||
|
s.pp(&s.top, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Set) pp(n *SetValue, indent int) {
|
||||||
|
if n != nil {
|
||||||
|
if n.left != nil {
|
||||||
|
s.pp(n.left, indent+4)
|
||||||
|
}
|
||||||
|
if n.right != nil {
|
||||||
|
s.pp(n.right, indent+4)
|
||||||
|
}
|
||||||
|
for ; indent > 0; indent-- {
|
||||||
|
fmt.Print(" ")
|
||||||
|
}
|
||||||
|
fmt.Println(n.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// balance balances the binary tree
|
||||||
|
func (s *Set) balance() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Set) find(v string) *SetValue {
|
||||||
|
if s.top.value != "" {
|
||||||
|
sv, _ := s.top.find(v)
|
||||||
|
return sv
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// findWithParent finds a node with a child value v
|
||||||
|
// a return of nil, nil means it's the top node
|
||||||
|
func (s *Set) findParent(v string) (*SetValue, error) {
|
||||||
|
if s.top.value == v {
|
||||||
|
// no parent, it's the top.
|
||||||
|
return nil, nil
|
||||||
|
} else {
|
||||||
|
return s.top.findParent(v)
|
||||||
|
}
|
||||||
|
return nil, errors.New("Empty Set")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Set) findHome(v *SetValue) {
|
||||||
|
if s.top.value == "" {
|
||||||
|
s.top.value = v.value
|
||||||
|
s.top.left = v.left
|
||||||
|
s.top.right = v.right
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.top.findHome(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete removes the given value from the set
|
||||||
|
func (s Set) Delete(v string) {
|
||||||
|
if sv, err := s.findParent(v); err == nil {
|
||||||
|
var cmp int
|
||||||
|
var delNode, repNode, orphan *SetValue
|
||||||
|
if sv == nil {
|
||||||
|
// Deleting 'top'
|
||||||
|
delNode = &s.top
|
||||||
|
if delNode.left != nil {
|
||||||
|
repNode = delNode.left
|
||||||
|
orphan = delNode.right
|
||||||
|
} else if delNode.right != nil {
|
||||||
|
repNode = delNode.right
|
||||||
|
}
|
||||||
|
if repNode == nil {
|
||||||
|
// No node to replace it with, we're done
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.top = *repNode
|
||||||
|
} else {
|
||||||
|
cmp = strings.Compare(v, sv.value)
|
||||||
|
if cmp < 0 && sv.left != nil {
|
||||||
|
fmt.Println(" Left: " + sv.left.value)
|
||||||
|
// It's the left node
|
||||||
|
delNode = sv.left
|
||||||
|
} else if cmp > 0 && sv.right != nil {
|
||||||
|
fmt.Println(" Right: " + sv.right.value)
|
||||||
|
// It's the right node
|
||||||
|
delNode = sv.right
|
||||||
|
}
|
||||||
|
if delNode == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if delNode.left != nil {
|
||||||
|
repNode = delNode.left
|
||||||
|
orphan = delNode.right
|
||||||
|
} else if delNode.right != nil {
|
||||||
|
repNode = delNode.right
|
||||||
|
}
|
||||||
|
if repNode == nil {
|
||||||
|
// No replacement node, we're done
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if cmp < 0 {
|
||||||
|
sv.left = repNode
|
||||||
|
} else if cmp > 0 {
|
||||||
|
sv.right = repNode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we have an orphaned branch, find it a home
|
||||||
|
if orphan != nil {
|
||||||
|
s.findHome(orphan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has returns if the set contains the given value.
|
||||||
|
func (s *Set) Has(v string) bool {
|
||||||
|
return s.find(v) != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty returns whether the set is empty or not.
|
||||||
|
func (s *Set) IsEmpty() bool {
|
||||||
|
return s.top.value == ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of values in the set
|
||||||
|
func (s *Set) Len() int {
|
||||||
|
if !s.IsEmpty() {
|
||||||
|
return s.top.Len()
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slice returns a string slice of the set
|
||||||
|
func (s Set) Slice() []string {
|
||||||
|
if !s.IsEmpty() {
|
||||||
|
return s.top.Slice()
|
||||||
|
}
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String converts the set to a string
|
||||||
|
func (s Set) String() string {
|
||||||
|
ret := "{"
|
||||||
|
if s.top.value != "" {
|
||||||
|
ret += s.top.String()
|
||||||
|
}
|
||||||
|
ret += "}"
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// find looks for a node with value val, it either returns the node
|
||||||
|
// or an error stating it couldn't find it.
|
||||||
|
func (sv *SetValue) find(val string) (*SetValue, error) {
|
||||||
|
if sv.value == val {
|
||||||
|
return sv, nil
|
||||||
|
}
|
||||||
|
cmp := strings.Compare(val, sv.value)
|
||||||
|
if cmp < 0 && sv.left != nil {
|
||||||
|
return sv.left.find(val)
|
||||||
|
}
|
||||||
|
if cmp > 0 && sv.right != nil {
|
||||||
|
return sv.right.find(val)
|
||||||
|
}
|
||||||
|
return nil, errors.New("Value not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// findParent looks for the parent of the node with value val
|
||||||
|
// If nil, nil is returned, it _is_ this node.
|
||||||
|
func (sv *SetValue) findParent(val string) (*SetValue, error) {
|
||||||
|
if sv.value == val {
|
||||||
|
// This should only trigger if this is the top node of the tree
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
cmp := strings.Compare(val, sv.value)
|
||||||
|
if cmp < 0 && sv.left != nil {
|
||||||
|
if sv.left.value == val {
|
||||||
|
return sv, nil
|
||||||
|
}
|
||||||
|
return sv.left.findParent(val)
|
||||||
|
}
|
||||||
|
if cmp > 0 && sv.right != nil {
|
||||||
|
if sv.right.value == val {
|
||||||
|
return sv, nil
|
||||||
|
}
|
||||||
|
return sv.right.findParent(val)
|
||||||
|
}
|
||||||
|
return nil, errors.New("Value not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sv *SetValue) findHome(v *SetValue) {
|
||||||
|
cmp := strings.Compare(v.value, sv.value)
|
||||||
|
if cmp < 0 {
|
||||||
|
if sv.left == nil {
|
||||||
|
sv.left = v
|
||||||
|
} else {
|
||||||
|
sv.left.findHome(v)
|
||||||
|
}
|
||||||
|
} else if cmp > 0 {
|
||||||
|
if sv.right == nil {
|
||||||
|
sv.right = v
|
||||||
|
} else {
|
||||||
|
sv.right.findHome(v)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Discard the top node, find homes for it's children
|
||||||
|
if v.left != nil {
|
||||||
|
sv.findHome(v.left)
|
||||||
|
}
|
||||||
|
if v.right != nil {
|
||||||
|
sv.findHome(v.right)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sv *SetValue) Add(v string) {
|
||||||
|
cmp := strings.Compare(v, sv.value)
|
||||||
|
if cmp < 0 {
|
||||||
|
if sv.left == nil {
|
||||||
|
sv.left = &SetValue{value: v}
|
||||||
|
} else {
|
||||||
|
sv.left.Add(v)
|
||||||
|
}
|
||||||
|
} else if cmp > 0 {
|
||||||
|
if sv.right == nil {
|
||||||
|
sv.right = &SetValue{value: v}
|
||||||
|
} else {
|
||||||
|
sv.right.Add(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns how many elements are in the branches
|
||||||
|
func (sv *SetValue) Len() int {
|
||||||
|
ret := 1
|
||||||
|
if sv.left != nil {
|
||||||
|
ret += sv.left.Len()
|
||||||
|
}
|
||||||
|
if sv.right != nil {
|
||||||
|
ret += sv.right.Len()
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has checks if this branch contains the value v
|
||||||
|
func (sv *SetValue) Has(v string) bool {
|
||||||
|
ret, _ := sv.find(v)
|
||||||
|
return ret != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String gets a string value of this branch
|
||||||
|
func (sv *SetValue) String() string {
|
||||||
|
var ret string
|
||||||
|
if sv.left != nil {
|
||||||
|
ret += sv.left.String() + ", "
|
||||||
|
}
|
||||||
|
ret += "\"" + sv.value + "\""
|
||||||
|
if sv.right != nil {
|
||||||
|
ret += ", " + sv.right.String()
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slice returns a string slice of all values in the branch
|
||||||
|
func (sv *SetValue) Slice() []string {
|
||||||
|
var ret []string
|
||||||
|
if sv.left != nil {
|
||||||
|
ret = sv.left.Slice()
|
||||||
|
}
|
||||||
|
ret = append(ret, sv.value)
|
||||||
|
if sv.right != nil {
|
||||||
|
ret = append(ret, sv.right.Slice()...)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal returns whether the given sets are the same.
|
||||||
|
func Equal(s1, s2 Set) bool {
|
||||||
|
return s1.String() == s2.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subset returns whether s1 is a subset of s2.
|
||||||
|
func Subset(s1, s2 Set) bool {
|
||||||
|
if s1.Len() == 0 || s2.Len() == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
s1Sl := s1.Slice()
|
||||||
|
for i := range s1Sl {
|
||||||
|
if !s2.Has(s1Sl[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disjoint returns whether two sets _do not_ intersect
|
||||||
|
func Disjoint(s1, s2 Set) bool {
|
||||||
|
s1Sl := s1.Slice()
|
||||||
|
for i := range s1Sl {
|
||||||
|
if s2.Has(s1Sl[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intersection finds elements that exist in both sets and makes a new
|
||||||
|
// set of them
|
||||||
|
func Intersection(s1, s2 Set) Set {
|
||||||
|
var vals []string
|
||||||
|
s1Sl := s1.Slice()
|
||||||
|
for i := range s1Sl {
|
||||||
|
if s2.Has(s1Sl[i]) {
|
||||||
|
vals = append(vals, s1Sl[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NewFromSlice(vals)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union gets all elements in both sets and makes a new set with them.
|
||||||
|
func Union(s1, s2 Set) Set {
|
||||||
|
var vals []string
|
||||||
|
vals = append(vals, s1.Slice()...)
|
||||||
|
vals = append(vals, s2.Slice()...)
|
||||||
|
return NewFromSlice(vals)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Difference returns a Set of all elements in s1 that aren't in s2
|
||||||
|
func Difference(s1, s2 Set) Set {
|
||||||
|
var vals []string
|
||||||
|
s1Sl := s1.Slice()
|
||||||
|
for i := range s1Sl {
|
||||||
|
if !s2.Has(s1Sl[i]) {
|
||||||
|
vals = append(vals, s1Sl[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NewFromSlice(vals)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SymmetricDifference returns all elements from s1 & s2 that occur in only one of the
|
||||||
|
// sets.
|
||||||
|
func SymmetricDifference(s1, s2 Set) Set {
|
||||||
|
return Union(Difference(s1, s2), Difference(s2, s1))
|
||||||
|
}
|
19
haskell/leap/package.yaml
Normal file
19
haskell/leap/package.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name: leap
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- base
|
||||||
|
|
||||||
|
library:
|
||||||
|
exposed-modules: LeapYear
|
||||||
|
source-dirs: src
|
||||||
|
dependencies:
|
||||||
|
# - foo # List here the packages you
|
||||||
|
# - bar # want to use in your solution.
|
||||||
|
|
||||||
|
tests:
|
||||||
|
test:
|
||||||
|
main: Tests.hs
|
||||||
|
source-dirs: test
|
||||||
|
dependencies:
|
||||||
|
- leap
|
||||||
|
- HUnit
|
3
haskell/leap/src/LeapYear.hs
Normal file
3
haskell/leap/src/LeapYear.hs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module LeapYear (isLeapYear) where
|
||||||
|
|
||||||
|
isLeapYear = undefined
|
1
haskell/leap/stack.yaml
Normal file
1
haskell/leap/stack.yaml
Normal file
@ -0,0 +1 @@
|
|||||||
|
resolver: nightly-2016-07-17
|
31
haskell/leap/test/Tests.hs
Normal file
31
haskell/leap/test/Tests.hs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
|
||||||
|
|
||||||
|
import Control.Monad (unless)
|
||||||
|
import System.Exit (exitFailure)
|
||||||
|
|
||||||
|
import Test.HUnit
|
||||||
|
( (~:)
|
||||||
|
, (~=?)
|
||||||
|
, Counts (failures, errors)
|
||||||
|
, Test (TestList)
|
||||||
|
, runTestTT
|
||||||
|
)
|
||||||
|
|
||||||
|
import LeapYear (isLeapYear)
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
counts <- runTestTT isLeapYearTests
|
||||||
|
unless (failures counts == 0 && errors counts == 0) exitFailure
|
||||||
|
|
||||||
|
isLeapYearTests :: Test
|
||||||
|
isLeapYearTests = TestList $ map test cases
|
||||||
|
where
|
||||||
|
test (label, year, expected) = label ~: isLeapYear year ~=? expected
|
||||||
|
cases = [ ("leap year" , 1996, True )
|
||||||
|
, ("standard and odd year" , 1997, False)
|
||||||
|
, ("standard even year" , 1998, False)
|
||||||
|
, ("standard nineteenth century", 1900, False)
|
||||||
|
, ("standard eighteenth century", 1800, False)
|
||||||
|
, ("leap twenty fourth century" , 2400, True )
|
||||||
|
, ("leap y2k" , 2000, True ) ]
|
@ -1 +1 @@
|
|||||||
hamming
|
robot-name
|
25
java/robot-name/README.md
Normal file
25
java/robot-name/README.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Robot Name
|
||||||
|
|
||||||
|
Write a program that manages robot factory settings.
|
||||||
|
|
||||||
|
When robots come off the factory floor, they have no name.
|
||||||
|
|
||||||
|
The first time you boot them up, a random name is generated in the format
|
||||||
|
of two uppercase letters followed by three digits, such as RX837 or BC811.
|
||||||
|
|
||||||
|
Every once in a while we need to reset a robot to its factory settings,
|
||||||
|
which means that their name gets wiped. The next time you ask, it will
|
||||||
|
respond with a new random name.
|
||||||
|
|
||||||
|
The names must be random: they should not follow a predictable sequence.
|
||||||
|
Random names means a risk of collisions. Your solution should not allow
|
||||||
|
the use of the same name twice when avoidable. In some exercism language
|
||||||
|
tracks there are tests to ensure that the same name is never used twice.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
A debugging session with Paul Blackwell at gSchool. [http://gschool.it](http://gschool.it)
|
||||||
|
|
||||||
|
## Submitting Incomplete Problems
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
12
java/robot-name/build.gradle
Normal file
12
java/robot-name/build.gradle
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
apply plugin: "java"
|
||||||
|
apply plugin: "eclipse"
|
||||||
|
apply plugin: "idea"
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testCompile "junit:junit:4.10"
|
||||||
|
}
|
||||||
|
|
0
java/robot-name/src/main/java/.keep
Normal file
0
java/robot-name/src/main/java/.keep
Normal file
35
java/robot-name/src/test/java/RobotTest.java
Normal file
35
java/robot-name/src/test/java/RobotTest.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.hamcrest.core.Is.is;
|
||||||
|
import static org.hamcrest.core.IsNot.not;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
public class RobotTest {
|
||||||
|
|
||||||
|
private static final String EXPECTED_ROBOT_NAME_PATTERN = "[A-Z]{2}\\d{3}";
|
||||||
|
private final Robot robot = new Robot();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hasName() {
|
||||||
|
assertIsValidName(robot.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void differentRobotsHaveDifferentNames() {
|
||||||
|
assertThat(robot.getName(), not(equalTo(new Robot().getName())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void resetName() {
|
||||||
|
final String name = robot.getName();
|
||||||
|
robot.reset();
|
||||||
|
final String name2 = robot.getName();
|
||||||
|
assertThat(name, not(equalTo(name2)));
|
||||||
|
assertIsValidName(name2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertIsValidName(String name) {
|
||||||
|
assertThat(name.matches(EXPECTED_ROBOT_NAME_PATTERN), is(true));
|
||||||
|
}
|
||||||
|
}
|
1
kotlin/current
Symbolic link
1
kotlin/current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
hello-world
|
48
kotlin/hello-world/README.md
Normal file
48
kotlin/hello-world/README.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Hello World
|
||||||
|
|
||||||
|
Write a function that greets the user by name, or by saying "Hello, World!" if no name is given.
|
||||||
|
|
||||||
|
["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is the traditional first program for beginning programming in a new language.
|
||||||
|
|
||||||
|
**Note:** You can skip this exercise by running:
|
||||||
|
|
||||||
|
exercism skip $LANGUAGE hello-world
|
||||||
|
|
||||||
|
## Specification
|
||||||
|
|
||||||
|
Write a `Hello World!` function that can greet someone given their name.
|
||||||
|
The function should return the appropriate greeting.
|
||||||
|
|
||||||
|
For an input of "Alice", the response should be "Hello, Alice!".
|
||||||
|
|
||||||
|
If a name is not given, the response should be "Hello, World!"
|
||||||
|
|
||||||
|
## Test-Driven Development
|
||||||
|
|
||||||
|
As programmers mature, they eventually want to test their code.
|
||||||
|
|
||||||
|
Here at Exercism we simulate [Test-Driven Development](http://en.wikipedia.org/wiki/Test-driven_development) (TDD), where you write your tests before writing any functionality. The simulation comes in the form of a pre-written test suite, which will signal that you have solved the problem.
|
||||||
|
|
||||||
|
It will also provide you with a safety net to explore other solutions without breaking the functionality.
|
||||||
|
|
||||||
|
### A typical TDD workflow on Exercism:
|
||||||
|
|
||||||
|
1. Run the test file and pick one test that's failing.
|
||||||
|
2. Write some code to fix the test you picked.
|
||||||
|
3. Re-run the tests to confirm the test is now passing.
|
||||||
|
4. Repeat from step 1.
|
||||||
|
5. Submit your solution (`exercism submit /path/to/file`)
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Submissions are encouraged to be general, within reason. Having said that, it's also important not to over-engineer a solution.
|
||||||
|
|
||||||
|
It's important to remember that the goal is to make code as expressive and readable as we can. However, solutions to the hello-world exercise will not be reviewed by a person, but by rikki- the robot, who will offer an encouraging word.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||||
|
|
||||||
|
## Submitting Incomplete Problems
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
22
kotlin/hello-world/build.gradle
Normal file
22
kotlin/hello-world/build.gradle
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
buildscript {
|
||||||
|
ext.kotlin_version = '1.0.2'
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'kotlin'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
|
||||||
|
testCompile 'junit:junit:4.12'
|
||||||
|
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
|
||||||
|
}
|
31
kotlin/hello-world/src/main/kotlin/HelloWorld.kt
Normal file
31
kotlin/hello-world/src/main/kotlin/HelloWorld.kt
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Simple HelloWorld singleton class as defined by the `Kotlin object keyword`.
|
||||||
|
* See: https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations
|
||||||
|
*
|
||||||
|
* As an alternative one could create a class such as:
|
||||||
|
* ```
|
||||||
|
* class HelloWorld(name: String? = "Default Value") {
|
||||||
|
* fun hello(): String {
|
||||||
|
*
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* Resulting in a call such as: `HelloWorld("Bob").hello()`
|
||||||
|
* See: https://kotlinlang.org/docs/reference/classes.html#constructors
|
||||||
|
*
|
||||||
|
* In Kotlin we make objects defined as nullable via the trailing `?`, if you try
|
||||||
|
* to assign a null value to any value that isn't nullable a compilation error is thrown.
|
||||||
|
* Kotlin makes sure you are accessing nullable values safely and provides null safe calls
|
||||||
|
* and the use of the elvis operator. See: https://kotlinlang.org/docs/reference/null-safety.html
|
||||||
|
*
|
||||||
|
* You may provide default values on methods, so if an argument is omitted the default is used.
|
||||||
|
* See: https://kotlinlang.org/docs/reference/functions.html#default-arguments
|
||||||
|
*
|
||||||
|
* Kotlin provides String interpolation to make String formatting simple.
|
||||||
|
* See: https://kotlinlang.org/docs/reference/idioms.html#string-interpolation
|
||||||
|
*/
|
||||||
|
object HelloWorld {
|
||||||
|
fun hello(name: String? = "Default Argument"): String {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
32
kotlin/hello-world/src/test/kotlin/HelloWorldTest.kt
Normal file
32
kotlin/hello-world/src/test/kotlin/HelloWorldTest.kt
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import kotlin.test.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class HelloWorldTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun helloNoName() {
|
||||||
|
assertEquals("Hello, World!", HelloWorld.hello())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun helloBlankName() {
|
||||||
|
assertEquals("Hello, World!", HelloWorld.hello(""))
|
||||||
|
assertEquals("Hello, World!", HelloWorld.hello(" "))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun helloNullName() {
|
||||||
|
//This isn't advised in Kotlin but demonstrates the null safety in Kotlin
|
||||||
|
assertEquals("Hello, World!", HelloWorld.hello(null))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun helloSampleName() {
|
||||||
|
assertEquals("Hello, Alice!", HelloWorld.hello("Alice"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun helloAnotherSampleName() {
|
||||||
|
assertEquals("Hello, Bob!", HelloWorld.hello("Bob"))
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
point-mutations
|
hamming
|
90
lisp/hamming/README.md
Normal file
90
lisp/hamming/README.md
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
# Hamming
|
||||||
|
|
||||||
|
Write a program that can calculate the Hamming difference between two DNA strands.
|
||||||
|
|
||||||
|
A mutation is simply a mistake that occurs during the creation or
|
||||||
|
copying of a nucleic acid, in particular DNA. Because nucleic acids are
|
||||||
|
vital to cellular functions, mutations tend to cause a ripple effect
|
||||||
|
throughout the cell. Although mutations are technically mistakes, a very
|
||||||
|
rare mutation may equip the cell with a beneficial attribute. In fact,
|
||||||
|
the macro effects of evolution are attributable by the accumulated
|
||||||
|
result of beneficial microscopic mutations over many generations.
|
||||||
|
|
||||||
|
The simplest and most common type of nucleic acid mutation is a point
|
||||||
|
mutation, which replaces one base with another at a single nucleotide.
|
||||||
|
|
||||||
|
By counting the number of differences between two homologous DNA strands
|
||||||
|
taken from different genomes with a common ancestor, we get a measure of
|
||||||
|
the minimum number of point mutations that could have occurred on the
|
||||||
|
evolutionary path between the two strands.
|
||||||
|
|
||||||
|
This is called the 'Hamming distance'.
|
||||||
|
|
||||||
|
It is found by comparing two DNA strands and counting how many of the
|
||||||
|
nucleotides are different from their equivalent in the other string.
|
||||||
|
|
||||||
|
GAGCCTACTAACGGGAT
|
||||||
|
CATCGTAATGACGGCCT
|
||||||
|
^ ^ ^ ^ ^ ^^
|
||||||
|
|
||||||
|
The Hamming distance between these two DNA strands is 7.
|
||||||
|
|
||||||
|
# Implementation notes
|
||||||
|
|
||||||
|
The Hamming distance is only defined for sequences of equal length. This means
|
||||||
|
that based on the definition, each language could deal with getting sequences
|
||||||
|
of equal length differently.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Check out [Exercism Help](http://exercism.io/languages/lisp) for instructions to
|
||||||
|
get started writing Common Lisp. That page will explain how to install and setup
|
||||||
|
a Lisp implementation and how to run the tests.
|
||||||
|
|
||||||
|
## Formatting
|
||||||
|
|
||||||
|
While Common Lisp doesn't care about indentation and layout of code,
|
||||||
|
nor whether you use spaces or tabs, this is an important consideration
|
||||||
|
for submissions to exercism.io. Excercism.io's code widget cannot
|
||||||
|
handle mixing of tab and space characters well so using only spaces is recommended to make
|
||||||
|
the code more readable to the human reviewers. Please review your
|
||||||
|
editors settings on how to accomplish this. Below are instructions for
|
||||||
|
popular editors for Common Lisp.
|
||||||
|
|
||||||
|
### VIM
|
||||||
|
|
||||||
|
Use the following commands to ensure VIM uses only spaces for
|
||||||
|
indentation:
|
||||||
|
|
||||||
|
```vimscript
|
||||||
|
:set tabstop=2
|
||||||
|
:set shiftwidth=2
|
||||||
|
:set expandtab
|
||||||
|
```
|
||||||
|
|
||||||
|
(or as a oneliner `:set tabstop=2 shiftwidth=2 expandtab`). This can
|
||||||
|
be added to your `~/.vimrc` file to use it all the time.
|
||||||
|
|
||||||
|
### Emacs
|
||||||
|
|
||||||
|
Emacs is very well suited for editing Common Lisp and has many
|
||||||
|
powerful add-on packages available. The only thing that one needs to
|
||||||
|
do with a stock emacs to make it work well with exercism.io is to
|
||||||
|
evaluate the following code:
|
||||||
|
|
||||||
|
`(setq indent-tab-mode nil)`
|
||||||
|
|
||||||
|
This can be placed in your `~/.emacs` (or `~/.emacs.d/init.el`) in
|
||||||
|
order to have it set whenever Emacs is launched.
|
||||||
|
|
||||||
|
One suggested add-on for Emacs and Common Lisp is
|
||||||
|
[SLIME](https://github.com/slime/slime) which offers tight integration
|
||||||
|
with the REPL; making iterative coding and testing very easy.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
The Calculating Point Mutations problem at Rosalind [http://rosalind.info/problems/hamm/](http://rosalind.info/problems/hamm/)
|
||||||
|
|
||||||
|
## Submitting Incomplete Problems
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
33
lisp/hamming/hamming-test.lisp
Normal file
33
lisp/hamming/hamming-test.lisp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
(ql:quickload "lisp-unit")
|
||||||
|
|
||||||
|
#-xlisp-test (load "hamming")
|
||||||
|
|
||||||
|
(defpackage #:hamming-test
|
||||||
|
(:use #:common-lisp #:lisp-unit))
|
||||||
|
|
||||||
|
(in-package #:hamming-test)
|
||||||
|
|
||||||
|
(define-test no-difference-between-empty-strands
|
||||||
|
(assert-equal 0 (hamming:distance "" "")))
|
||||||
|
|
||||||
|
(define-test no-difference-between-identical-strands
|
||||||
|
(assert-equal 0 (hamming:distance "GGACTGA" "GGACTGA")))
|
||||||
|
|
||||||
|
(define-test complete-hamming-distance-in-small-strand
|
||||||
|
(assert-equal 3 (hamming:distance "ACT" "GGA")))
|
||||||
|
|
||||||
|
(define-test small-hamming-distance-in-middle-somewhere
|
||||||
|
(assert-equal 1 (hamming:distance "GGACG" "GGTCG")))
|
||||||
|
|
||||||
|
(define-test larger-distance
|
||||||
|
(assert-equal 2 (hamming:distance "ACCAGGG" "ACTATGG")))
|
||||||
|
|
||||||
|
(define-test invalid-to-get-distance-for-different-length-strings
|
||||||
|
(assert-equal nil (hamming:distance "AGACAACAGCCAGCCGCCGGATT" "AGGCAA"))
|
||||||
|
(assert-equal nil (hamming:distance "AGACAACAGCCAGCCGCCGGATT" "AGACATCTTTCAGCCGCCGGATTAGGCAA"))
|
||||||
|
(assert-equal nil (hamming:distance "AGG" "AGACAACAGCCAGCCGCCGGATT")))
|
||||||
|
|
||||||
|
#-xlisp-test
|
||||||
|
(let ((*print-errors* t)
|
||||||
|
(*print-failures* t))
|
||||||
|
(run-tests :all :hamming-test))
|
9
lisp/hamming/hamming.lisp
Normal file
9
lisp/hamming/hamming.lisp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
(defpackage #:hamming
|
||||||
|
(:use #:cl)
|
||||||
|
(:export #:distance))
|
||||||
|
|
||||||
|
(in-package #:hamming)
|
||||||
|
|
||||||
|
(defun distance (dna1 dna2)
|
||||||
|
"Number of positional differences in two equal length dna strands."
|
||||||
|
)
|
5
ocaml/bob/.merlin
Normal file
5
ocaml/bob/.merlin
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
PKG findlib
|
||||||
|
PKG core
|
||||||
|
PKG ounit
|
||||||
|
S *
|
||||||
|
B *
|
@ -1 +1 @@
|
|||||||
hamming
|
hello-world
|
61
php/hello-world/README.md
Normal file
61
php/hello-world/README.md
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# Hello World
|
||||||
|
|
||||||
|
Write a function that greets the user by name, or by saying "Hello, World!" if no name is given.
|
||||||
|
|
||||||
|
["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is the traditional first program for beginning programming in a new language.
|
||||||
|
|
||||||
|
**Note:** You can skip this exercise by running:
|
||||||
|
|
||||||
|
exercism skip $LANGUAGE hello-world
|
||||||
|
|
||||||
|
## Specification
|
||||||
|
|
||||||
|
Write a `Hello World!` function that can greet someone given their name.
|
||||||
|
The function should return the appropriate greeting.
|
||||||
|
|
||||||
|
For an input of "Alice", the response should be "Hello, Alice!".
|
||||||
|
|
||||||
|
If a name is not given, the response should be "Hello, World!"
|
||||||
|
|
||||||
|
## Test-Driven Development
|
||||||
|
|
||||||
|
As programmers mature, they eventually want to test their code.
|
||||||
|
|
||||||
|
Here at Exercism we simulate [Test-Driven Development](http://en.wikipedia.org/wiki/Test-driven_development) (TDD), where you write your tests before writing any functionality. The simulation comes in the form of a pre-written test suite, which will signal that you have solved the problem.
|
||||||
|
|
||||||
|
It will also provide you with a safety net to explore other solutions without breaking the functionality.
|
||||||
|
|
||||||
|
### A typical TDD workflow on Exercism:
|
||||||
|
|
||||||
|
1. Run the test file and pick one test that's failing.
|
||||||
|
2. Write some code to fix the test you picked.
|
||||||
|
3. Re-run the tests to confirm the test is now passing.
|
||||||
|
4. Repeat from step 1.
|
||||||
|
5. Submit your solution (`exercism submit /path/to/file`)
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Submissions are encouraged to be general, within reason. Having said that, it's also important not to over-engineer a solution.
|
||||||
|
|
||||||
|
It's important to remember that the goal is to make code as expressive and readable as we can. However, solutions to the hello-world exercise will not be reviewed by a person, but by rikki- the robot, who will offer an encouraging word.
|
||||||
|
|
||||||
|
## Making the Test Suite Pass
|
||||||
|
|
||||||
|
1. Get [PHPUnit].
|
||||||
|
|
||||||
|
% wget --no-check-certificate https://phar.phpunit.de/phpunit.phar
|
||||||
|
% chmod +x phpunit.phar
|
||||||
|
|
||||||
|
2. Execute the tests for an assignment.
|
||||||
|
|
||||||
|
% phpunit.phar wordy/wordy_test.php
|
||||||
|
|
||||||
|
[PHPUnit]: http://phpunit.de
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||||
|
|
||||||
|
## Submitting Incomplete Problems
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||||
|
|
13
php/hello-world/hello-world.php
Normal file
13
php/hello-world/hello-world.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is only a SKELETON file for the "Hello World" exercise.
|
||||||
|
// It's been provided as a convenience to get you started writing code faster.
|
||||||
|
//
|
||||||
|
|
||||||
|
function helloWorld($name = null)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// YOUR CODE GOES HERE
|
||||||
|
//
|
||||||
|
}
|
21
php/hello-world/hello-world_test.php
Normal file
21
php/hello-world/hello-world_test.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require "hello-world.php";
|
||||||
|
|
||||||
|
class HelloWorldTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
public function testNoName()
|
||||||
|
{
|
||||||
|
$this->assertEquals('Hello, World!', helloWorld());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSampleName()
|
||||||
|
{
|
||||||
|
$this->assertEquals('Hello, Alice!', helloWorld('Alice'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAnotherSampleName()
|
||||||
|
{
|
||||||
|
$this->assertEquals('Hello, Bob!', helloWorld('Bob'));
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
hello-world
|
leap
|
Loading…
Reference in New Issue
Block a user