diff --git a/clojure/hello-world/src/hello_world.clj b/clojure/hello-world/src/hello_world.clj new file mode 100644 index 0000000..ef6258f --- /dev/null +++ b/clojure/hello-world/src/hello_world.clj @@ -0,0 +1,5 @@ +(ns hello-world) + +(defn hello [] ;; <- arglist goes here + ;; your code goes here +) diff --git a/crystal/current b/crystal/current new file mode 120000 index 0000000..bdd51cc --- /dev/null +++ b/crystal/current @@ -0,0 +1 @@ +hello-world \ No newline at end of file diff --git a/crystal/hello-world/GETTING_STARTED.md b/crystal/hello-world/GETTING_STARTED.md new file mode 100644 index 0000000..6914987 --- /dev/null +++ b/crystal/hello-world/GETTING_STARTED.md @@ -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` diff --git a/crystal/hello-world/README.md b/crystal/hello-world/README.md new file mode 100644 index 0000000..0061aab --- /dev/null +++ b/crystal/hello-world/README.md @@ -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. + diff --git a/crystal/hello-world/hello_world_spec.cr b/crystal/hello-world/hello_world_spec.cr new file mode 100644 index 0000000..fa89d00 --- /dev/null +++ b/crystal/hello-world/hello_world_spec.cr @@ -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 diff --git a/dlang/current b/dlang/current new file mode 120000 index 0000000..bdd51cc --- /dev/null +++ b/dlang/current @@ -0,0 +1 @@ +hello-world \ No newline at end of file diff --git a/dlang/hello-world/README.md b/dlang/hello-world/README.md new file mode 100644 index 0000000..9a89789 --- /dev/null +++ b/dlang/hello-world/README.md @@ -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. + diff --git a/dlang/hello-world/hello_test.d b/dlang/hello-world/hello_test.d new file mode 100644 index 0000000..27fbc9b --- /dev/null +++ b/dlang/hello-world/hello_test.d @@ -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."); +} diff --git a/elixir/current b/elixir/current index bdd51cc..2529de8 120000 --- a/elixir/current +++ b/elixir/current @@ -1 +1 @@ -hello-world \ No newline at end of file +bob \ No newline at end of file diff --git a/elm/current b/elm/current new file mode 120000 index 0000000..bdd51cc --- /dev/null +++ b/elm/current @@ -0,0 +1 @@ +hello-world \ No newline at end of file diff --git a/elm/hello-world/HelloWorld.elm b/elm/hello-world/HelloWorld.elm new file mode 100644 index 0000000..731e3fb --- /dev/null +++ b/elm/hello-world/HelloWorld.elm @@ -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! +-} diff --git a/elm/hello-world/HelloWorldTests.elm b/elm/hello-world/HelloWorldTests.elm new file mode 100644 index 0000000..6bb3b1c --- /dev/null +++ b/elm/hello-world/HelloWorldTests.elm @@ -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 diff --git a/elm/hello-world/README.md b/elm/hello-world/README.md new file mode 100644 index 0000000..9f4e110 --- /dev/null +++ b/elm/hello-world/README.md @@ -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. + diff --git a/elm/hello-world/elm-package.json b/elm/hello-world/elm-package.json new file mode 100644 index 0000000..1ab2bdf --- /dev/null +++ b/elm/hello-world/elm-package.json @@ -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" +} diff --git a/elm/hello-world/runtests.bat b/elm/hello-world/runtests.bat new file mode 100644 index 0000000..2a38cd8 --- /dev/null +++ b/elm/hello-world/runtests.bat @@ -0,0 +1,4 @@ +@echo off +for %%f in (*Tests.elm) do ( + elm-make %%f --yes --output build.js && node build.js +) diff --git a/elm/hello-world/runtests.sh b/elm/hello-world/runtests.sh new file mode 100644 index 0000000..2bed7b2 --- /dev/null +++ b/elm/hello-world/runtests.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +elm-make *Tests.elm --yes --output build.js && node build.js diff --git a/fsharp/current b/fsharp/current index bfcf9aa..bdd51cc 120000 --- a/fsharp/current +++ b/fsharp/current @@ -1 +1 @@ -sum-of-multiples \ No newline at end of file +hello-world \ No newline at end of file diff --git a/fsharp/hello-world/HelloWorldTest.fs b/fsharp/hello-world/HelloWorldTest.fs new file mode 100644 index 0000000..25f3ee7 --- /dev/null +++ b/fsharp/hello-world/HelloWorldTest.fs @@ -0,0 +1,19 @@ +module HelloWorldTest + +open NUnit.Framework + +open HelloWorld + +[] +let ``No name`` () = + Assert.That(hello None, Is.EqualTo("Hello, World!")) + +[] +[] +let ``Sample name`` () = + Assert.That(hello (Some "Alice"), Is.EqualTo("Hello, Alice!")) + +[] +[] +let ``Other sample name`` () = + Assert.That(hello (Some "Bob"), Is.EqualTo("Hello, Bob!")) \ No newline at end of file diff --git a/fsharp/hello-world/README.md b/fsharp/hello-world/README.md new file mode 100644 index 0000000..9f4e110 --- /dev/null +++ b/fsharp/hello-world/README.md @@ -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. + diff --git a/go/current b/go/current index 8f1726f..bcc6b93 120000 --- a/go/current +++ b/go/current @@ -1 +1 @@ -react \ No newline at end of file +custom-set \ No newline at end of file diff --git a/go/custom-set/README.md b/go/custom-set/README.md new file mode 100644 index 0000000..85f2cb3 --- /dev/null +++ b/go/custom-set/README.md @@ -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. + diff --git a/go/custom-set/cases_test.go b/go/custom-set/cases_test.go new file mode 100644 index 0000000..90523b8 --- /dev/null +++ b/go/custom-set/cases_test.go @@ -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"}, + }, +} diff --git a/go/custom-set/cmd/cmd b/go/custom-set/cmd/cmd new file mode 100755 index 0000000..8bd1f22 Binary files /dev/null and b/go/custom-set/cmd/cmd differ diff --git a/go/custom-set/cmd/main.go b/go/custom-set/cmd/main.go new file mode 100644 index 0000000..b993aab --- /dev/null +++ b/go/custom-set/cmd/main.go @@ -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()) +} diff --git a/go/custom-set/custom_set_test.go b/go/custom-set/custom_set_test.go new file mode 100644 index 0000000..7b8d0ba --- /dev/null +++ b/go/custom-set/custom_set_test.go @@ -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) + } +} diff --git a/go/custom-set/stringset.go b/go/custom-set/stringset.go new file mode 100644 index 0000000..b126270 --- /dev/null +++ b/go/custom-set/stringset.go @@ -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)) +} diff --git a/haskell/leap/package.yaml b/haskell/leap/package.yaml new file mode 100644 index 0000000..c8ff09b --- /dev/null +++ b/haskell/leap/package.yaml @@ -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 diff --git a/haskell/leap/src/LeapYear.hs b/haskell/leap/src/LeapYear.hs new file mode 100644 index 0000000..f9675bc --- /dev/null +++ b/haskell/leap/src/LeapYear.hs @@ -0,0 +1,3 @@ +module LeapYear (isLeapYear) where + +isLeapYear = undefined diff --git a/haskell/leap/stack.yaml b/haskell/leap/stack.yaml new file mode 100644 index 0000000..657fb00 --- /dev/null +++ b/haskell/leap/stack.yaml @@ -0,0 +1 @@ +resolver: nightly-2016-07-17 diff --git a/haskell/leap/test/Tests.hs b/haskell/leap/test/Tests.hs new file mode 100644 index 0000000..63b7e1b --- /dev/null +++ b/haskell/leap/test/Tests.hs @@ -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 ) ] diff --git a/java/current b/java/current index 547c5c3..b6dcd94 120000 --- a/java/current +++ b/java/current @@ -1 +1 @@ -hamming \ No newline at end of file +robot-name \ No newline at end of file diff --git a/java/robot-name/README.md b/java/robot-name/README.md new file mode 100644 index 0000000..90fd7be --- /dev/null +++ b/java/robot-name/README.md @@ -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. + diff --git a/java/robot-name/build.gradle b/java/robot-name/build.gradle new file mode 100644 index 0000000..1dd4b23 --- /dev/null +++ b/java/robot-name/build.gradle @@ -0,0 +1,12 @@ +apply plugin: "java" +apply plugin: "eclipse" +apply plugin: "idea" + +repositories { + mavenCentral() +} + +dependencies { + testCompile "junit:junit:4.10" +} + diff --git a/java/robot-name/src/main/java/.keep b/java/robot-name/src/main/java/.keep new file mode 100644 index 0000000..e69de29 diff --git a/java/robot-name/src/test/java/RobotTest.java b/java/robot-name/src/test/java/RobotTest.java new file mode 100644 index 0000000..f2c34c8 --- /dev/null +++ b/java/robot-name/src/test/java/RobotTest.java @@ -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)); + } +} diff --git a/kotlin/current b/kotlin/current new file mode 120000 index 0000000..bdd51cc --- /dev/null +++ b/kotlin/current @@ -0,0 +1 @@ +hello-world \ No newline at end of file diff --git a/kotlin/hello-world/README.md b/kotlin/hello-world/README.md new file mode 100644 index 0000000..9f4e110 --- /dev/null +++ b/kotlin/hello-world/README.md @@ -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. + diff --git a/kotlin/hello-world/build.gradle b/kotlin/hello-world/build.gradle new file mode 100644 index 0000000..3ed2722 --- /dev/null +++ b/kotlin/hello-world/build.gradle @@ -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" +} diff --git a/kotlin/hello-world/src/main/kotlin/HelloWorld.kt b/kotlin/hello-world/src/main/kotlin/HelloWorld.kt new file mode 100644 index 0000000..9738a23 --- /dev/null +++ b/kotlin/hello-world/src/main/kotlin/HelloWorld.kt @@ -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 { + + } +} diff --git a/kotlin/hello-world/src/test/kotlin/HelloWorldTest.kt b/kotlin/hello-world/src/test/kotlin/HelloWorldTest.kt new file mode 100644 index 0000000..c1c41a2 --- /dev/null +++ b/kotlin/hello-world/src/test/kotlin/HelloWorldTest.kt @@ -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")) + } +} diff --git a/lisp/current b/lisp/current index 27c76fb..547c5c3 120000 --- a/lisp/current +++ b/lisp/current @@ -1 +1 @@ -point-mutations \ No newline at end of file +hamming \ No newline at end of file diff --git a/lisp/hamming/README.md b/lisp/hamming/README.md new file mode 100644 index 0000000..e0fe147 --- /dev/null +++ b/lisp/hamming/README.md @@ -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. + diff --git a/lisp/hamming/hamming-test.lisp b/lisp/hamming/hamming-test.lisp new file mode 100644 index 0000000..1428e30 --- /dev/null +++ b/lisp/hamming/hamming-test.lisp @@ -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)) diff --git a/lisp/hamming/hamming.lisp b/lisp/hamming/hamming.lisp new file mode 100644 index 0000000..d1a1926 --- /dev/null +++ b/lisp/hamming/hamming.lisp @@ -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." + ) diff --git a/ocaml/bob/.merlin b/ocaml/bob/.merlin new file mode 100644 index 0000000..d9fadbc --- /dev/null +++ b/ocaml/bob/.merlin @@ -0,0 +1,5 @@ +PKG findlib +PKG core +PKG ounit +S * +B * diff --git a/php/current b/php/current index 547c5c3..bdd51cc 120000 --- a/php/current +++ b/php/current @@ -1 +1 @@ -hamming \ No newline at end of file +hello-world \ No newline at end of file diff --git a/php/hello-world/README.md b/php/hello-world/README.md new file mode 100644 index 0000000..73cf3a8 --- /dev/null +++ b/php/hello-world/README.md @@ -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. + diff --git a/php/hello-world/hello-world.php b/php/hello-world/hello-world.php new file mode 100644 index 0000000..439fedc --- /dev/null +++ b/php/hello-world/hello-world.php @@ -0,0 +1,13 @@ +assertEquals('Hello, World!', helloWorld()); + } + + public function testSampleName() + { + $this->assertEquals('Hello, Alice!', helloWorld('Alice')); + } + + public function testAnotherSampleName() + { + $this->assertEquals('Hello, Bob!', helloWorld('Bob')); + } +} diff --git a/rust/current b/rust/current index bdd51cc..b905e3b 120000 --- a/rust/current +++ b/rust/current @@ -1 +1 @@ -hello-world \ No newline at end of file +leap \ No newline at end of file