Merge branch 'master' of ssh://git.bullercodeworks.com:2200/brian/exercism
This commit is contained in:
commit
5c8e8cba21
d/hello-world
delphi/hello-world
go
accumulate
error-handling
paasio
pov
perl6/hello-world
python
example/__pycache__
hello-world
leap
pangram
r/hello-world
typescript/hello-world
vimscript/hello-world
52
d/hello-world/README.md
Normal file
52
d/hello-world/README.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# 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 [D page](http://exercism.io/languages/dlang) on
|
||||||
|
exercism.io. This covers the basic information on setting up the development
|
||||||
|
environment expected by the exercises.
|
||||||
|
|
||||||
|
## Passing the Tests
|
||||||
|
|
||||||
|
Get the first test compiling, linking and passing by following the [three
|
||||||
|
rules of test-driven development](http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd).
|
||||||
|
Create just enough structure by declaring namespaces, functions, classes,
|
||||||
|
etc., to satisfy any compiler errors and get the test to fail. Then write
|
||||||
|
just enough code to get the test to pass. Once you've done that,
|
||||||
|
uncomment the next test by moving the following line past the next test.
|
||||||
|
|
||||||
|
```D
|
||||||
|
static if (all_tests_enabled)
|
||||||
|
```
|
||||||
|
|
||||||
|
This may result in compile errors as new constructs may be invoked that
|
||||||
|
you haven't yet declared or defined. Again, fix the compile errors minimally
|
||||||
|
to get a failing test, then change the code minimally to pass the test,
|
||||||
|
refactor your implementation for readability and expressiveness and then
|
||||||
|
go on to the next test.
|
||||||
|
|
||||||
|
Try to use standard D facilities in preference to writing your own
|
||||||
|
low-level algorithms or facilities by hand. [DRefLanguage](https://dlang.org/spec/spec.html)
|
||||||
|
and [DReference](https://dlang.org/phobos/index.html) are references to the D language and D standard library.
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
2
d/hello-world/dub.sdl
Normal file
2
d/hello-world/dub.sdl
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
name "hello-world"
|
||||||
|
buildRequirements "disallowDeprecations"
|
13
d/hello-world/source/hello_world.d
Normal file
13
d/hello-world/source/hello_world.d
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module helloworld_test;
|
||||||
|
|
||||||
|
unittest {
|
||||||
|
const int allTestsEnabled = 0;
|
||||||
|
|
||||||
|
assert(hello() == "Hello, World!");
|
||||||
|
static if (allTestsEnabled) {
|
||||||
|
assert(hello("Alice") == "Hello, Alice!");
|
||||||
|
assert(hello("Bob") == "Hello, Bob!");
|
||||||
|
assert(hello("") == "Hello, !");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
60
delphi/hello-world/HelloWorld.dpr
Normal file
60
delphi/hello-world/HelloWorld.dpr
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
program HelloWorld;
|
||||||
|
|
||||||
|
{$IFNDEF TESTINSIGHT}
|
||||||
|
{$APPTYPE CONSOLE}
|
||||||
|
{$ENDIF}{$STRONGLINKTYPES ON}
|
||||||
|
uses
|
||||||
|
System.SysUtils,
|
||||||
|
{$IFDEF TESTINSIGHT}
|
||||||
|
TestInsight.DUnitX,
|
||||||
|
{$ENDIF }
|
||||||
|
DUnitX.Loggers.Console,
|
||||||
|
DUnitX.Loggers.Xml.NUnit,
|
||||||
|
DUnitX.TestFramework,
|
||||||
|
uTestHelloWorld in 'uTestHelloWorld.pas',
|
||||||
|
uHelloWorld in 'uHelloWorld.pas';
|
||||||
|
|
||||||
|
var
|
||||||
|
runner : ITestRunner;
|
||||||
|
results : IRunResults;
|
||||||
|
logger : ITestLogger;
|
||||||
|
nunitLogger : ITestLogger;
|
||||||
|
begin
|
||||||
|
{$IFDEF TESTINSIGHT}
|
||||||
|
TestInsight.DUnitX.RunRegisteredTests;
|
||||||
|
exit;
|
||||||
|
{$ENDIF}
|
||||||
|
try
|
||||||
|
//Check command line options, will exit if invalid
|
||||||
|
TDUnitX.CheckCommandLine;
|
||||||
|
//Create the test runner
|
||||||
|
runner := TDUnitX.CreateRunner;
|
||||||
|
//Tell the runner to use RTTI to find Fixtures
|
||||||
|
runner.UseRTTI := True;
|
||||||
|
//tell the runner how we will log things
|
||||||
|
//Log to the console window
|
||||||
|
logger := TDUnitXConsoleLogger.Create(true);
|
||||||
|
runner.AddLogger(logger);
|
||||||
|
//Generate an NUnit compatible XML File
|
||||||
|
nunitLogger := TDUnitXXMLNUnitFileLogger.Create(TDUnitX.Options.XMLOutputFile);
|
||||||
|
runner.AddLogger(nunitLogger);
|
||||||
|
runner.FailsOnNoAsserts := False; //When true, Assertions must be made during tests;
|
||||||
|
|
||||||
|
//Run tests
|
||||||
|
results := runner.Execute;
|
||||||
|
if not results.AllPassed then
|
||||||
|
System.ExitCode := EXIT_ERRORS;
|
||||||
|
|
||||||
|
{$IFNDEF CI}
|
||||||
|
//We don't want this happening when running under CI.
|
||||||
|
if TDUnitX.Options.ExitBehavior = TDUnitXExitBehavior.Pause then
|
||||||
|
begin
|
||||||
|
System.Write('Done.. press <Enter> key to quit.');
|
||||||
|
System.Readln;
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
except
|
||||||
|
on E: Exception do
|
||||||
|
System.Writeln(E.ClassName, ': ', E.Message);
|
||||||
|
end;
|
||||||
|
end.
|
42
delphi/hello-world/README.md
Normal file
42
delphi/hello-world/README.md
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
In order to run the tests for this track, you will need to install
|
||||||
|
DUnitX. Please see the [installation](http://www.exercism.io/languages/delphi/installing) instructions for more information.
|
||||||
|
|
||||||
|
### Loading Exercises into Delphi
|
||||||
|
|
||||||
|
If Delphi is properly installed, and `*.dpr` file types have been associated with Delphi, then double clicking the supplied `*.dpr` file will start Delphi and load the exercise/project. `control + F9` is the keyboard shortcut to compile the project or pressing `F9` will compile and run the project.
|
||||||
|
|
||||||
|
Alternatively you may opt to start Delphi and load your project via. the `File` drop down menu.
|
||||||
|
|
||||||
|
### When Questions Come Up
|
||||||
|
We monitor the [Pascal-Delphi](https://gitter.im/exercism/Pascal-Delphi) support room on [gitter.im](https://gitter.im) to help you with any questions that might arise.
|
||||||
|
|
||||||
|
### Submitting Exercises
|
||||||
|
|
||||||
|
Note that, when trying to submit an exercise, make sure the exercise file you're submitting is in the `exercism/delphi/<exerciseName>` directory.
|
||||||
|
|
||||||
|
For example, if you're submitting `ubob.pas` for the Bob exercise, the submit command would be something like `exercism submit <path_to_exercism_dir>/delphi/bob/ubob.pas`.
|
||||||
|
|
||||||
|
## 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.
|
85
delphi/hello-world/uTestHelloWorld.pas
Normal file
85
delphi/hello-world/uTestHelloWorld.pas
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
(******************************************************************************
|
||||||
|
You got an error, which is exactly as it should be.
|
||||||
|
This is the first step in the Test-Driven Development
|
||||||
|
(TDD) process.
|
||||||
|
|
||||||
|
The most important part of the error is
|
||||||
|
|
||||||
|
"cannot compile"
|
||||||
|
|
||||||
|
It's looking for a file named uHelloWorld.pas that doesn't exist.
|
||||||
|
|
||||||
|
To fix the error, create a unit file named uHelloWorld.pas
|
||||||
|
in the same directory as the file uTestHelloWorld.pas.
|
||||||
|
|
||||||
|
The beginning of the new unit file should contain a unit statement:
|
||||||
|
|
||||||
|
unit uHelloWorld;
|
||||||
|
|
||||||
|
The new unit should contain Interface, Implementation, and End. statements.
|
||||||
|
|
||||||
|
The primary focus of this exercise is to provide you with a very simple
|
||||||
|
exercise that you can use to test the tools necessary for this language track,
|
||||||
|
are working correctly. To that end we are providing you with code that you may
|
||||||
|
use as the solution to this exercise:
|
||||||
|
|
||||||
|
{------------------< start solution >------------------}
|
||||||
|
unit uHelloWorld;
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
function Hello: string;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
function Hello: string;
|
||||||
|
begin
|
||||||
|
result := 'Hello, World!';
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
{------------------< end solution >------------------}
|
||||||
|
|
||||||
|
Hint: Delphi will take care of all this if you instruct it to add a new unit
|
||||||
|
to your project. Be sure to save the new unit as uHelloWorld.pas before
|
||||||
|
trying to compile again.
|
||||||
|
|
||||||
|
For more guidance as you work on this exercise, see
|
||||||
|
GETTING_STARTED.md.
|
||||||
|
******************************************************************************)
|
||||||
|
unit uTestHelloWorld;
|
||||||
|
|
||||||
|
interface
|
||||||
|
uses
|
||||||
|
DUnitX.TestFramework;
|
||||||
|
|
||||||
|
type
|
||||||
|
[TestFixture]
|
||||||
|
HelloWorldTest = class(TObject)
|
||||||
|
public
|
||||||
|
[Test]
|
||||||
|
procedure Say_hi;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
uses uHelloWorld;
|
||||||
|
|
||||||
|
procedure HelloWorldTest.Say_hi;
|
||||||
|
var
|
||||||
|
Expected: string;
|
||||||
|
Actual: string;
|
||||||
|
begin
|
||||||
|
Expected := 'Hello, World!'; //Expected: This is what is expected to be returned by the function/method (Hello)
|
||||||
|
Actual := Hello; //Actual: This is what is actually returned by the function/method (Hello)
|
||||||
|
Assert.AreEqual(Expected, Actual);
|
||||||
|
|
||||||
|
//As you progress in this track you will find that not every exercise has Expected and
|
||||||
|
//Actual defined as explicitly as they have been above. Often times you may find
|
||||||
|
//that the Expected outcome is inserted as an inline statement and the the call
|
||||||
|
//to the method being tested will be inserted in the Actual position of AreEqual like so:
|
||||||
|
//Assert.AreEqual('Hello, World!', Hello);
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
TDUnitX.RegisterTestFixture(HelloWorldTest);
|
||||||
|
end.
|
53
go/accumulate/README.md
Normal file
53
go/accumulate/README.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# Accumulate
|
||||||
|
|
||||||
|
Implement the `accumulate` operation, which, given a collection and an
|
||||||
|
operation to perform on each element of the collection, returns a new
|
||||||
|
collection containing the result of applying that operation to each element of
|
||||||
|
the input collection.
|
||||||
|
|
||||||
|
Given the collection of numbers:
|
||||||
|
|
||||||
|
- 1, 2, 3, 4, 5
|
||||||
|
|
||||||
|
And the operation:
|
||||||
|
|
||||||
|
- square a number (`x => x * x`)
|
||||||
|
|
||||||
|
Your code should be able to produce the collection of squares:
|
||||||
|
|
||||||
|
- 1, 4, 9, 16, 25
|
||||||
|
|
||||||
|
Check out the test suite to see the expected function signature.
|
||||||
|
|
||||||
|
## Restrictions
|
||||||
|
|
||||||
|
Keep your hands off that collect/map/fmap/whatchamacallit functionality
|
||||||
|
provided by your standard library!
|
||||||
|
Solve this one yourself using other basic tools instead.
|
||||||
|
|
||||||
|
Lisp specific: it's perfectly fine to use `MAPCAR` or the equivalent,
|
||||||
|
as this is idiomatic Lisp, not a library function.
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
Conversation with James Edward Gray II [https://twitter.com/jeg2](https://twitter.com/jeg2)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
11
go/accumulate/accumulate.go
Normal file
11
go/accumulate/accumulate.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package accumulate
|
||||||
|
|
||||||
|
const testVersion = 1
|
||||||
|
|
||||||
|
func Accumulate(vals []string, f func(string) string) []string {
|
||||||
|
ret := make([]string, len(vals))
|
||||||
|
for i := range vals {
|
||||||
|
ret[i] = f(vals[i])
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
57
go/accumulate/accumulate_test.go
Normal file
57
go/accumulate/accumulate_test.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package accumulate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const targetTestVersion = 1
|
||||||
|
|
||||||
|
func echo(c string) string {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func capitalize(word string) string {
|
||||||
|
return strings.Title(word)
|
||||||
|
}
|
||||||
|
|
||||||
|
var tests = []struct {
|
||||||
|
expected []string
|
||||||
|
given []string
|
||||||
|
converter func(string) string
|
||||||
|
description string
|
||||||
|
}{
|
||||||
|
{[]string{}, []string{}, echo, "echo"},
|
||||||
|
{[]string{"echo", "echo", "echo", "echo"}, []string{"echo", "echo", "echo", "echo"}, echo, "echo"},
|
||||||
|
{[]string{"First", "Letter", "Only"}, []string{"first", "letter", "only"}, capitalize, "capitalize"},
|
||||||
|
{[]string{"HELLO", "WORLD"}, []string{"hello", "world"}, strings.ToUpper, "strings.ToUpper"},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTestVersion(t *testing.T) {
|
||||||
|
if testVersion != targetTestVersion {
|
||||||
|
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccumulate(t *testing.T) {
|
||||||
|
for _, test := range tests {
|
||||||
|
actual := Accumulate(test.given, test.converter)
|
||||||
|
if fmt.Sprintf("%q", actual) != fmt.Sprintf("%q", test.expected) {
|
||||||
|
t.Fatalf("Accumulate(%q, %q): expected %q, actual %q", test.given, test.description, test.expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAccumulate(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
for _, test := range tests {
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
Accumulate(test.given, test.converter)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
}
|
||||||
|
}
|
31
go/error-handling/README.md
Normal file
31
go/error-handling/README.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Error Handling
|
||||||
|
|
||||||
|
Implement various kinds of error handling and resource management.
|
||||||
|
|
||||||
|
An important point of programming is how to handle errors and close
|
||||||
|
resources even if errors occur.
|
||||||
|
|
||||||
|
This exercise requires you to handle various errors. Because error handling
|
||||||
|
is rather programming language specific you'll have to refer to the tests
|
||||||
|
for your track to see what's exactly required.
|
||||||
|
|
||||||
|
## 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).
|
||||||
|
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
57
go/error-handling/common.go
Normal file
57
go/error-handling/common.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package erratum
|
||||||
|
|
||||||
|
import "io"
|
||||||
|
|
||||||
|
// These are the support types and interface definitions used in the
|
||||||
|
// implementation if your Use function. See the test suite file at
|
||||||
|
// for information on the expected implementation.
|
||||||
|
//
|
||||||
|
// Because this is part of the package "erratum", if your solution file
|
||||||
|
// is also declared in the package you will automatically have access to
|
||||||
|
// these definitions (you do not have to re-declare them).
|
||||||
|
|
||||||
|
// TransientError is an error that may occur while opening a resource via
|
||||||
|
// ResourceOpener.
|
||||||
|
type TransientError struct {
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e TransientError) Error() string {
|
||||||
|
return e.err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FrobError is a possible error from doing some frobbing, your implementation
|
||||||
|
// will require calling your Resource's Defrob(string) method.
|
||||||
|
// When this error occurs, the FrobError's defrobTag string will contain the
|
||||||
|
// string you must pass into Defrob.
|
||||||
|
type FrobError struct {
|
||||||
|
defrobTag string
|
||||||
|
inner error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e FrobError) Error() string {
|
||||||
|
return e.inner.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Resource interface {
|
||||||
|
|
||||||
|
// Resource is using composition to inherit the requirements of the io.Closer
|
||||||
|
// interface. What this means is that a Resource will have a .Close() method.
|
||||||
|
io.Closer
|
||||||
|
|
||||||
|
// Frob does something with the input string.
|
||||||
|
// Because this is an incredibly badly designed system if there is an error
|
||||||
|
// it panics.
|
||||||
|
//
|
||||||
|
// The paniced error may be a FrobError in which case Defrob should be called
|
||||||
|
// with the defrobTag string.
|
||||||
|
Frob(string)
|
||||||
|
|
||||||
|
Defrob(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResourceOpener is a function that creates a resource.
|
||||||
|
//
|
||||||
|
// It may return a wrapped error of type TransientError. In this case the resource
|
||||||
|
// is temporarily unavailable and the caller should retry soon.
|
||||||
|
type ResourceOpener func() (Resource, error)
|
35
go/error-handling/error_handling.go
Normal file
35
go/error-handling/error_handling.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package erratum
|
||||||
|
|
||||||
|
const testVersion = 2
|
||||||
|
|
||||||
|
func Use(o ResourceOpener, inp string) (err error) {
|
||||||
|
var r Resource
|
||||||
|
moveOn := false
|
||||||
|
for !moveOn {
|
||||||
|
moveOn = true
|
||||||
|
if r, err = o(); err != nil {
|
||||||
|
switch err.(type) {
|
||||||
|
case TransientError:
|
||||||
|
moveOn = false
|
||||||
|
default:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
defer func() {
|
||||||
|
if rec := recover(); rec != nil {
|
||||||
|
switch v := rec.(type) {
|
||||||
|
case FrobError:
|
||||||
|
r.Defrob(v.defrobTag)
|
||||||
|
err = v
|
||||||
|
case error:
|
||||||
|
err = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
r.Frob(inp)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
191
go/error-handling/error_handling_test.go
Normal file
191
go/error-handling/error_handling_test.go
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
package erratum
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Because this exercise is generally unique to each language and how it
|
||||||
|
// handles errors, most of the definition of your expected solution is provided
|
||||||
|
// here instead of the README.
|
||||||
|
// You should read this carefully (more than once) before implementation.
|
||||||
|
|
||||||
|
// Define a function `Use(o ResourceOpener, input string) error` that opens a
|
||||||
|
// resource, calls Frob(input) and closes the resource (in all cases). Your
|
||||||
|
// function should properly handle errors, as defined by the expectations of
|
||||||
|
// this test suite. ResourceOpener will be a function you may invoke directly
|
||||||
|
// `o()` in an attempt to "open" the resource. It returns a Resource and error
|
||||||
|
// value in the idiomatic Go fashion:
|
||||||
|
// https://blog.golang.org/error-handling-and-go
|
||||||
|
//
|
||||||
|
// See the ./common.go file for the definitions of Resource, ResourceOpener,
|
||||||
|
// FrobError and TransientError.
|
||||||
|
//
|
||||||
|
// There will be a few places in your Use function where errors may occur:
|
||||||
|
//
|
||||||
|
// - Invoking the ResourceOpener function passed into Use as the first
|
||||||
|
// parameter, it may fail with a TransientError, if so keep trying to open it.
|
||||||
|
// If it is some other sort of error, return it.
|
||||||
|
//
|
||||||
|
// - Calling the Frob function on the Resource returned from the ResourceOpener
|
||||||
|
// function, it may panic with a FrobError (or another type of error). If
|
||||||
|
// it is indeed a FrobError you will have to call the Resource's Defrob
|
||||||
|
// function using the FrobError's defrobTag variable as input. Either way
|
||||||
|
// return the error.
|
||||||
|
//
|
||||||
|
// Also note: if the Resource was opened successfully make sure to call its
|
||||||
|
// Close function no matter what (even if errors occur).
|
||||||
|
//
|
||||||
|
// If you are new to Go errors or panics here is a good place to start:
|
||||||
|
// https://blog.golang.org/defer-panic-and-recover
|
||||||
|
//
|
||||||
|
// You may also need to look at named return values as a helpful way to
|
||||||
|
// return error information from panic recovery:
|
||||||
|
// https://tour.golang.org/basics/7
|
||||||
|
|
||||||
|
const targetTestVersion = 2
|
||||||
|
|
||||||
|
// Little helper to let us customize behaviour of the resource on a per-test
|
||||||
|
// basis.
|
||||||
|
type mockResource struct {
|
||||||
|
close func() error
|
||||||
|
frob func(string)
|
||||||
|
defrob func(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mr mockResource) Close() error { return mr.close() }
|
||||||
|
func (mr mockResource) Frob(input string) { mr.frob(input) }
|
||||||
|
func (mr mockResource) Defrob(tag string) { mr.defrob(tag) }
|
||||||
|
|
||||||
|
func TestTestVersion(t *testing.T) {
|
||||||
|
if testVersion != targetTestVersion {
|
||||||
|
t.Fatalf("Found testVersion = %v, want %v", testVersion, targetTestVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use should not return an error on the "happy" path.
|
||||||
|
func TestNoErrors(t *testing.T) {
|
||||||
|
var frobInput string
|
||||||
|
var closeCalled bool
|
||||||
|
mr := mockResource{
|
||||||
|
close: func() error { closeCalled = true; return nil },
|
||||||
|
frob: func(input string) { frobInput = input },
|
||||||
|
}
|
||||||
|
opener := func() (Resource, error) { return mr, nil }
|
||||||
|
inp := "hello"
|
||||||
|
err := Use(opener, inp)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected error from Use: %v", err)
|
||||||
|
}
|
||||||
|
if frobInput != inp {
|
||||||
|
t.Fatalf("Wrong string passed to Frob: got %v, expected %v", frobInput, inp)
|
||||||
|
}
|
||||||
|
if !closeCalled {
|
||||||
|
t.Fatalf("Close was not called")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use should keep trying if a transient error is returned on open.
|
||||||
|
func TestKeepTryOpenOnTransient(t *testing.T) {
|
||||||
|
var frobInput string
|
||||||
|
mr := mockResource{
|
||||||
|
close: func() error { return nil },
|
||||||
|
frob: func(input string) { frobInput = input },
|
||||||
|
}
|
||||||
|
nthCall := 0
|
||||||
|
opener := func() (Resource, error) {
|
||||||
|
if nthCall < 3 {
|
||||||
|
nthCall++
|
||||||
|
return mockResource{}, TransientError{errors.New("some error")}
|
||||||
|
}
|
||||||
|
return mr, nil
|
||||||
|
}
|
||||||
|
inp := "hello"
|
||||||
|
err := Use(opener, inp)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unexpected error from Use: %v", err)
|
||||||
|
}
|
||||||
|
if frobInput != inp {
|
||||||
|
t.Fatalf("Wrong string passed to Frob: got %v, expected %v", frobInput, inp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use should fail if a non-transient error is returned on open.
|
||||||
|
func TestFailOpenOnNonTransient(t *testing.T) {
|
||||||
|
nthCall := 0
|
||||||
|
opener := func() (Resource, error) {
|
||||||
|
if nthCall < 3 {
|
||||||
|
nthCall++
|
||||||
|
return mockResource{}, TransientError{errors.New("some error")}
|
||||||
|
}
|
||||||
|
return nil, errors.New("too awesome")
|
||||||
|
}
|
||||||
|
inp := "hello"
|
||||||
|
err := Use(opener, inp)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("Unexpected lack of error from Use")
|
||||||
|
}
|
||||||
|
if err.Error() != "too awesome" {
|
||||||
|
t.Fatalf("Invalid error returned from Use")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use should call Defrob and Close on FrobError panic from Frob
|
||||||
|
// and return the error.
|
||||||
|
func TestCallDefrobAndCloseOnFrobError(t *testing.T) {
|
||||||
|
tag := "moo"
|
||||||
|
var closeCalled bool
|
||||||
|
var defrobTag string
|
||||||
|
mr := mockResource{
|
||||||
|
close: func() error { closeCalled = true; return nil },
|
||||||
|
frob: func(input string) { panic(FrobError{tag, errors.New("meh")}) },
|
||||||
|
defrob: func(tag string) {
|
||||||
|
if closeCalled {
|
||||||
|
t.Fatalf("Close was called before Defrob")
|
||||||
|
}
|
||||||
|
defrobTag = tag
|
||||||
|
},
|
||||||
|
}
|
||||||
|
opener := func() (Resource, error) { return mr, nil }
|
||||||
|
inp := "hello"
|
||||||
|
err := Use(opener, inp)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("Unexpected lack of error from Use")
|
||||||
|
}
|
||||||
|
if err.Error() != "meh" {
|
||||||
|
t.Fatalf("Invalid error returned from Use")
|
||||||
|
}
|
||||||
|
if defrobTag != tag {
|
||||||
|
t.Fatalf("Wrong string passed to Defrob: got %v, expected %v", defrobTag, tag)
|
||||||
|
}
|
||||||
|
if !closeCalled {
|
||||||
|
t.Fatalf("Close was not called")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use should call Close but not Defrob on non-FrobError panic from Frob
|
||||||
|
// and return the error.
|
||||||
|
func TestCallCloseNonOnFrobError(t *testing.T) {
|
||||||
|
var closeCalled bool
|
||||||
|
var defrobCalled bool
|
||||||
|
mr := mockResource{
|
||||||
|
close: func() error { closeCalled = true; return nil },
|
||||||
|
frob: func(input string) { panic(errors.New("meh")) },
|
||||||
|
defrob: func(tag string) { defrobCalled = true },
|
||||||
|
}
|
||||||
|
opener := func() (Resource, error) { return mr, nil }
|
||||||
|
inp := "hello"
|
||||||
|
err := Use(opener, inp)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("Unexpected lack of error from Use")
|
||||||
|
}
|
||||||
|
if err.Error() != "meh" {
|
||||||
|
t.Fatalf("Invalid error returned from Use")
|
||||||
|
}
|
||||||
|
if defrobCalled {
|
||||||
|
t.Fatalf("Defrob was called")
|
||||||
|
}
|
||||||
|
if !closeCalled {
|
||||||
|
t.Fatalf("Close was not called")
|
||||||
|
}
|
||||||
|
}
|
@ -1,26 +1,109 @@
|
|||||||
package paasio
|
package paasio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
const testVersion = 3
|
const testVersion = 3
|
||||||
|
|
||||||
func NewWriteCounter() WriteCounter {
|
func NewReadCounter(r io.Reader) ReadCounter {
|
||||||
w := new(WriteCounter)
|
return &readCounter{
|
||||||
return w
|
r: r,
|
||||||
|
lock: new(sync.Mutex),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WriteCounter) WriteCount() (int64, int) {
|
type readCounter struct {
|
||||||
|
r io.Reader
|
||||||
|
bytesRead int64
|
||||||
|
ops int
|
||||||
|
lock *sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *readCounter) Read(p []byte) (int, error) {
|
||||||
|
m, err := rc.r.Read(p)
|
||||||
|
rc.lock.Lock()
|
||||||
|
rc.bytesRead += int64(m)
|
||||||
|
rc.ops++
|
||||||
|
rc.lock.Unlock()
|
||||||
|
return m, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rc *readCounter) ReadCount() (n int64, ops int) {
|
||||||
|
rc.lock.Lock()
|
||||||
|
n, ops = rc.bytesRead, rc.ops
|
||||||
|
rc.lock.Unlock()
|
||||||
|
return n, ops
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWriteCounter(w io.Writer) WriteCounter {
|
||||||
|
return &writeCounter{
|
||||||
|
w: w,
|
||||||
|
lock: new(sync.Mutex),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type writeCounter struct {
|
||||||
|
w io.Writer
|
||||||
|
bytesWrote int64
|
||||||
|
ops int
|
||||||
|
lock *sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *writeCounter) Write(p []byte) (int, error) {
|
||||||
|
m, err := wc.w.Write(p)
|
||||||
|
wc.lock.Lock()
|
||||||
|
wc.bytesWrote += int64(m)
|
||||||
|
wc.ops++
|
||||||
|
wc.lock.Unlock()
|
||||||
|
return m, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *writeCounter) WriteCount() (n int64, ops int) {
|
||||||
|
wc.lock.Lock()
|
||||||
|
n, ops = wc.bytesWrote, wc.ops
|
||||||
|
wc.lock.Unlock()
|
||||||
|
return n, ops
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReadWriter interface {
|
||||||
|
io.Reader
|
||||||
|
io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewReadWriteCounter(rw ReadWriter) ReadWriteCounter {
|
||||||
|
return &readWriteCounter{
|
||||||
|
r: NewReadCounter(rw),
|
||||||
|
w: NewWriteCounter(rw),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type readWriteCounter struct {
|
||||||
|
r ReadCounter
|
||||||
|
w WriteCounter
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rw *readWriteCounter) Read(p []byte) (int, error) {
|
||||||
|
return rw.r.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rw *readWriteCounter) Write(p []byte) (int, error) {
|
||||||
|
return rw.w.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rw *readWriteCounter) ReadCount() (n int64, ops int) {
|
||||||
|
return rw.r.ReadCount()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rw *readWriteCounter) WriteCount() (n int64, ops int) {
|
||||||
|
return rw.w.WriteCount()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nr *nopReader) ReadCount() (n int64, ops int) {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewReadCounter() ReadCounter {
|
func (nw *nopWriter) WriteCount() (n int64, ops int) {
|
||||||
r := new(ReadCounter)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *ReadCounter) ReadCount() (int64, int) {
|
|
||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewReadWriteCounter() *ReadWriteCounter {
|
|
||||||
r := new(ReadWriteCounter)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
BIN
go/pov/cmd/cmd
Executable file
BIN
go/pov/cmd/cmd
Executable file
Binary file not shown.
13
go/pov/cmd/main.go
Normal file
13
go/pov/cmd/main.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import pov ".."
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
g := pov.New()
|
||||||
|
g.AddNode("sibling")
|
||||||
|
g.AddNode("x")
|
||||||
|
g.AddNode("parent")
|
||||||
|
g.AddArc("parent", "sibling")
|
||||||
|
g.AddArc("parent", "x")
|
||||||
|
pov.PrintGraph(g)
|
||||||
|
}
|
134
go/pov/pov.go
Normal file
134
go/pov/pov.go
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
package pov
|
||||||
|
|
||||||
|
const testVersion = 2
|
||||||
|
|
||||||
|
type Graph struct {
|
||||||
|
leaves []Node
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *Graph {
|
||||||
|
g := new(Graph)
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNode returns the node from the graph with label lbl
|
||||||
|
func (g *Graph) GetNode(lbl string) *Node {
|
||||||
|
for i := range g.leaves {
|
||||||
|
if n := g.leaves[i].GetNode(lbl); n != nil {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNode adds a top level leaf with label lbl
|
||||||
|
func (g *Graph) AddNode(lbl string) {
|
||||||
|
g.leaves = append(g.leaves, Node{label: lbl})
|
||||||
|
}
|
||||||
|
|
||||||
|
// addRealNode adds the node n to the top level
|
||||||
|
func (g *Graph) addRealNode(n *Node) {
|
||||||
|
g.leaves = append(g.leaves, *n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddArc creates a new node after to named from
|
||||||
|
func (g *Graph) AddArc(from, to string) {
|
||||||
|
if n := g.GetNode(to); n != nil {
|
||||||
|
n.AddNode(from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArcList returns a list of all arcs
|
||||||
|
func (g *Graph) ArcList() []string {
|
||||||
|
var ret []string
|
||||||
|
for i := range g.leaves {
|
||||||
|
ret = append(ret, g.leaves[i].ArcList()...)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangeRoot changes the graph from starting at oldRoot going to newRoot
|
||||||
|
func (g *Graph) ChangeRoot(oldRoot, newRoot string) *Graph {
|
||||||
|
// First of all, find the newRoot node
|
||||||
|
ret := New()
|
||||||
|
// The new graph will start with newRoot and have newRoot's leaves
|
||||||
|
var rt *Node
|
||||||
|
if rt = g.GetNode(newRoot); rt == nil {
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
// It'll have one more leaf, it's parent node
|
||||||
|
//rt.addRealNode(g.GetNode(oldRoot))
|
||||||
|
ret.addRealNode(rt)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Graph) getPath(from, to string) []string {
|
||||||
|
var ret []string
|
||||||
|
// Get the 'from' node
|
||||||
|
frNode := g.GetNode(from)
|
||||||
|
if frNode == nil {
|
||||||
|
// Couldn't find the starting node
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
// Just in case we got the same value for both
|
||||||
|
if from == to {
|
||||||
|
return []string{from}
|
||||||
|
}
|
||||||
|
// Found it
|
||||||
|
return frNode.getPath(to)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Node struct {
|
||||||
|
label string
|
||||||
|
leaves []Node
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) AddNode(lbl string) {
|
||||||
|
n.leaves = append(n.leaves, Node{label: lbl})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) addRealNode(nd *Node) {
|
||||||
|
n.leaves = append(n.leaves, *nd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) GetNode(lbl string) *Node {
|
||||||
|
if n.label == lbl {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
for i := range n.leaves {
|
||||||
|
if r := n.leaves[i].GetNode(lbl); r != nil {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) ArcList() []string {
|
||||||
|
var ret []string
|
||||||
|
for i := range n.leaves {
|
||||||
|
ret = append(ret, n.leaves[i].label+" -> "+n.label)
|
||||||
|
ret = append(ret, n.leaves[i].ArcList()...)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) getPath(to string) []string {
|
||||||
|
ret := []string{n.label}
|
||||||
|
if n.label == to {
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
var i int
|
||||||
|
var found bool
|
||||||
|
for i = range n.leaves {
|
||||||
|
if n.leaves[i].GetNode(to) != nil {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
// We didn't find a path... :(
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
// n.leaves[i] should be the right leaf now
|
||||||
|
return append(ret, n.leaves[i].getPath(to)...)
|
||||||
|
}
|
20
go/pov/pov_helper.go
Normal file
20
go/pov/pov_helper.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package pov
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PrintGraph(g *Graph) {
|
||||||
|
for i := range g.leaves {
|
||||||
|
PrintNode(&g.leaves[i], 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrintNode(n *Node, lvl int) {
|
||||||
|
strings.Repeat(" ", lvl)
|
||||||
|
fmt.Println(n.label)
|
||||||
|
for i := range n.leaves {
|
||||||
|
PrintNode(&n.leaves[i], lvl+1)
|
||||||
|
}
|
||||||
|
}
|
15
perl6/hello-world/HelloWorld.pm6
Normal file
15
perl6/hello-world/HelloWorld.pm6
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#`(
|
||||||
|
This is a 'stub' file. It's a little start on your solution.
|
||||||
|
It is not a complete solution though; you will have to write some code.
|
||||||
|
|
||||||
|
The ':ver<>' adverb defines the version of a module or class.
|
||||||
|
The version is checked in the test suite to ensure the exercise
|
||||||
|
and test suite line up. If the test is updated, it will indicate
|
||||||
|
to others who test your code that some tests may no longer pass.
|
||||||
|
)
|
||||||
|
unit module HelloWorld:ver<2>;
|
||||||
|
|
||||||
|
sub hello is export {
|
||||||
|
# Write your solution to pass the test suite here.
|
||||||
|
# Be sure to remove all stock comments once you are done!
|
||||||
|
}
|
36
perl6/hello-world/README.md
Normal file
36
perl6/hello-world/README.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
Remember to check out the Perl 6 [documentation](https://docs.perl6.org/) and
|
||||||
|
[resources](https://perl6.org/resources/) pages for information, tips, and
|
||||||
|
examples if you get stuck.
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
There is a test script included with the exercise; a file with the extension
|
||||||
|
`.t`. You can run the test script for the exercise by executing the command
|
||||||
|
`prove . --exec=perl6` in the exercise directory. You can also add the `-v` flag
|
||||||
|
e.g. `prove . --exec=perl6 -v` to display all tests, including any optional
|
||||||
|
tests marked as 'TODO'.
|
||||||
|
|
||||||
|
## 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.
|
60
perl6/hello-world/hello-world.t
Normal file
60
perl6/hello-world/hello-world.t
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#!/usr/bin/env perl6
|
||||||
|
use v6;
|
||||||
|
use Test;
|
||||||
|
use lib my $dir = $?FILE.IO.dirname; #`[Look for the module inside the same directory as this test file.]
|
||||||
|
use JSON::Fast;
|
||||||
|
|
||||||
|
my $exercise = 'HelloWorld'; #`[The name of this exercise.]
|
||||||
|
my $version = v2; #`[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 :)]
|
||||||
|
plan 3; #`[This is how many tests we expect to run.]
|
||||||
|
|
||||||
|
#`[Check that the module can be use-d.]
|
||||||
|
use-ok $module or bail-out;
|
||||||
|
require ::($module);
|
||||||
|
|
||||||
|
#`[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!]
|
||||||
|
if ::($exercise).^ver !~~ $version {
|
||||||
|
warn "\nExercise version mismatch. Further tests may fail!"
|
||||||
|
~ "\n$exercise is $(::($exercise).^ver.gist). "
|
||||||
|
~ "Test is $($version.gist).\n";
|
||||||
|
bail-out 'Example version must match test version.' if %*ENV<EXERCISM>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#`[Import '&hello' from 'HelloWorld']
|
||||||
|
require ::($module) <&hello>;
|
||||||
|
|
||||||
|
my $c-data;
|
||||||
|
#`[Go through the cases (hiding at the bottom of this file)
|
||||||
|
and check that &hello gives us the correct response.]
|
||||||
|
is &::('hello')(), |.<expected description> for @($c-data<cases>);
|
||||||
|
|
||||||
|
#`[Ignore this for your exercise! Tells Exercism folks when exercise cases become out of date.]
|
||||||
|
if %*ENV<EXERCISM> {
|
||||||
|
if (my $c-data-file = "$dir/../../problem-specifications/exercises/{$dir.IO.resolve.basename}/canonical-data.json".IO.resolve) ~~ :f {
|
||||||
|
is-deeply $c-data, EVAL('use JSON::Fast; from-json($c-data-file.slurp);'), 'canonical-data';
|
||||||
|
} else { flunk 'canonical-data' }
|
||||||
|
} else { skip }
|
||||||
|
|
||||||
|
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 := from-json q:to/END/;
|
||||||
|
|
||||||
|
{
|
||||||
|
"exercise": "hello-world",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"cases": [
|
||||||
|
{
|
||||||
|
"description": "Say Hi!",
|
||||||
|
"property": "hello",
|
||||||
|
"expected": "Hello, World!"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
END
|
||||||
|
}
|
BIN
python/example/__pycache__/example.cpython-36.pyc
Normal file
BIN
python/example/__pycache__/example.cpython-36.pyc
Normal file
Binary file not shown.
BIN
python/example/__pycache__/example_test.cpython-36-PYTEST.pyc
Normal file
BIN
python/example/__pycache__/example_test.cpython-36-PYTEST.pyc
Normal file
Binary file not shown.
1
python/hello-world/.cache/v/cache/lastfailed
vendored
Normal file
1
python/hello-world/.cache/v/cache/lastfailed
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
BIN
python/hello-world/__pycache__/hello_world.cpython-36-PYTEST.pyc
Normal file
BIN
python/hello-world/__pycache__/hello_world.cpython-36-PYTEST.pyc
Normal file
Binary file not shown.
BIN
python/hello-world/__pycache__/hello_world.cpython-36.pyc
Normal file
BIN
python/hello-world/__pycache__/hello_world.cpython-36.pyc
Normal file
Binary file not shown.
Binary file not shown.
@ -3,5 +3,5 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
def hello(name=''):
|
def hello(name='World'):
|
||||||
return
|
return 'Hello, '+name+'!'
|
||||||
|
1
python/leap/.cache/v/cache/lastfailed
vendored
Normal file
1
python/leap/.cache/v/cache/lastfailed
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
44
python/leap/README.md
Normal file
44
python/leap/README.md
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# Leap
|
||||||
|
|
||||||
|
Given a year, report if it is a leap year.
|
||||||
|
|
||||||
|
The tricky thing here is that a leap year in the Gregorian calendar occurs:
|
||||||
|
|
||||||
|
```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
|
||||||
|
|
||||||
|
Though our exercise adopts some very simple rules, there is more to
|
||||||
|
learn!
|
||||||
|
|
||||||
|
For a delightful, four minute explanation of the whole leap year
|
||||||
|
phenomenon, go watch [this youtube video][video].
|
||||||
|
|
||||||
|
[video]: http://www.youtube.com/watch?v=xX96xng7sAE
|
||||||
|
|
||||||
|
### 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
|
||||||
|
|
||||||
|
JavaRanch Cattle Drive, exercise 3 [http://www.javaranch.com/leap.jsp](http://www.javaranch.com/leap.jsp)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
BIN
python/leap/__pycache__/leap.cpython-36.pyc
Normal file
BIN
python/leap/__pycache__/leap.cpython-36.pyc
Normal file
Binary file not shown.
BIN
python/leap/__pycache__/leap_test.cpython-36-PYTEST.pyc
Normal file
BIN
python/leap/__pycache__/leap_test.cpython-36-PYTEST.pyc
Normal file
Binary file not shown.
2
python/leap/leap.py
Normal file
2
python/leap/leap.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
def is_leap_year(yr):
|
||||||
|
return yr % 4 == 0 and (yr % 100 != 0 or yr % 400 == 0)
|
23
python/leap/leap_test.py
Normal file
23
python/leap/leap_test.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from leap import is_leap_year
|
||||||
|
|
||||||
|
|
||||||
|
# test cases adapted from `x-common//canonical-data.json` @ version: 1.0.0
|
||||||
|
|
||||||
|
class YearTest(unittest.TestCase):
|
||||||
|
def test_year_not_divisible_by_4(self):
|
||||||
|
self.assertFalse(is_leap_year(2015))
|
||||||
|
|
||||||
|
def test_year_divisible_by_4_not_divisible_by_100(self):
|
||||||
|
self.assertTrue(is_leap_year(2016))
|
||||||
|
|
||||||
|
def test_year_divisible_by_100_not_divisible_by_400(self):
|
||||||
|
self.assertFalse(is_leap_year(2100))
|
||||||
|
|
||||||
|
def test_year_divisible_by_400(self):
|
||||||
|
self.assertTrue(is_leap_year(2000))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
@ -1,6 +1,6 @@
|
|||||||
def is_pangram(inp):
|
def is_pangram(inp):
|
||||||
inp = inp.lower()
|
inp = inp.lower()
|
||||||
for i in "abcdefghijkklmnopqrstuvwxyz":
|
for i in "abcdefghijklmnopqrstuvwxyz":
|
||||||
if inp.count(i) == 0:
|
if inp.count(i) == 0:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
31
r/hello-world/README.md
Normal file
31
r/hello-world/README.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
See [this guide](https://github.com/exercism/xr/blob/master/docs/INSTALLATION.md) for instructions on how to setup your local R environment.
|
||||||
|
|
||||||
|
## How to implement your solution
|
||||||
|
In each problem folder, there is a file named `<exercise_name>.R` containing a function that returns a `NULL` value. Place your implementation inside the body of the function.
|
||||||
|
|
||||||
|
## How to run tests
|
||||||
|
Inside of RStudio, simply execute the `test_<exercise_name>.R` script. This can be conveniently done with [testthat's `auto_test` function](https://www.rdocumentation.org/packages/testthat/topics/auto_test). Because exercism code and tests are in the same folder, use this same path for both `code_path` and `test_path` parameters. On the command-line, you can also run `Rscript test_<exercise_name>.R`.
|
||||||
|
|
||||||
|
## 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.
|
3
r/hello-world/hello-world.R
Normal file
3
r/hello-world/hello-world.R
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
hello_world <- function() {
|
||||||
|
|
||||||
|
}
|
16
r/hello-world/test_hello-world.R
Normal file
16
r/hello-world/test_hello-world.R
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
source("./hello-world.R")
|
||||||
|
library(testthat)
|
||||||
|
|
||||||
|
test_that("no name", {
|
||||||
|
expect_equal(hello_world(), "Hello, World!")
|
||||||
|
})
|
||||||
|
|
||||||
|
test_that("sample name", {
|
||||||
|
expect_equal(hello_world("Alice"), "Hello, Alice!")
|
||||||
|
})
|
||||||
|
|
||||||
|
test_that("other sample name", {
|
||||||
|
expect_equal(hello_world("Bob"), "Hello, Bob!")
|
||||||
|
})
|
||||||
|
|
||||||
|
message("All tests passed for exercise: hello-world")
|
47
typescript/hello-world/README.md
Normal file
47
typescript/hello-world/README.md
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Go through the setup instructions for TypeScript to
|
||||||
|
install the necessary dependencies:
|
||||||
|
|
||||||
|
http://exercism.io/languages/typescript
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
Install assignment dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ yarn install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Making the test suite pass
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ yarn test
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 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.
|
17
typescript/hello-world/hello-world.test.ts
Normal file
17
typescript/hello-world/hello-world.test.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
import HelloWorld from "./hello-world"
|
||||||
|
|
||||||
|
describe('Hello World', () => {
|
||||||
|
|
||||||
|
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!')
|
||||||
|
})
|
||||||
|
})
|
36
typescript/hello-world/package.json
Normal file
36
typescript/hello-world/package.json
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "xtypescript",
|
||||||
|
"version": "0",
|
||||||
|
"description": "Exercism exercises in Typescript.",
|
||||||
|
"author": "",
|
||||||
|
"private": true,
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/exercism/xtypescript"
|
||||||
|
},
|
||||||
|
"devDependencies": {},
|
||||||
|
"scripts": {
|
||||||
|
"test": "tsc --noEmit -p . && jest --no-cache",
|
||||||
|
"lint": "tsc --noEmit -p . && tslint \"*.ts?(x)\"",
|
||||||
|
"lintci": "tslint \"*.ts?(x)\" --force"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/jest": "^20.0.0",
|
||||||
|
"@types/node": "^7.0.5",
|
||||||
|
"jest": "^20.0.4",
|
||||||
|
"ts-jest": "^20.0.6",
|
||||||
|
"tslint": "^5.4.3",
|
||||||
|
"typescript": "^2.2.1"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"transform": {
|
||||||
|
".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
|
||||||
|
},
|
||||||
|
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
|
||||||
|
"moduleFileExtensions": [
|
||||||
|
"ts",
|
||||||
|
"tsx",
|
||||||
|
"js"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
22
typescript/hello-world/tsconfig.json
Normal file
22
typescript/hello-world/tsconfig.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2017",
|
||||||
|
"module": "commonjs",
|
||||||
|
"alwaysStrict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"preserveConstEnums": true,
|
||||||
|
"noFallthroughCasesInSwitch":true,
|
||||||
|
"noImplicitThis":true,
|
||||||
|
"noImplicitReturns":true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"noEmitOnError": true,
|
||||||
|
"outDir": "./build"
|
||||||
|
},
|
||||||
|
"compileOnSave": true,
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
127
typescript/hello-world/tslint.json
Normal file
127
typescript/hello-world/tslint.json
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
{
|
||||||
|
"jsRules": {
|
||||||
|
"class-name": true,
|
||||||
|
"comment-format": [
|
||||||
|
true,
|
||||||
|
"check-space"
|
||||||
|
],
|
||||||
|
"indent": [
|
||||||
|
true,
|
||||||
|
"spaces"
|
||||||
|
],
|
||||||
|
"no-duplicate-variable": true,
|
||||||
|
"no-eval": true,
|
||||||
|
"no-trailing-whitespace": true,
|
||||||
|
"no-unsafe-finally": true,
|
||||||
|
"one-line": [
|
||||||
|
true,
|
||||||
|
"check-open-brace",
|
||||||
|
"check-whitespace"
|
||||||
|
],
|
||||||
|
"quotemark": [
|
||||||
|
false,
|
||||||
|
"double"
|
||||||
|
],
|
||||||
|
"semicolon": [
|
||||||
|
true,
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"triple-equals": [
|
||||||
|
true,
|
||||||
|
"allow-null-check"
|
||||||
|
],
|
||||||
|
"variable-name": [
|
||||||
|
true,
|
||||||
|
"ban-keywords"
|
||||||
|
],
|
||||||
|
"whitespace": [
|
||||||
|
true,
|
||||||
|
"check-branch",
|
||||||
|
"check-decl",
|
||||||
|
"check-operator",
|
||||||
|
"check-separator",
|
||||||
|
"check-type"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"class-name": true,
|
||||||
|
"comment-format": [
|
||||||
|
true,
|
||||||
|
"check-space"
|
||||||
|
],
|
||||||
|
"indent": [
|
||||||
|
true,
|
||||||
|
"spaces"
|
||||||
|
],
|
||||||
|
"no-eval": true,
|
||||||
|
"no-internal-module": true,
|
||||||
|
"no-trailing-whitespace": true,
|
||||||
|
"no-unsafe-finally": true,
|
||||||
|
"no-var-keyword": true,
|
||||||
|
"one-line": [
|
||||||
|
true,
|
||||||
|
"check-open-brace",
|
||||||
|
"check-whitespace"
|
||||||
|
],
|
||||||
|
"semicolon": [
|
||||||
|
true,
|
||||||
|
"never"
|
||||||
|
],
|
||||||
|
"triple-equals": [
|
||||||
|
true,
|
||||||
|
"allow-null-check"
|
||||||
|
],
|
||||||
|
"typedef-whitespace": [
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
"call-signature": "nospace",
|
||||||
|
"index-signature": "nospace",
|
||||||
|
"parameter": "nospace",
|
||||||
|
"property-declaration": "nospace",
|
||||||
|
"variable-declaration": "nospace"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"variable-name": [
|
||||||
|
true,
|
||||||
|
"ban-keywords"
|
||||||
|
],
|
||||||
|
"whitespace": [
|
||||||
|
true,
|
||||||
|
"check-branch",
|
||||||
|
"check-decl",
|
||||||
|
"check-operator",
|
||||||
|
"check-separator",
|
||||||
|
"check-type"
|
||||||
|
],
|
||||||
|
"no-namespace": true,
|
||||||
|
"prefer-for-of": true,
|
||||||
|
"only-arrow-functions": [true, "allow-declarations"],
|
||||||
|
"no-var-requires": true,
|
||||||
|
"no-any": true,
|
||||||
|
"curly": true,
|
||||||
|
"forin": true,
|
||||||
|
"no-arg": true,
|
||||||
|
"label-position": true,
|
||||||
|
"no-conditional-assignment": true,
|
||||||
|
"no-console": [true, "log", "error"],
|
||||||
|
"no-construct": true,
|
||||||
|
"no-duplicate-variable": true,
|
||||||
|
"no-empty": true,
|
||||||
|
"no-invalid-this": [true, "check-function-in-method"],
|
||||||
|
"no-misused-new": true,
|
||||||
|
"no-null-keyword": true,
|
||||||
|
"no-string-literal": true,
|
||||||
|
"radix": true,
|
||||||
|
"typeof-compare": true,
|
||||||
|
"use-isnan": true,
|
||||||
|
"prefer-const": true,
|
||||||
|
"array-type": [true, "array-simple"],
|
||||||
|
"arrow-parens": true,
|
||||||
|
"new-parens": true,
|
||||||
|
"no-consecutive-blank-lines": [true,1],
|
||||||
|
"no-parameter-properties": true,
|
||||||
|
"no-unnecessary-initializer": true,
|
||||||
|
"object-literal-shorthand": true,
|
||||||
|
"object-literal-key-quotes": [true, "as-needed"]
|
||||||
|
}
|
||||||
|
}
|
2305
typescript/hello-world/yarn.lock
Normal file
2305
typescript/hello-world/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
30
vimscript/hello-world/README.md
Normal file
30
vimscript/hello-world/README.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
# How to run the tests
|
||||||
|
|
||||||
|
If you don't know how to run Vader tests, see:
|
||||||
|
[Tests](http://exercism.io/languages/vimscript/tests).
|
||||||
|
|
||||||
|
For general information about the Vim script track, see:
|
||||||
|
[Help](http://exercism.io/languages/vimscript).
|
||||||
|
|
||||||
|
## 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.
|
8
vimscript/hello-world/hello_world.vader
Normal file
8
vimscript/hello-world/hello_world.vader
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
Execute (says hello using default argument):
|
||||||
|
AssertEqual "Hello, World!", Hello()
|
||||||
|
|
||||||
|
Execute (says hello using name "Bram"):
|
||||||
|
AssertEqual "Hello, Bram!", Hello('Bram')
|
||||||
|
|
||||||
|
Execute (says hello using name "Bill Joy"):
|
||||||
|
AssertEqual "Hello, Bill Joy!", Hello('Bill Joy')
|
20
vimscript/hello-world/hello_world.vim
Normal file
20
vimscript/hello-world/hello_world.vim
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
"
|
||||||
|
" Greet someone or something!
|
||||||
|
"
|
||||||
|
" If no argument is given, return 'Hello, World!'.
|
||||||
|
" If the optional argument is given, greet that name instead.
|
||||||
|
"
|
||||||
|
" Hint: If you're confused by the first line in the function,
|
||||||
|
" read `:help a:0`.
|
||||||
|
"
|
||||||
|
" It also uses the short if-then-else syntax which is
|
||||||
|
" called ternary operator in other languages:
|
||||||
|
"
|
||||||
|
" condition ? true : false
|
||||||
|
"
|
||||||
|
function! Hello(...) abort
|
||||||
|
let name = (a:0 == 1 ? a:1 : 'World')
|
||||||
|
|
||||||
|
" your implementation goes here
|
||||||
|
|
||||||
|
endfunction
|
Loading…
x
Reference in New Issue
Block a user