Initial Commit
This commit is contained in:
commit
50f4a86fd8
35
clojure/bob/README.md
Normal file
35
clojure/bob/README.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Bob
|
||||||
|
|
||||||
|
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
|
||||||
|
|
||||||
|
Bob answers 'Sure.' if you ask him a question.
|
||||||
|
|
||||||
|
He answers 'Whoa, chill out!' if you yell at him.
|
||||||
|
|
||||||
|
He says 'Fine. Be that way!' if you address him without actually saying
|
||||||
|
anything.
|
||||||
|
|
||||||
|
He answers 'Whatever.' to anything else.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Run the test file, and fix each of the errors in turn. When you get the
|
||||||
|
first test to pass, go to the first pending or skipped test, and make
|
||||||
|
that pass as well. When all of the tests are passing, feel free to
|
||||||
|
submit.
|
||||||
|
|
||||||
|
Remember that passing code is just the first step. The goal is to work
|
||||||
|
towards a solution that is as readable and expressive as you can make
|
||||||
|
it.
|
||||||
|
|
||||||
|
Please make your solution as general as possible. Good code doesn't just
|
||||||
|
pass the test suite, it works with any input that fits the
|
||||||
|
specification.
|
||||||
|
|
||||||
|
Have fun!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. [view source](http://pine.fm/LearnToProgram/?Chapter=06)
|
48
clojure/bob/bob_test.clj
Normal file
48
clojure/bob/bob_test.clj
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
(ns bob-test
|
||||||
|
(:require [clojure.test :refer :all]))
|
||||||
|
|
||||||
|
(load-file "bob.clj")
|
||||||
|
|
||||||
|
(deftest responds-to-something
|
||||||
|
(is (= "Whatever." (bob/response-for "Tom-ay-to, tom-aaaah-to."))))
|
||||||
|
|
||||||
|
(deftest responds-to-shouts
|
||||||
|
(is (= "Whoa, chill out!" (bob/response-for "WATCH OUT!"))))
|
||||||
|
|
||||||
|
(deftest responds-to-questions
|
||||||
|
(is (= "Sure." (bob/response-for "Does this cryogenic chamber make me look fat?"))))
|
||||||
|
|
||||||
|
(deftest responds-to-forceful-talking
|
||||||
|
(is (= "Whatever." (bob/response-for "Let's go make out behind the gym!"))))
|
||||||
|
|
||||||
|
(deftest responds-to-acronyms
|
||||||
|
(is (= "Whatever." (bob/response-for "It's OK if you don't want to go to the DMV."))))
|
||||||
|
|
||||||
|
(deftest responds-to-forceful-questions
|
||||||
|
(is (= "Whoa, chill out!" (bob/response-for "WHAT THE HELL WERE YOU THINKING?"))))
|
||||||
|
|
||||||
|
(deftest responds-to-shouting-with-special-characters
|
||||||
|
(is (= "Whoa, chill out!" (bob/response-for "ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!"))))
|
||||||
|
|
||||||
|
(deftest responds-to-shouting-numbers
|
||||||
|
(is (= "Whoa, chill out!" (bob/response-for "1, 2, 3 GO!"))))
|
||||||
|
|
||||||
|
(deftest responds-to-shouting-with-no-exclamation-mark
|
||||||
|
(is (= "Whoa, chill out!" (bob/response-for "I HATE YOU"))))
|
||||||
|
|
||||||
|
(deftest responds-to-statement-containing-question-mark
|
||||||
|
(is (= "Whatever." (bob/response-for "Ending with ? means a question."))))
|
||||||
|
|
||||||
|
(deftest responds-to-silence
|
||||||
|
(is (= "Fine. Be that way!" (bob/response-for ""))))
|
||||||
|
|
||||||
|
(deftest responds-to-prolonged-silence
|
||||||
|
(is (= "Fine. Be that way!" (bob/response-for " "))))
|
||||||
|
|
||||||
|
(deftest responds-to-only-numbers
|
||||||
|
(is (= "Whatever." (bob/response-for "1, 2, 3"))))
|
||||||
|
|
||||||
|
(deftest responds-to-number-question
|
||||||
|
(is (= "Sure." (bob/response-for "4?"))))
|
||||||
|
|
||||||
|
(run-tests)
|
6
clojure/bob/project.clj
Normal file
6
clojure/bob/project.clj
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
(defproject bob "0.1.0-SNAPSHOT"
|
||||||
|
:description "bob exercise."
|
||||||
|
:url "https://github.com/exercism/xclojure/tree/master/bob"
|
||||||
|
:source-paths [""]
|
||||||
|
:test-paths [""]
|
||||||
|
:dependencies [[org.clojure/clojure "1.7.0"]])
|
1
clojure/current
Symbolic link
1
clojure/current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
hello-world
|
82
clojure/hello-world/README.md
Normal file
82
clojure/hello-world/README.md
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# Hello World
|
||||||
|
|
||||||
|
Write a program 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
|
||||||
|
|
||||||
|
The `Hello World!` program will greet me, the caller.
|
||||||
|
|
||||||
|
If I tell the program my name is Alice, it will greet me by saying "Hello, Alice!".
|
||||||
|
|
||||||
|
If I neglect to give it my name, it will greet me by saying "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](http://help.exercism.io/submitting-exercises.html).
|
||||||
|
|
||||||
|
## 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 be not be reviewed by a person, but by rikki- the robot, who will offer an encouraging word.
|
||||||
|
|
||||||
|
* * * *
|
||||||
|
|
||||||
|
For learning resources and help with installation, refer to the
|
||||||
|
[Exercism help page][].
|
||||||
|
|
||||||
|
To run the tests provided, you will need to install [Leiningen][].
|
||||||
|
|
||||||
|
To install Leiningen on Mac OS X using [Homebrew][], run the following command:
|
||||||
|
|
||||||
|
brew install leiningen
|
||||||
|
|
||||||
|
For help installing on Linux, Windows or without Homebrew see:
|
||||||
|
[Leiningen installation][].
|
||||||
|
|
||||||
|
[Exercism help page]: http://exercism.io/languages/clojure
|
||||||
|
[Leiningen]: http://leiningen.org
|
||||||
|
[Homebrew]: http://brew.sh
|
||||||
|
[Leiningen installation]: https://github.com/technomancy/leiningen#installation
|
||||||
|
|
||||||
|
In an exercise directory, create a `src` directory and a file therein to hold
|
||||||
|
your solution. The name of the file should be the exercise name with dashes `-`
|
||||||
|
replaced by underscores `_`. For example, if the exercise is called
|
||||||
|
`hello-world`, name the solution file `hello_world.clj`.
|
||||||
|
|
||||||
|
Your resulting file tree should look something like this:
|
||||||
|
|
||||||
|
/path/to/hello-world
|
||||||
|
├── project.clj
|
||||||
|
├── src
|
||||||
|
│ └── hello_world.clj
|
||||||
|
└── test
|
||||||
|
└── hello_world_test.clj
|
||||||
|
|
||||||
|
|
||||||
|
To run the tests, navigate to the exercise directory and run the following
|
||||||
|
command:
|
||||||
|
|
||||||
|
lein test
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
This is a program to introduce users to using Exercism [view source](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
4
clojure/hello-world/project.clj
Normal file
4
clojure/hello-world/project.clj
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
(defproject hello-world "0.1.0-SNAPSHOT"
|
||||||
|
:description "hello-world exercise."
|
||||||
|
:url "https://github.com/exercism/xclojure/tree/master/hello-world"
|
||||||
|
:dependencies [[org.clojure/clojure "1.7.0"]])
|
12
clojure/hello-world/test/hello_world_test.clj
Normal file
12
clojure/hello-world/test/hello_world_test.clj
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
(ns hello-world-test
|
||||||
|
(:require [clojure.test :refer [deftest is]]
|
||||||
|
hello-world))
|
||||||
|
|
||||||
|
(deftest hello-world-test
|
||||||
|
(is (= "Hello, World!" (hello-world/hello))))
|
||||||
|
|
||||||
|
(deftest hello-alice-test
|
||||||
|
(is (= "Hello, Alice!" (hello-world/hello "Alice"))))
|
||||||
|
|
||||||
|
(deftest hello-bob-test
|
||||||
|
(is (= "Hello, Bob!" (hello-world/hello "Bob"))))
|
1
coffeescript/current
Symbolic link
1
coffeescript/current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
hello-world
|
48
coffeescript/hello-world/README.md
Normal file
48
coffeescript/hello-world/README.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Hello World
|
||||||
|
|
||||||
|
Write a program 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
|
||||||
|
|
||||||
|
The `Hello World!` program will greet me, the caller.
|
||||||
|
|
||||||
|
If I tell the program my name is Alice, it will greet me by saying "Hello, Alice!".
|
||||||
|
|
||||||
|
If I neglect to give it my name, it will greet me by saying "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](http://help.exercism.io/submitting-exercises.html).
|
||||||
|
|
||||||
|
## 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 be not be reviewed by a person, but by rikki- the robot, who will offer an encouraging word.
|
||||||
|
|
||||||
|
Refer to the [Exercism help page](http://help.exercism.io/getting-started-with-coffeescript.html) for getting started with CoffeeScript.
|
||||||
|
|
||||||
|
In order to run the test, you can run the test file from the exercise directory. For example, if the test suite is called hello_world.spec.coffee, you can run the following command:
|
||||||
|
jasmine-node --coffee hello_world.spec.coffee
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
This is a program to introduce users to using Exercism [view source](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
16
coffeescript/hello-world/hello_world.spec.coffee
Normal file
16
coffeescript/hello-world/hello_world.spec.coffee
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
HelloWorld = require "./hello_world"
|
||||||
|
|
||||||
|
describe "HelloWorld", ->
|
||||||
|
hello_world = new HelloWorld()
|
||||||
|
|
||||||
|
it "given no name", ->
|
||||||
|
result = hello_world.hello()
|
||||||
|
expect(result).toEqual "Hello, World!"
|
||||||
|
|
||||||
|
it "given the name 'Alice'", ->
|
||||||
|
result = hello_world.hello 'Alice'
|
||||||
|
expect(result).toEqual "Hello, Alice!"
|
||||||
|
|
||||||
|
it "given the name 'Bob'", ->
|
||||||
|
result = hello_world.hello 'Bob'
|
||||||
|
expect(result).toEqual "Hello, Bob!"
|
52
cpp/bob/CMakeLists.txt
Normal file
52
cpp/bob/CMakeLists.txt
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Get the exercise name from the current directory
|
||||||
|
get_filename_component(exercise ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||||
|
|
||||||
|
# Basic CMake project
|
||||||
|
cmake_minimum_required(VERSION 2.8.11)
|
||||||
|
|
||||||
|
# Name the project after the exercise
|
||||||
|
project(${exercise} CXX)
|
||||||
|
|
||||||
|
# Locate Boost libraries: unit_test_framework, date_time and regex
|
||||||
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
|
set(Boost_USE_MULTITHREADED ON)
|
||||||
|
set(Boost_USE_STATIC_RUNTIME OFF)
|
||||||
|
find_package(Boost 1.55 REQUIRED COMPONENTS unit_test_framework date_time regex)
|
||||||
|
|
||||||
|
# Enable C++11 features on gcc/clang
|
||||||
|
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(GNU|Clang)")
|
||||||
|
set(CMAKE_CXX_FLAGS "-std=c++11")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Configure to run all the tests?
|
||||||
|
if(${EXERCISM_RUN_ALL_TESTS})
|
||||||
|
add_definitions(-DEXERCISM_RUN_ALL_TESTS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Get a source filename from the exercise name by replacing -'s with _'s
|
||||||
|
string(REPLACE "-" "_" file ${exercise})
|
||||||
|
|
||||||
|
# Implementation could be only a header
|
||||||
|
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.cpp)
|
||||||
|
set(exercise_cpp ${file}.cpp)
|
||||||
|
else()
|
||||||
|
set(exercise_cpp "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Build executable from sources and headers
|
||||||
|
add_executable(${exercise} ${file}_test.cpp ${exercise_cpp} ${file}.h)
|
||||||
|
|
||||||
|
# We need boost includes
|
||||||
|
target_include_directories(${exercise} PRIVATE ${Boost_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
# We need boost libraries
|
||||||
|
target_link_libraries(${exercise} ${Boost_LIBRARIES})
|
||||||
|
|
||||||
|
# Tell MSVC not to warn us about unchecked iterators in debug builds
|
||||||
|
if(${MSVC})
|
||||||
|
set_target_properties(${exercise} PROPERTIES
|
||||||
|
COMPILE_DEFINITIONS_DEBUG _SCL_SECURE_NO_WARNINGS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Run the tests on every build
|
||||||
|
add_custom_command(TARGET ${exercise} POST_BUILD COMMAND ${exercise})
|
66
cpp/bob/README.md
Normal file
66
cpp/bob/README.md
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# Bob
|
||||||
|
|
||||||
|
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
|
||||||
|
|
||||||
|
Bob answers 'Sure.' if you ask him a question.
|
||||||
|
|
||||||
|
He answers 'Whoa, chill out!' if you yell at him.
|
||||||
|
|
||||||
|
He says 'Fine. Be that way!' if you address him without actually saying
|
||||||
|
anything.
|
||||||
|
|
||||||
|
He answers 'Whatever.' to anything else.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Run the test file, and fix each of the errors in turn. When you get the
|
||||||
|
first test to pass, go to the first pending or skipped test, and make
|
||||||
|
that pass as well. When all of the tests are passing, feel free to
|
||||||
|
submit.
|
||||||
|
|
||||||
|
Remember that passing code is just the first step. The goal is to work
|
||||||
|
towards a solution that is as readable and expressive as you can make
|
||||||
|
it.
|
||||||
|
|
||||||
|
Please make your solution as general as possible. Good code doesn't just
|
||||||
|
pass the test suite, it works with any input that fits the
|
||||||
|
specification.
|
||||||
|
|
||||||
|
Have fun!
|
||||||
|
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
Make sure you have read the [getting started with C++](http://help.exercism.io/getting-started-with-cpp.html)
|
||||||
|
page on the [exercism help site](http://help.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.
|
||||||
|
|
||||||
|
```C++
|
||||||
|
#if defined(EXERCISM_RUN_ALL_TESTS)
|
||||||
|
```
|
||||||
|
|
||||||
|
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 C++11 facilities in preference to writing your own
|
||||||
|
low-level algorithms or facilities by hand. [CppReference](http://en.cppreference.com/)
|
||||||
|
is a wiki reference to the C++ language and standard library. If you
|
||||||
|
are new to C++, but have programmed in C, beware of
|
||||||
|
[C traps and pitfalls](http://www.slideshare.net/LegalizeAdulthood/c-traps-and-pitfalls-for-c-programmers).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. [view source](http://pine.fm/LearnToProgram/?Chapter=06)
|
90
cpp/bob/bob_test.cpp
Normal file
90
cpp/bob/bob_test.cpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#include "bob.h"
|
||||||
|
#define BOOST_TEST_MAIN
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(stating_something)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Whatever.", bob::hey("Tom-ay-to, tom-aaaah-to."));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(EXERCISM_RUN_ALL_TESTS)
|
||||||
|
BOOST_AUTO_TEST_CASE(shouting)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Whoa, chill out!", bob::hey("WATCH OUT!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(asking_a_question)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Sure.", bob::hey("Does this cryogenic chamber make me look fat?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(talking_forcefully)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Whatever.", bob::hey("Let's go make out behind the gym!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(using_acronyms_in_regular_speech)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Whatever.", bob::hey("It's OK if you don't want to go to the DMV."));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(forceful_questions)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Whoa, chill out!", bob::hey("WHAT THE HELL WERE YOU THINKING?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(shouting_numbers)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Whoa, chill out!", bob::hey("1, 2, 3 GO!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(only_numbers)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Whatever.", bob::hey("1, 2, 3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(question_with_only_numbers)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Sure.", bob::hey("4?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(shouting_with_special_characters)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Whoa, chill out!", bob::hey("ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(shouting_with_no_exclamation_mark)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Whoa, chill out!", bob::hey("I HATE YOU"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(statement_containing_question_mark)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Whatever.", bob::hey("Ending with a ? means a question."));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(prattling_on)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Sure.", bob::hey("Wait! Hang on. Are you going to be OK?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(question_with_trailing_whitespace)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Sure.", bob::hey("Are you ok? "));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(silence)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Fine. Be that way!", bob::hey(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(prolonged_silence)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Fine. Be that way!", bob::hey(" "));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(not_all_silence)
|
||||||
|
{
|
||||||
|
BOOST_REQUIRE_EQUAL("Whatever.", bob::hey(" A bit of silence can be nice. "));
|
||||||
|
}
|
||||||
|
#endif
|
1
cpp/current
Symbolic link
1
cpp/current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
bob
|
1
csharp/current
Symbolic link
1
csharp/current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
leap
|
32
csharp/leap/LeapTest.cs
Normal file
32
csharp/leap/LeapTest.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
[TestFixture]
|
||||||
|
public class LeapTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void Valid_leap_year()
|
||||||
|
{
|
||||||
|
Assert.That(Year.IsLeap(1996), Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Ignore]
|
||||||
|
[Test]
|
||||||
|
public void Invalid_leap_year()
|
||||||
|
{
|
||||||
|
Assert.That(Year.IsLeap(1997), Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Ignore]
|
||||||
|
[Test]
|
||||||
|
public void Turn_of_the_20th_century_is_not_a_leap_year()
|
||||||
|
{
|
||||||
|
Assert.That(Year.IsLeap(1900), Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Ignore]
|
||||||
|
[Test]
|
||||||
|
public void Turn_of_the_25th_century_is_a_leap_year()
|
||||||
|
{
|
||||||
|
Assert.That(Year.IsLeap(2400), Is.True);
|
||||||
|
}
|
||||||
|
}
|
33
csharp/leap/README.md
Normal file
33
csharp/leap/README.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Leap
|
||||||
|
|
||||||
|
Write a program that will take a year and report if it is a leap year.
|
||||||
|
|
||||||
|
The tricky thing here is that a leap year occurs:
|
||||||
|
|
||||||
|
```plain
|
||||||
|
on every year that is evenly divisible by 4
|
||||||
|
except every year that is evenly divisible by 100
|
||||||
|
unless the year is also evenly divisible by 400
|
||||||
|
```
|
||||||
|
|
||||||
|
For example, 1997 is not a leap year, but 1996 is. 1900 is not a leap
|
||||||
|
year, but 2000 is.
|
||||||
|
|
||||||
|
If your language provides a method in the standard library that does
|
||||||
|
this look-up, pretend it doesn't exist and implement it yourself.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
For a delightful, four minute explanation of the whole leap year
|
||||||
|
phenomenon, go watch [this youtube video][video].
|
||||||
|
|
||||||
|
[video]: http://www.youtube.com/watch?v=xX96xng7sAE
|
||||||
|
|
||||||
|
### Submitting Exercises
|
||||||
|
|
||||||
|
Note that, when trying to submit an exercise, make sure you're exercise file you're submitting is in the `exercism/csharp/<exerciseName>` directory.
|
||||||
|
|
||||||
|
For example, if you're submitting `bob.cs` for the Bob exercise, the submit command would be something like `exercism submit <path_to_exercism_dir>/csharp/bob/bob.cs`.
|
||||||
|
## Source
|
||||||
|
|
||||||
|
JavaRanch Cattle Drive, exercise 3 [view source](http://www.javaranch.com/leap.jsp)
|
1
ecmascript/current
Symbolic link
1
ecmascript/current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
hello-world
|
82
ecmascript/hello-world/README.md
Normal file
82
ecmascript/hello-world/README.md
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# Hello World
|
||||||
|
|
||||||
|
Write a program 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
|
||||||
|
|
||||||
|
The `Hello World!` program will greet me, the caller.
|
||||||
|
|
||||||
|
If I tell the program my name is Alice, it will greet me by saying "Hello, Alice!".
|
||||||
|
|
||||||
|
If I neglect to give it my name, it will greet me by saying "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](http://help.exercism.io/submitting-exercises.html).
|
||||||
|
|
||||||
|
## 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 be not be reviewed by a person, but by rikki- the robot, who will offer an encouraging word.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Go through the setup instructions for ECMAScript to
|
||||||
|
install the necessary dependencies:
|
||||||
|
|
||||||
|
http://help.exercism.io/getting-started-with-ecmascript.html
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
They are already described in the link above, but just as a
|
||||||
|
quick reference:
|
||||||
|
|
||||||
|
Install globally a tool to run [Gulp](http://gulpjs.com) if
|
||||||
|
it is not installed yet:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install -g gulp-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
Install assignment dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Making the test suite pass
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ gulp test
|
||||||
|
```
|
||||||
|
|
||||||
|
In many test suites all but the first test have been skipped.
|
||||||
|
|
||||||
|
Once you get a test passing, you can unskip the next one by
|
||||||
|
changing `xit` to `it`.
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
This is a program to introduce users to using Exercism [view source](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
42
ecmascript/hello-world/gulpfile.js
Normal file
42
ecmascript/hello-world/gulpfile.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
function getInputDirectory(argv) {
|
||||||
|
if (argv.input) {
|
||||||
|
return argv.input;
|
||||||
|
}
|
||||||
|
return '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOutputDirectory(argv) {
|
||||||
|
if (argv.output) {
|
||||||
|
return argv.output;
|
||||||
|
}
|
||||||
|
return 'babel-output';
|
||||||
|
}
|
||||||
|
|
||||||
|
var gulp = require('gulp'),
|
||||||
|
jasmine = require('gulp-jasmine'),
|
||||||
|
babel = require('gulp-babel'),
|
||||||
|
polyfill = require('babel/polyfill'),
|
||||||
|
del = require('del'),
|
||||||
|
argv = require('yargs').argv,
|
||||||
|
inputDir = getInputDirectory(argv),
|
||||||
|
outputDir = getOutputDirectory(argv);
|
||||||
|
|
||||||
|
// Gulp tasks definition
|
||||||
|
|
||||||
|
gulp.task('default', [ 'test' ]);
|
||||||
|
|
||||||
|
gulp.task('test', [ 'babel' ], function () {
|
||||||
|
return gulp.src([ outputDir + '/*.spec.js' ])
|
||||||
|
.pipe(jasmine());
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('babel', function () {
|
||||||
|
return gulp.src([ inputDir + '/*.js' ])
|
||||||
|
.pipe(babel())
|
||||||
|
.pipe(gulp.dest(outputDir));
|
||||||
|
});
|
||||||
|
|
||||||
|
gulp.task('clean', function (cb) {
|
||||||
|
del([ outputDir ], cb);
|
||||||
|
});
|
||||||
|
|
15
ecmascript/hello-world/hello-world.js
Normal file
15
ecmascript/hello-world/hello-world.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
class HelloWorld {
|
||||||
|
hello(name) {
|
||||||
|
//
|
||||||
|
// YOUR CODE GOES HERE
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HelloWorld;
|
||||||
|
|
18
ecmascript/hello-world/hello-world.spec.js
Normal file
18
ecmascript/hello-world/hello-world.spec.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import HelloWorld from './hello-world';
|
||||||
|
|
||||||
|
describe('Hello World', () => {
|
||||||
|
const helloWorld = new HelloWorld();
|
||||||
|
|
||||||
|
it('says hello world with no name', () => {
|
||||||
|
expect(helloWorld.hello('')).toEqual('Hello, World!');
|
||||||
|
});
|
||||||
|
|
||||||
|
xit('says hello to bob', () => {
|
||||||
|
expect(helloWorld.hello('Bob')).toEqual('Hello, Bob!');
|
||||||
|
});
|
||||||
|
|
||||||
|
xit('says hello to sally', () => {
|
||||||
|
expect(helloWorld.hello('Sally')).toEqual('Hello, Sally!');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
25
ecmascript/hello-world/package.json
Normal file
25
ecmascript/hello-world/package.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "assignment",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Exercism ECMAScript assignment",
|
||||||
|
"scripts": {
|
||||||
|
"test": "gulp test"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/exercism/xecmascript"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/exercism/xecmascript/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/exercism/xecmascript",
|
||||||
|
"devDependencies": {
|
||||||
|
"gulp": "~3.9.0",
|
||||||
|
"gulp-jasmine": "~2.0.1",
|
||||||
|
"gulp-clean": "~0.3.1",
|
||||||
|
"del": "~2.0.2",
|
||||||
|
"yargs": "~3.27.0",
|
||||||
|
"gulp-babel": "~5.3.0",
|
||||||
|
"babel": "~5.8.29"
|
||||||
|
}
|
||||||
|
}
|
1
elisp/current
Symbolic link
1
elisp/current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
hello-world
|
44
elisp/hello-world/README.md
Normal file
44
elisp/hello-world/README.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# Hello World
|
||||||
|
|
||||||
|
Write a program 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
|
||||||
|
|
||||||
|
The `Hello World!` program will greet me, the caller.
|
||||||
|
|
||||||
|
If I tell the program my name is Alice, it will greet me by saying "Hello, Alice!".
|
||||||
|
|
||||||
|
If I neglect to give it my name, it will greet me by saying "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](http://help.exercism.io/submitting-exercises.html).
|
||||||
|
|
||||||
|
## 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 be not be reviewed by a person, but by rikki- the robot, who will offer an encouraging word.
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
This is a program to introduce users to using Exercism [view source](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
18
elisp/hello-world/hello-world-test.el
Normal file
18
elisp/hello-world/hello-world-test.el
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
;;; hello-world-test.el --- Tests for Hello World (exercism)
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(load-file "hello-world.el")
|
||||||
|
|
||||||
|
(ert-deftest no-args ()
|
||||||
|
(should (equal (hello) "Hello, World!")))
|
||||||
|
|
||||||
|
(ert-deftest with-args ()
|
||||||
|
(should (equal (hello "Emacs") "Hello, Emacs!"))
|
||||||
|
(should (equal (hello "Exercism") "Hello, Exercism!")))
|
||||||
|
|
||||||
|
(provide 'hello-world-test)
|
||||||
|
|
||||||
|
;;; hello-world-test.el ends here
|
9
elisp/hello-world/hello-world.el
Normal file
9
elisp/hello-world/hello-world.el
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
;;; hello-world.el --- Hello World Exercise (exercism)
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
|
||||||
|
(provide 'hello-world)
|
||||||
|
;;; hello-world.el ends here
|
42
elixir/bob/README.md
Normal file
42
elixir/bob/README.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Bob
|
||||||
|
|
||||||
|
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
|
||||||
|
|
||||||
|
Bob answers 'Sure.' if you ask him a question.
|
||||||
|
|
||||||
|
He answers 'Whoa, chill out!' if you yell at him.
|
||||||
|
|
||||||
|
He says 'Fine. Be that way!' if you address him without actually saying
|
||||||
|
anything.
|
||||||
|
|
||||||
|
He answers 'Whatever.' to anything else.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Run the test file, and fix each of the errors in turn. When you get the
|
||||||
|
first test to pass, go to the first pending or skipped test, and make
|
||||||
|
that pass as well. When all of the tests are passing, feel free to
|
||||||
|
submit.
|
||||||
|
|
||||||
|
Remember that passing code is just the first step. The goal is to work
|
||||||
|
towards a solution that is as readable and expressive as you can make
|
||||||
|
it.
|
||||||
|
|
||||||
|
Please make your solution as general as possible. Good code doesn't just
|
||||||
|
pass the test suite, it works with any input that fits the
|
||||||
|
specification.
|
||||||
|
|
||||||
|
Have fun!
|
||||||
|
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir bob_test.exs
|
||||||
|
```
|
||||||
|
|
||||||
|
(Replace `bob_test.exs` with the name of the test file.)
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. [view source](http://pine.fm/LearnToProgram/?Chapter=06)
|
8
elixir/bob/bob.exs
Normal file
8
elixir/bob/bob.exs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
defmodule Teenager do
|
||||||
|
def hey(input) do
|
||||||
|
cond do
|
||||||
|
true -> raise "Your implementation goes here"
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
82
elixir/bob/bob_test.exs
Normal file
82
elixir/bob/bob_test.exs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
if System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("example.exs")
|
||||||
|
else
|
||||||
|
Code.load_file("bob.exs")
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start
|
||||||
|
ExUnit.configure(exclude: :pending)
|
||||||
|
|
||||||
|
defmodule TeenagerTest do
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
|
test "stating something" do
|
||||||
|
assert Teenager.hey("Tom-ay-to, tom-aaaah-to.") == "Whatever."
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "shouting" do
|
||||||
|
assert Teenager.hey("WATCH OUT!") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "asking a question" do
|
||||||
|
assert Teenager.hey("Does this cryogenic chamber make me look fat?") == "Sure."
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "talking forcefully" do
|
||||||
|
assert Teenager.hey("Let's go make out behind the gym!") == "Whatever."
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "talking in capitals" do
|
||||||
|
assert Teenager.hey("This Isn't Shouting!") == "Whatever."
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "shouting numbers" do
|
||||||
|
assert Teenager.hey("1, 2, 3 GO!") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "shouting with special characters" do
|
||||||
|
assert Teenager.hey("ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "shouting with no exclamation mark" do
|
||||||
|
assert Teenager.hey("I HATE YOU") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "statement containing question mark" do
|
||||||
|
assert Teenager.hey("Ending with ? means a question.") == "Whatever."
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "silence" do
|
||||||
|
assert Teenager.hey("") == "Fine. Be that way!"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "prolonged silence" do
|
||||||
|
assert Teenager.hey(" ") == "Fine. Be that way!"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "only numbers" do
|
||||||
|
assert Teenager.hey("1, 2, 3") == "Whatever."
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "question with numbers" do
|
||||||
|
assert Teenager.hey("4?") == "Sure."
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "shouting in Russian" do
|
||||||
|
# Hopefully this is Russian for "GET OUT"
|
||||||
|
assert Teenager.hey("УХОДИТЬ") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
end
|
1
elixir/current
Symbolic link
1
elixir/current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
hello-world
|
51
elixir/hello-world/README.md
Normal file
51
elixir/hello-world/README.md
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Hello World
|
||||||
|
|
||||||
|
Write a program 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
|
||||||
|
|
||||||
|
The `Hello World!` program will greet me, the caller.
|
||||||
|
|
||||||
|
If I tell the program my name is Alice, it will greet me by saying "Hello, Alice!".
|
||||||
|
|
||||||
|
If I neglect to give it my name, it will greet me by saying "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](http://help.exercism.io/submitting-exercises.html).
|
||||||
|
|
||||||
|
## 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 be not be reviewed by a person, but by rikki- the robot, who will offer an encouraging word.
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir bob_test.exs
|
||||||
|
```
|
||||||
|
|
||||||
|
(Replace `bob_test.exs` with the name of the test file.)
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
This is a program to introduce users to using Exercism [view source](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
7
elixir/hello-world/hello_world.exs
Normal file
7
elixir/hello-world/hello_world.exs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
defmodule HelloWorld do
|
||||||
|
def hello(name) do
|
||||||
|
|
||||||
|
"Your implementation goes here"
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
27
elixir/hello-world/hello_world_test.exs
Normal file
27
elixir/hello-world/hello_world_test.exs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
if System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("example.exs")
|
||||||
|
else
|
||||||
|
Code.load_file("hello_world.exs")
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start
|
||||||
|
ExUnit.configure exclude: :pending, trace: true
|
||||||
|
|
||||||
|
defmodule HelloWorldTest do
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
|
test "says hello with no name" do
|
||||||
|
assert HelloWorld.hello() == "Hello, World!"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "says hello sample name" do
|
||||||
|
assert HelloWorld.hello("Alice") == "Hello, Alice!"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "says hello other sample name" do
|
||||||
|
assert HelloWorld.hello("Bob") == "Hello, Bob!"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
1
erlang/current
Symbolic link
1
erlang/current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
hello-world
|
44
erlang/hello-world/README.md
Normal file
44
erlang/hello-world/README.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# Hello World
|
||||||
|
|
||||||
|
Write a program 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
|
||||||
|
|
||||||
|
The `Hello World!` program will greet me, the caller.
|
||||||
|
|
||||||
|
If I tell the program my name is Alice, it will greet me by saying "Hello, Alice!".
|
||||||
|
|
||||||
|
If I neglect to give it my name, it will greet me by saying "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](http://help.exercism.io/submitting-exercises.html).
|
||||||
|
|
||||||
|
## 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 be not be reviewed by a person, but by rikki- the robot, who will offer an encouraging word.
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
This is a program to introduce users to using Exercism [view source](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
19
erlang/hello-world/hello_world_tests.erl
Normal file
19
erlang/hello-world/hello_world_tests.erl
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
% To run tests:
|
||||||
|
% erl -make
|
||||||
|
% erl -noshell -eval "eunit:test(hello_world, [verbose])" -s init stop
|
||||||
|
%
|
||||||
|
|
||||||
|
-module(hello_world_tests).
|
||||||
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
||||||
|
no_name_test() ->
|
||||||
|
?assertEqual("Hello, World!", hello_world:greet()).
|
||||||
|
|
||||||
|
alice_test() ->
|
||||||
|
?assertEqual("Hello, Alice!", hello_world:greet("Alice")).
|
||||||
|
|
||||||
|
bob_test() ->
|
||||||
|
?assertEqual("Hello, Bob!", hello_world:greet("Bob")).
|
||||||
|
|
||||||
|
strange_test() ->
|
||||||
|
?assertEqual("Hello, !", hello_world:greet("")).
|
29
erlang/leap/README.md
Normal file
29
erlang/leap/README.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Leap
|
||||||
|
|
||||||
|
Write a program that will take a year and report if it is a leap year.
|
||||||
|
|
||||||
|
The tricky thing here is that a leap year occurs:
|
||||||
|
|
||||||
|
```plain
|
||||||
|
on every year that is evenly divisible by 4
|
||||||
|
except every year that is evenly divisible by 100
|
||||||
|
unless the year is also evenly divisible by 400
|
||||||
|
```
|
||||||
|
|
||||||
|
For example, 1997 is not a leap year, but 1996 is. 1900 is not a leap
|
||||||
|
year, but 2000 is.
|
||||||
|
|
||||||
|
If your language provides a method in the standard library that does
|
||||||
|
this look-up, pretend it doesn't exist and implement it yourself.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
For a delightful, four minute explanation of the whole leap year
|
||||||
|
phenomenon, go watch [this youtube video][video].
|
||||||
|
|
||||||
|
[video]: http://www.youtube.com/watch?v=xX96xng7sAE
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
JavaRanch Cattle Drive, exercise 3 [view source](http://www.javaranch.com/leap.jsp)
|
20
erlang/leap/leap_tests.erl
Normal file
20
erlang/leap/leap_tests.erl
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
% To run tests:
|
||||||
|
% erl -make
|
||||||
|
% erl -noshell -eval "eunit:test(leap, [verbose])" -s init stop
|
||||||
|
%
|
||||||
|
|
||||||
|
-module(leap_tests).
|
||||||
|
|
||||||
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
||||||
|
leap_year_test() ->
|
||||||
|
?assert(leap:leap_year(1996)).
|
||||||
|
|
||||||
|
non_leap_year_test() ->
|
||||||
|
?assertNot(leap:leap_year(1997)).
|
||||||
|
|
||||||
|
century_test() ->
|
||||||
|
?assertNot(leap:leap_year(1900)).
|
||||||
|
|
||||||
|
fourth_century_test() ->
|
||||||
|
?assert(leap:leap_year(2400)).
|
1
fsharp/current
Symbolic link
1
fsharp/current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
sum-of-multiples
|
16
fsharp/sum-of-multiples/README.md
Normal file
16
fsharp/sum-of-multiples/README.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Sum Of Multiples
|
||||||
|
|
||||||
|
Write a program that, given a number, can find the sum of all the multiples of particular numbers up to but not including that number.
|
||||||
|
|
||||||
|
If we list all the natural numbers up to but not including 15 that are
|
||||||
|
multiples of either 3 or 5, we get 3, 5, 6 and 9, 10, and 12.
|
||||||
|
|
||||||
|
The sum of these multiples is 45.
|
||||||
|
|
||||||
|
Write a program that can find the sum of the multiples of a given set of
|
||||||
|
numbers.
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
A variation on Problem 1 at Project Euler [view source](http://projecteuler.net/problem=1)
|
32
fsharp/sum-of-multiples/SumOfMultiplesTest.fs
Normal file
32
fsharp/sum-of-multiples/SumOfMultiplesTest.fs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
module SumOfMultiplesTest
|
||||||
|
|
||||||
|
open NUnit.Framework
|
||||||
|
open SumOfMultiples
|
||||||
|
|
||||||
|
[<TestFixture>]
|
||||||
|
type SumOfMultiplesTest() =
|
||||||
|
let mutable sumOfMultiples = SumOfMultiples()
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
member tc.Sum_to_1() =
|
||||||
|
Assert.That(sumOfMultiples.To(0), Is.EqualTo(0))
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
[<Ignore>]
|
||||||
|
member tc.Sum_to_3() =
|
||||||
|
Assert.That(sumOfMultiples.To(3), Is.EqualTo(0))
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
[<Ignore>]
|
||||||
|
member tc.Sum_to_10() =
|
||||||
|
Assert.That(sumOfMultiples.To(10), Is.EqualTo(23))
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
[<Ignore>]
|
||||||
|
member tc.Configurable_7_13_17_to_20() =
|
||||||
|
Assert.That(SumOfMultiples([7; 13; 17]).To(20), Is.EqualTo(51))
|
||||||
|
|
||||||
|
[<Test>]
|
||||||
|
[<Ignore>]
|
||||||
|
member tc.Configurable_43_47_to_10000() =
|
||||||
|
Assert.That(SumOfMultiples([43; 47]).To(10000), Is.EqualTo(2203160))
|
39
go/allergies/README.md
Normal file
39
go/allergies/README.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# Allergies
|
||||||
|
|
||||||
|
Write a program that, given a person's allergy score, can tell them whether or not they're allergic to a given item, and their full list of allergies.
|
||||||
|
|
||||||
|
An allergy test produces a single numeric score which contains the
|
||||||
|
information about all the allergies the person has (that they were
|
||||||
|
tested for).
|
||||||
|
|
||||||
|
The list of items (and their value) that were tested are:
|
||||||
|
|
||||||
|
* eggs (1)
|
||||||
|
* peanuts (2)
|
||||||
|
* shellfish (4)
|
||||||
|
* strawberries (8)
|
||||||
|
* tomatoes (16)
|
||||||
|
* chocolate (32)
|
||||||
|
* pollen (64)
|
||||||
|
* cats (128)
|
||||||
|
|
||||||
|
So if Tom is allergic to peanuts and chocolate, he gets a score of 34.
|
||||||
|
|
||||||
|
Now, given just that score of 34, your program should be able to say:
|
||||||
|
|
||||||
|
- Whether Tom is allergic to any one of those allergens listed above.
|
||||||
|
- All the allergens Tom is allergic to.
|
||||||
|
|
||||||
|
To run the tests simply run the command `go test` in the exercise directory.
|
||||||
|
|
||||||
|
If the test suite contains benchmarks, you can run these with the `-bench`
|
||||||
|
flag:
|
||||||
|
|
||||||
|
go test -bench .
|
||||||
|
|
||||||
|
For more detailed info about the Go track see the [help
|
||||||
|
page](http://exercism.io/languages/go).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Jumpstart Lab Warm-up [view source](http://jumpstartlab.com)
|
44
go/allergies/allergies.go
Normal file
44
go/allergies/allergies.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package allergies
|
||||||
|
|
||||||
|
// Allergies takes a score and returns all of the
|
||||||
|
// things that the score is allergic to.
|
||||||
|
func Allergies(score int) []string {
|
||||||
|
var ret []string
|
||||||
|
|
||||||
|
for _, v := range getAllAllergens() {
|
||||||
|
if AllergicTo(score, v) {
|
||||||
|
ret = append(ret, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// AllergicTo takes a score and an allergen and returns if
|
||||||
|
// That score is allergic to that thing.
|
||||||
|
func AllergicTo(score int, tst string) bool {
|
||||||
|
return score&getScoreForAllergen(tst) == getScoreForAllergen(tst)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAllAllergens() []string {
|
||||||
|
return []string{
|
||||||
|
"eggs",
|
||||||
|
"peanuts",
|
||||||
|
"shellfish",
|
||||||
|
"strawberries",
|
||||||
|
"tomatoes",
|
||||||
|
"chocolate",
|
||||||
|
"pollen",
|
||||||
|
"cats",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getScoreForAllergen(tst string) int {
|
||||||
|
ret := 1
|
||||||
|
for _, v := range getAllAllergens() {
|
||||||
|
if tst == v {
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
ret *= 2
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
79
go/allergies/allergies_test.go
Normal file
79
go/allergies/allergies_test.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package allergies
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var allergiesTests = []struct {
|
||||||
|
expected []string
|
||||||
|
input int
|
||||||
|
}{
|
||||||
|
{[]string{}, 0},
|
||||||
|
{[]string{"eggs"}, 1},
|
||||||
|
{[]string{"peanuts"}, 2},
|
||||||
|
{[]string{"strawberries"}, 8},
|
||||||
|
{[]string{"eggs", "peanuts"}, 3},
|
||||||
|
{[]string{"eggs", "shellfish"}, 5},
|
||||||
|
{[]string{"strawberries", "tomatoes", "chocolate", "pollen", "cats"}, 248},
|
||||||
|
{[]string{"eggs", "peanuts", "shellfish", "strawberries", "tomatoes", "chocolate", "pollen", "cats"}, 255},
|
||||||
|
{[]string{"eggs", "shellfish", "strawberries", "tomatoes", "chocolate", "pollen", "cats"}, 509},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAllergies(t *testing.T) {
|
||||||
|
for _, test := range allergiesTests {
|
||||||
|
actual := Allergies(test.input)
|
||||||
|
if fmt.Sprintf("%s", actual) != fmt.Sprintf("%s", test.expected) {
|
||||||
|
t.Fatalf("FAIL: Allergies(%d): expected %s, actual %s", test.input, test.expected, actual)
|
||||||
|
} else {
|
||||||
|
t.Logf("PASS: Allergic to %v", test.expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAllergies(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
for _, test := range allergicToTests {
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Allergies(test.i)
|
||||||
|
}
|
||||||
|
b.StopTimer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var allergicToTests = []struct {
|
||||||
|
expected bool
|
||||||
|
i int
|
||||||
|
allergen string
|
||||||
|
}{
|
||||||
|
{false, 0, "peanuts"},
|
||||||
|
{false, 0, "cats"},
|
||||||
|
{false, 0, "strawberries"},
|
||||||
|
{true, 1, "eggs"},
|
||||||
|
{true, 5, "eggs"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAllergicTo(t *testing.T) {
|
||||||
|
for _, test := range allergicToTests {
|
||||||
|
actual := AllergicTo(test.i, test.allergen)
|
||||||
|
if actual != test.expected {
|
||||||
|
t.Fatalf("FAIL: AllergicTo(%d, %s): expected %t, actual %t", test.i, test.allergen, test.expected, actual)
|
||||||
|
} else {
|
||||||
|
t.Logf("PASS: AllergicTo(%d, %s) %t", test.i, test.allergen, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAllergicTo(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
for _, test := range allergicToTests {
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
AllergicTo(test.i, test.allergen)
|
||||||
|
}
|
||||||
|
b.StopTimer()
|
||||||
|
}
|
||||||
|
}
|
21
go/anagram/README.md
Normal file
21
go/anagram/README.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Anagram
|
||||||
|
|
||||||
|
Write a program that, given a word and a list of possible anagrams, selects the correct sublist.
|
||||||
|
|
||||||
|
Given `"listen"` and a list of candidates like `"enlists" "google"
|
||||||
|
"inlets" "banana"` the program should return a list containing
|
||||||
|
`"inlets"`.
|
||||||
|
|
||||||
|
To run the tests simply run the command `go test` in the exercise directory.
|
||||||
|
|
||||||
|
If the test suite contains benchmarks, you can run these with the `-bench`
|
||||||
|
flag:
|
||||||
|
|
||||||
|
go test -bench .
|
||||||
|
|
||||||
|
For more detailed info about the Go track see the [help
|
||||||
|
page](http://exercism.io/languages/go).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Inspired by the Extreme Startup game [view source](https://github.com/rchatley/extreme_startup)
|
28
go/anagram/anagram.go
Normal file
28
go/anagram/anagram.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package anagram
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// Detect returns all candidates that are anagrams of subject
|
||||||
|
func Detect(subject string, candidates []string) []string {
|
||||||
|
var ret []string
|
||||||
|
for i := range candidates {
|
||||||
|
if isAnagram(subject, candidates[i]) {
|
||||||
|
ret = append(ret, strings.ToLower(candidates[i]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAnagram(s, c string) bool {
|
||||||
|
s = strings.ToLower(s)
|
||||||
|
c = strings.ToLower(c)
|
||||||
|
if s == c || len(s) != len(c) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, v := range strings.Split(s, "") {
|
||||||
|
if strings.Count(s, v) != strings.Count(c, v) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
172
go/anagram/anagram_test.go
Normal file
172
go/anagram/anagram_test.go
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
package anagram
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testCases = []struct {
|
||||||
|
subject string
|
||||||
|
candidates []string
|
||||||
|
expected []string
|
||||||
|
description string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
subject: "diaper",
|
||||||
|
candidates: []string{
|
||||||
|
"hello",
|
||||||
|
"world",
|
||||||
|
"zombies",
|
||||||
|
"pants",
|
||||||
|
},
|
||||||
|
expected: []string{},
|
||||||
|
description: "no matches",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subject: "ant",
|
||||||
|
candidates: []string{
|
||||||
|
"tan",
|
||||||
|
"stand",
|
||||||
|
"at",
|
||||||
|
},
|
||||||
|
expected: []string{"tan"},
|
||||||
|
description: "simple anagram",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subject: "listen",
|
||||||
|
candidates: []string{
|
||||||
|
"enlists",
|
||||||
|
"google",
|
||||||
|
"inlets",
|
||||||
|
"banana",
|
||||||
|
},
|
||||||
|
expected: []string{"inlets"},
|
||||||
|
description: "another simple anagram",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subject: "master",
|
||||||
|
candidates: []string{
|
||||||
|
"stream",
|
||||||
|
"pigeon",
|
||||||
|
"maters",
|
||||||
|
},
|
||||||
|
expected: []string{"maters", "stream"},
|
||||||
|
description: "multiple anagrams",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subject: "allergy",
|
||||||
|
candidates: []string{
|
||||||
|
"gallery",
|
||||||
|
"ballerina",
|
||||||
|
"regally",
|
||||||
|
"clergy",
|
||||||
|
"largely",
|
||||||
|
"leading",
|
||||||
|
},
|
||||||
|
expected: []string{"gallery", "largely", "regally"},
|
||||||
|
description: "multiple anagrams (again)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subject: "galea",
|
||||||
|
candidates: []string{
|
||||||
|
"eagle",
|
||||||
|
},
|
||||||
|
expected: []string{},
|
||||||
|
description: "does not confuse different duplicates",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subject: "corn",
|
||||||
|
candidates: []string{
|
||||||
|
"corn",
|
||||||
|
"dark",
|
||||||
|
"Corn",
|
||||||
|
"rank",
|
||||||
|
"CORN",
|
||||||
|
"cron",
|
||||||
|
"park",
|
||||||
|
},
|
||||||
|
expected: []string{"cron"},
|
||||||
|
description: "identical word is not anagram",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subject: "mass",
|
||||||
|
candidates: []string{
|
||||||
|
"last",
|
||||||
|
},
|
||||||
|
expected: []string{},
|
||||||
|
description: "eliminate anagrams with same checksum",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subject: "good",
|
||||||
|
candidates: []string{
|
||||||
|
"dog",
|
||||||
|
"goody",
|
||||||
|
},
|
||||||
|
expected: []string{},
|
||||||
|
description: "eliminate anagram subsets",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subject: "Orchestra",
|
||||||
|
candidates: []string{
|
||||||
|
"cashregiser",
|
||||||
|
"carthorse",
|
||||||
|
"radishes",
|
||||||
|
},
|
||||||
|
expected: []string{"carthorse"},
|
||||||
|
description: "subjects are case insensitive",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subject: "orchestra",
|
||||||
|
candidates: []string{
|
||||||
|
"cashregiser",
|
||||||
|
"Carthorse",
|
||||||
|
"radishes",
|
||||||
|
},
|
||||||
|
expected: []string{"carthorse"},
|
||||||
|
description: "candidates are case insensitive",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func equal(a []string, b []string) bool {
|
||||||
|
if len(b) != len(a) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(a)
|
||||||
|
sort.Strings(b)
|
||||||
|
return fmt.Sprintf("%v", a) == fmt.Sprintf("%v", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDetectAnagrams(t *testing.T) {
|
||||||
|
for _, tt := range testCases {
|
||||||
|
actual := Detect(tt.subject, tt.candidates)
|
||||||
|
if !equal(tt.expected, actual) {
|
||||||
|
msg := `FAIL: %s
|
||||||
|
Subject %s
|
||||||
|
Candidates %v
|
||||||
|
Expected %v
|
||||||
|
Got %v
|
||||||
|
`
|
||||||
|
t.Fatalf(msg, tt.description, tt.subject, tt.candidates, tt.expected, actual)
|
||||||
|
} else {
|
||||||
|
t.Logf("PASS: %s", tt.description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDetectAnagrams(b *testing.B) {
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
|
||||||
|
for _, tt := range testCases {
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Detect(tt.subject, tt.candidates)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
40
go/bank-account/README.md
Normal file
40
go/bank-account/README.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# Bank Account
|
||||||
|
|
||||||
|
Bank accounts can be accessed in different ways at the same time.
|
||||||
|
|
||||||
|
A bank account can be accessed in multiple ways. Clients can make
|
||||||
|
deposits and withdrawals using the internet, mobile phones, etc. Shops
|
||||||
|
can charge against the account.
|
||||||
|
|
||||||
|
Create an account that can be accessed from multiple threads/processes
|
||||||
|
(terminology depends on your programming language).
|
||||||
|
|
||||||
|
It should be possible to close an account; operations against a closed
|
||||||
|
account must fail.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Run the test file, and fix each of the errors in turn. When you get the
|
||||||
|
first test to pass, go to the first pending or skipped test, and make
|
||||||
|
that pass as well. When all of the tests are passing, feel free to
|
||||||
|
submit.
|
||||||
|
|
||||||
|
Remember that passing code is just the first step. The goal is to work
|
||||||
|
towards a solution that is as readable and expressive as you can make
|
||||||
|
it.
|
||||||
|
|
||||||
|
Have fun!
|
||||||
|
|
||||||
|
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://help.exercism.io/getting-started-with-go.html).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
[view source]()
|
58
go/bank-account/account.go
Normal file
58
go/bank-account/account.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package account
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
// Account just represents a user's account
|
||||||
|
type Account struct {
|
||||||
|
sync.RWMutex
|
||||||
|
balance int
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open returns a new account
|
||||||
|
func Open(amt int) *Account {
|
||||||
|
a := new(Account)
|
||||||
|
_, ok := a.Deposit(amt)
|
||||||
|
if ok {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close returns the payout amount and an 'ok' flag
|
||||||
|
func (a *Account) Close() (int, bool) {
|
||||||
|
a.Lock()
|
||||||
|
ret := a.balance
|
||||||
|
if a.closed {
|
||||||
|
a.Unlock()
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
a.closed = true
|
||||||
|
a.balance = 0
|
||||||
|
a.Unlock()
|
||||||
|
return ret, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Balance returns the current account balance
|
||||||
|
// and an 'ok' flag
|
||||||
|
func (a *Account) Balance() (int, bool) {
|
||||||
|
if a.closed {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return a.balance, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deposit takes an amount (can be a withdrawal)
|
||||||
|
// and returns the new balance and an 'ok' flag
|
||||||
|
func (a *Account) Deposit(amount int) (int, bool) {
|
||||||
|
var ret int
|
||||||
|
var ok bool
|
||||||
|
a.Lock()
|
||||||
|
if !a.closed && a.balance+amount >= 0 {
|
||||||
|
a.balance += amount
|
||||||
|
ret = a.balance
|
||||||
|
ok = true
|
||||||
|
}
|
||||||
|
a.Unlock()
|
||||||
|
return ret, ok
|
||||||
|
}
|
289
go/bank-account/bank_account_test.go
Normal file
289
go/bank-account/bank_account_test.go
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
// API:
|
||||||
|
//
|
||||||
|
// Open(initalDeposit int64) *Account
|
||||||
|
// (Account) Close() (payout int64, ok bool)
|
||||||
|
// (Account) Balance() (balance int64, ok bool)
|
||||||
|
// (Account) Deposit(amount uint64) (newBalance int64, ok bool)
|
||||||
|
//
|
||||||
|
// If Open is given a negative initial deposit, it must return nil.
|
||||||
|
// Deposit must handle a negative amount as a withdrawal.
|
||||||
|
// If any Account method is called on an closed account, it must not modify
|
||||||
|
// the account and must return ok = false.
|
||||||
|
|
||||||
|
package account
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSeqOpenBalanceClose(t *testing.T) {
|
||||||
|
// open account
|
||||||
|
const amt = 10
|
||||||
|
a := Open(amt)
|
||||||
|
if a == nil {
|
||||||
|
t.Fatalf("Open(%d) = nil, want non-nil *Account.", amt)
|
||||||
|
}
|
||||||
|
t.Logf("Account 'a' opened with initial balance of %d.", amt)
|
||||||
|
|
||||||
|
// verify balance after open
|
||||||
|
switch b, ok := a.Balance(); {
|
||||||
|
case !ok:
|
||||||
|
t.Fatal("a.Balance() returned !ok, want ok.")
|
||||||
|
case b != amt:
|
||||||
|
t.Fatalf("a.Balance() = %d, want %d", b, amt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// close account
|
||||||
|
switch p, ok := a.Close(); {
|
||||||
|
case !ok:
|
||||||
|
t.Fatalf("a.Close() returned !ok, want ok.")
|
||||||
|
case p != amt:
|
||||||
|
t.Fatalf("a.Close() returned payout = %d, want %d.", p, amt)
|
||||||
|
}
|
||||||
|
t.Log("Account 'a' closed.")
|
||||||
|
|
||||||
|
// verify balance no longer accessible
|
||||||
|
if b, ok := a.Balance(); ok {
|
||||||
|
t.Log("Balance still available on closed account.")
|
||||||
|
t.Fatalf("a.Balance() = %d, %t. Want ok == false", b, ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSeqOpenDepositClose(t *testing.T) {
|
||||||
|
// open account
|
||||||
|
const openAmt = 10
|
||||||
|
a := Open(openAmt)
|
||||||
|
if a == nil {
|
||||||
|
t.Fatalf("Open(%d) = nil, want non-nil *Account.", openAmt)
|
||||||
|
}
|
||||||
|
t.Logf("Account 'a' opened with initial balance of %d.", openAmt)
|
||||||
|
|
||||||
|
// deposit
|
||||||
|
const depAmt = 20
|
||||||
|
const newAmt = openAmt + depAmt
|
||||||
|
switch b, ok := a.Deposit(depAmt); {
|
||||||
|
case !ok:
|
||||||
|
t.Fatalf("a.Deposit(%d) returned !ok, want ok.", depAmt)
|
||||||
|
case b != openAmt+depAmt:
|
||||||
|
t.Fatalf("a.Deposit(%d) = %d, want new balance = %d", depAmt, b, newAmt)
|
||||||
|
}
|
||||||
|
t.Logf("Deposit of %d accepted to account 'a'", depAmt)
|
||||||
|
|
||||||
|
// close account
|
||||||
|
switch p, ok := a.Close(); {
|
||||||
|
case !ok:
|
||||||
|
t.Fatalf("a.Close() returned !ok, want ok.")
|
||||||
|
case p != newAmt:
|
||||||
|
t.Fatalf("a.Close() returned payout = %d, want %d.", p, newAmt)
|
||||||
|
}
|
||||||
|
t.Log("Account 'a' closed.")
|
||||||
|
|
||||||
|
// verify deposits no longer accepted
|
||||||
|
if b, ok := a.Deposit(1); ok {
|
||||||
|
t.Log("Deposit accepted on closed account.")
|
||||||
|
t.Fatalf("a.Deposit(1) = %d, %t. Want ok == false", b, ok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMoreSeqCases(t *testing.T) {
|
||||||
|
// open account 'a' as before
|
||||||
|
const openAmt = 10
|
||||||
|
a := Open(openAmt)
|
||||||
|
if a == nil {
|
||||||
|
t.Fatalf("Open(%d) = nil, want non-nil *Account.", openAmt)
|
||||||
|
}
|
||||||
|
t.Logf("Account 'a' opened with initial balance of %d.", openAmt)
|
||||||
|
|
||||||
|
// open account 'z' with zero balance
|
||||||
|
z := Open(0)
|
||||||
|
if z == nil {
|
||||||
|
t.Fatal("Open(0) = nil, want non-nil *Account.")
|
||||||
|
}
|
||||||
|
t.Log("Account 'z' opened with initial balance of 0.")
|
||||||
|
|
||||||
|
// attempt to open account with negative opening balance
|
||||||
|
if Open(-10) != nil {
|
||||||
|
t.Fatal("Open(-10) seemed to work, " +
|
||||||
|
"want nil result for negative opening balance.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify both balances a and z still there
|
||||||
|
switch b, ok := a.Balance(); {
|
||||||
|
case !ok:
|
||||||
|
t.Fatal("a.Balance() returned !ok, want ok.")
|
||||||
|
case b != openAmt:
|
||||||
|
t.Fatalf("a.Balance() = %d, want %d", b, openAmt)
|
||||||
|
}
|
||||||
|
switch b, ok := z.Balance(); {
|
||||||
|
case !ok:
|
||||||
|
t.Fatal("z.Balance() returned !ok, want ok.")
|
||||||
|
case b != 0:
|
||||||
|
t.Fatalf("z.Balance() = %d, want 0", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// withdrawals
|
||||||
|
const wAmt = 3
|
||||||
|
const newAmt = openAmt - wAmt
|
||||||
|
switch b, ok := a.Deposit(-wAmt); {
|
||||||
|
case !ok:
|
||||||
|
t.Fatalf("a.Deposit(%d) returned !ok, want ok.", -wAmt)
|
||||||
|
case b != newAmt:
|
||||||
|
t.Fatalf("a.Deposit(%d) = %d, want new balance = %d", -wAmt, b, newAmt)
|
||||||
|
}
|
||||||
|
t.Logf("Withdrawal of %d accepted from account 'a'", wAmt)
|
||||||
|
if _, ok := z.Deposit(-1); ok {
|
||||||
|
t.Fatal("z.Deposit(-1) returned ok, want !ok.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify both balances
|
||||||
|
switch b, ok := a.Balance(); {
|
||||||
|
case !ok:
|
||||||
|
t.Fatal("a.Balance() returned !ok, want ok.")
|
||||||
|
case b != newAmt:
|
||||||
|
t.Fatalf("a.Balance() = %d, want %d", b, newAmt)
|
||||||
|
}
|
||||||
|
switch b, ok := z.Balance(); {
|
||||||
|
case !ok:
|
||||||
|
t.Fatal("z.Balance() returned !ok, want ok.")
|
||||||
|
case b != 0:
|
||||||
|
t.Fatalf("z.Balance() = %d, want 0", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// close just z
|
||||||
|
switch p, ok := z.Close(); {
|
||||||
|
case !ok:
|
||||||
|
t.Fatalf("z.Close() returned !ok, want ok.")
|
||||||
|
case p != 0:
|
||||||
|
t.Fatalf("z.Close() returned payout = %d, want 0.", p)
|
||||||
|
}
|
||||||
|
t.Log("Account 'z' closed.")
|
||||||
|
|
||||||
|
// verify 'a' balance one more time
|
||||||
|
switch b, ok := a.Balance(); {
|
||||||
|
case !ok:
|
||||||
|
t.Fatal("a.Balance() returned !ok, want ok.")
|
||||||
|
case b != newAmt:
|
||||||
|
t.Fatalf("a.Balance() = %d, want %d", b, newAmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConcClose(t *testing.T) {
|
||||||
|
if runtime.NumCPU() < 2 {
|
||||||
|
t.Skip("Multiple CPU cores required for concurrency tests.")
|
||||||
|
}
|
||||||
|
if runtime.GOMAXPROCS(0) < 2 {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test competing close attempts
|
||||||
|
for rep := 0; rep < 1000; rep++ {
|
||||||
|
const openAmt = 10
|
||||||
|
a := Open(openAmt)
|
||||||
|
if a == nil {
|
||||||
|
t.Fatalf("Open(%d) = nil, want non-nil *Account.", openAmt)
|
||||||
|
}
|
||||||
|
var start sync.WaitGroup
|
||||||
|
start.Add(1)
|
||||||
|
const closeAttempts = 10
|
||||||
|
res := make(chan string)
|
||||||
|
for i := 0; i < closeAttempts; i++ {
|
||||||
|
go func() { // on your mark,
|
||||||
|
start.Wait() // get set...
|
||||||
|
switch p, ok := a.Close(); {
|
||||||
|
case !ok:
|
||||||
|
if p != 0 {
|
||||||
|
t.Errorf("a.Close() = %d, %t. "+
|
||||||
|
"Want payout = 0 for unsuccessful close", p, ok)
|
||||||
|
res <- "fail"
|
||||||
|
} else {
|
||||||
|
res <- "already closed"
|
||||||
|
}
|
||||||
|
case p != openAmt:
|
||||||
|
t.Errorf("a.Close() = %d, %t. "+
|
||||||
|
"Want payout = %d for successful close", p, ok, openAmt)
|
||||||
|
res <- "fail"
|
||||||
|
default:
|
||||||
|
res <- "close" // exactly one goroutine should reach here
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
start.Done() // ...go
|
||||||
|
var closes, fails int
|
||||||
|
for i := 0; i < closeAttempts; i++ {
|
||||||
|
switch <-res {
|
||||||
|
case "close":
|
||||||
|
closes++
|
||||||
|
case "fail":
|
||||||
|
fails++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case fails > 0:
|
||||||
|
t.FailNow() // error already logged by other goroutine
|
||||||
|
case closes == 0:
|
||||||
|
t.Fatal("Concurrent a.Close() attempts all failed. " +
|
||||||
|
"Want one to succeed.")
|
||||||
|
case closes > 1:
|
||||||
|
t.Fatalf("%d concurrent a.Close() attempts succeeded, "+
|
||||||
|
"each paying out %d!. Want just one to succeed.",
|
||||||
|
closes, openAmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConcDeposit(t *testing.T) {
|
||||||
|
if runtime.NumCPU() < 2 {
|
||||||
|
t.Skip("Multiple CPU cores required for concurrency tests.")
|
||||||
|
}
|
||||||
|
if runtime.GOMAXPROCS(0) < 2 {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
}
|
||||||
|
a := Open(0)
|
||||||
|
if a == nil {
|
||||||
|
t.Fatal("Open(0) = nil, want non-nil *Account.")
|
||||||
|
}
|
||||||
|
const amt = 10
|
||||||
|
const c = 1000
|
||||||
|
var negBal int32
|
||||||
|
var start, g sync.WaitGroup
|
||||||
|
start.Add(1)
|
||||||
|
g.Add(3 * c)
|
||||||
|
for i := 0; i < c; i++ {
|
||||||
|
go func() { // deposit
|
||||||
|
start.Wait()
|
||||||
|
a.Deposit(amt) // ignore return values
|
||||||
|
g.Done()
|
||||||
|
}()
|
||||||
|
go func() { // withdraw
|
||||||
|
start.Wait()
|
||||||
|
for {
|
||||||
|
if _, ok := a.Deposit(-amt); ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(time.Microsecond) // retry
|
||||||
|
}
|
||||||
|
g.Done()
|
||||||
|
}()
|
||||||
|
go func() { // watch that balance stays >= 0
|
||||||
|
start.Wait()
|
||||||
|
if p, _ := a.Balance(); p < 0 {
|
||||||
|
atomic.StoreInt32(&negBal, 1)
|
||||||
|
}
|
||||||
|
g.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
start.Done()
|
||||||
|
g.Wait()
|
||||||
|
if negBal == 1 {
|
||||||
|
t.Fatal("Balance went negative with concurrent deposits and " +
|
||||||
|
"withdrawals. Want balance always >= 0.")
|
||||||
|
}
|
||||||
|
if p, ok := a.Balance(); !ok || p != 0 {
|
||||||
|
t.Fatalf("After equal concurrent deposits and withdrawals, "+
|
||||||
|
"a.Balance = %d, %t. Want 0, true", p, ok)
|
||||||
|
}
|
||||||
|
}
|
43
go/binary/README.md
Normal file
43
go/binary/README.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Binary
|
||||||
|
|
||||||
|
Write a program that will convert a binary number, represented as a string (e.g. '101010'), to its decimal equivalent using first principles
|
||||||
|
|
||||||
|
Implement binary to decimal conversion. Given a binary input
|
||||||
|
string, your program should produce a decimal output. The
|
||||||
|
program should handle invalid inputs.
|
||||||
|
|
||||||
|
## Note
|
||||||
|
- Implement the conversion yourself.
|
||||||
|
Do not use something else to perform the conversion for you.
|
||||||
|
|
||||||
|
## About Binary (Base-2)
|
||||||
|
Decimal is a base-10 system.
|
||||||
|
|
||||||
|
A number 23 in base 10 notation can be understood
|
||||||
|
as a linear combination of powers of 10:
|
||||||
|
|
||||||
|
- The rightmost digit gets multiplied by 10^0 = 1
|
||||||
|
- The next number gets multiplied by 10^1 = 10
|
||||||
|
- ...
|
||||||
|
- The *n*th number gets multiplied by 10^*(n-1)*.
|
||||||
|
- All these values are summed.
|
||||||
|
|
||||||
|
So: `23 => 2*10^1 + 3*10^0 => 2*10 + 3*1 = 23 base 10`
|
||||||
|
|
||||||
|
Binary is similar, but uses powers of 2 rather than powers of 10.
|
||||||
|
|
||||||
|
So: `101 => 1*2^2 + 0*2^1 + 1*2^0 => 1*4 + 0*2 + 1*1 => 4 + 1 => 5 base 10`.
|
||||||
|
|
||||||
|
To run the tests simply run the command `go test` in the exercise directory.
|
||||||
|
|
||||||
|
If the test suite contains benchmarks, you can run these with the `-bench`
|
||||||
|
flag:
|
||||||
|
|
||||||
|
go test -bench .
|
||||||
|
|
||||||
|
For more detailed info about the Go track see the [help
|
||||||
|
page](http://exercism.io/languages/go).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
All of Computer Science [view source](http://www.wolframalpha.com/input/?i=binary&a=*C.binary-_*MathWorld-)
|
22
go/binary/binary.go
Normal file
22
go/binary/binary.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package binary
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// ParseBinary takes a binary string and returns the
|
||||||
|
// integer representation of it.
|
||||||
|
func ParseBinary(bin string) (int, error) {
|
||||||
|
var ret int
|
||||||
|
currSpot := 1
|
||||||
|
for len(bin) > 0 {
|
||||||
|
v := bin[len(bin)-1]
|
||||||
|
if v != '0' && v != '1' {
|
||||||
|
return 0, fmt.Errorf("Invalid String")
|
||||||
|
}
|
||||||
|
if v == '1' {
|
||||||
|
ret = ret + currSpot
|
||||||
|
}
|
||||||
|
currSpot = currSpot * 2
|
||||||
|
bin = bin[:len(bin)-1]
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
55
go/binary/binary_test.go
Normal file
55
go/binary/binary_test.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package binary
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// You must implement the function,
|
||||||
|
//
|
||||||
|
// func ParseBinary(string) (int, error)
|
||||||
|
//
|
||||||
|
// It is standard for Go functions to return error values to report error conditions.
|
||||||
|
// The test cases below are all valid binary numbers however. For this exercise you
|
||||||
|
// may simply return nil for the error value in all cases.
|
||||||
|
//
|
||||||
|
// For bonus points though, what errors might be possible when parsing a number?
|
||||||
|
// Can you add code to detect error conditions and return appropriate error values?
|
||||||
|
|
||||||
|
var testCases = []struct {
|
||||||
|
binary string
|
||||||
|
expected int
|
||||||
|
}{
|
||||||
|
{"1", 1},
|
||||||
|
{"10", 2},
|
||||||
|
{"11", 3},
|
||||||
|
{"100", 4},
|
||||||
|
{"1001", 9},
|
||||||
|
{"11010", 26},
|
||||||
|
{"10001101000", 1128},
|
||||||
|
{"0", 0},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseBinary(t *testing.T) {
|
||||||
|
for _, tt := range testCases {
|
||||||
|
actual, err := ParseBinary(tt.binary)
|
||||||
|
// We don't expect errors for any of the test cases.
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ParseBinary(%v) returned error %q. Error not expected.",
|
||||||
|
tt.binary, err)
|
||||||
|
}
|
||||||
|
// Well, we don't expect wrong answers either.
|
||||||
|
if actual != tt.expected {
|
||||||
|
t.Fatalf("ParseBinary(%v): actual %d, expected %v",
|
||||||
|
tt.binary, actual, tt.expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Benchmark combined time for all tests
|
||||||
|
func BenchmarkBinary(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, tt := range testCases {
|
||||||
|
ParseBinary(tt.binary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
go/bob/README.md
Normal file
44
go/bob/README.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# Bob
|
||||||
|
|
||||||
|
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
|
||||||
|
|
||||||
|
Bob answers 'Sure.' if you ask him a question.
|
||||||
|
|
||||||
|
He answers 'Whoa, chill out!' if you yell at him.
|
||||||
|
|
||||||
|
He says 'Fine. Be that way!' if you address him without actually saying
|
||||||
|
anything.
|
||||||
|
|
||||||
|
He answers 'Whatever.' to anything else.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Run the test file, and fix each of the errors in turn. When you get the
|
||||||
|
first test to pass, go to the first pending or skipped test, and make
|
||||||
|
that pass as well. When all of the tests are passing, feel free to
|
||||||
|
submit.
|
||||||
|
|
||||||
|
Remember that passing code is just the first step. The goal is to work
|
||||||
|
towards a solution that is as readable and expressive as you can make
|
||||||
|
it.
|
||||||
|
|
||||||
|
Please make your solution as general as possible. Good code doesn't just
|
||||||
|
pass the test suite, it works with any input that fits the
|
||||||
|
specification.
|
||||||
|
|
||||||
|
Have fun!
|
||||||
|
|
||||||
|
|
||||||
|
To run the tests simply run the command `go test` in the exercise directory.
|
||||||
|
|
||||||
|
If the test suite contains benchmarks, you can run these with the `-bench`
|
||||||
|
flag:
|
||||||
|
|
||||||
|
go test -bench .
|
||||||
|
|
||||||
|
For more detailed info about the Go track see the [help
|
||||||
|
page](http://exercism.io/languages/go).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. [view source](http://pine.fm/LearnToProgram/?Chapter=06)
|
19
go/bob/bob.go
Normal file
19
go/bob/bob.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package bob
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// TestVersion is an exercism thing
|
||||||
|
const TestVersion = 1
|
||||||
|
|
||||||
|
// Hey provokes a response from Bob
|
||||||
|
func Hey(inp string) string {
|
||||||
|
inp = strings.TrimSpace(inp)
|
||||||
|
if inp == "" {
|
||||||
|
return "Fine. Be that way!"
|
||||||
|
} else if inp == strings.ToUpper(inp) && inp != strings.ToLower(inp) {
|
||||||
|
return "Whoa, chill out!"
|
||||||
|
} else if strings.HasSuffix(inp, "?") {
|
||||||
|
return "Sure."
|
||||||
|
}
|
||||||
|
return "Whatever."
|
||||||
|
}
|
33
go/bob/bob_test.go
Normal file
33
go/bob/bob_test.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package bob
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
const testVersion = 1
|
||||||
|
|
||||||
|
// Retired testVersions
|
||||||
|
// (none) 4a9e144a3c5dc0d9773f4cf641ffe3efe48641d8
|
||||||
|
|
||||||
|
func TestHeyBob(t *testing.T) {
|
||||||
|
if TestVersion != testVersion {
|
||||||
|
t.Fatalf("Found TestVersion = %v, want %v", TestVersion, testVersion)
|
||||||
|
}
|
||||||
|
for _, tt := range testCases {
|
||||||
|
actual := Hey(tt.input)
|
||||||
|
if actual != tt.expected {
|
||||||
|
msg := `
|
||||||
|
ALICE (%s): %q
|
||||||
|
BOB: %s
|
||||||
|
|
||||||
|
Expected Bob to respond: %s`
|
||||||
|
t.Fatalf(msg, tt.description, tt.input, actual, tt.expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBob(b *testing.B) {
|
||||||
|
for _, tt := range testCases {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Hey(tt.input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
141
go/bob/cases_test.go
Normal file
141
go/bob/cases_test.go
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package bob
|
||||||
|
|
||||||
|
// Source: exercism/x-common
|
||||||
|
// Commit: 945d08e Merge pull request #50 from soniakeys/master
|
||||||
|
|
||||||
|
var testCases = []struct {
|
||||||
|
description string
|
||||||
|
input string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"stating something",
|
||||||
|
"Tom-ay-to, tom-aaaah-to.",
|
||||||
|
"Whatever.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shouting",
|
||||||
|
"WATCH OUT!",
|
||||||
|
"Whoa, chill out!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shouting gibberish",
|
||||||
|
"FCECDFCAAB",
|
||||||
|
"Whoa, chill out!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"asking a question",
|
||||||
|
"Does this cryogenic chamber make me look fat?",
|
||||||
|
"Sure.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"asking a numeric question",
|
||||||
|
"You are, what, like 15?",
|
||||||
|
"Sure.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"asking gibberish",
|
||||||
|
"fffbbcbeab?",
|
||||||
|
"Sure.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"talking forcefully",
|
||||||
|
"Let's go make out behind the gym!",
|
||||||
|
"Whatever.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"using acronyms in regular speech",
|
||||||
|
"It's OK if you don't want to go to the DMV.",
|
||||||
|
"Whatever.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"forceful question",
|
||||||
|
"WHAT THE HELL WERE YOU THINKING?",
|
||||||
|
"Whoa, chill out!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shouting numbers",
|
||||||
|
"1, 2, 3 GO!",
|
||||||
|
"Whoa, chill out!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"only numbers",
|
||||||
|
"1, 2, 3",
|
||||||
|
"Whatever.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question with only numbers",
|
||||||
|
"4?",
|
||||||
|
"Sure.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shouting with special characters",
|
||||||
|
"ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!",
|
||||||
|
"Whoa, chill out!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shouting with umlauts",
|
||||||
|
"ÜMLÄÜTS!",
|
||||||
|
"Whoa, chill out!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"calmly speaking with umlauts",
|
||||||
|
"ÜMLäÜTS!",
|
||||||
|
"Whatever.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shouting with no exclamation mark",
|
||||||
|
"I HATE YOU",
|
||||||
|
"Whoa, chill out!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"statement containing question mark",
|
||||||
|
"Ending with ? means a question.",
|
||||||
|
"Whatever.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"non-letters with question",
|
||||||
|
":) ?",
|
||||||
|
"Sure.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"prattling on",
|
||||||
|
"Wait! Hang on. Are you going to be OK?",
|
||||||
|
"Sure.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"silence",
|
||||||
|
"",
|
||||||
|
"Fine. Be that way!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"prolonged silence",
|
||||||
|
" ",
|
||||||
|
"Fine. Be that way!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alternate silence",
|
||||||
|
"\t\t\t\t\t\t\t\t\t\t",
|
||||||
|
"Fine. Be that way!",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"multiple line question",
|
||||||
|
"\nDoes this cryogenic chamber make me look fat?\nno",
|
||||||
|
"Whatever.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"starting with whitespace",
|
||||||
|
" hmmmmmmm...",
|
||||||
|
"Whatever.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ending with whitespace",
|
||||||
|
"Okay if like my spacebar quite a bit? ",
|
||||||
|
"Sure.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"other whitespace",
|
||||||
|
"\n\r \t\v\u00a0\u2002",
|
||||||
|
"Fine. Be that way!",
|
||||||
|
},
|
||||||
|
}
|
20
go/bracket-push/README.md
Normal file
20
go/bracket-push/README.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Bracket Push
|
||||||
|
|
||||||
|
Make sure the brackets and braces all match.
|
||||||
|
|
||||||
|
Ensure that all the brackets and braces are matched correctly,
|
||||||
|
and nested correctly.
|
||||||
|
|
||||||
|
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://help.exercism.io/getting-started-with-go.html).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Ginna Baker [view source]()
|
26
go/bracket-push/bracket-push.go
Normal file
26
go/bracket-push/bracket-push.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package bracket_push
|
||||||
|
|
||||||
|
// Bracket makes sure that all brackets match
|
||||||
|
func Bracket(s string) (bool, error) {
|
||||||
|
// Set up a map of matches that we care about
|
||||||
|
matches := make(map[byte]byte)
|
||||||
|
matches['}'] = '{'
|
||||||
|
matches[')'] = '('
|
||||||
|
matches[']'] = '['
|
||||||
|
var pairs []byte
|
||||||
|
for i := range s {
|
||||||
|
if v, ok := matches[s[i]]; ok {
|
||||||
|
// Found a match, it's a closing bracket
|
||||||
|
if len(pairs) == 0 || pairs[len(pairs)-1] != v {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
pairs = pairs[:len(pairs)-1]
|
||||||
|
} else {
|
||||||
|
pairs = append(pairs, s[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(pairs) > 0 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
72
go/bracket-push/bracket-push_test.go
Normal file
72
go/bracket-push/bracket-push_test.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package bracket_push
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testCases = []struct {
|
||||||
|
input string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: "",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "{}",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "{{",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "}{",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "{}[]",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "{[]}",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "{[}]",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "{[)][]}",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "{[]([()])}",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBracket(t *testing.T) {
|
||||||
|
for _, tt := range testCases {
|
||||||
|
actual, err := Bracket(tt.input)
|
||||||
|
// We don't expect errors for any of the test cases
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Bracket(%q) returned error %q. Error not expected.", tt.input, err)
|
||||||
|
}
|
||||||
|
if actual != tt.expected {
|
||||||
|
t.Fatalf("Bracket(%q) was expected to return %v but returned %v.",
|
||||||
|
tt.input, tt.expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBracket(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
for _, tt := range testCases {
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Bracket(tt.input)
|
||||||
|
}
|
||||||
|
b.StopTimer()
|
||||||
|
}
|
||||||
|
}
|
77
go/bracket-push/bracket_push_test.go
Normal file
77
go/bracket-push/bracket_push_test.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package brackets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const testVersion = 2
|
||||||
|
|
||||||
|
var testCases = []struct {
|
||||||
|
input string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
input: "",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "{}",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "{{",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "}{",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "{}[]",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "{[]}",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "{[}]",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "{[)][]}",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "{[]([()])}",
|
||||||
|
expected: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBracket(t *testing.T) {
|
||||||
|
for _, tt := range testCases {
|
||||||
|
actual, err := Bracket(tt.input)
|
||||||
|
// We don't expect errors for any of the test cases
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Bracket(%q) returned error %q. Error not expected.", tt.input, err)
|
||||||
|
}
|
||||||
|
if actual != tt.expected {
|
||||||
|
t.Fatalf("Bracket(%q) was expected to return %v but returned %v.",
|
||||||
|
tt.input, tt.expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if TestVersion != testVersion {
|
||||||
|
t.Fatalf("Found TestVersion = %v, want %v.", TestVersion, testVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBracket(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
for _, tt := range testCases {
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Bracket(tt.input)
|
||||||
|
}
|
||||||
|
b.StopTimer()
|
||||||
|
}
|
||||||
|
}
|
23
go/clock/README.md
Normal file
23
go/clock/README.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Clock
|
||||||
|
|
||||||
|
Implement a clock that handles times without dates.
|
||||||
|
|
||||||
|
Create a clock that is independent of date.
|
||||||
|
|
||||||
|
You should be able to add and subtract minutes to it.
|
||||||
|
|
||||||
|
Two clocks that represent the same time should be equal to each other.
|
||||||
|
|
||||||
|
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://help.exercism.io/getting-started-with-go.html).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Pairing session with Erin Drummond [view source](https://twitter.com/ebdrummond)
|
78
go/clock/cases_test.go
Normal file
78
go/clock/cases_test.go
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
package clock
|
||||||
|
|
||||||
|
// Source: exercism/x-common
|
||||||
|
// Commit: 269f498 Merge pull request #48 from soniakeys/custom-set-json
|
||||||
|
|
||||||
|
// Test creating a new clock with an initial time.
|
||||||
|
var timeTests = []struct {
|
||||||
|
h, m int
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{8, 0, "08:00"}, // on the hour
|
||||||
|
{9, 0, "09:00"}, // on the hour
|
||||||
|
{11, 9, "11:09"}, // past the hour
|
||||||
|
{11, 19, "11:19"}, // past the hour
|
||||||
|
{24, 0, "00:00"}, // midnight is zero hours
|
||||||
|
{25, 0, "01:00"}, // hour rolls over
|
||||||
|
{1, 60, "02:00"}, // sixty minutes is next hour
|
||||||
|
{0, 160, "02:40"}, // minutes roll over
|
||||||
|
{25, 160, "03:40"}, // hour and minutes roll over
|
||||||
|
{-1, 15, "23:15"}, // negative hour
|
||||||
|
{-25, 0, "23:00"}, // negative hour rolls over
|
||||||
|
{1, -40, "00:20"}, // negative minutes
|
||||||
|
{1, -160, "22:20"}, // negative minutes roll over
|
||||||
|
{-25, -160, "20:20"}, // negative hour and minutes both roll over
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test adding and subtracting minutes.
|
||||||
|
var addTests = []struct {
|
||||||
|
h, m, a int
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{10, 0, 3, "10:03"}, // add minutes
|
||||||
|
{0, 45, 40, "01:25"}, // add to next hour
|
||||||
|
{10, 0, 61, "11:01"}, // add more than one hour
|
||||||
|
{23, 59, 2, "00:01"}, // add across midnight
|
||||||
|
{5, 32, 1500, "06:32"}, // add more than one day (1500 min = 25 hrs)
|
||||||
|
{0, 45, 160, "03:25"}, // add more than two hours with carry
|
||||||
|
{10, 3, -3, "10:00"}, // subtract minutes
|
||||||
|
{10, 3, -30, "09:33"}, // subtract to previous hour
|
||||||
|
{10, 3, -70, "08:53"}, // subtract more than an hour
|
||||||
|
{0, 3, -4, "23:59"}, // subtract across midnight
|
||||||
|
{0, 0, -160, "21:20"}, // subtract more than two hours
|
||||||
|
{5, 32, -1500, "04:32"}, // subtract more than one day (1500 min = 25 hrs)
|
||||||
|
{6, 15, -160, "03:35"}, // subtract more than two hours with borrow
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct two separate clocks, set times, test if they are equal.
|
||||||
|
type hm struct{ h, m int }
|
||||||
|
|
||||||
|
var eqTests = []struct {
|
||||||
|
c1, c2 hm
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
// clocks with same time
|
||||||
|
{
|
||||||
|
hm{15, 37},
|
||||||
|
hm{15, 37},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
// clocks a minute apart
|
||||||
|
{
|
||||||
|
hm{15, 36},
|
||||||
|
hm{15, 37},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
// clocks an hour apart
|
||||||
|
{
|
||||||
|
hm{14, 37},
|
||||||
|
hm{15, 37},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
// clocks set 24 hours apart
|
||||||
|
{
|
||||||
|
hm{10, 37},
|
||||||
|
hm{34, 37},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
34
go/clock/clock.go
Normal file
34
go/clock/clock.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package clock
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// TestVersion is for exercism
|
||||||
|
const TestVersion = 2
|
||||||
|
|
||||||
|
// Clock is an int representing the time of day
|
||||||
|
type Clock int
|
||||||
|
|
||||||
|
// Time returns a Clock representing the given hour & minute
|
||||||
|
func Time(hour, minute int) Clock {
|
||||||
|
return TimeFromMinutes(hour*60 + minute)
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of Clock
|
||||||
|
func (c Clock) String() string {
|
||||||
|
return fmt.Sprintf("%02d:%02d", c/60, c%60)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add adds minutes to the clock
|
||||||
|
func (c Clock) Add(minutes int) Clock {
|
||||||
|
return TimeFromMinutes(int(c) + minutes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimeFromMinutes takes a minutes integer value and returns a Clock
|
||||||
|
func TimeFromMinutes(minutes int) Clock {
|
||||||
|
for minutes < 0 {
|
||||||
|
// Keep adding 24 hours to the minutes value until it's positive
|
||||||
|
minutes = minutes + (24 * 60)
|
||||||
|
}
|
||||||
|
minutes = minutes % (24 * 60)
|
||||||
|
return Clock(minutes)
|
||||||
|
}
|
69
go/clock/clock_test.go
Normal file
69
go/clock/clock_test.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package clock
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Clock type API:
|
||||||
|
//
|
||||||
|
// Time(hour, minute int) Clock // a "constructor"
|
||||||
|
// (Clock) String() string // a "stringer"
|
||||||
|
// (Clock) Add(minutes int) Clock
|
||||||
|
//
|
||||||
|
// Add should also handle subtraction by accepting negative values.
|
||||||
|
// To satisfy the readme requirement about clocks being equal, values of
|
||||||
|
// your Clock type need to work with the == operator.
|
||||||
|
//
|
||||||
|
// It might help to study the time.Time type in the standard library
|
||||||
|
// (https://golang.org/pkg/time/#Time) as a model. See how constructors there
|
||||||
|
// (Date and Now) return Time values rather than pointers. Note also how
|
||||||
|
// most time.Time methods have value receivers rather that pointer recievers.
|
||||||
|
// For more background on this read
|
||||||
|
// https://github.com/golang/go/wiki/CodeReviewComments#receiver-type.
|
||||||
|
|
||||||
|
const testVersion = 2
|
||||||
|
|
||||||
|
// Retired testVersions
|
||||||
|
// (none) 79937f6d58e25ebafe12d1cb4a9f88f4de70cfd6
|
||||||
|
// 1 8d0cb8b617be2e36b2ca5ad2034e5f80f2372924
|
||||||
|
|
||||||
|
func TestCreateClock(t *testing.T) {
|
||||||
|
if TestVersion != testVersion {
|
||||||
|
t.Fatalf("Found TestVersion = %v, want %v", TestVersion, testVersion)
|
||||||
|
}
|
||||||
|
for _, n := range timeTests {
|
||||||
|
if got := Time(n.h, n.m); got.String() != n.want {
|
||||||
|
t.Fatalf("Time(%d, %d) = %q, want %q", n.h, n.m, got, n.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Log(len(timeTests), "test cases")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddMinutes(t *testing.T) {
|
||||||
|
for _, a := range addTests {
|
||||||
|
if got := Time(a.h, a.m).Add(a.a); got.String() != a.want {
|
||||||
|
t.Fatalf("Time(%d, %d).Add(%d) = %q, want %q",
|
||||||
|
a.h, a.m, a.a, got, a.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Log(len(addTests), "test cases")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompareClocks(t *testing.T) {
|
||||||
|
for _, e := range eqTests {
|
||||||
|
clock1 := Time(e.c1.h, e.c1.m)
|
||||||
|
clock2 := Time(e.c2.h, e.c2.m)
|
||||||
|
got := clock1 == clock2
|
||||||
|
if got != e.want {
|
||||||
|
t.Log("Clock1:", clock1)
|
||||||
|
t.Log("Clock2:", clock2)
|
||||||
|
t.Logf("Clock1 == Clock2 is %t, want %t", got, e.want)
|
||||||
|
if reflect.DeepEqual(clock1, clock2) {
|
||||||
|
t.Log("(Hint: see comments in clock_test.go.)")
|
||||||
|
}
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Log(len(eqTests), "test cases")
|
||||||
|
}
|
87
go/crypto-square/README.md
Normal file
87
go/crypto-square/README.md
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
# Crypto Square
|
||||||
|
|
||||||
|
Implement the classic method for composing secret messages called a square code.
|
||||||
|
|
||||||
|
The input is first normalized: The spaces and punctuation are removed
|
||||||
|
from the English text and the message is downcased.
|
||||||
|
|
||||||
|
Then, the normalized characters are broken into rows. These rows can be
|
||||||
|
regarded as forming a rectangle when printed with intervening newlines.
|
||||||
|
|
||||||
|
For example, the sentence
|
||||||
|
|
||||||
|
> If man was meant to stay on the ground god would have given us roots
|
||||||
|
|
||||||
|
is 54 characters long.
|
||||||
|
|
||||||
|
Broken into 8-character columns, it yields 7 rows.
|
||||||
|
|
||||||
|
Those 7 rows produce this rectangle when printed one per line:
|
||||||
|
|
||||||
|
```plain
|
||||||
|
ifmanwas
|
||||||
|
meanttos
|
||||||
|
tayonthe
|
||||||
|
groundgo
|
||||||
|
dwouldha
|
||||||
|
vegivenu
|
||||||
|
sroots
|
||||||
|
```
|
||||||
|
|
||||||
|
The coded message is obtained by reading down the columns going left to
|
||||||
|
right.
|
||||||
|
|
||||||
|
For example, the message above is coded as:
|
||||||
|
|
||||||
|
```plain
|
||||||
|
imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau
|
||||||
|
```
|
||||||
|
|
||||||
|
Write a program that, given an English text, outputs the encoded version
|
||||||
|
of that text.
|
||||||
|
|
||||||
|
The size of the square (number of columns) should be decided by the
|
||||||
|
length of the message.
|
||||||
|
|
||||||
|
If the message is a length that creates a perfect square (e.g. 4, 9, 16,
|
||||||
|
25, 36, etc), use that number of columns.
|
||||||
|
|
||||||
|
If the message doesn't fit neatly into a square, choose the number of
|
||||||
|
columns that corresponds to the smallest square that is larger than the
|
||||||
|
number of characters in the message.
|
||||||
|
|
||||||
|
For example, a message 4 characters long should use a 2 x 2 square. A
|
||||||
|
message that is 81 characters long would use a square that is 9 columns
|
||||||
|
wide.
|
||||||
|
|
||||||
|
A message between 5 and 8 characters long should use a rectangle 3
|
||||||
|
characters wide.
|
||||||
|
|
||||||
|
Output the encoded text grouped by column.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
- "Have a nice day. Feed the dog & chill out!"
|
||||||
|
- Normalizes to: "haveanicedayfeedthedogchillout"
|
||||||
|
- Which has length: 30
|
||||||
|
- And splits into 5 6-character rows:
|
||||||
|
- "havean"
|
||||||
|
- "iceday"
|
||||||
|
- "feedth"
|
||||||
|
- "edogch"
|
||||||
|
- "illout"
|
||||||
|
- Which yields a ciphertext beginning: "hifei acedl v…"
|
||||||
|
|
||||||
|
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://help.exercism.io/getting-started-with-go.html).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
J Dalbey's Programming Practice problems [view source](http://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html)
|
45
go/crypto-square/crypto_square.go
Normal file
45
go/crypto-square/crypto_square.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package cryptosquare
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestVersion is an exercism thing
|
||||||
|
const TestVersion = 1
|
||||||
|
|
||||||
|
// Encode implements the classic method for composing
|
||||||
|
// secret messages called a square code
|
||||||
|
func Encode(txt string) string {
|
||||||
|
r := regexp.MustCompile("[^a-zA-Z0-9]+")
|
||||||
|
nrm := strings.ToLower(r.ReplaceAllString(txt, ""))
|
||||||
|
// The string should be normalized now (alphanumeric, lower case)
|
||||||
|
sqrt := int(math.Ceil(math.Sqrt(float64(len(nrm)))))
|
||||||
|
var square, ret []string
|
||||||
|
var tmp string
|
||||||
|
|
||||||
|
// Build the initial square
|
||||||
|
for i := 0; i < len(nrm); i++ {
|
||||||
|
if i%sqrt == 0 && len(tmp) != 0 {
|
||||||
|
square = append(square, tmp)
|
||||||
|
tmp = ""
|
||||||
|
}
|
||||||
|
tmp += string(nrm[i])
|
||||||
|
}
|
||||||
|
square = append(square, tmp)
|
||||||
|
tmp = ""
|
||||||
|
|
||||||
|
// Now rebuild the string by columns
|
||||||
|
for i := 0; i < len(square[0]); i++ {
|
||||||
|
for j := 0; j < len(square); j++ {
|
||||||
|
if i < len(square[j]) {
|
||||||
|
tmp += string(square[j][i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = append(ret, tmp)
|
||||||
|
tmp = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(ret, " ")
|
||||||
|
}
|
111
go/crypto-square/crypto_square_test.go
Normal file
111
go/crypto-square/crypto_square_test.go
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
package cryptosquare
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
const testVersion = 1
|
||||||
|
|
||||||
|
// Retired testVersions
|
||||||
|
// (none) 71ad8ac57fe7d5b777cfa1afd116cd41e1af55ed
|
||||||
|
|
||||||
|
var tests = []struct {
|
||||||
|
pt string // plain text
|
||||||
|
ct string // cipher text
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"s#$%^&plunk",
|
||||||
|
"su pn lk",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"1, 2, 3 GO!",
|
||||||
|
"1g 2o 3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"1234",
|
||||||
|
"13 24",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"123456789",
|
||||||
|
"147 258 369",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"123456789abc",
|
||||||
|
"159 26a 37b 48c",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Never vex thine heart with idle woes",
|
||||||
|
"neewl exhie vtetw ehaho ririe vntds",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ZOMG! ZOMBIES!!!",
|
||||||
|
"zzi ooe mms gb",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Time is an illusion. Lunchtime doubly so.",
|
||||||
|
"tasney inicds miohoo elntu illib suuml",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"We all know interspecies romance is weird.",
|
||||||
|
"wneiaw eorene awssci liprer lneoid ktcms",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Madness, and then illumination.",
|
||||||
|
"msemo aanin dnin ndla etlt shui",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Vampires are people too!",
|
||||||
|
"vrel aepe mset paoo irpo",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"12",
|
||||||
|
"1 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"12 3",
|
||||||
|
"13 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"12345678",
|
||||||
|
"147 258 36",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"123456789a",
|
||||||
|
"159 26a 37 48",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"If man was meant to stay on the ground god would have given us roots",
|
||||||
|
"imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Have a nice day. Feed the dog & chill out!",
|
||||||
|
"hifei acedl veeol eddgo aatcu nyhht",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncode(t *testing.T) {
|
||||||
|
if TestVersion != testVersion {
|
||||||
|
t.Errorf("Found TestVersion = %v, want %v.", TestVersion, testVersion)
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
if ct := Encode(test.pt); ct != test.ct {
|
||||||
|
t.Fatalf(`Encode(%q):
|
||||||
|
got %q
|
||||||
|
want %q`, test.pt, ct, test.ct)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEncode(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, test := range tests {
|
||||||
|
Encode(test.pt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
go/current
Symbolic link
1
go/current
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
react
|
30
go/difference-of-squares/README.md
Normal file
30
go/difference-of-squares/README.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Difference Of Squares
|
||||||
|
|
||||||
|
Find the difference between the sum of the squares and the square of the sums of the first N natural numbers.
|
||||||
|
|
||||||
|
The square of the sum of the first ten natural numbers is,
|
||||||
|
|
||||||
|
(1 + 2 + ... + 10)**2 = 55**2 = 3025
|
||||||
|
|
||||||
|
The sum of the squares of the first ten natural numbers is,
|
||||||
|
|
||||||
|
1**2 + 2**2 + ... + 10**2 = 385
|
||||||
|
|
||||||
|
Hence the difference between the square of the sum of the first
|
||||||
|
ten natural numbers and the sum of the squares is 2640:
|
||||||
|
|
||||||
|
3025 - 385 = 2640
|
||||||
|
|
||||||
|
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://help.exercism.io/getting-started-with-go.html).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Problem 6 at Project Euler [view source](http://projecteuler.net/problem=6)
|
32
go/difference-of-squares/difference_of_squares.go
Normal file
32
go/difference-of-squares/difference_of_squares.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package diffsquares
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
// SquareOfSums calculates the Square of the sums
|
||||||
|
// of the first 'num' natural numbers
|
||||||
|
func SquareOfSums(num int) int {
|
||||||
|
ret := 0
|
||||||
|
for num > 0 {
|
||||||
|
ret += num
|
||||||
|
num--
|
||||||
|
}
|
||||||
|
return int(math.Pow(float64(ret), 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SumOfSquares calculates the Sum of the Squares
|
||||||
|
// of the first 'num' natural numbers
|
||||||
|
func SumOfSquares(num int) int {
|
||||||
|
ret := 0
|
||||||
|
for num > 0 {
|
||||||
|
ret += int(math.Pow(float64(num), 2))
|
||||||
|
num--
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// Difference calculates the difference between
|
||||||
|
// The SquareOfSums and the SumOfSquares for the
|
||||||
|
// first 'num' natural numbers
|
||||||
|
func Difference(num int) int {
|
||||||
|
return SquareOfSums(num) - SumOfSquares(num)
|
||||||
|
}
|
54
go/difference-of-squares/difference_of_squares_test.go
Normal file
54
go/difference-of-squares/difference_of_squares_test.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package diffsquares
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
var tests = []struct{ n, sqOfSums, sumOfSq int }{
|
||||||
|
{5, 225, 55},
|
||||||
|
{10, 3025, 385},
|
||||||
|
{100, 25502500, 338350},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSquareOfSums(t *testing.T) {
|
||||||
|
for _, test := range tests {
|
||||||
|
if s := SquareOfSums(test.n); s != test.sqOfSums {
|
||||||
|
t.Fatalf("SquareOfSums(%d) = %d, want %d", test.n, s, test.sqOfSums)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSumOfSquares(t *testing.T) {
|
||||||
|
for _, test := range tests {
|
||||||
|
if s := SumOfSquares(test.n); s != test.sumOfSq {
|
||||||
|
t.Fatalf("SumOfSquares(%d) = %d, want %d", test.n, s, test.sumOfSq)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDifference(t *testing.T) {
|
||||||
|
for _, test := range tests {
|
||||||
|
want := test.sqOfSums - test.sumOfSq
|
||||||
|
if s := Difference(test.n); s != want {
|
||||||
|
t.Fatalf("Difference(%d) = %d, want %d", test.n, s, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Benchmark functions on just a single number (100, from the original PE problem)
|
||||||
|
// to avoid overhead of iterating over tests.
|
||||||
|
func BenchmarkSquareOfSums(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
SquareOfSums(100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSumOfSquares(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
SumOfSquares(100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDifference(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Difference(100)
|
||||||
|
}
|
||||||
|
}
|
62
go/etl/README.md
Normal file
62
go/etl/README.md
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# Etl
|
||||||
|
|
||||||
|
We are going to do the `Transform` step of an Extract-Transform-Load.
|
||||||
|
|
||||||
|
### ETL
|
||||||
|
Extract-Transform-Load (ETL) is a fancy way of saying, "We have some crufty, legacy data over in this system, and now we need it in this shiny new system over here, so
|
||||||
|
we're going to migrate this."
|
||||||
|
|
||||||
|
(Typically, this is followed by, "We're only going to need to run this
|
||||||
|
once." That's then typically followed by much forehead slapping and
|
||||||
|
moaning about how stupid we could possibly be.)
|
||||||
|
|
||||||
|
### The goal
|
||||||
|
We're going to extract some scrabble scores from a legacy system.
|
||||||
|
|
||||||
|
The old system stored a list of letters per score:
|
||||||
|
|
||||||
|
- 1 point: "A", "E", "I", "O", "U", "L", "N", "R", "S", "T",
|
||||||
|
- 2 points: "D", "G",
|
||||||
|
- 3 points: "B", "C", "M", "P",
|
||||||
|
- 4 points: "F", "H", "V", "W", "Y",
|
||||||
|
- 5 points: "K",
|
||||||
|
- 8 points: "J", "X",
|
||||||
|
- 10 points: "Q", "Z",
|
||||||
|
|
||||||
|
The shiny new scrabble system instead stores the score per letter, which
|
||||||
|
makes it much faster and easier to calculate the score for a word. It
|
||||||
|
also stores the letters in lower-case regardless of the case of the
|
||||||
|
input letters:
|
||||||
|
|
||||||
|
- "a" is worth 1 point.
|
||||||
|
- "b" is worth 3 points.
|
||||||
|
- "c" is worth 3 points.
|
||||||
|
- "d" is worth 2 points.
|
||||||
|
- Etc.
|
||||||
|
|
||||||
|
Your mission, should you choose to accept it, is to write a program that
|
||||||
|
transforms the legacy data format to the shiny new format.
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
Note that both the old and the new system use strings to represent
|
||||||
|
letters, even in languages that have a separate data type for
|
||||||
|
characters.
|
||||||
|
|
||||||
|
A final note about scoring, Scrabble is played around the world in a
|
||||||
|
variety of languages, each with its own unique scoring table. For
|
||||||
|
example, an "A" is scored at 14 in the Basque-language version of the
|
||||||
|
game while being scored at 9 in the Latin-language version.
|
||||||
|
|
||||||
|
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://help.exercism.io/getting-started-with-go.html).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
The Jumpstart Lab team [view source](http://jumpstartlab.com)
|
17
go/etl/etl.go
Normal file
17
go/etl/etl.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package etl
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
// Transform takes the legacy data structure
|
||||||
|
// and converts it into the new and improved
|
||||||
|
// data structure oh man this new system will
|
||||||
|
// make us so rich you guys.
|
||||||
|
func Transform(input map[int][]string) map[string]int {
|
||||||
|
ret := make(map[string]int)
|
||||||
|
for k, v := range input {
|
||||||
|
for _, let := range v {
|
||||||
|
ret[strings.ToLower(let)] = k
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
90
go/etl/etl_test.go
Normal file
90
go/etl/etl_test.go
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
package etl
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
type given map[int][]string
|
||||||
|
type expectation map[string]int
|
||||||
|
|
||||||
|
var transformTests = []struct {
|
||||||
|
input given
|
||||||
|
output expectation
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
given{1: {"A"}},
|
||||||
|
expectation{"a": 1},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
given{1: {"A", "E", "I", "O", "U"}},
|
||||||
|
expectation{"a": 1, "e": 1, "i": 1, "o": 1, "u": 1},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
given{
|
||||||
|
1: {"A", "E"},
|
||||||
|
2: {"D", "G"},
|
||||||
|
},
|
||||||
|
expectation{
|
||||||
|
"a": 1,
|
||||||
|
"e": 1,
|
||||||
|
"d": 2,
|
||||||
|
"g": 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
given{
|
||||||
|
1: {"A", "E", "I", "O", "U", "L", "N", "R", "S", "T"},
|
||||||
|
2: {"D", "G"},
|
||||||
|
3: {"B", "C", "M", "P"},
|
||||||
|
4: {"F", "H", "V", "W", "Y"},
|
||||||
|
5: {"K"},
|
||||||
|
8: {"J", "X"},
|
||||||
|
10: {"Q", "Z"},
|
||||||
|
},
|
||||||
|
expectation{
|
||||||
|
"a": 1, "e": 1, "i": 1, "o": 1, "u": 1, "l": 1, "n": 1, "r": 1, "s": 1, "t": 1,
|
||||||
|
"d": 2, "g": 2,
|
||||||
|
"b": 3, "c": 3, "m": 3, "p": 3,
|
||||||
|
"f": 4, "h": 4, "v": 4, "w": 4, "y": 4,
|
||||||
|
"k": 5,
|
||||||
|
"j": 8, "x": 8,
|
||||||
|
"q": 10, "z": 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func equal(actual map[string]int, expectation map[string]int) bool {
|
||||||
|
if len(actual) != len(expectation) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, actualVal := range actual {
|
||||||
|
expectationVal, present := expectation[k]
|
||||||
|
|
||||||
|
if !present || actualVal != expectationVal {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTranform(t *testing.T) {
|
||||||
|
for _, tt := range transformTests {
|
||||||
|
actual := Transform(map[int][]string(tt.input))
|
||||||
|
if !equal(actual, tt.output) {
|
||||||
|
t.Fatalf("Transform(%v). Expected [%v], Actual [%v]", tt.input, tt.output, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkTranform(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
for _, tt := range transformTests {
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Transform(map[int][]string(tt.input))
|
||||||
|
}
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
}
|
||||||
|
}
|
80
go/food-chain/README.md
Normal file
80
go/food-chain/README.md
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# Food Chain
|
||||||
|
|
||||||
|
Write a program that generates the lyrics of the song 'I Know an Old Lady Who Swallowed a Fly'
|
||||||
|
|
||||||
|
Write a program that generates the lyrics to the song
|
||||||
|
"I know an old lady who swallowed a fly". While you could
|
||||||
|
copy/paste the lyrics, or read them from a file, this
|
||||||
|
problem is much more interesting if you approach it
|
||||||
|
algorithmically.
|
||||||
|
|
||||||
|
This is a [cumulative song](http://en.wikipedia.org/wiki/Cumulative_song) of unknown origin.
|
||||||
|
|
||||||
|
This is one of many common variants.
|
||||||
|
|
||||||
|
```plain
|
||||||
|
I know an old lady who swallowed a fly.
|
||||||
|
I don't know why she swallowed the fly. Perhaps she'll die.
|
||||||
|
|
||||||
|
I know an old lady who swallowed a spider.
|
||||||
|
It wriggled and jiggled and tickled inside her.
|
||||||
|
She swallowed the spider to catch the fly.
|
||||||
|
I don't know why she swallowed the fly. Perhaps she'll die.
|
||||||
|
|
||||||
|
I know an old lady who swallowed a bird.
|
||||||
|
How absurd to swallow a bird!
|
||||||
|
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
|
||||||
|
She swallowed the spider to catch the fly.
|
||||||
|
I don't know why she swallowed the fly. Perhaps she'll die.
|
||||||
|
|
||||||
|
I know an old lady who swallowed a cat.
|
||||||
|
Imagine that, to swallow a cat!
|
||||||
|
She swallowed the cat to catch the bird.
|
||||||
|
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
|
||||||
|
She swallowed the spider to catch the fly.
|
||||||
|
I don't know why she swallowed the fly. Perhaps she'll die.
|
||||||
|
|
||||||
|
I know an old lady who swallowed a dog.
|
||||||
|
What a hog, to swallow a dog!
|
||||||
|
She swallowed the dog to catch the cat.
|
||||||
|
She swallowed the cat to catch the bird.
|
||||||
|
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
|
||||||
|
She swallowed the spider to catch the fly.
|
||||||
|
I don't know why she swallowed the fly. Perhaps she'll die.
|
||||||
|
|
||||||
|
I know an old lady who swallowed a goat.
|
||||||
|
Just opened her throat and swallowed a goat!
|
||||||
|
She swallowed the goat to catch the dog.
|
||||||
|
She swallowed the dog to catch the cat.
|
||||||
|
She swallowed the cat to catch the bird.
|
||||||
|
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
|
||||||
|
She swallowed the spider to catch the fly.
|
||||||
|
I don't know why she swallowed the fly. Perhaps she'll die.
|
||||||
|
|
||||||
|
I know an old lady who swallowed a cow.
|
||||||
|
I don't know how she swallowed a cow!
|
||||||
|
She swallowed the cow to catch the goat.
|
||||||
|
She swallowed the goat to catch the dog.
|
||||||
|
She swallowed the dog to catch the cat.
|
||||||
|
She swallowed the cat to catch the bird.
|
||||||
|
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
|
||||||
|
She swallowed the spider to catch the fly.
|
||||||
|
I don't know why she swallowed the fly. Perhaps she'll die.
|
||||||
|
|
||||||
|
I know an old lady who swallowed a horse.
|
||||||
|
She's dead, of course!
|
||||||
|
```
|
||||||
|
|
||||||
|
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://help.exercism.io/getting-started-with-go.html).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Wikipedia [view source](http://en.wikipedia.org/wiki/There_Was_an_Old_Lady_Who_Swallowed_a_Fly)
|
100
go/food-chain/food_chain.go
Normal file
100
go/food-chain/food_chain.go
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package foodchain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestVersion is an exercism thing
|
||||||
|
const TestVersion = 1
|
||||||
|
|
||||||
|
// An Inedible is something that you probably shouldn't eat.
|
||||||
|
// At the least, you shouldn't eat it whole/live.
|
||||||
|
type Inedible struct {
|
||||||
|
// What it is
|
||||||
|
Name string
|
||||||
|
// A quick jab about it
|
||||||
|
FollowUp string
|
||||||
|
}
|
||||||
|
|
||||||
|
// DoNotEat is a non-exhaustive list of Inedibles. It's recommended
|
||||||
|
// that you don't eat them. Yet the old lady did.
|
||||||
|
var DoNotEat = []Inedible{
|
||||||
|
Inedible{
|
||||||
|
"fly", "I don't know why she swallowed the fly. Perhaps she'll die.",
|
||||||
|
},
|
||||||
|
Inedible{
|
||||||
|
"spider", "It wriggled and jiggled and tickled inside her.",
|
||||||
|
},
|
||||||
|
Inedible{
|
||||||
|
"bird", "How absurd to swallow a bird!",
|
||||||
|
},
|
||||||
|
Inedible{
|
||||||
|
"cat", "Imagine that, to swallow a cat!",
|
||||||
|
},
|
||||||
|
Inedible{
|
||||||
|
"dog", "What a hog, to swallow a dog!",
|
||||||
|
},
|
||||||
|
Inedible{
|
||||||
|
"goat", "Just opened her throat and swallowed a goat!",
|
||||||
|
},
|
||||||
|
Inedible{
|
||||||
|
"cow", "I don't know how she swallowed a cow!",
|
||||||
|
},
|
||||||
|
Inedible{
|
||||||
|
"horse", "She's dead, of course!",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verse generates the text for a specific verse
|
||||||
|
func Verse(verseNum int) string {
|
||||||
|
return strings.Trim(Swallow(verseNum-1, true), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verses generates the text for all verses from verse1 to verse2
|
||||||
|
func Verses(verse1, verse2 int) string {
|
||||||
|
var ret string
|
||||||
|
for verse1 <= verse2 {
|
||||||
|
ret += Verse(verse1) + "\n\n"
|
||||||
|
verse1++
|
||||||
|
}
|
||||||
|
return strings.Trim(ret, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Song generates all verses
|
||||||
|
func Song() string {
|
||||||
|
var ret string
|
||||||
|
for verseNum := 1; verseNum <= len(DoNotEat); verseNum++ {
|
||||||
|
ret += Verse(verseNum) + "\n\n"
|
||||||
|
}
|
||||||
|
return strings.Trim(ret, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swallow generates the text for swallowing something
|
||||||
|
func Swallow(dneIdx int, first bool) string {
|
||||||
|
var ret string
|
||||||
|
|
||||||
|
if first || dneIdx == len(DoNotEat)-1 {
|
||||||
|
ret = fmt.Sprintf(
|
||||||
|
"I know an old lady who swallowed a %s.\n%s\n",
|
||||||
|
DoNotEat[dneIdx].Name,
|
||||||
|
DoNotEat[dneIdx].FollowUp,
|
||||||
|
)
|
||||||
|
if dneIdx == 0 || dneIdx == len(DoNotEat)-1 {
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret += fmt.Sprintf("She swallowed the %s to catch the %s",
|
||||||
|
DoNotEat[dneIdx].Name,
|
||||||
|
DoNotEat[dneIdx-1].Name,
|
||||||
|
)
|
||||||
|
if DoNotEat[dneIdx-1].Name == "spider" {
|
||||||
|
ret += " that wriggled and jiggled and tickled inside her.\n"
|
||||||
|
} else if DoNotEat[dneIdx-1].Name == "fly" {
|
||||||
|
ret += ".\nI don't know why she swallowed the fly. Perhaps she'll die.\n"
|
||||||
|
return ret
|
||||||
|
} else {
|
||||||
|
ret += ".\n"
|
||||||
|
}
|
||||||
|
return ret + Swallow(dneIdx-1, false)
|
||||||
|
}
|
95
go/food-chain/food_chain_test.go
Normal file
95
go/food-chain/food_chain_test.go
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package foodchain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const testVersion = 1
|
||||||
|
|
||||||
|
func TestTestVersion(t *testing.T) {
|
||||||
|
if TestVersion != testVersion {
|
||||||
|
t.Errorf("Found TestVersion = %v, want %v.", TestVersion, testVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ref = []string{``,
|
||||||
|
|
||||||
|
`I know an old lady who swallowed a fly.
|
||||||
|
I don't know why she swallowed the fly. Perhaps she'll die.`,
|
||||||
|
|
||||||
|
`I know an old lady who swallowed a spider.
|
||||||
|
It wriggled and jiggled and tickled inside her.
|
||||||
|
She swallowed the spider to catch the fly.
|
||||||
|
I don't know why she swallowed the fly. Perhaps she'll die.`,
|
||||||
|
|
||||||
|
`I know an old lady who swallowed a bird.
|
||||||
|
How absurd to swallow a bird!
|
||||||
|
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
|
||||||
|
She swallowed the spider to catch the fly.
|
||||||
|
I don't know why she swallowed the fly. Perhaps she'll die.`,
|
||||||
|
|
||||||
|
`I know an old lady who swallowed a cat.
|
||||||
|
Imagine that, to swallow a cat!
|
||||||
|
She swallowed the cat to catch the bird.
|
||||||
|
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
|
||||||
|
She swallowed the spider to catch the fly.
|
||||||
|
I don't know why she swallowed the fly. Perhaps she'll die.`,
|
||||||
|
|
||||||
|
`I know an old lady who swallowed a dog.
|
||||||
|
What a hog, to swallow a dog!
|
||||||
|
She swallowed the dog to catch the cat.
|
||||||
|
She swallowed the cat to catch the bird.
|
||||||
|
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
|
||||||
|
She swallowed the spider to catch the fly.
|
||||||
|
I don't know why she swallowed the fly. Perhaps she'll die.`,
|
||||||
|
|
||||||
|
`I know an old lady who swallowed a goat.
|
||||||
|
Just opened her throat and swallowed a goat!
|
||||||
|
She swallowed the goat to catch the dog.
|
||||||
|
She swallowed the dog to catch the cat.
|
||||||
|
She swallowed the cat to catch the bird.
|
||||||
|
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
|
||||||
|
She swallowed the spider to catch the fly.
|
||||||
|
I don't know why she swallowed the fly. Perhaps she'll die.`,
|
||||||
|
|
||||||
|
`I know an old lady who swallowed a cow.
|
||||||
|
I don't know how she swallowed a cow!
|
||||||
|
She swallowed the cow to catch the goat.
|
||||||
|
She swallowed the goat to catch the dog.
|
||||||
|
She swallowed the dog to catch the cat.
|
||||||
|
She swallowed the cat to catch the bird.
|
||||||
|
She swallowed the bird to catch the spider that wriggled and jiggled and tickled inside her.
|
||||||
|
She swallowed the spider to catch the fly.
|
||||||
|
I don't know why she swallowed the fly. Perhaps she'll die.`,
|
||||||
|
|
||||||
|
`I know an old lady who swallowed a horse.
|
||||||
|
She's dead, of course!`,
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVerse(t *testing.T) {
|
||||||
|
for v := 1; v <= 8; v++ {
|
||||||
|
if ret := Verse(v); ret != ref[v] {
|
||||||
|
t.Fatalf("Verse(%d) =\n%s\n want:\n%s\n", v, ret, ref[v])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVerses(t *testing.T) {
|
||||||
|
if ret, want := Verses(1, 2), ref[1]+"\n\n"+ref[2]; ret != want {
|
||||||
|
t.Fatalf("Verses(1, 2) =\n%s\n want:\n%s\n", ret, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSong(t *testing.T) {
|
||||||
|
if ret, want := Song(), strings.Join(ref[1:], "\n\n"); ret != want {
|
||||||
|
t.Fatalf("Song() =\n%s\n want:\n%s\n", ret, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSong(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Song()
|
||||||
|
}
|
||||||
|
}
|
19
go/gigasecond/README.md
Normal file
19
go/gigasecond/README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Gigasecond
|
||||||
|
|
||||||
|
Write a program that will calculate the date that someone turned or will celebrate their 1 Gs anniversary.
|
||||||
|
|
||||||
|
A gigasecond is one billion (10**9) seconds.
|
||||||
|
|
||||||
|
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://help.exercism.io/getting-started-with-go.html).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Chapter 9 in Chris Pine's online Learn to Program tutorial. [view source](http://pine.fm/LearnToProgram/?Chapter=09)
|
31
go/gigasecond/cases_test.go
Normal file
31
go/gigasecond/cases_test.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package gigasecond
|
||||||
|
|
||||||
|
// Source: exercism/x-common
|
||||||
|
// Commit: 1e9e232 Merge pull request #45 from soniakeys/gigasecond-tests
|
||||||
|
|
||||||
|
// Add one gigasecond to the input.
|
||||||
|
var addCases = []struct {
|
||||||
|
in string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"2011-04-25",
|
||||||
|
"2043-01-01T01:46:40",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"1977-06-13",
|
||||||
|
"2009-02-19T01:46:40",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"1959-07-19",
|
||||||
|
"1991-03-27T01:46:40",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"2015-01-24T22:00:00",
|
||||||
|
"2046-10-02T23:46:40",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"2015-01-24T23:59:59",
|
||||||
|
"2046-10-03T01:46:39",
|
||||||
|
},
|
||||||
|
}
|
14
go/gigasecond/gigasecond.go
Normal file
14
go/gigasecond/gigasecond.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package gigasecond
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// TestVersion
|
||||||
|
const TestVersion = 2 // find the value in gigasecond_test.go
|
||||||
|
|
||||||
|
// AddGigasecond Adds a gigasecond to the time t
|
||||||
|
func AddGigasecond(t time.Time) time.Time {
|
||||||
|
return t.Add(time.Second * 1000000000)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Birthday is my fake birthday
|
||||||
|
var Birthday = time.Date(1979, 4, 23, 10, 2, 0, 0, time.UTC)
|
73
go/gigasecond/gigasecond_test.go
Normal file
73
go/gigasecond/gigasecond_test.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package gigasecond
|
||||||
|
|
||||||
|
// Write a function AddGigasecond that works with time.Time.
|
||||||
|
// Also define a variable Birthday set to your (or someone else's) birthday.
|
||||||
|
// Run go test -v to see your gigasecond anniversary.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const testVersion = 2
|
||||||
|
|
||||||
|
// Retired testVersions
|
||||||
|
// (none) 98807b314216ff27492378a00df60410cc971d32
|
||||||
|
// 1 ed0594b6fd6664928d17bbc70b543a56da05a5b8
|
||||||
|
|
||||||
|
// date formats used in test data
|
||||||
|
const (
|
||||||
|
fmtD = "2006-01-02"
|
||||||
|
fmtDT = "2006-01-02T15:04:05"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAddGigasecond(t *testing.T) {
|
||||||
|
if TestVersion != testVersion {
|
||||||
|
t.Fatalf("Found TestVersion = %v, want %v.", TestVersion, testVersion)
|
||||||
|
}
|
||||||
|
for _, tc := range addCases {
|
||||||
|
in := parse(tc.in, t)
|
||||||
|
want := parse(tc.want, t)
|
||||||
|
got := AddGigasecond(in)
|
||||||
|
if !got.Equal(want) {
|
||||||
|
t.Fatalf(`AddGigasecond(%s)
|
||||||
|
= %s
|
||||||
|
want %s`, in, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Log("Tested", len(addCases), "cases.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestYourAnniversary(t *testing.T) {
|
||||||
|
t.Logf(`
|
||||||
|
Your birthday: %s
|
||||||
|
Your gigasecond anniversary: %s`, Birthday, AddGigasecond(Birthday))
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse(s string, t *testing.T) time.Time {
|
||||||
|
tt, err := time.Parse(fmtDT, s) // try full date time format first
|
||||||
|
if err != nil {
|
||||||
|
tt, err = time.Parse(fmtD, s) // also allow just date
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
// can't run tests if input won't parse. if this seems to be a
|
||||||
|
// development or ci environment, raise an error. if this condition
|
||||||
|
// makes it to the solver though, ask for a bug report.
|
||||||
|
_, statErr := os.Stat("example_gen.go")
|
||||||
|
if statErr == nil || os.Getenv("TRAVIS_GO_VERSION") > "" {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
t.Log(err)
|
||||||
|
t.Skip("(Not your problem. " +
|
||||||
|
"please file issue at https://github.com/exercism/xgo.)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tt
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAddGigasecond(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
AddGigasecond(time.Time{})
|
||||||
|
}
|
||||||
|
}
|
41
go/grains/README.md
Normal file
41
go/grains/README.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# Grains
|
||||||
|
|
||||||
|
Write a program that calculates the number of grains of wheat on a chessboard given that the number on each square doubles.
|
||||||
|
|
||||||
|
There once was a wise servant who saved the life of a prince. The king
|
||||||
|
promised to pay whatever the servant could dream up. Knowing that the
|
||||||
|
king loved chess, the servant told the king he would like to have grains
|
||||||
|
of wheat. One grain on the first square of a chess board. Two grains on
|
||||||
|
the next. Four on the third, and so on.
|
||||||
|
|
||||||
|
There are 64 squares on a chessboard.
|
||||||
|
|
||||||
|
Write a program that shows:
|
||||||
|
- how many grains were on each square, and
|
||||||
|
- the total number of grains
|
||||||
|
|
||||||
|
|
||||||
|
## For bonus points
|
||||||
|
|
||||||
|
Did you get the tests passing and the code clean? If you want to, these
|
||||||
|
are some additional things you could try:
|
||||||
|
|
||||||
|
- Optimize for speed.
|
||||||
|
- Optimize for readability.
|
||||||
|
|
||||||
|
Then please share your thoughts in a comment on the submission. Did this
|
||||||
|
experiment make the code better? Worse? Did you learn anything from it?
|
||||||
|
|
||||||
|
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://help.exercism.io/getting-started-with-go.html).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
JavaRanch Cattle Drive, exercise 6 [view source](http://www.javaranch.com/grains.jsp)
|
30
go/grains/grains.go
Normal file
30
go/grains/grains.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package grains
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
// Square just takes 1 * 2^sq
|
||||||
|
func Square(sq int) (uint64, error) {
|
||||||
|
if sq > 0 && sq < 65 {
|
||||||
|
return (1 << uint(sq-1)), nil
|
||||||
|
}
|
||||||
|
return 0, errors.New("Invalid Square Requested")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TotalForSquare calculates the total number
|
||||||
|
// for all squares up to sq (cause why not)
|
||||||
|
func TotalForSquare(sq int) (uint64, error) {
|
||||||
|
if sq < 0 || sq > 64 {
|
||||||
|
return 0, errors.New("Invalid Square Requested")
|
||||||
|
}
|
||||||
|
var ret uint64
|
||||||
|
for i := 0; i <= sq; i++ {
|
||||||
|
ret = (ret << 1) | 1
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Total calculates the total for the entire board
|
||||||
|
func Total() uint64 {
|
||||||
|
ret, _ := TotalForSquare(64)
|
||||||
|
return ret
|
||||||
|
}
|
61
go/grains/grains_test.go
Normal file
61
go/grains/grains_test.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package grains
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var squareTests = []struct {
|
||||||
|
input int
|
||||||
|
expectedVal uint64
|
||||||
|
expectError bool
|
||||||
|
}{
|
||||||
|
{1, 1, false},
|
||||||
|
{2, 2, false},
|
||||||
|
{3, 4, false},
|
||||||
|
{4, 8, false},
|
||||||
|
{16, 32768, false},
|
||||||
|
{32, 2147483648, false},
|
||||||
|
{64, 9223372036854775808, false},
|
||||||
|
{65, 0, true},
|
||||||
|
{0, 0, true},
|
||||||
|
{-1, 0, true},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSquare(t *testing.T) {
|
||||||
|
for _, test := range squareTests {
|
||||||
|
actualVal, actualErr := Square(test.input)
|
||||||
|
if actualVal != test.expectedVal {
|
||||||
|
t.Errorf("Square(%d) expected %d, Actual %d", test.input, test.expectedVal, actualVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we expect an error and there isn't one
|
||||||
|
if test.expectError && actualErr == nil {
|
||||||
|
t.Errorf("Square(%d) expected an error, but error is nil", test.input)
|
||||||
|
}
|
||||||
|
// if we don't expect an error and there is one
|
||||||
|
if !test.expectError && actualErr != nil {
|
||||||
|
t.Errorf("Square(%d) expected no error, but error is: %s", test.input, actualErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTotal(t *testing.T) {
|
||||||
|
var expected uint64 = 18446744073709551615
|
||||||
|
if actual := Total(); actual != expected {
|
||||||
|
t.Errorf("Total() expected %d, Actual %d", expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSquare(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
|
||||||
|
for _, test := range squareTests {
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Square(test.input)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
}
|
||||||
|
}
|
50
go/hamming/README.md
Normal file
50
go/hamming/README.md
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
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://help.exercism.io/getting-started-with-go.html).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
The Calculating Point Mutations problem at Rosalind [view source](http://rosalind.info/problems/hamm/)
|
81
go/hamming/cases_test.go
Normal file
81
go/hamming/cases_test.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package hamming
|
||||||
|
|
||||||
|
// Source: exercism/x-common
|
||||||
|
// Commit: c84e435 Merge pull request #51 from soniakeys/master
|
||||||
|
|
||||||
|
var testCases = []struct {
|
||||||
|
s1 string
|
||||||
|
s2 string
|
||||||
|
want int
|
||||||
|
}{
|
||||||
|
{ // identical strands
|
||||||
|
"A",
|
||||||
|
"A",
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // long identical strands
|
||||||
|
"GGACTGA",
|
||||||
|
"GGACTGA",
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // complete distance in single nucleotide strands
|
||||||
|
"A",
|
||||||
|
"G",
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
{ // complete distance in small strands
|
||||||
|
"AG",
|
||||||
|
"CT",
|
||||||
|
2,
|
||||||
|
},
|
||||||
|
{ // small distance in small strands
|
||||||
|
"AT",
|
||||||
|
"CT",
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
{ // small distance
|
||||||
|
"GGACG",
|
||||||
|
"GGTCG",
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
{ // small distance in long strands
|
||||||
|
"ACCAGGG",
|
||||||
|
"ACTATGG",
|
||||||
|
2,
|
||||||
|
},
|
||||||
|
{ // non-unique character in first strand
|
||||||
|
"AGA",
|
||||||
|
"AGG",
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
{ // non-unique character in second strand
|
||||||
|
"AGG",
|
||||||
|
"AGA",
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
{ // large distance
|
||||||
|
"GATACA",
|
||||||
|
"GCATAA",
|
||||||
|
4,
|
||||||
|
},
|
||||||
|
{ // large distance in off-by-one strand
|
||||||
|
"GGACGGATTCTG",
|
||||||
|
"AGGACGGATTCT",
|
||||||
|
9,
|
||||||
|
},
|
||||||
|
{ // empty strands
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{ // disallow first strand longer
|
||||||
|
"AATG",
|
||||||
|
"AAA",
|
||||||
|
-1,
|
||||||
|
},
|
||||||
|
{ // disallow second strand longer
|
||||||
|
"ATA",
|
||||||
|
"AGTG",
|
||||||
|
-1,
|
||||||
|
},
|
||||||
|
}
|
21
go/hamming/hamming.go
Normal file
21
go/hamming/hamming.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package hamming
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
// TestVersion is an exercism thing
|
||||||
|
const TestVersion = 2
|
||||||
|
|
||||||
|
// Distance measures the hamming distance between two sequences
|
||||||
|
// and returns the number if different bytes and an error value
|
||||||
|
func Distance(seq1, seq2 string) (int, error) {
|
||||||
|
if len(seq1) != len(seq2) {
|
||||||
|
return -1, errors.New("Strands must be equal length")
|
||||||
|
}
|
||||||
|
var ret int
|
||||||
|
for i := 0; i < len(seq1); i++ {
|
||||||
|
if seq1[i] != seq2[i] {
|
||||||
|
ret++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
39
go/hamming/hamming_test.go
Normal file
39
go/hamming/hamming_test.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package hamming
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
const testVersion = 2
|
||||||
|
|
||||||
|
// Retired testVersions
|
||||||
|
// (none) df178dc24b57f7d4ccf54d47430192749d56898f
|
||||||
|
// 1 4f6fe21682f7f2a7845683cb26ff557208153ffe
|
||||||
|
|
||||||
|
func TestHamming(t *testing.T) {
|
||||||
|
if TestVersion != testVersion {
|
||||||
|
t.Errorf("Found TestVersion = %v, want %v.", TestVersion, testVersion)
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
switch got, err := Distance(tc.s1, tc.s2); {
|
||||||
|
case err != nil:
|
||||||
|
if tc.want >= 0 {
|
||||||
|
t.Fatalf("Distance(%q, %q) returned error: %v",
|
||||||
|
tc.s1, tc.s2, err)
|
||||||
|
}
|
||||||
|
case tc.want < 0:
|
||||||
|
t.Fatalf("Distance(%q, %q) = %d. Expected error.",
|
||||||
|
tc.s1, tc.s2, got)
|
||||||
|
case got != tc.want:
|
||||||
|
t.Fatalf("Distance(%q, %q) = %d, want %d.",
|
||||||
|
tc.s1, tc.s2, got, tc.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkHamming(b *testing.B) {
|
||||||
|
// bench combined time to run through all test cases
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, tc := range testCases {
|
||||||
|
Distance(tc.s1, tc.s2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
121
go/house/README.md
Normal file
121
go/house/README.md
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
# House
|
||||||
|
|
||||||
|
Write a program that outputs the nursery rhyme 'This is the House that Jack Built'.
|
||||||
|
|
||||||
|
> [The] process of placing a phrase of clause within another phrase of
|
||||||
|
> clause is called embedding. It is through the processes of recursion
|
||||||
|
> and embedding that we are able to take a finite number of forms (words
|
||||||
|
> and phrases) and construct an infinite number of expressions.
|
||||||
|
> Furthermore, embedding also allows us to construct an infinitely long
|
||||||
|
> structure, in theory anyway.
|
||||||
|
|
||||||
|
- [papyr.com](http://papyr.com/hypertextbooks/grammar/ph_noun.htm)
|
||||||
|
|
||||||
|
|
||||||
|
The nursery rhyme reads as follows:
|
||||||
|
|
||||||
|
```plain
|
||||||
|
This is the house that Jack built.
|
||||||
|
|
||||||
|
This is the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the cow with the crumpled horn
|
||||||
|
that tossed the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the maiden all forlorn
|
||||||
|
that milked the cow with the crumpled horn
|
||||||
|
that tossed the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the man all tattered and torn
|
||||||
|
that kissed the maiden all forlorn
|
||||||
|
that milked the cow with the crumpled horn
|
||||||
|
that tossed the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the priest all shaven and shorn
|
||||||
|
that married the man all tattered and torn
|
||||||
|
that kissed the maiden all forlorn
|
||||||
|
that milked the cow with the crumpled horn
|
||||||
|
that tossed the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the rooster that crowed in the morn
|
||||||
|
that woke the priest all shaven and shorn
|
||||||
|
that married the man all tattered and torn
|
||||||
|
that kissed the maiden all forlorn
|
||||||
|
that milked the cow with the crumpled horn
|
||||||
|
that tossed the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the farmer sowing his corn
|
||||||
|
that kept the rooster that crowed in the morn
|
||||||
|
that woke the priest all shaven and shorn
|
||||||
|
that married the man all tattered and torn
|
||||||
|
that kissed the maiden all forlorn
|
||||||
|
that milked the cow with the crumpled horn
|
||||||
|
that tossed the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the horse and the hound and the horn
|
||||||
|
that belonged to the farmer sowing his corn
|
||||||
|
that kept the rooster that crowed in the morn
|
||||||
|
that woke the priest all shaven and shorn
|
||||||
|
that married the man all tattered and torn
|
||||||
|
that kissed the maiden all forlorn
|
||||||
|
that milked the cow with the crumpled horn
|
||||||
|
that tossed the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
```
|
||||||
|
|
||||||
|
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://help.exercism.io/getting-started-with-go.html).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
British nursery rhyme [view source](http://en.wikipedia.org/wiki/This_Is_The_House_That_Jack_Built)
|
50
go/house/house.go
Normal file
50
go/house/house.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package house
|
||||||
|
|
||||||
|
// ASong holds the data we need to generate a song
|
||||||
|
type ASong struct {
|
||||||
|
start string
|
||||||
|
clauses []string
|
||||||
|
end string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Embed takes two strings and returns a string with the embedded
|
||||||
|
func Embed(l, p string) string {
|
||||||
|
return l + " " + p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verse takes three things and returns a verse
|
||||||
|
func Verse(start string, clause []string, end string) string {
|
||||||
|
ret := start + " "
|
||||||
|
for i := 0; i < len(clause); i++ {
|
||||||
|
ret += clause[i] + " "
|
||||||
|
}
|
||||||
|
ret += end
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// Song generates the whole song
|
||||||
|
func Song() string {
|
||||||
|
jackSong := ASong{
|
||||||
|
start: "This is",
|
||||||
|
clauses: []string{
|
||||||
|
"the horse and the hound and the horn\nthat belonged to",
|
||||||
|
"the farmer sowing his corn\nthat kept",
|
||||||
|
"the rooster that crowed in the morn\nthat woke",
|
||||||
|
"the priest all shaven and shorn\nthat married",
|
||||||
|
"the man all tattered and torn\nthat kissed",
|
||||||
|
"the maiden all forlorn\nthat milked",
|
||||||
|
"the cow with the crumpled horn\nthat tossed",
|
||||||
|
"the dog\nthat worried",
|
||||||
|
"the cat\nthat killed",
|
||||||
|
"the rat\nthat ate",
|
||||||
|
"the malt\nthat lay in",
|
||||||
|
},
|
||||||
|
end: "the house that Jack built.",
|
||||||
|
}
|
||||||
|
var ret string
|
||||||
|
for i := len(jackSong.clauses); i >= 0; i-- {
|
||||||
|
ret += Verse(jackSong.start, jackSong.clauses[i:], jackSong.end) + "\n\n"
|
||||||
|
}
|
||||||
|
// Trim the trailing "\n\n"
|
||||||
|
return ret[:len(ret)-2]
|
||||||
|
}
|
171
go/house/house_test.go
Normal file
171
go/house/house_test.go
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
// Embed embeds a noun phrase as the object of relative clause with a
|
||||||
|
// transitive verb.
|
||||||
|
//
|
||||||
|
// Argument relPhrase is a phrase with a relative clause, minus the object
|
||||||
|
// of the clause. That is, relPhrase consists of a subject, a relative
|
||||||
|
// pronoun, a transitive verb, possibly a preposition, but then no object.
|
||||||
|
//
|
||||||
|
// func Embed(relPhrase, nounPhrase string) string
|
||||||
|
|
||||||
|
// Verse generates a verse of a song with relative clauses that have
|
||||||
|
// a recursive structure.
|
||||||
|
//
|
||||||
|
// func Verse(subject string, relPhrases []string, nounPhrase string) string
|
||||||
|
//
|
||||||
|
// There are different ways to do this of course, but try using Embed as a
|
||||||
|
// subroutine and using programmatic recursion that reflects the grammatical
|
||||||
|
// recursion.
|
||||||
|
|
||||||
|
// Song generates the full text of "The House That Jack Built". Oh yes, you
|
||||||
|
// could just return a string literal, but humor us; use Verse as a subroutine.
|
||||||
|
//
|
||||||
|
// func Song() string
|
||||||
|
|
||||||
|
package house
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
s = "This is"
|
||||||
|
r = []string{
|
||||||
|
"the cat that broke",
|
||||||
|
"the vase that was on",
|
||||||
|
}
|
||||||
|
p = "the shelf."
|
||||||
|
last = len(r) - 1
|
||||||
|
// song copied from readme
|
||||||
|
song = `This is the house that Jack built.
|
||||||
|
|
||||||
|
This is the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the cow with the crumpled horn
|
||||||
|
that tossed the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the maiden all forlorn
|
||||||
|
that milked the cow with the crumpled horn
|
||||||
|
that tossed the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the man all tattered and torn
|
||||||
|
that kissed the maiden all forlorn
|
||||||
|
that milked the cow with the crumpled horn
|
||||||
|
that tossed the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the priest all shaven and shorn
|
||||||
|
that married the man all tattered and torn
|
||||||
|
that kissed the maiden all forlorn
|
||||||
|
that milked the cow with the crumpled horn
|
||||||
|
that tossed the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the rooster that crowed in the morn
|
||||||
|
that woke the priest all shaven and shorn
|
||||||
|
that married the man all tattered and torn
|
||||||
|
that kissed the maiden all forlorn
|
||||||
|
that milked the cow with the crumpled horn
|
||||||
|
that tossed the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the farmer sowing his corn
|
||||||
|
that kept the rooster that crowed in the morn
|
||||||
|
that woke the priest all shaven and shorn
|
||||||
|
that married the man all tattered and torn
|
||||||
|
that kissed the maiden all forlorn
|
||||||
|
that milked the cow with the crumpled horn
|
||||||
|
that tossed the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.
|
||||||
|
|
||||||
|
This is the horse and the hound and the horn
|
||||||
|
that belonged to the farmer sowing his corn
|
||||||
|
that kept the rooster that crowed in the morn
|
||||||
|
that woke the priest all shaven and shorn
|
||||||
|
that married the man all tattered and torn
|
||||||
|
that kissed the maiden all forlorn
|
||||||
|
that milked the cow with the crumpled horn
|
||||||
|
that tossed the dog
|
||||||
|
that worried the cat
|
||||||
|
that killed the rat
|
||||||
|
that ate the malt
|
||||||
|
that lay in the house that Jack built.`
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEmbed(t *testing.T) {
|
||||||
|
l := r[last]
|
||||||
|
want := l + " " + p
|
||||||
|
if e := Embed(l, p); e != want {
|
||||||
|
t.Fatalf("Embed(%q, %q) = %q, want %q.", l, p, e, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVerse(t *testing.T) {
|
||||||
|
for i := len(r); i >= 0; i-- {
|
||||||
|
ri := r[i:]
|
||||||
|
want := s + " " + strings.Join(append(ri, p), " ")
|
||||||
|
if v := Verse(s, ri, p); v != want {
|
||||||
|
t.Fatalf("Verse(%q, %q, %q) = %q, want %q.", s, ri, p, v, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSong(t *testing.T) {
|
||||||
|
s := Song()
|
||||||
|
if s == song {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Print(s)
|
||||||
|
// a little help in locating an error
|
||||||
|
got := strings.Split(s, "\n")
|
||||||
|
want := strings.Split(song, "\n")
|
||||||
|
var g, w string
|
||||||
|
var i int
|
||||||
|
for i, w = range want {
|
||||||
|
if len(got) <= i {
|
||||||
|
g = ""
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if g = got[i]; g != w {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Fatalf("Song() line %d = %q, want %q", i+1, g, w)
|
||||||
|
}
|
24
go/largest-series-product/README.md
Normal file
24
go/largest-series-product/README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Largest Series Product
|
||||||
|
|
||||||
|
Write a program that, when given a string of digits, can calculate the largest product for a series of consecutive digits of length n.
|
||||||
|
|
||||||
|
For example, for the input `'0123456789'`, the largest product for a
|
||||||
|
series of 3 digits is 504 (7 * 8 * 9), and the largest product for a
|
||||||
|
series of 5 digits is 15120 (5 * 6 * 7 * 8 * 9).
|
||||||
|
|
||||||
|
For the input `'73167176531330624919225119674426574742355349194934'`,
|
||||||
|
the largest product for a series of 6 digits is 23520.
|
||||||
|
|
||||||
|
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://help.exercism.io/getting-started-with-go.html).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
A variation on Problem 8 at Project Euler [view source](http://projecteuler.net/problem=8)
|
29
go/largest-series-product/cases_test.go
Normal file
29
go/largest-series-product/cases_test.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package lsproduct
|
||||||
|
|
||||||
|
// Source: exercism/x-common
|
||||||
|
// Commit: 3764abd Merge pull request #167 from petertseng/largest-series-product-json
|
||||||
|
|
||||||
|
var tests = []struct {
|
||||||
|
digits string
|
||||||
|
span int
|
||||||
|
product int64
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{"0123456789", 2, 72, true},
|
||||||
|
{"576802143", 2, 48, true},
|
||||||
|
{"29", 2, 18, true},
|
||||||
|
{"0123456789", 3, 504, true},
|
||||||
|
{"1027839564", 3, 270, true},
|
||||||
|
{"0123456789", 5, 15120, true},
|
||||||
|
{"73167176531330624919225119674426574742355349194934", 6, 23520, true},
|
||||||
|
{"52677741234314237566414902593461595376319419139427", 6, 28350, true},
|
||||||
|
{"7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450", 13, 23514624000, true},
|
||||||
|
{"0000", 2, 0, true},
|
||||||
|
{"99099", 3, 0, true},
|
||||||
|
{"123", 4, -1, false},
|
||||||
|
{"", 0, 1, true},
|
||||||
|
{"123", 0, 1, true},
|
||||||
|
{"", 1, -1, false},
|
||||||
|
{"1234a5", 2, -1, false},
|
||||||
|
{"12345", -1, -1, false},
|
||||||
|
}
|
45
go/largest-series-product/largest_series_product.go
Normal file
45
go/largest-series-product/largest_series_product.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package lsproduct
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// TestVersion defines version testing.
|
||||||
|
const TestVersion = 1
|
||||||
|
|
||||||
|
// LargestSeriesProduct Takes an input string of digits
|
||||||
|
// and a length for the series. It returns the largest
|
||||||
|
// series product from that string of that length.
|
||||||
|
func LargestSeriesProduct(input string, size int) (int, error) {
|
||||||
|
if size == 0 {
|
||||||
|
return 1, nil
|
||||||
|
} else if size > len(input) {
|
||||||
|
return 0, fmt.Errorf("Invalid Span Size")
|
||||||
|
}
|
||||||
|
var high int
|
||||||
|
for i := 0; i < (len(input) - size + 1); i++ {
|
||||||
|
try := GetProduct(input[i : i+size])
|
||||||
|
if try < 0 {
|
||||||
|
return 0, fmt.Errorf("Invalid input")
|
||||||
|
}
|
||||||
|
if try > high {
|
||||||
|
high = try
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return high, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetProduct takes a string of numbers, splits it up
|
||||||
|
// and returns the product of them
|
||||||
|
func GetProduct(input string) int {
|
||||||
|
if len(input) > 0 {
|
||||||
|
total := 1
|
||||||
|
for i := range input {
|
||||||
|
next := input[i] - 48
|
||||||
|
if next < 0 || next > 9 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
total = total * int(next)
|
||||||
|
}
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
92
go/largest-series-product/largest_series_product_test.go
Normal file
92
go/largest-series-product/largest_series_product_test.go
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package lsproduct
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
const testVersion = 1
|
||||||
|
|
||||||
|
// Retired testVersions
|
||||||
|
// (none) ba7a22a355a32901caf46529c799fa53118ded0a
|
||||||
|
|
||||||
|
var tests = []struct {
|
||||||
|
digits string
|
||||||
|
span int
|
||||||
|
product int64
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{"0123456789",
|
||||||
|
2, 72, true},
|
||||||
|
{"12",
|
||||||
|
2, 2, true},
|
||||||
|
{"19",
|
||||||
|
2, 9, true},
|
||||||
|
{"576802143",
|
||||||
|
2, 48, true},
|
||||||
|
{"0123456789",
|
||||||
|
3, 504, true},
|
||||||
|
{"1027839564",
|
||||||
|
3, 270, true},
|
||||||
|
{"0123456789",
|
||||||
|
5, 15120, true},
|
||||||
|
{"73167176531330624919225119674426574742355349194934",
|
||||||
|
6, 23520, true},
|
||||||
|
{"52677741234314237566414902593461595376319419139427",
|
||||||
|
6, 28350, true},
|
||||||
|
{"",
|
||||||
|
0, 1, true},
|
||||||
|
{"123",
|
||||||
|
4, 0, false},
|
||||||
|
{pe1k, 5, 40824, true}, // original PE problem
|
||||||
|
{pe1k, 13, 23514624000, true}, // new PE problem
|
||||||
|
}
|
||||||
|
|
||||||
|
const pe1k = "73167176531330624919225119674426574742355349194934" +
|
||||||
|
"96983520312774506326239578318016984801869478851843" +
|
||||||
|
"85861560789112949495459501737958331952853208805511" +
|
||||||
|
"12540698747158523863050715693290963295227443043557" +
|
||||||
|
"66896648950445244523161731856403098711121722383113" +
|
||||||
|
"62229893423380308135336276614282806444486645238749" +
|
||||||
|
"30358907296290491560440772390713810515859307960866" +
|
||||||
|
"70172427121883998797908792274921901699720888093776" +
|
||||||
|
"65727333001053367881220235421809751254540594752243" +
|
||||||
|
"52584907711670556013604839586446706324415722155397" +
|
||||||
|
"53697817977846174064955149290862569321978468622482" +
|
||||||
|
"83972241375657056057490261407972968652414535100474" +
|
||||||
|
"82166370484403199890008895243450658541227588666881" +
|
||||||
|
"16427171479924442928230863465674813919123162824586" +
|
||||||
|
"17866458359124566529476545682848912883142607690042" +
|
||||||
|
"24219022671055626321111109370544217506941658960408" +
|
||||||
|
"07198403850962455444362981230987879927244284909188" +
|
||||||
|
"84580156166097919133875499200524063689912560717606" +
|
||||||
|
"05886116467109405077541002256983155200055935729725" +
|
||||||
|
"71636269561882670428252483600823257530420752963450"
|
||||||
|
|
||||||
|
func TestLargestSeriesProduct(t *testing.T) {
|
||||||
|
if TestVersion != testVersion {
|
||||||
|
t.Fatalf("Found TestVersion = %v, want %v", TestVersion, testVersion)
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
p, err := LargestSeriesProduct(test.digits, test.span)
|
||||||
|
switch {
|
||||||
|
case err != nil:
|
||||||
|
if test.ok {
|
||||||
|
t.Fatalf("LargestSeriesProduct(%s, %d) returned error %q. "+
|
||||||
|
"Error not expected.",
|
||||||
|
test.digits, test.span, err)
|
||||||
|
}
|
||||||
|
case !test.ok:
|
||||||
|
t.Fatalf("LargestSeriesProduct(%s, %d) = %d, %v. Expected error",
|
||||||
|
test.digits, test.span, p, err)
|
||||||
|
case int64(p) != test.product:
|
||||||
|
t.Fatalf("LargestSeriesProduct(%s, %d) = %d, want %d",
|
||||||
|
test.digits, test.span, p, test.product)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkLargestSeriesProduct(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, test := range tests {
|
||||||
|
LargestSeriesProduct(test.digits, test.span)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
go/leap/README.md
Normal file
38
go/leap/README.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Leap
|
||||||
|
|
||||||
|
Write a program that will take a year and report if it is a leap year.
|
||||||
|
|
||||||
|
The tricky thing here is that a leap year occurs:
|
||||||
|
|
||||||
|
```plain
|
||||||
|
on every year that is evenly divisible by 4
|
||||||
|
except every year that is evenly divisible by 100
|
||||||
|
unless the year is also evenly divisible by 400
|
||||||
|
```
|
||||||
|
|
||||||
|
For example, 1997 is not a leap year, but 1996 is. 1900 is not a leap
|
||||||
|
year, but 2000 is.
|
||||||
|
|
||||||
|
If your language provides a method in the standard library that does
|
||||||
|
this look-up, pretend it doesn't exist and implement it yourself.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
For a delightful, four minute explanation of the whole leap year
|
||||||
|
phenomenon, go watch [this youtube video][video].
|
||||||
|
|
||||||
|
[video]: http://www.youtube.com/watch?v=xX96xng7sAE
|
||||||
|
|
||||||
|
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://help.exercism.io/getting-started-with-go.html).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
JavaRanch Cattle Drive, exercise 3 [view source](http://www.javaranch.com/leap.jsp)
|
17
go/leap/cases_test.go
Normal file
17
go/leap/cases_test.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package leap
|
||||||
|
|
||||||
|
// Source: exercism/x-common
|
||||||
|
// Commit: 945d08e Merge pull request #50 from soniakeys/master
|
||||||
|
|
||||||
|
var testCases = []struct {
|
||||||
|
year int
|
||||||
|
expected bool
|
||||||
|
description string
|
||||||
|
}{
|
||||||
|
{1996, true, "leap year"},
|
||||||
|
{1997, false, "non-leap year"},
|
||||||
|
{1998, false, "non-leap even year"},
|
||||||
|
{1900, false, "century"},
|
||||||
|
{2400, true, "fourth century"},
|
||||||
|
{2000, true, "Y2K"},
|
||||||
|
}
|
15
go/leap/leap.go
Normal file
15
go/leap/leap.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package leap
|
||||||
|
|
||||||
|
// TestVersion is an exercism thing.
|
||||||
|
const TestVersion = 1
|
||||||
|
|
||||||
|
// IsLeapYear returns whether the given year is a leap year.
|
||||||
|
func IsLeapYear(year int) bool {
|
||||||
|
if year%4 != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if year%400 == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return year%100 != 0
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user