Merge branch 'master' of ssh://gogs.bullercodeworks.com:2200/brian/exercism
This commit is contained in:
commit
63b955575a
@ -1 +0,0 @@
|
||||
hello-world
|
@ -1 +0,0 @@
|
||||
packages.config
|
@ -1 +0,0 @@
|
||||
Debug
|
52
cpp/hello-world/CMakeLists.txt
Normal file
52
cpp/hello-world/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.59 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})
|
53
cpp/hello-world/README.md
Normal file
53
cpp/hello-world/README.md
Normal file
@ -0,0 +1,53 @@
|
||||
# Hello World
|
||||
|
||||
The classical introductory exercise. Just say "Hello, World!".
|
||||
|
||||
["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is
|
||||
the traditional first program for beginning programming in a new language
|
||||
or environment.
|
||||
|
||||
The objectives are simple:
|
||||
|
||||
- Write a function that returns the string "Hello, World!".
|
||||
- Run the test suite and make sure that it succeeds.
|
||||
- Submit your solution and check it at the website.
|
||||
|
||||
If everything goes well, you will be ready to fetch your first real exercise.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Make sure you have read [the C++ page](http://exercism.io/languages/cpp) on
|
||||
exercism.io. This covers the basic information on setting up the development
|
||||
environment expected by the exercises.
|
||||
|
||||
## Passing the Tests
|
||||
|
||||
Get the first test compiling, linking and passing by following the [three
|
||||
rules of test-driven development](http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd).
|
||||
Create just enough structure by declaring namespaces, functions, classes,
|
||||
etc., to satisfy any compiler errors and get the test to fail. Then write
|
||||
just enough code to get the test to pass. Once you've done that,
|
||||
uncomment the next test by moving the following line past the next test.
|
||||
|
||||
```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
|
||||
|
||||
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
12
cpp/hello-world/hello_world.h
Normal file
12
cpp/hello-world/hello_world.h
Normal file
@ -0,0 +1,12 @@
|
||||
#if !defined(HELLO_WORLD_H)
|
||||
#define HELLO_WORLD_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace hello_world {
|
||||
|
||||
std::string hello();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
8
cpp/hello-world/hello_world_test.cpp
Normal file
8
cpp/hello-world/hello_world_test.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "hello_world.h"
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_hello)
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL("Hello, World!", hello_world::hello());
|
||||
}
|
@ -1 +0,0 @@
|
||||
hello-world
|
16
crystal/hello-world/spec/hello_world_spec.cr
Normal file
16
crystal/hello-world/spec/hello_world_spec.cr
Normal file
@ -0,0 +1,16 @@
|
||||
require "spec"
|
||||
require "../src/*"
|
||||
|
||||
describe "HelloWorld" do
|
||||
it "no name" do
|
||||
HelloWorld.hello.should eq("Hello, World!")
|
||||
end
|
||||
|
||||
pending "sample name" do
|
||||
HelloWorld.hello("Alice").should eq("Hello, Alice!")
|
||||
end
|
||||
|
||||
pending "other sample name" do
|
||||
HelloWorld.hello("Bob").should eq("Hello, Bob!")
|
||||
end
|
||||
end
|
1
crystal/hello-world/src/hello_world.cr
Normal file
1
crystal/hello-world/src/hello_world.cr
Normal file
@ -0,0 +1 @@
|
||||
# Please implement your solution to hello-world in this file
|
@ -1 +0,0 @@
|
||||
gigasecond
|
28
csharp/sum-of-multiples/README.md
Normal file
28
csharp/sum-of-multiples/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Sum Of Multiples
|
||||
|
||||
Given a number, 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 20 that are
|
||||
multiples of either 3 or 5, we get 3, 5, 6 and 9, 10, 12, 15, and 18.
|
||||
|
||||
The sum of these multiples is 78.
|
||||
|
||||
Given a number, find the sum of the multiples of a given set of numbers,
|
||||
up to but not including that number.
|
||||
|
||||
## Hints
|
||||
This exercise requires you to process a collection of data. You can simplify your code by using LINQ (Language Integrated Query).
|
||||
For more information, see [this page](https://docs.microsoft.com/en-us/dotnet/articles/standard/using-linq).
|
||||
|
||||
### Submitting Exercises
|
||||
|
||||
Note that, when trying to submit an exercise, make sure the exercise file that 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
|
||||
|
||||
A variation on Problem 1 at Project Euler [http://projecteuler.net/problem=1](http://projecteuler.net/problem=1)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
10
csharp/sum-of-multiples/SumOfMultiples.cs
Normal file
10
csharp/sum-of-multiples/SumOfMultiples.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public static class SumOfMultiples
|
||||
{
|
||||
public static int To(IEnumerable<int> multiples, int max)
|
||||
{
|
||||
throw new NotImplementedException("You need to implement this function.");
|
||||
}
|
||||
}
|
18
csharp/sum-of-multiples/SumOfMultiples.csproj
Normal file
18
csharp/sum-of-multiples/SumOfMultiples.csproj
Normal file
@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp1.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Example.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
|
||||
<PackageReference Include="xunit" Version="2.2.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
46
csharp/sum-of-multiples/SumOfMultiplesTest.cs
Normal file
46
csharp/sum-of-multiples/SumOfMultiplesTest.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using Xunit;
|
||||
|
||||
public class SumOfMultiplesTest
|
||||
{
|
||||
[Fact]
|
||||
public void Sum_to_1()
|
||||
{
|
||||
Assert.Equal(0, SumOfMultiples.To(new[] { 3, 5 }, 1));
|
||||
}
|
||||
|
||||
[Fact(Skip = "Remove to run test")]
|
||||
public void Sum_to_3()
|
||||
{
|
||||
Assert.Equal(3, SumOfMultiples.To(new[] { 3, 5 }, 4));
|
||||
}
|
||||
|
||||
[Fact(Skip = "Remove to run test")]
|
||||
public void Sum_to_10()
|
||||
{
|
||||
Assert.Equal(23, SumOfMultiples.To(new[] { 3, 5 }, 10));
|
||||
}
|
||||
|
||||
[Fact(Skip = "Remove to run test")]
|
||||
public void Sum_to_100()
|
||||
{
|
||||
Assert.Equal(2318, SumOfMultiples.To(new[] { 3, 5 }, 100));
|
||||
}
|
||||
|
||||
[Fact(Skip = "Remove to run test")]
|
||||
public void Sum_to_1000()
|
||||
{
|
||||
Assert.Equal(233168, SumOfMultiples.To(new[] { 3, 5 }, 1000));
|
||||
}
|
||||
|
||||
[Fact(Skip = "Remove to run test")]
|
||||
public void Sum_to_20()
|
||||
{
|
||||
Assert.Equal(51, SumOfMultiples.To(new [] { 7, 13, 17 }, 20));
|
||||
}
|
||||
|
||||
[Fact(Skip = "Remove to run test")]
|
||||
public void Sum_to_10000()
|
||||
{
|
||||
Assert.Equal(2203160, SumOfMultiples.To(new [] { 43, 47 }, 10000));
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
hello-world
|
@ -1 +0,0 @@
|
||||
hello-world
|
@ -1 +0,0 @@
|
||||
hello-world
|
@ -1 +0,0 @@
|
||||
bob
|
@ -1 +0,0 @@
|
||||
hello-world
|
14
elm/hello-world/package.json
Normal file
14
elm/hello-world/package.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"description": "Exercism/Elm",
|
||||
"repository": "https://github.com/exercism/elm.git",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"postinstall": "elm-package install -y",
|
||||
"watch": "elm-test --watch",
|
||||
"test": "elm-test"
|
||||
},
|
||||
"dependencies": {
|
||||
"elm": "0.18.0",
|
||||
"elm-test": "0.18.3"
|
||||
}
|
||||
}
|
26
elm/hello-world/tests/Tests.elm
Normal file
26
elm/hello-world/tests/Tests.elm
Normal file
@ -0,0 +1,26 @@
|
||||
module Tests exposing (..)
|
||||
|
||||
import Test exposing (..)
|
||||
import Expect
|
||||
import HelloWorld exposing (helloWorld)
|
||||
|
||||
|
||||
tests : Test
|
||||
tests =
|
||||
describe "Hello, World!"
|
||||
[ test "Hello with no name" <|
|
||||
\() ->
|
||||
Expect.equal "Hello, World!" (helloWorld Nothing)
|
||||
|
||||
-- Once you get the first test passing, remove the
|
||||
-- `skip <|` (just leave the comma) on the next two
|
||||
-- lines to continue!
|
||||
, skip <|
|
||||
test "Hello to a sample name" <|
|
||||
\() ->
|
||||
Expect.equal "Hello, Alice!" (helloWorld (Just "Alice"))
|
||||
, skip <|
|
||||
test "Hello to another sample name" <|
|
||||
\() ->
|
||||
Expect.equal "Hello, Bob!" (helloWorld (Just "Bob"))
|
||||
]
|
16
elm/hello-world/tests/elm-package.json
Normal file
16
elm/hello-world/tests/elm-package.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"version": "3.0.0",
|
||||
"summary": "Exercism problems in Elm.",
|
||||
"repository": "https://github.com/exercism/elm.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
".",
|
||||
".."
|
||||
],
|
||||
"exposed-modules": [],
|
||||
"dependencies": {
|
||||
"elm-lang/core": "5.0.0 <= v < 6.0.0",
|
||||
"elm-community/elm-test": "4.0.0 <= v < 5.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
@ -1 +0,0 @@
|
||||
hello-world
|
11
erlang/hello-world/include/exercism.hrl
Normal file
11
erlang/hello-world/include/exercism.hrl
Normal file
@ -0,0 +1,11 @@
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
sut(Module) ->
|
||||
{ok, Files} = file:list_dir("./src"),
|
||||
case lists:member("example.erl", Files) of
|
||||
true -> example;
|
||||
false -> Module
|
||||
end.
|
||||
|
||||
version_test() ->
|
||||
?assertMatch(?TEST_VERSION, ?TESTED_MODULE:test_version()).
|
30
erlang/hello-world/rebar.config
Normal file
30
erlang/hello-world/rebar.config
Normal file
@ -0,0 +1,30 @@
|
||||
%% Erlang compiler options
|
||||
{erl_opts, [debug_info]}.
|
||||
|
||||
{deps, []}.
|
||||
|
||||
{dialyzer, [
|
||||
{warnings, [underspecs, no_return]},
|
||||
{get_warnings, true},
|
||||
{plt_apps, top_level_deps}, % top_level_deps | all_deps
|
||||
{plt_extra_apps, []},
|
||||
{plt_location, local}, % local | "/my/file/name"
|
||||
{plt_prefix, "rebar3"},
|
||||
{base_plt_apps, [stdlib, kernel, crypto]},
|
||||
{base_plt_location, global}, % global | "/my/file/name"
|
||||
{base_plt_prefix, "rebar3"}
|
||||
]}.
|
||||
|
||||
%% eunit:test(Tests)
|
||||
{eunit_tests, []}.
|
||||
%% Options for eunit:test(Tests, Opts)
|
||||
{eunit_opts, [verbose]}.
|
||||
|
||||
%% == xref ==
|
||||
|
||||
{xref_warnings, true}.
|
||||
|
||||
%% xref checks to run
|
||||
{xref_checks, [undefined_function_calls, undefined_functions,
|
||||
locals_not_used, exports_not_used,
|
||||
deprecated_function_calls, deprecated_functions]}.
|
9
erlang/hello-world/src/hello_world.app.src
Normal file
9
erlang/hello-world/src/hello_world.app.src
Normal file
@ -0,0 +1,9 @@
|
||||
{application, hello_world,
|
||||
[{description, "exercism.io - hello-world"},
|
||||
{vsn, "0.0.1"},
|
||||
{modules, []},
|
||||
{registered, []},
|
||||
{applications, [kernel,
|
||||
stdlib]},
|
||||
{env, []}
|
||||
]}.
|
8
erlang/hello-world/src/hello_world.erl
Normal file
8
erlang/hello-world/src/hello_world.erl
Normal file
@ -0,0 +1,8 @@
|
||||
-module(hello_world).
|
||||
|
||||
-export([hello/0, test_version/0]).
|
||||
|
||||
hello() ->
|
||||
undefined.
|
||||
|
||||
test_version() -> 2.
|
9
erlang/hello-world/test/hello_world_tests.erl
Normal file
9
erlang/hello-world/test/hello_world_tests.erl
Normal file
@ -0,0 +1,9 @@
|
||||
-module(hello_world_tests).
|
||||
|
||||
-define(TESTED_MODULE, (sut(hello_world))).
|
||||
-define(TEST_VERSION, 2).
|
||||
-include("exercism.hrl").
|
||||
|
||||
|
||||
say_hi_test() ->
|
||||
?assertEqual("Hello, World!", ?TESTED_MODULE:hello()).
|
@ -1 +0,0 @@
|
||||
example
|
@ -1,6 +1,6 @@
|
||||
# Pov
|
||||
|
||||
Reparent a graph on a selected node
|
||||
Reparent a graph on a selected node.
|
||||
|
||||
# Tree Reparenting
|
||||
|
||||
@ -14,7 +14,6 @@ ancestor's perspective:
|
||||
+-1-+ +-2-+ +-3-+
|
||||
| | | | | |
|
||||
4 5 6 7 8 9
|
||||
|
||||
```
|
||||
|
||||
But the same information can be presented from the perspective of any other node
|
||||
@ -40,20 +39,26 @@ a different leaf node) can be seen to follow the path 6-2-0-3-9
|
||||
This exercise involves taking an input graph and re-orientating it from the point
|
||||
of view of one of the nodes.
|
||||
|
||||
To run the tests simply run the command `go test` in the exercise directory.
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `-bench`
|
||||
flag:
|
||||
|
||||
go test -bench .
|
||||
|
||||
For more detailed info about the Go track see the [help
|
||||
page](http://exercism.io/languages/go).
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Further information
|
||||
|
||||
For more detailed information about the Go track, including how to get help if
|
||||
you're having trouble, please visit the exercism.io [Go language page](http://exercism.io/languages/go/about).
|
||||
|
||||
## Source
|
||||
|
||||
Adaptation of exercise from 4clojure [https://www.4clojure.com/](https://www.4clojure.com/)
|
||||
|
||||
## Submitting Incomplete Problems
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
||||
|
||||
|
@ -259,10 +259,13 @@ func (tc testCase) testResult(got, want []string, msg string, t *testing.T) {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
func TestConstruction(t *testing.T) {
|
||||
func TestTestVersion(t *testing.T) {
|
||||
if testVersion != targetTestVersion {
|
||||
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConstruction(t *testing.T) {
|
||||
for _, tc := range testCases {
|
||||
got := tc.graph().ArcList()
|
||||
want := tc.arcStrings
|
||||
|
83
go/transpose/README.md
Normal file
83
go/transpose/README.md
Normal file
@ -0,0 +1,83 @@
|
||||
# Transpose
|
||||
|
||||
Given an input text output it transposed.
|
||||
|
||||
Roughly explained, the transpose of a matrix:
|
||||
|
||||
```
|
||||
ABC
|
||||
DEF
|
||||
```
|
||||
|
||||
is given by:
|
||||
|
||||
```
|
||||
AD
|
||||
BE
|
||||
CF
|
||||
```
|
||||
|
||||
Rows become columns and columns become rows. See <https://en.wikipedia.org/wiki/Transpose>.
|
||||
|
||||
If the input has rows of different lengths, this is to be solved as follows:
|
||||
|
||||
- Pad to the left with spaces.
|
||||
- Don't pad to the right.
|
||||
|
||||
Therefore, transposing this matrix:
|
||||
|
||||
```
|
||||
ABC
|
||||
DE
|
||||
```
|
||||
|
||||
results in:
|
||||
|
||||
```
|
||||
AD
|
||||
BE
|
||||
C
|
||||
```
|
||||
|
||||
And transposing:
|
||||
|
||||
```
|
||||
AB
|
||||
DEF
|
||||
```
|
||||
|
||||
results in:
|
||||
|
||||
```
|
||||
AD
|
||||
BE
|
||||
F
|
||||
```
|
||||
|
||||
In general, all characters from the input should also be present in the transposed output.
|
||||
That means that if a column in the input text contains only spaces on its bottom-most row(s),
|
||||
the corresponding output row should contain the spaces in its right-most column(s).
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `-bench`
|
||||
flag:
|
||||
|
||||
go test -bench .
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Further information
|
||||
|
||||
For more detailed information about the Go track, including how to get help if
|
||||
you're having trouble, please visit the exercism.io [Go language page](http://exercism.io/languages/go/about).
|
||||
|
||||
## Source
|
||||
|
||||
Reddit r/dailyprogrammer challenge #270 [Easy]. [https://www.reddit.com/r/dailyprogrammer/comments/4msu2x/challenge_270_easy_transpose_the_input_text](https://www.reddit.com/r/dailyprogrammer/comments/4msu2x/challenge_270_easy_transpose_the_input_text)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
248
go/transpose/cases_test.go
Normal file
248
go/transpose/cases_test.go
Normal file
@ -0,0 +1,248 @@
|
||||
package transpose
|
||||
|
||||
// Source: exercism/x-common
|
||||
// Commit: 6dba022 transpose: Fix canonical-data.json formatting
|
||||
// x-common version: 1.0.0
|
||||
|
||||
var testCases = []struct {
|
||||
description string
|
||||
input []string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
"empty string",
|
||||
[]string{},
|
||||
[]string{},
|
||||
},
|
||||
{
|
||||
"two characters in a row",
|
||||
[]string{
|
||||
"A1",
|
||||
},
|
||||
[]string{
|
||||
"A",
|
||||
"1",
|
||||
},
|
||||
},
|
||||
{
|
||||
"two characters in a column",
|
||||
[]string{
|
||||
"A",
|
||||
"1",
|
||||
},
|
||||
[]string{
|
||||
"A1",
|
||||
},
|
||||
},
|
||||
{
|
||||
"simple",
|
||||
[]string{
|
||||
"ABC",
|
||||
"123",
|
||||
},
|
||||
[]string{
|
||||
"A1",
|
||||
"B2",
|
||||
"C3",
|
||||
},
|
||||
},
|
||||
{
|
||||
"single line",
|
||||
[]string{
|
||||
"Single line.",
|
||||
},
|
||||
[]string{
|
||||
"S",
|
||||
"i",
|
||||
"n",
|
||||
"g",
|
||||
"l",
|
||||
"e",
|
||||
" ",
|
||||
"l",
|
||||
"i",
|
||||
"n",
|
||||
"e",
|
||||
".",
|
||||
},
|
||||
},
|
||||
{
|
||||
"first line longer than second line",
|
||||
[]string{
|
||||
"The fourth line.",
|
||||
"The fifth line.",
|
||||
},
|
||||
[]string{
|
||||
"TT",
|
||||
"hh",
|
||||
"ee",
|
||||
" ",
|
||||
"ff",
|
||||
"oi",
|
||||
"uf",
|
||||
"rt",
|
||||
"th",
|
||||
"h ",
|
||||
" l",
|
||||
"li",
|
||||
"in",
|
||||
"ne",
|
||||
"e.",
|
||||
".",
|
||||
},
|
||||
},
|
||||
{
|
||||
"second line longer than first line",
|
||||
[]string{
|
||||
"The first line.",
|
||||
"The second line.",
|
||||
},
|
||||
[]string{
|
||||
"TT",
|
||||
"hh",
|
||||
"ee",
|
||||
" ",
|
||||
"fs",
|
||||
"ie",
|
||||
"rc",
|
||||
"so",
|
||||
"tn",
|
||||
" d",
|
||||
"l ",
|
||||
"il",
|
||||
"ni",
|
||||
"en",
|
||||
".e",
|
||||
" .",
|
||||
},
|
||||
},
|
||||
{
|
||||
"square",
|
||||
[]string{
|
||||
"HEART",
|
||||
"EMBER",
|
||||
"ABUSE",
|
||||
"RESIN",
|
||||
"TREND",
|
||||
},
|
||||
[]string{
|
||||
"HEART",
|
||||
"EMBER",
|
||||
"ABUSE",
|
||||
"RESIN",
|
||||
"TREND",
|
||||
},
|
||||
},
|
||||
{
|
||||
"rectangle",
|
||||
[]string{
|
||||
"FRACTURE",
|
||||
"OUTLINED",
|
||||
"BLOOMING",
|
||||
"SEPTETTE",
|
||||
},
|
||||
[]string{
|
||||
"FOBS",
|
||||
"RULE",
|
||||
"ATOP",
|
||||
"CLOT",
|
||||
"TIME",
|
||||
"UNIT",
|
||||
"RENT",
|
||||
"EDGE",
|
||||
},
|
||||
},
|
||||
{
|
||||
"triangle",
|
||||
[]string{
|
||||
"T",
|
||||
"EE",
|
||||
"AAA",
|
||||
"SSSS",
|
||||
"EEEEE",
|
||||
"RRRRRR",
|
||||
},
|
||||
[]string{
|
||||
"TEASER",
|
||||
" EASER",
|
||||
" ASER",
|
||||
" SER",
|
||||
" ER",
|
||||
" R",
|
||||
},
|
||||
},
|
||||
{
|
||||
"many lines",
|
||||
[]string{
|
||||
"Chor. Two households, both alike in dignity,",
|
||||
"In fair Verona, where we lay our scene,",
|
||||
"From ancient grudge break to new mutiny,",
|
||||
"Where civil blood makes civil hands unclean.",
|
||||
"From forth the fatal loins of these two foes",
|
||||
"A pair of star-cross'd lovers take their life;",
|
||||
"Whose misadventur'd piteous overthrows",
|
||||
"Doth with their death bury their parents' strife.",
|
||||
"The fearful passage of their death-mark'd love,",
|
||||
"And the continuance of their parents' rage,",
|
||||
"Which, but their children's end, naught could remove,",
|
||||
"Is now the two hours' traffic of our stage;",
|
||||
"The which if you with patient ears attend,",
|
||||
"What here shall miss, our toil shall strive to mend.",
|
||||
},
|
||||
[]string{
|
||||
"CIFWFAWDTAWITW",
|
||||
"hnrhr hohnhshh",
|
||||
"o oeopotedi ea",
|
||||
"rfmrmash cn t",
|
||||
".a e ie fthow ",
|
||||
" ia fr weh,whh",
|
||||
"Trnco miae ie",
|
||||
"w ciroitr btcr",
|
||||
"oVivtfshfcuhhe",
|
||||
" eeih a uote ",
|
||||
"hrnl sdtln is",
|
||||
"oot ttvh tttfh",
|
||||
"un bhaeepihw a",
|
||||
"saglernianeoyl",
|
||||
"e,ro -trsui ol",
|
||||
"h uofcu sarhu ",
|
||||
"owddarrdan o m",
|
||||
"lhg to'egccuwi",
|
||||
"deemasdaeehris",
|
||||
"sr als t ists",
|
||||
",ebk 'phool'h,",
|
||||
" reldi ffd ",
|
||||
"bweso tb rtpo",
|
||||
"oea ileutterau",
|
||||
"t kcnoorhhnatr",
|
||||
"hl isvuyee'fi ",
|
||||
" atv es iisfet",
|
||||
"ayoior trr ino",
|
||||
"l lfsoh ecti",
|
||||
"ion vedpn l",
|
||||
"kuehtteieadoe ",
|
||||
"erwaharrar,fas",
|
||||
" nekt te rh",
|
||||
"ismdsehphnnosa",
|
||||
"ncuse ra-tau l",
|
||||
" et tormsural",
|
||||
"dniuthwea'g t ",
|
||||
"iennwesnr hsts",
|
||||
"g,ycoi tkrttet",
|
||||
"n ,l r s'a anr",
|
||||
"i ef 'dgcgdi",
|
||||
"t aol eoe,v",
|
||||
"y nei sl,u; e",
|
||||
", .sf to l ",
|
||||
" e rv d t",
|
||||
" ; ie o",
|
||||
" f, r ",
|
||||
" e e m",
|
||||
" . m e",
|
||||
" o n",
|
||||
" v d",
|
||||
" e .",
|
||||
" ,",
|
||||
},
|
||||
},
|
||||
}
|
32
go/transpose/transpose.go
Normal file
32
go/transpose/transpose.go
Normal file
@ -0,0 +1,32 @@
|
||||
package transpose
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const testVersion = 1
|
||||
|
||||
func Transpose(inp []string) []string {
|
||||
// find the longest length string in the slice
|
||||
lng := 0
|
||||
for i := range inp {
|
||||
if len(inp[i]) > lng {
|
||||
lng = len(inp[i])
|
||||
}
|
||||
}
|
||||
ret := make([]string, lng, lng)
|
||||
for i := range inp {
|
||||
for j := 0; j < lng; j++ {
|
||||
if len(inp[i]) > j {
|
||||
ret[j] = ret[j] + string(inp[i][j])
|
||||
} else {
|
||||
ret[j] = ret[j] + " "
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(ret) > 0 {
|
||||
// Trim the spaces off of the end of the last line
|
||||
ret[len(ret)-1] = strings.TrimRight(ret[len(ret)-1], " ")
|
||||
}
|
||||
return ret
|
||||
}
|
52
go/transpose/transpose_test.go
Normal file
52
go/transpose/transpose_test.go
Normal file
@ -0,0 +1,52 @@
|
||||
package transpose
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const targetTestVersion = 1
|
||||
|
||||
func TestTestVersion(t *testing.T) {
|
||||
if testVersion != targetTestVersion {
|
||||
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTranspose(t *testing.T) {
|
||||
for _, test := range testCases {
|
||||
actual := Transpose(test.input)
|
||||
if !reflect.DeepEqual(actual, test.expected) {
|
||||
// check for zero length slices
|
||||
if len(actual) == 0 || len(test.expected) == 0 {
|
||||
t.Fatalf("\n\tTranspose(%q): %s\n\n\tExpected: %q\n\tGot: %q",
|
||||
test.input, test.description, test.expected, actual)
|
||||
}
|
||||
// let's make the error more specific and find the row it's on
|
||||
min := min(len(test.expected), len(actual))
|
||||
for i := 0; i < min; i++ {
|
||||
if test.expected[i] != actual[i] {
|
||||
t.Fatalf("\n\tTranspose(%q): %s\n\n\tExpected: %q\n\tGot: %q\n\n\tRow %d Expected: %q Got: %q",
|
||||
test.input, test.description, test.expected, actual, i, test.expected[i], actual[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// helper function
|
||||
// https://stackoverflow.com/questions/27516387/what-is-the-correct-way-to-find-the-min-between-two-integers-in-go
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func BenchmarkTranspose(b *testing.B) {
|
||||
for _, test := range testCases {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Transpose(test.input)
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
leap
|
83
haskell/hello-world/README.md
Normal file
83
haskell/hello-world/README.md
Normal file
@ -0,0 +1,83 @@
|
||||
# Hello World
|
||||
|
||||
The classical introductory exercise. Just say "Hello, World!".
|
||||
|
||||
["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is
|
||||
the traditional first program for beginning programming in a new language
|
||||
or environment.
|
||||
|
||||
The objectives are simple:
|
||||
|
||||
- Write a function that returns the string "Hello, World!".
|
||||
- Run the test suite and make sure that it succeeds.
|
||||
- Submit your solution and check it at the website.
|
||||
|
||||
If everything goes well, you will be ready to fetch your first real exercise.
|
||||
|
||||
## Hints
|
||||
|
||||
To complete this exercise, you need to implement the `hello` function.
|
||||
|
||||
You will find the type signature for `hello` already in place,
|
||||
but it is up to you to define the function.
|
||||
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
For installation and learning resources, refer to the
|
||||
[exercism help page](http://exercism.io/languages/haskell).
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the test suite, execute the following command:
|
||||
|
||||
```bash
|
||||
stack test
|
||||
```
|
||||
|
||||
#### If you get an error message like this...
|
||||
|
||||
```
|
||||
No .cabal file found in directory
|
||||
```
|
||||
|
||||
You are probably running an old stack version and need
|
||||
to upgrade it.
|
||||
|
||||
#### Otherwise, if you get an error message like this...
|
||||
|
||||
```
|
||||
No compiler found, expected minor version match with...
|
||||
Try running "stack setup" to install the correct GHC...
|
||||
```
|
||||
|
||||
Just do as it says and it will download and install
|
||||
the correct compiler version:
|
||||
|
||||
```bash
|
||||
stack setup
|
||||
```
|
||||
|
||||
## Running *GHCi*
|
||||
|
||||
If you want to play with your solution in GHCi, just run the command:
|
||||
|
||||
```bash
|
||||
stack ghci
|
||||
```
|
||||
|
||||
## Feedback, Issues, Pull Requests
|
||||
|
||||
The [exercism/haskell](https://github.com/exercism/haskell) repository on
|
||||
GitHub is the home for all of the Haskell exercises.
|
||||
|
||||
If you have feedback about an exercise, or want to help implementing a new
|
||||
one, head over there and create an issue. We'll do our best to help you!
|
||||
|
||||
## Source
|
||||
|
||||
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
20
haskell/hello-world/package.yaml
Normal file
20
haskell/hello-world/package.yaml
Normal file
@ -0,0 +1,20 @@
|
||||
name: hello-world
|
||||
version: 1.0.0.3
|
||||
|
||||
dependencies:
|
||||
- base
|
||||
|
||||
library:
|
||||
exposed-modules: HelloWorld
|
||||
source-dirs: src
|
||||
dependencies:
|
||||
# - foo # List here the packages you
|
||||
# - bar # want to use in your solution.
|
||||
|
||||
tests:
|
||||
test:
|
||||
main: Tests.hs
|
||||
source-dirs: test
|
||||
dependencies:
|
||||
- hello-world
|
||||
- hspec
|
4
haskell/hello-world/src/HelloWorld.hs
Normal file
4
haskell/hello-world/src/HelloWorld.hs
Normal file
@ -0,0 +1,4 @@
|
||||
module HelloWorld (hello) where
|
||||
|
||||
hello :: String
|
||||
hello = error "You need to implement this function."
|
1
haskell/hello-world/stack.yaml
Normal file
1
haskell/hello-world/stack.yaml
Normal file
@ -0,0 +1 @@
|
||||
resolver: lts-8.21
|
11
haskell/hello-world/test/Tests.hs
Normal file
11
haskell/hello-world/test/Tests.hs
Normal file
@ -0,0 +1,11 @@
|
||||
import Test.Hspec (Spec, it, shouldBe)
|
||||
import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)
|
||||
|
||||
import HelloWorld (hello)
|
||||
|
||||
main :: IO ()
|
||||
main = hspecWith defaultConfig {configFastFail = True} specs
|
||||
|
||||
specs :: Spec
|
||||
specs = it "hello" $
|
||||
hello `shouldBe` "Hello, World!"
|
@ -1 +0,0 @@
|
||||
robot-name
|
99
java/two-fer/README.md
Normal file
99
java/two-fer/README.md
Normal file
@ -0,0 +1,99 @@
|
||||
# Two Fer
|
||||
|
||||
`Two-fer` or `2-fer` is short for two for one. One for you and one for me.
|
||||
|
||||
```
|
||||
"One for X, one for me."
|
||||
```
|
||||
|
||||
When X is a name or "you".
|
||||
|
||||
If the given name is "Alice", the result should be "One for Alice, one for me."
|
||||
If no name is given, the result should be "One for you, one for me."
|
||||
|
||||
|
||||
## Test-Driven Development
|
||||
|
||||
As programmers mature, they eventually want to test their code.
|
||||
|
||||
Here at Exercism we simulate [Test-Driven
|
||||
Development](http://en.wikipedia.org/wiki/Test-driven_development) (TDD), where
|
||||
you write your tests before writing any functionality. The simulation comes in
|
||||
the form of a pre-written test suite, which will signal that you have solved
|
||||
the problem.
|
||||
|
||||
It will also provide you with a safety net to explore other solutions without
|
||||
breaking the functionality.
|
||||
|
||||
### A typical TDD workflow on Exercism:
|
||||
|
||||
1. Run the test file and pick one test that's failing.
|
||||
2. Write some code to fix the test you picked.
|
||||
3. Re-run the tests to confirm the test is now passing.
|
||||
4. Repeat from step 1.
|
||||
5. Submit your solution (`exercism submit /path/to/file`)
|
||||
|
||||
## Instructions
|
||||
|
||||
Submissions are encouraged to be general, within reason. Having said that, it's
|
||||
also important not to over-engineer a solution.
|
||||
|
||||
It's important to remember that the goal is to make code as expressive and
|
||||
readable as we can.
|
||||
|
||||
Most Java exercises include multiple test cases. These cases are structured to
|
||||
support a useful process known as
|
||||
[test-driven development (TDD)](https://en.wikipedia.org/wiki/Test-driven_development).
|
||||
TDD involves repeating a structured cycle that helps programmers build complex
|
||||
functionality piece by piece rather than all at once. That cycle can be
|
||||
described as follows:
|
||||
|
||||
1. Add a test that describes one piece of desired functionality your code is
|
||||
currently missing.
|
||||
2. Run the tests to verify that this newly-added test fails.
|
||||
3. Update your existing code until:
|
||||
- All the old tests continue to pass;
|
||||
- The new test also passes.
|
||||
4. [Clean up](https://en.wikipedia.org/wiki/Code_refactoring) your code, making
|
||||
sure that all tests continue to pass. This typically involves renaming
|
||||
variables, removing duplicated chunks of logic, removing leftover logging, etc.
|
||||
5. Return to step 1 until all desired functionality has been built!
|
||||
|
||||
The test files in this track contain _all_ the tests your solution should pass
|
||||
to be considered valid. That doesn't immediately seem to be compatible with the
|
||||
cycle described above, in which tests are written one by one. However, the
|
||||
tool that we use to write our tests, [JUnit](http://junit.org), provides an
|
||||
[@Ignore](http://junit.sourceforge.net/javadoc/org/junit/Ignore.html)
|
||||
[annotation](https://docs.oracle.com/javase/tutorial/java/annotations/) that
|
||||
can be used to temporarily skip an already-written test. Using this annotation,
|
||||
we make sure that the test files we deliver to you satisfy the following rules:
|
||||
|
||||
- The first test in any test file is _not_ skipped by default.
|
||||
- All but the first test in any test file _are_ skipped by default.
|
||||
|
||||
This allows you to simulate the TDD cycle by following these slightly-modified
|
||||
steps:
|
||||
|
||||
1. Run the tests to verify that _at most one_ test currently fails.
|
||||
2. Update your existing code until all the non-skipped tests pass.
|
||||
3. Clean up your code, making sure that all non-skipped tests continue to pass.
|
||||
4. Remove the topmost `@Ignore` annotation in the test file.
|
||||
5. Return to step 1 until no tests are skipped and all tests pass!
|
||||
|
||||
|
||||
|
||||
To run the tests:
|
||||
|
||||
```sh
|
||||
$ gradle test
|
||||
```
|
||||
|
||||
For more detailed info about the Java track see the [help page](http://exercism.io/languages/java).
|
||||
|
||||
|
||||
## Source
|
||||
|
||||
This is an exercise to introduce users to basic programming constructs, just after hello World. [https://en.wikipedia.org/wiki/Two-fer](https://en.wikipedia.org/wiki/Two-fer)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
17
java/two-fer/build.gradle
Normal file
17
java/two-fer/build.gradle
Normal file
@ -0,0 +1,17 @@
|
||||
apply plugin: "java"
|
||||
apply plugin: "eclipse"
|
||||
apply plugin: "idea"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile "junit:junit:4.12"
|
||||
}
|
||||
test {
|
||||
testLogging {
|
||||
exceptionFormat = 'full'
|
||||
events = ["passed", "failed", "skipped"]
|
||||
}
|
||||
}
|
5
java/two-fer/src/main/java/Twofer.java
Normal file
5
java/two-fer/src/main/java/Twofer.java
Normal file
@ -0,0 +1,5 @@
|
||||
public class Twofer {
|
||||
public String twofer(String name) {
|
||||
throw new UnsupportedOperationException("Delete this statement and write your own implementation.");
|
||||
}
|
||||
}
|
41
java/two-fer/src/test/java/TwoferTest.java
Normal file
41
java/two-fer/src/test/java/TwoferTest.java
Normal file
@ -0,0 +1,41 @@
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class TwoferTest {
|
||||
|
||||
private Twofer twofer;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
twofer = new Twofer();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noNameGiven() {
|
||||
String input = null;
|
||||
String expected = "One for you, one for me.";
|
||||
|
||||
assertEquals(expected, twofer.twofer(input));
|
||||
}
|
||||
|
||||
@Ignore("Remove to run test")
|
||||
@Test
|
||||
public void aNameGiven() {
|
||||
String input = "Alice";
|
||||
String expected = "One for Alice, one for me.";
|
||||
|
||||
assertEquals(expected, twofer.twofer(input));
|
||||
}
|
||||
|
||||
@Ignore("Remove to run test")
|
||||
@Test
|
||||
public void anotherNameGiven() {
|
||||
String input = "Bob";
|
||||
String expected = "One for Bob, one for me.";
|
||||
|
||||
assertEquals(expected, twofer.twofer(input));
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
example
|
@ -1 +0,0 @@
|
||||
hello-world
|
50
kotlin/hello-world/GETTING_STARTED.md
Normal file
50
kotlin/hello-world/GETTING_STARTED.md
Normal file
@ -0,0 +1,50 @@
|
||||
----
|
||||
# Quick Start Guide
|
||||
|
||||
This guide picks-up where [Running the Tests (in Kotlin)](http://exercism.io/languages/kotlin/tests)
|
||||
left off. If you haven't reviewed those instructions, do so now.
|
||||
|
||||
Need more information? A **step-by-step tutorial** is available in this directory at TUTORIAL.md or you can read
|
||||
the [HTML version](https://github.com/exercism/kotlin/blob/master/exercises/hello-world/TUTORIAL.md).
|
||||
|
||||
The following instructions work equally well on Windows, Mac OS X and Linux.
|
||||
|
||||
## Solve "Hello World"
|
||||
|
||||
Try writing a solution that passes one test at a time, running Gradle each time:
|
||||
|
||||
|
||||
```
|
||||
$ gradle test
|
||||
```
|
||||
|
||||
## Iterate through the tests
|
||||
|
||||
After your first test passes, remove the `@Ignore` from the next test, and iterate on your solution,
|
||||
testing after each change.
|
||||
|
||||
## All the tests pass? Submit your solution!
|
||||
|
||||
With a working solution that we've reviewed, we're ready to submit it to
|
||||
exercism.io.
|
||||
|
||||
```
|
||||
$ exercism submit src/main/kotlin/HelloWorld.kt
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
From here, there are a number of paths you can take.
|
||||
|
||||
1. Move on to the next exercise
|
||||
2. Review (and comment on) others' submissions to this exercise
|
||||
3. Submit another iteration
|
||||
4. Contribute to Exercism
|
||||
|
||||
|
||||
We sincerely hope you learn and enjoy being part of this community. If at any time you need assistance
|
||||
do not hesitate to ask for help:
|
||||
|
||||
http://exercism.io/languages/kotlin/help
|
||||
|
||||
Cheers!
|
692
kotlin/hello-world/TUTORIAL.md
Normal file
692
kotlin/hello-world/TUTORIAL.md
Normal file
@ -0,0 +1,692 @@
|
||||
NOTE: You can also view the HTML version of this file here:
|
||||
https://github.com/exercism/kotlin/blob/master/exercises/hello-world/TUTORIAL.md
|
||||
|
||||
* [Solving "Hello, World!"](#solving-hello-world)
|
||||
* [Reading Gradle output](#reading-gradle-output)
|
||||
* [Fixing the first failing test](#fixing-the-first-failing-test)
|
||||
* [Enabling and fixing the second test](#enabling-and-fixing-the-second-test)
|
||||
* [Enabling and fixing the third test](#enabling-and-fixing-the-third-test)
|
||||
* [Enabling the last test](#enabling-the-last-test)
|
||||
* [Refactoring](#refactoring)
|
||||
* [Submitting your first iteration](#submitting-your-first-iteration)
|
||||
* [Next Steps](#next-steps)
|
||||
* [Review (and comment on) others' submissions to this exercise](#review-and-comment-on-others-submissions-to-this-exercise)
|
||||
* [Extend an exercise](#extend-an-exercise)
|
||||
* [Contribute to Exercism](#contribute-to-exercism)
|
||||
|
||||
----
|
||||
|
||||
# Solving "Hello, World!"
|
||||
|
||||
Welcome to the first exercise on the Kotlin track!
|
||||
|
||||
This is a step-by-step guide to solving this exercise.
|
||||
|
||||
Each exercise comes with a set of tests. The first pass through the
|
||||
exercise is about getting all of the tests to pass, one at a time.
|
||||
|
||||
If you have not installed the Java Development Kit and Gradle, you must do
|
||||
so now. For help with this, see: http://exercism.io/languages/kotlin/installing
|
||||
|
||||
----
|
||||
|
||||
This guide picks-up where [Running the Tests (in Kotlin)](http://exercism.io/languages/kotlin/tests)
|
||||
left off. If you haven't reviewed those instructions, do so now.
|
||||
|
||||
The following instructions work equally well on Windows, Mac OS X and Linux.
|
||||
|
||||
## Reading Gradle output
|
||||
|
||||
Use Gradle to run the tests:
|
||||
|
||||
```
|
||||
$ gradle test
|
||||
```
|
||||
|
||||
This command does a lot and displays a bunch of stuff. Let's break it down...
|
||||
|
||||
```
|
||||
:compileKotlin
|
||||
w: /Users/jtigger/exercism/exercises/kotlin/hello-world/src/main/kotlin/HelloWorld.kt: (1, 11): Parameter 'name' is never used
|
||||
:compileJava UP-TO-DATE
|
||||
:copyMainKotlinClasses
|
||||
:processResources UP-TO-DATE
|
||||
:classes UP-TO-DATE
|
||||
```
|
||||
|
||||
Each line that begins with a colon (like `:compileKotlin`) is Gradle telling
|
||||
us that it's starting that task. The first five tasks are about compiling
|
||||
the source code of our *solution*. We've done you a favor and included just
|
||||
enough code for the solution that it compiles.
|
||||
|
||||
When a task is successful, it generally does not output anything. This is
|
||||
why `:copyMainKotlinClasses` does not produce any additional output.
|
||||
|
||||
A task may succeed but warn of a potential problem. This is what we see from
|
||||
`:compileKotlin`. The Kotlin compiler tells us that on line 1, 11 characters in
|
||||
of the `HelloWorld.kt` file, there is a parameter called `name` that was
|
||||
declared but never used. Usually, warnings _are_ helpful and should be heeded.
|
||||
We'll address this warning soon enough, but we're okay for now.
|
||||
|
||||
The next five tasks are about compiling source code of the *tests*.
|
||||
|
||||
```
|
||||
:compileTestKotlin
|
||||
:compileTestJava UP-TO-DATE
|
||||
:copyTestKotlinClasses
|
||||
:processTestResources UP-TO-DATE
|
||||
:testClasses UP-TO-DATE
|
||||
```
|
||||
|
||||
... with both sets of source code successfully compiled, Gradle turns to
|
||||
running the task you asked it to: executing the tests against the solution.
|
||||
|
||||
```
|
||||
:test
|
||||
|
||||
HelloWorldTest > helloSampleName SKIPPED
|
||||
|
||||
HelloWorldTest > helloBlankName SKIPPED
|
||||
|
||||
HelloWorldTest > helloNoName FAILED
|
||||
org.junit.ComparisonFailure: expected:<[Hello, World!]> but was:<[]>
|
||||
at org.junit.Assert.assertEquals(Assert.java:115)
|
||||
at org.junit.Assert.assertEquals(Assert.java:144)
|
||||
at HelloWorldTest.helloNoName(HelloWorldTest.kt:10)
|
||||
|
||||
HelloWorldTest > helloAnotherSampleName SKIPPED
|
||||
|
||||
4 tests completed, 1 failed, 3 skipped
|
||||
:test FAILED
|
||||
|
||||
FAILURE: Build failed with an exception.
|
||||
|
||||
* What went wrong:
|
||||
Execution failed for task ':test'.
|
||||
> There were failing tests. See the report at: file:///Users/jtigger/exercism/exercises/kotlin/hello-world/build/reports/tests/index.html
|
||||
|
||||
* Try:
|
||||
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
|
||||
|
||||
BUILD FAILED
|
||||
|
||||
Total time: 7.473 secs
|
||||
```
|
||||
|
||||
Seeing the word "fail" NINE TIMES might give you the impression you've done
|
||||
something horribly wrong! You haven't. It's a whole lot of noise over
|
||||
a single test not passing.
|
||||
|
||||
Let's focus in on the important bits:
|
||||
|
||||
```
|
||||
HelloWorldTest > helloNoName FAILED
|
||||
org.junit.ComparisonFailure: expected:<[Hello, World!]> but was:<[]>
|
||||
```
|
||||
|
||||
...is read: "Within the test class named `HelloWorldTest`, the test method
|
||||
`helloNoName` did not pass because the solution did not satisfy an
|
||||
assertion. Apparently, we expected to see the string 'Hello, World!' but
|
||||
a blank string was returned instead.
|
||||
|
||||
The last line of the stack trace tells us exactly where this unsatisfied
|
||||
assertion lives:
|
||||
|
||||
```
|
||||
at HelloWorldTest.helloNoName(HelloWorldTest.kt:10)
|
||||
```
|
||||
|
||||
Looks like the scene of the crime is on line 10 in the test file.
|
||||
|
||||
Knowing these two facts,
|
||||
|
||||
1. the return value was not what was expected, and
|
||||
2. the failure was on line 10 of the test,
|
||||
|
||||
we can turn this failure into success.
|
||||
|
||||
|
||||
|
||||
## Fixing the first failing test
|
||||
|
||||
In your favorite text editor, open `src/test/kotlin/HelloWorldTest.kt`
|
||||
and go to line 10.
|
||||
|
||||
```kotlin
|
||||
assertEquals("Hello, World!", hello(""))
|
||||
```
|
||||
|
||||
The test is expecting that `hello()`, when given an empty string (`""`),
|
||||
returns "Hello, World!". Instead, `hello()` is returning `""`.
|
||||
Let's fix that.
|
||||
|
||||
Open `src/main/kotlin/HelloWorld.kt`.
|
||||
|
||||
```kotlin
|
||||
fun hello(name: String = ""): String {
|
||||
return ""
|
||||
}
|
||||
```
|
||||
|
||||
Let's change that to return the expected string:
|
||||
|
||||
```kotlin
|
||||
fun hello(name: String = ""): String {
|
||||
return "Hello, World!"
|
||||
}
|
||||
```
|
||||
|
||||
Save the file and run the tests again:
|
||||
|
||||
```
|
||||
$ gradle test
|
||||
:compileKotlin
|
||||
w: /Users/jtigger/exercism/exercises/kotlin/hello-world/src/main/kotlin/HelloWorld.kt: (1, 11): Parameter 'name' is never used
|
||||
:compileJava UP-TO-DATE
|
||||
:copyMainKotlinClasses
|
||||
:processResources UP-TO-DATE
|
||||
:classes UP-TO-DATE
|
||||
:compileTestKotlin
|
||||
:compileTestJava UP-TO-DATE
|
||||
:copyTestKotlinClasses UP-TO-DATE
|
||||
:processTestResources UP-TO-DATE
|
||||
:testClasses UP-TO-DATE
|
||||
:test
|
||||
|
||||
HelloWorldTest > helloSampleName SKIPPED
|
||||
|
||||
HelloWorldTest > helloBlankName SKIPPED
|
||||
|
||||
HelloWorldTest > helloNoName PASSED
|
||||
|
||||
HelloWorldTest > helloAnotherSampleName SKIPPED
|
||||
|
||||
BUILD SUCCESSFUL
|
||||
|
||||
Total time: 7.318 secs
|
||||
```
|
||||
|
||||
"BUILD SUCCESSFUL"! Woohoo! :) You can see that `helloNoName()` test is
|
||||
now passing.
|
||||
|
||||
We still see the warning about `name` not being used; we'll get to that
|
||||
next.
|
||||
|
||||
With one win under our belt, we can turn our focus to some other messages
|
||||
that we've been ignoring: the lines ending in "`SKIPPED`".
|
||||
|
||||
Each test suite contains a series of tests, all of which have been marked
|
||||
to be skipped/ignored except the first one. We did this to help you focus
|
||||
on getting one test running at a time.
|
||||
|
||||
Let's tackle the next test...
|
||||
|
||||
|
||||
|
||||
## Enabling and fixing the second test
|
||||
|
||||
Right now, that second test is being skipped/ignored. Let's enable it.
|
||||
|
||||
(Re)open `src/test/kotlin/HelloWorldTest.kt` and find the second test:
|
||||
|
||||
```kotlin
|
||||
@Test
|
||||
@Ignore
|
||||
fun helloSampleName() {
|
||||
assertEquals("Hello, Alice!", hello("Alice"))
|
||||
}
|
||||
```
|
||||
|
||||
When the JUnit test runner sees that `@Ignore` annotation on the test
|
||||
method, it knows to skip over that test. Remove that line:
|
||||
|
||||
```kotlin
|
||||
@Test
|
||||
fun helloSampleName() {
|
||||
assertEquals("Hello, Alice!", hello("Alice"))
|
||||
}
|
||||
```
|
||||
|
||||
Now, when you run the tests, both tests run:
|
||||
|
||||
```
|
||||
$ gradle test
|
||||
:test
|
||||
|
||||
HelloWorldTest > helloSampleName FAILED
|
||||
org.junit.ComparisonFailure: expected:<Hello, [Alice]!> but was:<Hello, [World]!>
|
||||
at org.junit.Assert.assertEquals(Assert.java:115)
|
||||
at org.junit.Assert.assertEquals(Assert.java:144)
|
||||
at HelloWorldTest.helloSampleName(HelloWorldTest.kt:15)
|
||||
|
||||
HelloWorldTest > helloBlankName SKIPPED
|
||||
|
||||
HelloWorldTest > helloNoName PASSED
|
||||
|
||||
HelloWorldTest > helloAnotherSampleName SKIPPED
|
||||
|
||||
4 tests completed, 1 failed, 2 skipped
|
||||
```
|
||||
|
||||
The first test, `helloNoName()` continues to pass. We see that
|
||||
`helloSampleName` -- the test we just un-`@Ignore`'d -- is now running and
|
||||
failing. Yay, failing test! In fact, the "failure" message is just
|
||||
describing the difference between what the program does now and what it
|
||||
should do for us to call it "done."
|
||||
|
||||
Right now, we've hardcoded the greeting. Enabling this second test has
|
||||
unleashed a new expectation: that our program incorporate a name given
|
||||
into that greeting. When given the name "`Alice`", that's who should be
|
||||
greeted instead of "`World`".
|
||||
|
||||
(Re)open `src/main/kotlin/HelloWorld.kt`.
|
||||
|
||||
```kotlin
|
||||
fun hello(name: String = ""): String {
|
||||
return "Hello, World!"
|
||||
}
|
||||
```
|
||||
|
||||
While `hello()` does accept a reference to a string named `name`, it is not
|
||||
using it in the output. Let's change that:
|
||||
|
||||
|
||||
```kotlin
|
||||
fun hello(name: String = ""): String {
|
||||
return "Hello, $name!"
|
||||
}
|
||||
```
|
||||
|
||||
_(Kotlin allows you to embed expressions within strings, a feature known as
|
||||
string interpolation. For more about this feature, see
|
||||
https://kotlinlang.org/docs/reference/basic-types.html#string-templates )_
|
||||
|
||||
... and rerun the tests ...
|
||||
|
||||
```
|
||||
$ gradle test
|
||||
:test
|
||||
|
||||
HelloWorldTest > helloSampleName PASSED
|
||||
|
||||
HelloWorldTest > helloBlankName SKIPPED
|
||||
|
||||
HelloWorldTest > helloNoName FAILED
|
||||
org.junit.ComparisonFailure: expected:<Hello, [World]!> but was:<Hello, []!>
|
||||
at org.junit.Assert.assertEquals(Assert.java:115)
|
||||
at org.junit.Assert.assertEquals(Assert.java:144)
|
||||
at HelloWorldTest.helloNoName(HelloWorldTest.kt:10)
|
||||
|
||||
HelloWorldTest > helloAnotherSampleName SKIPPED
|
||||
|
||||
4 tests completed, 1 failed, 2 skipped
|
||||
```
|
||||
|
||||
Wait... didn't we just fix the test? Why is it failing? Take a closer look...
|
||||
|
||||
In fact, `helloSampleName()` *is* passing. It's just that at the same time,
|
||||
we just inadvertently broke that first test: `helloNoName()`.
|
||||
|
||||
This is one tiny example of the benefit of maintaining a test suite: if we
|
||||
use them to drive out our code, the second we break the program the tests
|
||||
say so. Since we saw them passing just *before* our latest change,
|
||||
whatever we *just* did most likely cause that regression.
|
||||
|
||||
Our latest change was making the greeting dependent on the name given. If
|
||||
no name is given, our function defaults to an empty string. The intent is
|
||||
that when `hello()` is called on no one in particular, our function greets
|
||||
the whole world. Sound like a job for a default value!
|
||||
|
||||
`src/main/kotlin/HelloWorld.kt`:
|
||||
```kotlin
|
||||
fun hello(name: String = "World"): String {
|
||||
return "Hello, $name!"
|
||||
}
|
||||
```
|
||||
|
||||
... and re-run the tests ...
|
||||
|
||||
```
|
||||
$ gradle test
|
||||
:compileKotlin
|
||||
:compileJava UP-TO-DATE
|
||||
:copyMainKotlinClasses
|
||||
:processResources UP-TO-DATE
|
||||
:classes UP-TO-DATE
|
||||
:compileTestKotlin
|
||||
:compileTestJava UP-TO-DATE
|
||||
:copyTestKotlinClasses
|
||||
:processTestResources UP-TO-DATE
|
||||
:testClasses UP-TO-DATE
|
||||
:test
|
||||
|
||||
HelloWorldTest > helloSampleName PASSED
|
||||
|
||||
HelloWorldTest > helloBlankName SKIPPED
|
||||
|
||||
HelloWorldTest > helloNoName PASSED
|
||||
|
||||
HelloWorldTest > helloAnotherSampleName SKIPPED
|
||||
|
||||
BUILD SUCCESSFUL
|
||||
```
|
||||
|
||||
Excellent! Not only are both our tests passing, but that pesky warning
|
||||
about not using `name` has faded into the distant past. We're now
|
||||
(at least) three-fourth the way done. Just two more tests to go...
|
||||
|
||||
|
||||
|
||||
## Enabling and fixing the third test
|
||||
|
||||
(Re)open `src/test/kotlin/HelloWorldTest.kt` and find the penultimate test:
|
||||
|
||||
```kotlin
|
||||
@Test
|
||||
@Ignore
|
||||
fun helloBlankName() {
|
||||
assertEquals("Hello, World!", hello(" "))
|
||||
}
|
||||
```
|
||||
|
||||
In this test, we're trying to be tricky. It's one thing to omit a
|
||||
parameter completely; it's a whole other situation when we provide a blank
|
||||
string for a name. This test is telling us that we'd like to treat these
|
||||
cases the same way.
|
||||
|
||||
... and remove it's `@Ignore` to enable it ...
|
||||
|
||||
```kotlin
|
||||
@Test
|
||||
fun helloBlankName() {
|
||||
assertEquals("Hello, World!", hello(" "))
|
||||
}
|
||||
```
|
||||
|
||||
... and re-run the tests ...
|
||||
|
||||
```
|
||||
$ gradle test
|
||||
:test
|
||||
|
||||
HelloWorldTest > helloSampleName PASSED
|
||||
|
||||
HelloWorldTest > helloBlankName FAILED
|
||||
org.junit.ComparisonFailure: expected:<Hello, [World]!> but was:<Hello, [ ]!>
|
||||
at org.junit.Assert.assertEquals(Assert.java:115)
|
||||
at org.junit.Assert.assertEquals(Assert.java:144)
|
||||
at HelloWorldTest.helloBlankName(HelloWorldTest.kt:20)
|
||||
|
||||
HelloWorldTest > helloNoName PASSED
|
||||
|
||||
HelloWorldTest > helloAnotherSampleName SKIPPED
|
||||
|
||||
4 tests completed, 1 failed, 1 skipped
|
||||
```
|
||||
|
||||
Since `" "` is an actual value, Kotlin does _not_ substitute in the
|
||||
default value.
|
||||
|
||||
(Re)open `src/main/kotlin/HelloWorld.kt`.
|
||||
|
||||
```kotlin
|
||||
fun hello(name: String = "World"): String {
|
||||
return "Hello, $name!"
|
||||
}
|
||||
```
|
||||
|
||||
One way to handle this case is to check to see if `name` is blank. Let's
|
||||
do that:
|
||||
|
||||
|
||||
```kotlin
|
||||
fun hello(name: String = "World"): String {
|
||||
return "Hello, ${if (name.isBlank()) "World" else name}!"
|
||||
}
|
||||
```
|
||||
|
||||
As you can see, string templates can contain not just references to
|
||||
variables, but entire expressions! This is appropriate in a case like this
|
||||
where we want to apply a simple condition to a value.
|
||||
|
||||
... and rerun the tests ...
|
||||
|
||||
```
|
||||
$ gradle test
|
||||
:test
|
||||
|
||||
HelloWorldTest > helloSampleName PASSED
|
||||
|
||||
HelloWorldTest > helloBlankName PASSED
|
||||
|
||||
HelloWorldTest > helloNoName PASSED
|
||||
|
||||
HelloWorldTest > helloAnotherSampleName SKIPPED
|
||||
|
||||
BUILD SUCCESSFUL
|
||||
```
|
||||
|
||||
We're almost there (perhaps closer than you think)! Just _one_ more test
|
||||
to pass before we have a solution we can have real confidence in.
|
||||
|
||||
|
||||
|
||||
## Enabling the last test
|
||||
|
||||
(Re)open `src/test/kotlin/HelloWorldTest.kt` and find the last test:
|
||||
|
||||
```kotlin
|
||||
@Test
|
||||
@Ignore
|
||||
fun helloAnotherSampleName() {
|
||||
assertEquals("Hello, Bob!", hello("Bob"))
|
||||
}
|
||||
```
|
||||
|
||||
... and pop-off that `@Ignore` ...
|
||||
|
||||
```kotlin
|
||||
@Test
|
||||
fun helloAnotherSampleName() {
|
||||
assertEquals("Hello, Bob!", hello("Bob"))
|
||||
}
|
||||
```
|
||||
|
||||
... then rerun the tests ...
|
||||
|
||||
```
|
||||
:test
|
||||
|
||||
HelloWorldTest > helloSampleName PASSED
|
||||
|
||||
HelloWorldTest > helloBlankName PASSED
|
||||
|
||||
HelloWorldTest > helloNoName PASSED
|
||||
|
||||
HelloWorldTest > helloAnotherSampleName PASSED
|
||||
|
||||
BUILD SUCCESSFUL
|
||||
```
|
||||
|
||||
Oh, hello! Turns out, the solution we put into place didn't just apply for
|
||||
"`Alice`" but for "`Bob`" equally well. In this case, the test succeeded
|
||||
with no additional code on our part.
|
||||
|
||||
Congratulations!
|
||||
|
||||
|
||||
|
||||
## Refactoring
|
||||
|
||||
Now that you've got all the tests passing, you might consider whether
|
||||
the code is in the most readable/maintainable/efficient shape. What makes
|
||||
for "good" design of software is a big topic. The pursuit of it underlies
|
||||
much of what makes up the more valuable conversations on Exercism.
|
||||
|
||||
Kotlin is such a concise language and this exercise is so small, there is
|
||||
not much room for us to make adjustments. Most would leave this code, as
|
||||
is.
|
||||
|
||||
That said, we've taken such pains to illustrate two core parts of the
|
||||
Test-Driven Development approach (i.e. "red", "green"), we'd be remiss if
|
||||
we skipped the all important final part: "refactor".
|
||||
|
||||
More on TDD at http://www.jamesshore.com/Blog/Red-Green-Refactor.html.
|
||||
|
||||
The core responsibility of `hello()` is to produce a personalized greeting.
|
||||
_How_ we determine whether or not a name is given (i.e. `name` is
|
||||
effectively an empty string) is a lower-level detail.
|
||||
|
||||
```kotlin
|
||||
fun hello(name: String = "World"): String {
|
||||
return "Hello, ${if (name.isBlank()) "World" else name}!"
|
||||
}
|
||||
```
|
||||
|
||||
How would things read if we extracted that detail into a separate method?
|
||||
|
||||
```kotlin
|
||||
fun hello(name: String = ""): String {
|
||||
return "Hello, ${whom(name)}!"
|
||||
}
|
||||
|
||||
private fun whom(name: String):String {
|
||||
return if(name.isBlank()) "World" else name
|
||||
}
|
||||
```
|
||||
|
||||
By extracting that logic into the `whom()` method, we've added a little
|
||||
abstraction to our program — it's not as literal as it was before. Yet,
|
||||
it allows us to defer _needing_ to understand _how_ the recipient of the
|
||||
greeting is determined.
|
||||
|
||||
If we can assume that `whom()` just works, we don't have to
|
||||
downshift in our head to those details. Instead, we can remain at the same
|
||||
level of thinking: what's the greeting?
|
||||
|
||||
_(Yes, this is considerable more lines of code; again, not a move we'd likely
|
||||
make typically. The takeaway is this: when you are "done" with an exercise
|
||||
ask yourself, "can I adjust the shape of this code to better tell the
|
||||
story of what's going on through its shape?")_
|
||||
|
||||
We made a bunch of changes, let's make sure we didn't break the program!
|
||||
|
||||
```
|
||||
$ gradle test
|
||||
:compileKotlin
|
||||
:compileJava UP-TO-DATE
|
||||
:copyMainKotlinClasses
|
||||
:processResources UP-TO-DATE
|
||||
:classes UP-TO-DATE
|
||||
:compileTestKotlin
|
||||
:compileTestJava UP-TO-DATE
|
||||
:copyTestKotlinClasses UP-TO-DATE
|
||||
:processTestResources UP-TO-DATE
|
||||
:testClasses UP-TO-DATE
|
||||
:test
|
||||
|
||||
HelloWorldTest > helloSampleName PASSED
|
||||
|
||||
HelloWorldTest > helloBlankName PASSED
|
||||
|
||||
HelloWorldTest > helloNoName PASSED
|
||||
|
||||
HelloWorldTest > helloAnotherSampleName PASSED
|
||||
|
||||
BUILD SUCCESSFUL
|
||||
```
|
||||
|
||||
This illustrates another benefit of writing tests: you can make significant
|
||||
changes to the structure of the program and very quickly restore your
|
||||
confidence that the program still works. These tests are a far cry from a
|
||||
"proof" of correctness, but well-written tests do a much better job of
|
||||
(very quickly) giving us evidence that it is. Without them, we manually
|
||||
run the program with different inputs and/or inspecting the code
|
||||
line-by-line — time-consuming and error prone.
|
||||
|
||||
|
||||
|
||||
# Submitting your first iteration
|
||||
|
||||
With a working solution that we've reviewed, we're ready to submit it to
|
||||
exercism.io.
|
||||
|
||||
```
|
||||
$ exercism submit src/main/kotlin/HelloWorld.kt
|
||||
```
|
||||
|
||||
|
||||
|
||||
# Next Steps
|
||||
|
||||
From here, there are a number of paths you can take.
|
||||
|
||||
|
||||
## Move on to the next exercise
|
||||
|
||||
There are many more exercises you can practice with. Grab the next one!
|
||||
|
||||
```
|
||||
$ exercism fetch kotlin
|
||||
```
|
||||
|
||||
|
||||
## Review (and comment on) others' submissions to this exercise
|
||||
|
||||
The heart of Exercism is the conversations about coding
|
||||
practices. It's definitely fun to practice, but engaging with others
|
||||
both in their attempts and your own is how you get feedback. That feedback
|
||||
can help point out what you're doing well and where you might need to
|
||||
improve.
|
||||
|
||||
Some submissions will be nearly identical to yours; others will be
|
||||
completely different. Seeing both kinds can be instructive and interesting.
|
||||
|
||||
Note that you can only view submissions of others for exercises you have
|
||||
completed yourself. This enriches the experience of reading others' code
|
||||
because you'll have your own experience of trying to solve the problem.
|
||||
|
||||
Here's an up-to-date list of submissions on the Kotlin track:
|
||||
|
||||
http://exercism.io/tracks/kotlin/exercises
|
||||
|
||||
|
||||
|
||||
## Submit another iteration
|
||||
|
||||
You are also encouraged to consider additional "requirements" on a given
|
||||
exercise.
|
||||
|
||||
For example, you could add a test or two that requires that the greeting
|
||||
use the capitalized form on the person's name, regardless of the case they
|
||||
used.
|
||||
|
||||
In that situation, you'd:
|
||||
|
||||
1. add a new test setting up that new expectation,
|
||||
2. implement that in the code (the same process we just went through
|
||||
together, above).
|
||||
3. review your code for readability and refactor as you see fit.
|
||||
|
||||
Exercism practitioners who "play" with each exercise — over trying to go as
|
||||
fast as they can through the stream of exercises — report deep rewards.
|
||||
|
||||
|
||||
## Contribute to Exercism
|
||||
|
||||
The entire of Exercism is Open Source and is the labor of love for more
|
||||
than 100 maintainers and many more contributors.
|
||||
|
||||
A starting point to jumping in can be found here:
|
||||
|
||||
https://github.com/exercism/docs/blob/master/contributing-to-language-tracks/README.md
|
||||
|
||||
----
|
||||
|
||||
Regardless of what you decide to do next, we sincerely hope you learn
|
||||
and enjoy being part of this community. If at any time you need assistance
|
||||
do not hesitate to ask for help:
|
||||
|
||||
http://exercism.io/languages/kotlin/help
|
||||
|
||||
Cheers!
|
@ -1 +0,0 @@
|
||||
leap
|
11
lfe/leap/.gitignore
vendored
Normal file
11
lfe/leap/.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
## -*- conf -*-
|
||||
.rebar3
|
||||
_build/
|
||||
ebin/
|
||||
erl_crash.dump
|
||||
rebar3.crashdump
|
||||
|
||||
tmp
|
||||
bin/configlet
|
||||
bin/configlet.exe
|
||||
CHECKLIST
|
6
lfe/leap/rebar.lock
Normal file
6
lfe/leap/rebar.lock
Normal file
@ -0,0 +1,6 @@
|
||||
{"1.1.0",
|
||||
[{<<"lfe">>,{pkg,<<"lfe">>,<<"1.1.1">>},0}]}.
|
||||
[
|
||||
{pkg_hash,[
|
||||
{<<"lfe">>, <<"F57D2D705AB239CE171318DD31F4E374558266A88E1435F91045C1E8A2965D9C">>}]}
|
||||
].
|
@ -1 +0,0 @@
|
||||
hamming
|
@ -1 +0,0 @@
|
||||
hello-world
|
18
lua/hello-world/hello-world.lua
Normal file
18
lua/hello-world/hello-world.lua
Normal file
@ -0,0 +1,18 @@
|
||||
-- This is a "stub" file. It's a little start on your solution.
|
||||
-- It's not a complete solution though; you have to write some code.
|
||||
|
||||
-- Table to be returned by the hello-world module.
|
||||
local hello_world = {}
|
||||
|
||||
-- Add the hello() function to the table returned by this module.
|
||||
function hello_world.hello()
|
||||
-- Write some code here to pass the test suite.
|
||||
|
||||
-- When you have a working solution, REMOVE ALL THE STOCK COMMENTS.
|
||||
-- They're here to help you get started but they only clutter a finished solution.
|
||||
-- If you leave them in, reviewers will protest!
|
||||
return ''
|
||||
end
|
||||
|
||||
-- Return the hello_world table to make it accessible as a module.
|
||||
return hello_world
|
@ -1 +0,0 @@
|
||||
binary
|
@ -1 +0,0 @@
|
||||
hello-world
|
@ -1 +0,0 @@
|
||||
bob
|
5
ocaml/hello-world/.merlin
Normal file
5
ocaml/hello-world/.merlin
Normal file
@ -0,0 +1,5 @@
|
||||
PKG findlib
|
||||
PKG core
|
||||
PKG ounit
|
||||
S *
|
||||
B *
|
11
ocaml/hello-world/Makefile
Normal file
11
ocaml/hello-world/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
test: test.native
|
||||
@./test.native
|
||||
|
||||
test.native: *.ml *.ml
|
||||
@corebuild -r -quiet -pkg oUnit test.native
|
||||
|
||||
clean:
|
||||
rm -rf _build
|
||||
rm -f test.native
|
||||
|
||||
.PHONY: clean
|
61
ocaml/hello-world/README.md
Normal file
61
ocaml/hello-world/README.md
Normal file
@ -0,0 +1,61 @@
|
||||
# Hello World
|
||||
|
||||
The classical introductory exercise. Just say "Hello, World!".
|
||||
|
||||
["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is
|
||||
the traditional first program for beginning programming in a new language
|
||||
or environment.
|
||||
|
||||
The objectives are simple:
|
||||
|
||||
- Write a function that returns the string "Hello, World!".
|
||||
- Run the test suite and make sure that it succeeds.
|
||||
- Submit your solution and check it at the website.
|
||||
|
||||
If everything goes well, you will be ready to fetch your first real exercise.
|
||||
|
||||
|
||||
## Getting Started
|
||||
For installation and learning resources, refer to the
|
||||
[exercism help page](http://exercism.io/languages/ocaml).
|
||||
|
||||
## Installation
|
||||
To work on the exercises, you will need `Opam` and `Core`. Consult [opam](https://opam.ocaml.org) website for instructions on how to install `opam` for your OS. Once `opam` is installed open a terminal window and run the following command to install core:
|
||||
|
||||
```bash
|
||||
opam install core
|
||||
```
|
||||
|
||||
To run the tests you will need `OUnit`. Install it using `opam`:
|
||||
|
||||
```bash
|
||||
opam install ounit
|
||||
```
|
||||
|
||||
## Running Tests
|
||||
A Makefile is provided with a default target to compile your solution and run the tests. At the command line, type:
|
||||
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
## Interactive Shell
|
||||
`utop` is a command line program which allows you to run Ocaml code interactively. The easiest way to install it is via opam:
|
||||
```bash
|
||||
opam install utop
|
||||
```
|
||||
Consult [utop](https://github.com/diml/utop/blob/master/README.md) for more detail.
|
||||
|
||||
## Feedback, Issues, Pull Requests
|
||||
The [exercism/ocaml](https://github.com/exercism/ocaml) repository on
|
||||
GitHub is the home for all of the Ocaml exercises.
|
||||
|
||||
If you have feedback about an exercise, or want to help implementing a new
|
||||
one, head over there and create an issue. We'll do our best to help you!
|
||||
|
||||
## Source
|
||||
|
||||
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
1
ocaml/hello-world/hello_world.ml
Normal file
1
ocaml/hello-world/hello_world.ml
Normal file
@ -0,0 +1 @@
|
||||
let hello = "Change me"
|
4
ocaml/hello-world/hello_world.mli
Normal file
4
ocaml/hello-world/hello_world.mli
Normal file
@ -0,0 +1,4 @@
|
||||
(*
|
||||
Returns "Hello, World!"
|
||||
*)
|
||||
val hello: string
|
14
ocaml/hello-world/test.ml
Normal file
14
ocaml/hello-world/test.ml
Normal file
@ -0,0 +1,14 @@
|
||||
(* Test/exercise version: "1.0.0" *)
|
||||
|
||||
open Core
|
||||
open OUnit2
|
||||
open Hello_world
|
||||
|
||||
let ae exp got _test_ctxt = assert_equal ~printer:String.to_string exp got
|
||||
|
||||
let tests = [
|
||||
"Say Hi!" >:: ae "Hello, World!" hello;
|
||||
]
|
||||
|
||||
let () =
|
||||
run_test_tt_main ("Hello World tests" >::: tests)
|
@ -1 +0,0 @@
|
||||
NUnit.3.4.1
|
@ -1 +0,0 @@
|
||||
bob
|
10
perl5/hello-world/HelloWorld.pm
Normal file
10
perl5/hello-world/HelloWorld.pm
Normal file
@ -0,0 +1,10 @@
|
||||
# Declare package 'HelloWorld' with version
|
||||
package HelloWorld 1;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub hello {
|
||||
# Remove the comments and write some code here to pass the test suite.
|
||||
}
|
||||
|
||||
1;
|
21
perl5/hello-world/README.md
Normal file
21
perl5/hello-world/README.md
Normal file
@ -0,0 +1,21 @@
|
||||
# Hello World
|
||||
|
||||
The classical introductory exercise. Just say "Hello, World!".
|
||||
|
||||
["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is
|
||||
the traditional first program for beginning programming in a new language
|
||||
or environment.
|
||||
|
||||
The objectives are simple:
|
||||
|
||||
- Write a function that returns the string "Hello, World!".
|
||||
- Run the test suite and make sure that it succeeds.
|
||||
- Submit your solution and check it at the website.
|
||||
|
||||
If everything goes well, you will be ready to fetch your first real exercise.
|
||||
## Source
|
||||
|
||||
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
64
perl5/hello-world/hello-world.t
Normal file
64
perl5/hello-world/hello-world.t
Normal file
@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
use FindBin;
|
||||
my $dir;
|
||||
use lib $dir = $FindBin::Bin; # Look for the module inside the same directory as this test file.
|
||||
use JSON::PP;
|
||||
|
||||
my $exercise = 'HelloWorld'; # The name of this exercise.
|
||||
my $test_version = 1; # The version we will be matching against the exercise.
|
||||
my $module = $ENV{EXERCISM} ? 'Example' : $exercise; # $ENV{EXERCISM} is for tests not directly for the exercise, don't worry about these :)
|
||||
use Test::More tests => 4; # This is how many tests we expect to run.
|
||||
|
||||
use_ok $module or BAIL_OUT; # Check that the module can be use-d.
|
||||
|
||||
# If the exercise is updated, we want to make sure other people testing
|
||||
# your code don't think you've made a mistake if things have changed!
|
||||
my $exercise_version = $exercise->VERSION // 0;
|
||||
if ($exercise_version != $test_version) {
|
||||
warn "\nExercise version mismatch. Further tests may fail!"
|
||||
. "\n$exercise is v$exercise_version. "
|
||||
. "Test is v$test_version.\n";
|
||||
BAIL_OUT if $ENV{EXERCISM};
|
||||
}
|
||||
|
||||
my %subs;
|
||||
foreach ( qw(hello) ) {
|
||||
can_ok $exercise, $_;
|
||||
$subs{$_} = $exercise->can($_);
|
||||
}
|
||||
|
||||
my $C_DATA;
|
||||
is $subs{hello}->($_->{input}), $_->{expected}, $_->{description} foreach @{$C_DATA->{cases}};
|
||||
|
||||
# Ignore this for your exercise! Tells Exercism folks when exercise cases become out of date.
|
||||
SKIP: {
|
||||
skip '', 1 unless $ENV{EXERCISM};
|
||||
is_deeply eval q{
|
||||
use Path::Tiny;
|
||||
decode_json path("$dir/../../problem-specifications/exercises/".path($dir)->basename.'/canonical-data.json')->realpath->slurp;
|
||||
}, $C_DATA, 'canonical-data';
|
||||
}
|
||||
|
||||
done_testing; # There are no more tests after this :)
|
||||
|
||||
# 'INIT' is a phaser, it makes sure that the test data is available before everything else
|
||||
# starts running (otherwise we'd have to shove the test data into the middle of the file!)
|
||||
INIT {
|
||||
$C_DATA = decode_json <<'EOF';
|
||||
|
||||
{
|
||||
"exercise": "hello-world",
|
||||
"version": "1.0.0",
|
||||
"cases": [
|
||||
{
|
||||
"description": "Say Hi!",
|
||||
"property": "hello",
|
||||
"expected": "Hello, World!"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
EOF
|
||||
}
|
@ -1 +0,0 @@
|
||||
hello-world
|
@ -1 +0,0 @@
|
||||
hamming
|
2
python/.gitignore
vendored
Normal file
2
python/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# Ignore compiled python tests
|
||||
*.pyc
|
@ -1,2 +1,9 @@
|
||||
def is_isogram():
|
||||
pass
|
||||
def is_isogram(inp):
|
||||
letList = []
|
||||
for i in inp.lower():
|
||||
if i.isalpha():
|
||||
if not(i in letList):
|
||||
letList.append(i)
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
26
python/pangram/README.md
Normal file
26
python/pangram/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
# Pangram
|
||||
|
||||
Determine if a sentence is a pangram. A pangram (Greek: παν γράμμα, pan gramma,
|
||||
"every letter") is a sentence using every letter of the alphabet at least once.
|
||||
The best known English pangram is:
|
||||
> The quick brown fox jumps over the lazy dog.
|
||||
|
||||
The alphabet used consists of ASCII letters `a` to `z`, inclusive, and is case
|
||||
insensitive. Input will not contain non-ASCII symbols.
|
||||
|
||||
### Submitting Exercises
|
||||
|
||||
Note that, when trying to submit an exercise, make sure the solution is in the `exercism/python/<exerciseName>` directory.
|
||||
|
||||
For example, if you're submitting `bob.py` for the Bob exercise, the submit command would be something like `exercism submit <path_to_exercism_dir>/python/bob/bob.py`.
|
||||
|
||||
|
||||
For more detailed information about running tests, code style and linting,
|
||||
please see the [help page](http://exercism.io/languages/python).
|
||||
|
||||
## Source
|
||||
|
||||
Wikipedia [https://en.wikipedia.org/wiki/Pangram](https://en.wikipedia.org/wiki/Pangram)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
6
python/pangram/pangram.py
Normal file
6
python/pangram/pangram.py
Normal file
@ -0,0 +1,6 @@
|
||||
def is_pangram(inp):
|
||||
inp = inp.lower()
|
||||
for i in "abcdefghijkklmnopqrstuvwxyz":
|
||||
if inp.count(i) == 0:
|
||||
return False
|
||||
return True
|
46
python/pangram/pangram_test.py
Normal file
46
python/pangram/pangram_test.py
Normal file
@ -0,0 +1,46 @@
|
||||
import unittest
|
||||
|
||||
from pangram import is_pangram
|
||||
|
||||
|
||||
# test cases adapted from `x-common//canonical-data.json` @ version: 1.0.0
|
||||
|
||||
class PangramTests(unittest.TestCase):
|
||||
def test_sentence_empty(self):
|
||||
self.assertFalse(is_pangram(''))
|
||||
|
||||
def test_pangram_with_only_lower_case(self):
|
||||
self.assertTrue(
|
||||
is_pangram('the quick brown fox jumps over the lazy dog'))
|
||||
|
||||
def test_missing_character_x(self):
|
||||
self.assertFalse(
|
||||
is_pangram('a quick movement of the enemy will '
|
||||
'jeopardize five gunboats'))
|
||||
|
||||
def test_another_missing_character_x(self):
|
||||
self.assertFalse(
|
||||
is_pangram('the quick brown fish jumps over the lazy dog'))
|
||||
|
||||
def test_pangram_with_underscores(self):
|
||||
self.assertTrue(
|
||||
is_pangram('the_quick_brown_fox_jumps_over_the_lazy_dog'))
|
||||
|
||||
def test_pangram_with_numbers(self):
|
||||
self.assertTrue(
|
||||
is_pangram('the 1 quick brown fox jumps over the 2 lazy dogs'))
|
||||
|
||||
def test_missing_letters_replaced_by_numbers(self):
|
||||
self.assertFalse(
|
||||
is_pangram('7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog'))
|
||||
|
||||
def test_pangram_with_mixedcase_and_punctuation(self):
|
||||
self.assertTrue(is_pangram('"Five quacking Zephyrs jolt my wax bed."'))
|
||||
|
||||
def test_upper_and_lower_case_versions_of_the_same_character(self):
|
||||
self.assertFalse(
|
||||
is_pangram('the quick brown fox jumped over the lazy FOX'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -1 +0,0 @@
|
||||
hello-world
|
@ -1 +0,0 @@
|
||||
hello-world
|
@ -1 +0,0 @@
|
||||
leap
|
7
rust/hello-world/.gitignore
vendored
Normal file
7
rust/hello-world/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
|
||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||
# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
|
||||
Cargo.lock
|
5
rust/hello-world/src/lib.rs
Normal file
5
rust/hello-world/src/lib.rs
Normal file
@ -0,0 +1,5 @@
|
||||
// The &'static here means the return type has a static lifetime.
|
||||
// This is a Rust feature that you don't need to worry about now.
|
||||
pub fn hello() -> &'static str {
|
||||
"Goodbye, World!"
|
||||
}
|
@ -1 +0,0 @@
|
||||
hello-world
|
4
scala/hello-world/src/main/scala/HelloWorld.scala
Normal file
4
scala/hello-world/src/main/scala/HelloWorld.scala
Normal file
@ -0,0 +1,4 @@
|
||||
object HelloWorld {
|
||||
def hello() = ???
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
hello-world
|
@ -1 +0,0 @@
|
||||
hello-world
|
4
swift/hello-world/.gitignore
vendored
Normal file
4
swift/hello-world/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
.DS_Store
|
||||
/.build
|
||||
/Packages
|
||||
/*.xcodeproj
|
5
swift/hello-world/Package.swift
Normal file
5
swift/hello-world/Package.swift
Normal file
@ -0,0 +1,5 @@
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "HelloWorld"
|
||||
)
|
1
swift/hello-world/Sources/HelloWorld.swift
Normal file
1
swift/hello-world/Sources/HelloWorld.swift
Normal file
@ -0,0 +1 @@
|
||||
//Solution goes in Sources
|
@ -0,0 +1,34 @@
|
||||
import XCTest
|
||||
@testable import HelloWorld
|
||||
|
||||
class HelloWorldTests: XCTestCase {
|
||||
|
||||
func testNoName() {
|
||||
let expected = "Hello, World!"
|
||||
XCTAssertEqual(HelloWorld.hello(), expected, "When given no name, we should greet the world!")
|
||||
}
|
||||
|
||||
func testSampleName() {
|
||||
let expected = "Hello, Alice!"
|
||||
XCTAssertEqual(HelloWorld.hello("Alice"), expected, "When given 'Alice' we should greet Alice!")
|
||||
}
|
||||
|
||||
func testOtherSampleName() {
|
||||
let expected = "Hello, Bob!"
|
||||
XCTAssertEqual(HelloWorld.hello("Bob"), expected, "When given 'Bob' we should greet Bob!")
|
||||
}
|
||||
|
||||
func testNoStrangeName() {
|
||||
let expected = "Hello, !"
|
||||
XCTAssertEqual(HelloWorld.hello(""), expected, "When given an empty string, it is strange, but should have a space and punctuation")
|
||||
}
|
||||
|
||||
static var allTests: [(String, (HelloWorldTests) -> () throws -> Void)] {
|
||||
return [
|
||||
("testNoName", testNoName),
|
||||
("testSampleName", testSampleName),
|
||||
("testOtherSampleName", testOtherSampleName),
|
||||
("testNoStrangeName", testNoStrangeName),
|
||||
]
|
||||
}
|
||||
}
|
6
swift/hello-world/Tests/LinuxMain.swift
Normal file
6
swift/hello-world/Tests/LinuxMain.swift
Normal file
@ -0,0 +1,6 @@
|
||||
import XCTest
|
||||
@testable import HelloWorldTests
|
||||
|
||||
XCTMain([
|
||||
testCase(HelloWorldTests.allTests),
|
||||
])
|
Loading…
Reference in New Issue
Block a user