init
This commit is contained in:
commit
105e38b22f
|
@ -0,0 +1,17 @@
|
||||||
|
.DS_Store
|
||||||
|
/.tags
|
||||||
|
/.tags_sorted_by_file
|
||||||
|
/.vagrant
|
||||||
|
.crystal/
|
||||||
|
coverage/
|
||||||
|
/deps/
|
||||||
|
/.build/
|
||||||
|
.*.swp
|
||||||
|
/Makefile.local
|
||||||
|
all_spec
|
||||||
|
/tmp
|
||||||
|
/docs/
|
||||||
|
/src/llvm/ext/llvm_ext.o
|
||||||
|
/src/llvm/ext/llvm_ext.dwo
|
||||||
|
/src/ext/*.o
|
||||||
|
/src/ext/libcrystal.a
|
|
@ -0,0 +1,78 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
* `src` contains your solution to the exercise
|
||||||
|
* `spec` contains the tests to run for the exercise
|
||||||
|
|
||||||
|
## Running Tests
|
||||||
|
|
||||||
|
If you're in the right directory (i.e. the one containing `src` and `spec`), you can run the tests for that exercise by running `crystal spec`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ pwd
|
||||||
|
/Users/johndoe/Code/exercism/crystal/hello-world
|
||||||
|
|
||||||
|
$ ls
|
||||||
|
GETTING_STARTED.md README.md spec src
|
||||||
|
|
||||||
|
$ crystal spec
|
||||||
|
```
|
||||||
|
|
||||||
|
This will run all of the test files in the `spec` directory.
|
||||||
|
|
||||||
|
In each test file, all but the first test have been skipped.
|
||||||
|
|
||||||
|
Once you get a test passing, you can unskip the next one by changing `pending` to `it`.
|
||||||
|
|
||||||
|
## Submitting Your Solution
|
||||||
|
|
||||||
|
Be sure to submit the source file in the `src` directory when submitting your solution:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ exercism submit src/hello_world.cr
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Follow the setup instructions for Crystal here:
|
||||||
|
|
||||||
|
http://exercism.io/languages/crystal
|
||||||
|
|
||||||
|
More help installing can be found here:
|
||||||
|
|
||||||
|
http://crystal-lang.org/docs/installation/index.html
|
||||||
|
|
||||||
|
## Making the Test Suit Pass
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ crystal spec
|
||||||
|
```
|
||||||
|
|
||||||
|
In each test suite all but the first test have been skipped.
|
||||||
|
|
||||||
|
Once you get a test passing, you can unskip the next one by changing `pending` to `it`.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,8 @@
|
||||||
|
require "spec"
|
||||||
|
require "../src/*"
|
||||||
|
|
||||||
|
describe "HelloWorld" do
|
||||||
|
it "Say Hi!" do
|
||||||
|
HelloWorld.hello.should eq("Hello, World!")
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
# Please implement your solution to hello-world in this file
|
||||||
|
puts "Hello, World!"
|
|
@ -0,0 +1,33 @@
|
||||||
|
*.swp
|
||||||
|
*.*~
|
||||||
|
project.lock.json
|
||||||
|
.DS_Store
|
||||||
|
*.pyc
|
||||||
|
nupkg/
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
build/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
msbuild.log
|
||||||
|
msbuild.err
|
||||||
|
msbuild.wrn
|
||||||
|
|
||||||
|
# Visual Studio 2015
|
||||||
|
.vs/
|
|
@ -0,0 +1,10 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public static class AccumulateExtensions
|
||||||
|
{
|
||||||
|
public static IEnumerable<U> Accumulate<T, U>(this IEnumerable<T> collection, Func<T, U> func)
|
||||||
|
{
|
||||||
|
foreach (var elem in collection) yield return func(elem);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Example.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,63 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
public class AccumulateTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Empty_accumulation_produces_empty_accumulation()
|
||||||
|
{
|
||||||
|
Assert.Equal(new int[0], new int[0].Accumulate(x => x * x));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Accumulate_squares()
|
||||||
|
{
|
||||||
|
Assert.Equal(new[] { 1, 4, 9 }, new[] { 1, 2, 3 }.Accumulate(x => x * x));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Accumulate_upcases()
|
||||||
|
{
|
||||||
|
Assert.Equal(new List<string> { "HELLO", "WORLD" }, new List<string> { "hello", "world" }.Accumulate(x => x.ToUpper()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Accumulate_reversed_strings()
|
||||||
|
{
|
||||||
|
Assert.Equal("eht kciuq nworb xof cte".Split(' '), "the quick brown fox etc".Split(' ').Accumulate(Reverse));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string Reverse(string value)
|
||||||
|
{
|
||||||
|
var array = value.ToCharArray();
|
||||||
|
Array.Reverse(array);
|
||||||
|
return new string(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Accumulate_within_accumulate()
|
||||||
|
{
|
||||||
|
var actual = new[] { "a", "b", "c" }.Accumulate(c =>
|
||||||
|
string.Join(" ", new[] { "1", "2", "3" }.Accumulate(d => c + d)));
|
||||||
|
Assert.Equal(new[] { "a1 a2 a3", "b1 b2 b3", "c1 c2 c3" }, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Accumulate_is_lazy()
|
||||||
|
{
|
||||||
|
var counter = 0;
|
||||||
|
var accumulation = new[] { 1, 2, 3 }.Accumulate(x => x * counter++);
|
||||||
|
|
||||||
|
Assert.Equal(0, counter);
|
||||||
|
accumulation.ToList();
|
||||||
|
Assert.Equal(3, counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Accumulate_allows_different_return_type()
|
||||||
|
{
|
||||||
|
Assert.Equal(new[] { "1", "2", "3" }, new[] { 1, 2, 3 }.Accumulate(x => x.ToString()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
## Hints
|
||||||
|
This exercise requires you to write an extension method. For more information, see [this page](https://msdn.microsoft.com/en-us//library/bb383977.aspx).
|
||||||
|
|
||||||
|
|
||||||
|
## 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.
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
public static class Bob
|
||||||
|
{
|
||||||
|
public static string Response(string statement)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(statement))
|
||||||
|
return "Fine. Be that way!";
|
||||||
|
if (statement.Any(Char.IsLetter) && statement.Where(Char.IsLetter).All(Char.IsUpper))
|
||||||
|
if (statement.Contains("?"))
|
||||||
|
return "Calm down, I know what I'm doing!";
|
||||||
|
else
|
||||||
|
return "Whoa, chill out!";
|
||||||
|
if (statement.Trim().EndsWith("?"))
|
||||||
|
return "Sure.";
|
||||||
|
|
||||||
|
return "Whatever.";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Example.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,156 @@
|
||||||
|
// This file was auto-generated based on version 1.1.0 of the canonical data.
|
||||||
|
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
public class BobTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Stating_something()
|
||||||
|
{
|
||||||
|
Assert.Equal("Whatever.", Bob.Response("Tom-ay-to, tom-aaaah-to."));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Shouting()
|
||||||
|
{
|
||||||
|
Assert.Equal("Whoa, chill out!", Bob.Response("WATCH OUT!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Shouting_gibberish()
|
||||||
|
{
|
||||||
|
Assert.Equal("Whoa, chill out!", Bob.Response("FCECDFCAAB"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Asking_a_question()
|
||||||
|
{
|
||||||
|
Assert.Equal("Sure.", Bob.Response("Does this cryogenic chamber make me look fat?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Asking_a_numeric_question()
|
||||||
|
{
|
||||||
|
Assert.Equal("Sure.", Bob.Response("You are, what, like 15?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Asking_gibberish()
|
||||||
|
{
|
||||||
|
Assert.Equal("Sure.", Bob.Response("fffbbcbeab?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Talking_forcefully()
|
||||||
|
{
|
||||||
|
Assert.Equal("Whatever.", Bob.Response("Let's go make out behind the gym!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Using_acronyms_in_regular_speech()
|
||||||
|
{
|
||||||
|
Assert.Equal("Whatever.", Bob.Response("It's OK if you don't want to go to the DMV."));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Forceful_question()
|
||||||
|
{
|
||||||
|
Assert.Equal("Calm down, I know what I'm doing!", Bob.Response("WHAT THE HELL WERE YOU THINKING?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Shouting_numbers()
|
||||||
|
{
|
||||||
|
Assert.Equal("Whoa, chill out!", Bob.Response("1, 2, 3 GO!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Only_numbers()
|
||||||
|
{
|
||||||
|
Assert.Equal("Whatever.", Bob.Response("1, 2, 3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Question_with_only_numbers()
|
||||||
|
{
|
||||||
|
Assert.Equal("Sure.", Bob.Response("4?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Shouting_with_special_characters()
|
||||||
|
{
|
||||||
|
Assert.Equal("Whoa, chill out!", Bob.Response("ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Shouting_with_no_exclamation_mark()
|
||||||
|
{
|
||||||
|
Assert.Equal("Whoa, chill out!", Bob.Response("I HATE YOU"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Statement_containing_question_mark()
|
||||||
|
{
|
||||||
|
Assert.Equal("Whatever.", Bob.Response("Ending with ? means a question."));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Non_letters_with_question()
|
||||||
|
{
|
||||||
|
Assert.Equal("Sure.", Bob.Response(":) ?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Prattling_on()
|
||||||
|
{
|
||||||
|
Assert.Equal("Sure.", Bob.Response("Wait! Hang on. Are you going to be OK?"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Silence()
|
||||||
|
{
|
||||||
|
Assert.Equal("Fine. Be that way!", Bob.Response(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Prolonged_silence()
|
||||||
|
{
|
||||||
|
Assert.Equal("Fine. Be that way!", Bob.Response(" "));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Alternate_silence()
|
||||||
|
{
|
||||||
|
Assert.Equal("Fine. Be that way!", Bob.Response("\t\t\t\t\t\t\t\t\t\t"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Multiple_line_question()
|
||||||
|
{
|
||||||
|
Assert.Equal("Whatever.", Bob.Response("\nDoes this cryogenic chamber make me look fat?\nno"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Starting_with_whitespace()
|
||||||
|
{
|
||||||
|
Assert.Equal("Whatever.", Bob.Response(" hmmmmmmm..."));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Ending_with_whitespace()
|
||||||
|
{
|
||||||
|
Assert.Equal("Sure.", Bob.Response("Okay if like my spacebar quite a bit? "));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Other_whitespace()
|
||||||
|
{
|
||||||
|
Assert.Equal("Fine. Be that way!", Bob.Response("\n\r \t"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Non_question_ending_with_whitespace()
|
||||||
|
{
|
||||||
|
Assert.Equal("Whatever.", Bob.Response("This is a statement ending with whitespace "));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Bob
|
||||||
|
|
||||||
|
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
|
||||||
|
|
||||||
|
Bob answers 'Sure.' if you ask him a question.
|
||||||
|
|
||||||
|
He answers 'Whoa, chill out!' if you yell at him.
|
||||||
|
|
||||||
|
He answers 'Calm down, I know what I'm doing!' if you yell a question at him.
|
||||||
|
|
||||||
|
He says 'Fine. Be that way!' if you address him without actually saying
|
||||||
|
anything.
|
||||||
|
|
||||||
|
He answers 'Whatever.' to anything else.
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. [http://pine.fm/LearnToProgram/?Chapter=06](http://pine.fm/LearnToProgram/?Chapter=06)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class School
|
||||||
|
{
|
||||||
|
public void Add(string student, int grade)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("You need to implement this function.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> Roster()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("You need to implement this function.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<string> Grade(int grade)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("You need to implement this function.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Example.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,85 @@
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
public class GradeSchoolTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Adding_a_student_adds_them_to_the_sorted_roster()
|
||||||
|
{
|
||||||
|
var school = new School();
|
||||||
|
school.Add("Aimee", 2);
|
||||||
|
|
||||||
|
var actual = school.Roster();
|
||||||
|
|
||||||
|
var expected = new[] { "Aimee" };
|
||||||
|
Assert.Equal(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact(Skip = "Remove to run test")]
|
||||||
|
public void Adding_more_students_adds_them_to_the_sorted_roster()
|
||||||
|
{
|
||||||
|
var school = new School();
|
||||||
|
school.Add("Blair", 2);
|
||||||
|
school.Add("James", 2);
|
||||||
|
school.Add("Paul", 2);
|
||||||
|
|
||||||
|
var actual = school.Roster();
|
||||||
|
|
||||||
|
var expected = new[] { "Blair", "James", "Paul" };
|
||||||
|
Assert.Equal(expected, actual );
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact(Skip = "Remove to run test")]
|
||||||
|
public void Adding_students_to_different_grades_adds_them_to_the_same_sorted_roster()
|
||||||
|
{
|
||||||
|
var school = new School();
|
||||||
|
school.Add("Chelsea", 3);
|
||||||
|
school.Add("Logan", 7);
|
||||||
|
|
||||||
|
var actual = school.Roster();
|
||||||
|
|
||||||
|
var expected = new[] { "Chelsea", "Logan"};
|
||||||
|
Assert.Equal(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact(Skip = "Remove to run test")]
|
||||||
|
public void Grade_returns_the_students_in_that_grade_in_alphabetical_order()
|
||||||
|
{
|
||||||
|
var school = new School();
|
||||||
|
school.Add("Franklin", 5);
|
||||||
|
school.Add("Bradley", 5);
|
||||||
|
school.Add("Jeff", 1);
|
||||||
|
|
||||||
|
var actual = school.Grade(5);
|
||||||
|
|
||||||
|
var expected = new[] { "Bradley", "Franklin" };
|
||||||
|
Assert.Equal(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact(Skip = "Remove to run test")]
|
||||||
|
public void Grade_returns_an_empty_list_if_there_are_no_students_in_that_grade()
|
||||||
|
{
|
||||||
|
var school = new School();
|
||||||
|
|
||||||
|
var actual = school.Grade(1);
|
||||||
|
|
||||||
|
Assert.Empty(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact(Skip = "Remove to run test")]
|
||||||
|
public void Student_names_with_grades_are_displayed_in_the_same_sorted_roster()
|
||||||
|
{
|
||||||
|
var school = new School();
|
||||||
|
school.Add("Peter", 2);
|
||||||
|
school.Add("Anna", 1);
|
||||||
|
school.Add("Barb", 1);
|
||||||
|
school.Add("Zoe", 2);
|
||||||
|
school.Add("Alex", 2);
|
||||||
|
school.Add("Jim", 3);
|
||||||
|
school.Add("Charlie", 1);
|
||||||
|
|
||||||
|
var actual = school.Roster();
|
||||||
|
|
||||||
|
var expected = new[] { "Anna", "Barb", "Charlie", "Alex", "Peter", "Zoe", "Jim" };
|
||||||
|
Assert.Equal(expected, actual);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
# Grade School
|
||||||
|
|
||||||
|
Given students' names along with the grade that they are in, create a roster
|
||||||
|
for the school.
|
||||||
|
|
||||||
|
In the end, you should be able to:
|
||||||
|
|
||||||
|
- Add a student's name to the roster for a grade
|
||||||
|
- "Add Jim to grade 2."
|
||||||
|
- "OK."
|
||||||
|
- Get a list of all students enrolled in a grade
|
||||||
|
- "Which students are in grade 2?"
|
||||||
|
- "We've only got Jim just now."
|
||||||
|
- Get a sorted list of all students in all grades. Grades should sort
|
||||||
|
as 1, 2, 3, etc., and students within a grade should be sorted
|
||||||
|
alphabetically by name.
|
||||||
|
- "Who all is enrolled in school right now?"
|
||||||
|
- "Grade 1: Anna, Barb, and Charlie. Grade 2: Alex, Peter, and Zoe.
|
||||||
|
Grade 3…"
|
||||||
|
|
||||||
|
Note that all our students only have one name. (It's a small town, what
|
||||||
|
do you want?)
|
||||||
|
|
||||||
|
## For bonus points
|
||||||
|
|
||||||
|
Did you get the tests passing and the code clean? If you want to, these
|
||||||
|
are some additional things you could try:
|
||||||
|
|
||||||
|
- If you're working in a language with mutable data structures and your
|
||||||
|
implementation allows outside code to mutate the school's internal DB
|
||||||
|
directly, see if you can prevent this. Feel free to introduce additional
|
||||||
|
tests.
|
||||||
|
|
||||||
|
Then please share your thoughts in a comment on the submission. Did this
|
||||||
|
experiment make the code better? Worse? Did you learn anything from it?
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
A pairing session with Phil Battos at gSchool [http://gschool.it](http://gschool.it)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,6 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public static class HelloWorld
|
||||||
|
{
|
||||||
|
public static string Hello() => "Hello, World!";
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Example.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,12 @@
|
||||||
|
// This file was auto-generated based on version 1.0.0 of the canonical data.
|
||||||
|
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
public class HelloWorldTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Say_hi_()
|
||||||
|
{
|
||||||
|
Assert.Equal("Hello, World!", HelloWorld.Hello());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
# 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.
|
|
@ -0,0 +1,9 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public static class Leap
|
||||||
|
{
|
||||||
|
public static bool IsLeapYear(int year)
|
||||||
|
{
|
||||||
|
return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Example.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,30 @@
|
||||||
|
// This file was auto-generated based on version 1.2.0 of the canonical data.
|
||||||
|
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
public class LeapTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Year_not_divisible_by_4_is_common_year()
|
||||||
|
{
|
||||||
|
Assert.False(Leap.IsLeapYear(2015));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Year_divisible_by_4_not_divisible_by_100_is_leap_year()
|
||||||
|
{
|
||||||
|
Assert.True(Leap.IsLeapYear(1996));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Year_divisible_by_100_not_divisible_by_400_is_common_year()
|
||||||
|
{
|
||||||
|
Assert.False(Leap.IsLeapYear(2100));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Year_divisible_by_400_is_leap_year()
|
||||||
|
{
|
||||||
|
Assert.True(Leap.IsLeapYear(2000));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
# 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:
|
||||||
|
|
||||||
|
```text
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
## 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.
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
public class NucleotideCount
|
||||||
|
{
|
||||||
|
private string _seq;
|
||||||
|
private char[] keys = new[] {'A', 'C', 'G', 'T'};
|
||||||
|
|
||||||
|
public NucleotideCount(string sequence)
|
||||||
|
{
|
||||||
|
_seq = sequence;
|
||||||
|
if (_seq.Any(c => !keys.Contains(c))) throw new InvalidNucleotideException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int CountOne(char key)
|
||||||
|
=> _seq.Count(c => c == key);
|
||||||
|
|
||||||
|
public IDictionary<char, int> NucleotideCounts
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var c = new Dictionary<char, int>();
|
||||||
|
foreach (var key in keys)
|
||||||
|
c.Add(key, CountOne(key));
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InvalidNucleotideException : Exception { }
|
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Example.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,69 @@
|
||||||
|
// This file was auto-generated based on version 1.2.0 of the canonical data.
|
||||||
|
|
||||||
|
using Xunit;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class NucleotideCountTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Empty_strand()
|
||||||
|
{
|
||||||
|
var sut = new NucleotideCount("");
|
||||||
|
var expected = new Dictionary<char, int>
|
||||||
|
{
|
||||||
|
['A'] = 0,
|
||||||
|
['C'] = 0,
|
||||||
|
['G'] = 0,
|
||||||
|
['T'] = 0
|
||||||
|
};
|
||||||
|
Assert.Equal(expected, sut.NucleotideCounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Can_count_one_nucleotide_in_single_character_input()
|
||||||
|
{
|
||||||
|
var sut = new NucleotideCount("G");
|
||||||
|
var expected = new Dictionary<char, int>
|
||||||
|
{
|
||||||
|
['A'] = 0,
|
||||||
|
['C'] = 0,
|
||||||
|
['G'] = 1,
|
||||||
|
['T'] = 0
|
||||||
|
};
|
||||||
|
Assert.Equal(expected, sut.NucleotideCounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Strand_with_repeated_nucleotide()
|
||||||
|
{
|
||||||
|
var sut = new NucleotideCount("GGGGGGG");
|
||||||
|
var expected = new Dictionary<char, int>
|
||||||
|
{
|
||||||
|
['A'] = 0,
|
||||||
|
['C'] = 0,
|
||||||
|
['G'] = 7,
|
||||||
|
['T'] = 0
|
||||||
|
};
|
||||||
|
Assert.Equal(expected, sut.NucleotideCounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Strand_with_multiple_nucleotides()
|
||||||
|
{
|
||||||
|
var sut = new NucleotideCount("AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC");
|
||||||
|
var expected = new Dictionary<char, int>
|
||||||
|
{
|
||||||
|
['A'] = 20,
|
||||||
|
['C'] = 12,
|
||||||
|
['G'] = 17,
|
||||||
|
['T'] = 21
|
||||||
|
};
|
||||||
|
Assert.Equal(expected, sut.NucleotideCounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Strand_with_invalid_nucleotides()
|
||||||
|
{
|
||||||
|
Assert.Throws<InvalidNucleotideException>(() => new NucleotideCount("AGXXACT"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Nucleotide Count
|
||||||
|
|
||||||
|
Given a single stranded DNA string, compute how many times each nucleotide occurs in the string.
|
||||||
|
|
||||||
|
The genetic language of every living thing on the planet is DNA.
|
||||||
|
DNA is a large molecule that is built from an extremely long sequence of individual elements called nucleotides.
|
||||||
|
4 types exist in DNA and these differ only slightly and can be represented as the following symbols: 'A' for adenine, 'C' for cytosine, 'G' for guanine, and 'T' thymine.
|
||||||
|
|
||||||
|
Here is an analogy:
|
||||||
|
- twigs are to birds nests as
|
||||||
|
- nucleotides are to DNA as
|
||||||
|
- legos are to lego houses as
|
||||||
|
- words are to sentences as...
|
||||||
|
|
||||||
|
## Hints
|
||||||
|
This exercise requires the use of a Dictionary. For more information see
|
||||||
|
[this page.](https://msdn.microsoft.com/en-us/library/s4ys34ea(v=vs.110).aspx)
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
The Calculating DNA Nucleotides_problem at Rosalind [http://rosalind.info/problems/dna/](http://rosalind.info/problems/dna/)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Raindrops
|
||||||
|
|
||||||
|
Convert a number to a string, the contents of which depend on the number's factors.
|
||||||
|
|
||||||
|
- If the number has 3 as a factor, output 'Pling'.
|
||||||
|
- If the number has 5 as a factor, output 'Plang'.
|
||||||
|
- If the number has 7 as a factor, output 'Plong'.
|
||||||
|
- If the number does not have 3, 5, or 7 as a factor,
|
||||||
|
just pass the number's digits straight through.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
- 28's factors are 1, 2, 4, **7**, 14, 28.
|
||||||
|
- In raindrop-speak, this would be a simple "Plong".
|
||||||
|
- 30's factors are 1, 2, **3**, **5**, 6, 10, 15, 30.
|
||||||
|
- In raindrop-speak, this would be a "PlingPlang".
|
||||||
|
- 34 has four factors: 1, 2, 17, and 34.
|
||||||
|
- In raindrop-speak, this would be "34".
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
A variation on a famous interview question intended to weed out potential candidates. [http://jumpstartlab.com](http://jumpstartlab.com)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
public static class Raindrops
|
||||||
|
{
|
||||||
|
public static string Convert(int number)
|
||||||
|
{
|
||||||
|
var s = new StringBuilder();
|
||||||
|
if (number % 3 == 0)
|
||||||
|
s.Append("Pling");
|
||||||
|
if (number % 5 == 0)
|
||||||
|
s.Append("Plang");
|
||||||
|
if (number % 7 == 0)
|
||||||
|
s.Append("Plong");
|
||||||
|
if (new [] {3, 5, 7}.All(n => number % n != 0))
|
||||||
|
s.Append(number);
|
||||||
|
return s.ToString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Example.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,114 @@
|
||||||
|
// This file was auto-generated based on version 1.0.0 of the canonical data.
|
||||||
|
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
public class RaindropsTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_1_is_1()
|
||||||
|
{
|
||||||
|
Assert.Equal("1", Raindrops.Convert(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_3_is_pling()
|
||||||
|
{
|
||||||
|
Assert.Equal("Pling", Raindrops.Convert(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_5_is_plang()
|
||||||
|
{
|
||||||
|
Assert.Equal("Plang", Raindrops.Convert(5));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_7_is_plong()
|
||||||
|
{
|
||||||
|
Assert.Equal("Plong", Raindrops.Convert(7));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_6_is_pling_as_it_has_a_factor_3()
|
||||||
|
{
|
||||||
|
Assert.Equal("Pling", Raindrops.Convert(6));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Number_2_to_the_power_3_does_not_make_a_raindrop_sound_as_3_is_the_exponent_not_the_base()
|
||||||
|
{
|
||||||
|
Assert.Equal("8", Raindrops.Convert(8));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_9_is_pling_as_it_has_a_factor_3()
|
||||||
|
{
|
||||||
|
Assert.Equal("Pling", Raindrops.Convert(9));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_10_is_plang_as_it_has_a_factor_5()
|
||||||
|
{
|
||||||
|
Assert.Equal("Plang", Raindrops.Convert(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_14_is_plong_as_it_has_a_factor_of_7()
|
||||||
|
{
|
||||||
|
Assert.Equal("Plong", Raindrops.Convert(14));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_15_is_plingplang_as_it_has_factors_3_and_5()
|
||||||
|
{
|
||||||
|
Assert.Equal("PlingPlang", Raindrops.Convert(15));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_21_is_plingplong_as_it_has_factors_3_and_7()
|
||||||
|
{
|
||||||
|
Assert.Equal("PlingPlong", Raindrops.Convert(21));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_25_is_plang_as_it_has_a_factor_5()
|
||||||
|
{
|
||||||
|
Assert.Equal("Plang", Raindrops.Convert(25));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_27_is_pling_as_it_has_a_factor_3()
|
||||||
|
{
|
||||||
|
Assert.Equal("Pling", Raindrops.Convert(27));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_35_is_plangplong_as_it_has_factors_5_and_7()
|
||||||
|
{
|
||||||
|
Assert.Equal("PlangPlong", Raindrops.Convert(35));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_49_is_plong_as_it_has_a_factor_7()
|
||||||
|
{
|
||||||
|
Assert.Equal("Plong", Raindrops.Convert(49));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_52_is_52()
|
||||||
|
{
|
||||||
|
Assert.Equal("52", Raindrops.Convert(52));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_105_is_plingplangplong_as_it_has_factors_3_5_and_7()
|
||||||
|
{
|
||||||
|
Assert.Equal("PlingPlangPlong", Raindrops.Convert(105));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void The_sound_for_3125_is_plang_as_it_has_a_factor_5()
|
||||||
|
{
|
||||||
|
Assert.Equal("Plang", Raindrops.Convert(3125));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
# Reverse String
|
||||||
|
|
||||||
|
Reverse a string
|
||||||
|
|
||||||
|
For example:
|
||||||
|
input: "cool"
|
||||||
|
output: "looc"
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Introductory challenge to reverse an input string [https://medium.freecodecamp.org/how-to-reverse-a-string-in-javascript-in-3-different-ways-75e4763c68cb](https://medium.freecodecamp.org/how-to-reverse-a-string-in-javascript-in-3-different-ways-75e4763c68cb)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,7 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
public static class ReverseString
|
||||||
|
{
|
||||||
|
public static string Reverse(string input)=> string.Concat(input.ToCharArray().Reverse());
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Example.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,36 @@
|
||||||
|
// This file was auto-generated based on version 1.0.1 of the canonical data.
|
||||||
|
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
public class ReverseStringTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void An_empty_string()
|
||||||
|
{
|
||||||
|
Assert.Equal("", ReverseString.Reverse(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void A_word()
|
||||||
|
{
|
||||||
|
Assert.Equal("tobor", ReverseString.Reverse("robot"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void A_capitalized_word()
|
||||||
|
{
|
||||||
|
Assert.Equal("nemaR", ReverseString.Reverse("Ramen"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void A_sentence_with_punctuation()
|
||||||
|
{
|
||||||
|
Assert.Equal("!yrgnuh m'I", ReverseString.Reverse("I'm hungry!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void A_palindrome()
|
||||||
|
{
|
||||||
|
Assert.Equal("racecar", ReverseString.Reverse("racecar"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Sum Of Multiples
|
||||||
|
|
||||||
|
Given a number, find the sum of all the unique multiples of particular numbers up to
|
||||||
|
but not including that number.
|
||||||
|
|
||||||
|
If we list all the natural numbers below 20 that are multiples of 3 or 5,
|
||||||
|
we get 3, 5, 6, 9, 10, 12, 15, and 18.
|
||||||
|
|
||||||
|
The sum of these multiples is 78.
|
||||||
|
|
||||||
|
## 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).
|
||||||
|
|
||||||
|
|
||||||
|
## 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.
|
|
@ -0,0 +1,9 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
public static class SumOfMultiples
|
||||||
|
{
|
||||||
|
public static int Sum(IEnumerable<int> multiples, int max)
|
||||||
|
=> Enumerable.Range(0, max).Where(c => multiples.Any(m => c % m == 0)).Sum();
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Example.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,84 @@
|
||||||
|
// This file was auto-generated based on version 1.1.0 of the canonical data.
|
||||||
|
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
public class SumOfMultiplesTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Multiples_of_3_or_5_up_to_1()
|
||||||
|
{
|
||||||
|
Assert.Equal(0, SumOfMultiples.Sum(new[] { 3, 5 }, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Multiples_of_3_or_5_up_to_4()
|
||||||
|
{
|
||||||
|
Assert.Equal(3, SumOfMultiples.Sum(new[] { 3, 5 }, 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Multiples_of_3_up_to_7()
|
||||||
|
{
|
||||||
|
Assert.Equal(9, SumOfMultiples.Sum(new[] { 3 }, 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Multiples_of_3_or_5_up_to_10()
|
||||||
|
{
|
||||||
|
Assert.Equal(23, SumOfMultiples.Sum(new[] { 3, 5 }, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Multiples_of_3_or_5_up_to_100()
|
||||||
|
{
|
||||||
|
Assert.Equal(2318, SumOfMultiples.Sum(new[] { 3, 5 }, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Multiples_of_3_or_5_up_to_1000()
|
||||||
|
{
|
||||||
|
Assert.Equal(233168, SumOfMultiples.Sum(new[] { 3, 5 }, 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Multiples_of_7_13_or_17_up_to_20()
|
||||||
|
{
|
||||||
|
Assert.Equal(51, SumOfMultiples.Sum(new[] { 7, 13, 17 }, 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Multiples_of_4_or_6_up_to_15()
|
||||||
|
{
|
||||||
|
Assert.Equal(30, SumOfMultiples.Sum(new[] { 4, 6 }, 15));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Multiples_of_5_6_or_8_up_to_150()
|
||||||
|
{
|
||||||
|
Assert.Equal(4419, SumOfMultiples.Sum(new[] { 5, 6, 8 }, 150));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Multiples_of_5_or_25_up_to_51()
|
||||||
|
{
|
||||||
|
Assert.Equal(275, SumOfMultiples.Sum(new[] { 5, 25 }, 51));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Multiples_of_43_or_47_up_to_10000()
|
||||||
|
{
|
||||||
|
Assert.Equal(2203160, SumOfMultiples.Sum(new[] { 43, 47 }, 10000));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Multiples_of_1_up_to_100()
|
||||||
|
{
|
||||||
|
Assert.Equal(4950, SumOfMultiples.Sum(new[] { 1 }, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Multiples_of_an_empty_list_up_to_10000()
|
||||||
|
{
|
||||||
|
Assert.Equal(0, SumOfMultiples.Sum(new int[0], 10000));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Two Fer
|
||||||
|
|
||||||
|
`Two-fer` or `2-fer` is short for two for one. One for you and one for me.
|
||||||
|
|
||||||
|
```text
|
||||||
|
"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."
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
[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.
|
|
@ -0,0 +1,7 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public static class TwoFer
|
||||||
|
{
|
||||||
|
public static string Name(string input = null)
|
||||||
|
=> $"One for {(input ?? "you")}, one for me.";
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Example.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,24 @@
|
||||||
|
// This file was auto-generated based on version 1.1.0 of the canonical data.
|
||||||
|
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
public class TwoFerTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void No_name_given()
|
||||||
|
{
|
||||||
|
Assert.Equal("One for you, one for me.", TwoFer.Name());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void A_name_given()
|
||||||
|
{
|
||||||
|
Assert.Equal("One for Alice, one for me.", TwoFer.Name("Alice"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Another_name_given()
|
||||||
|
{
|
||||||
|
Assert.Equal("One for Bob, one for me.", TwoFer.Name("Bob"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir hello_world_test.exs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pending tests
|
||||||
|
|
||||||
|
In the test suites, all but the first test have been skipped.
|
||||||
|
|
||||||
|
Once you get a test passing, you can unskip the next one by
|
||||||
|
commenting out the relevant `@tag :pending` with a `#` symbol.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# @tag :pending
|
||||||
|
test "shouting" do
|
||||||
|
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, you can enable all the tests by commenting out the
|
||||||
|
`ExUnit.configure` line in the test suite.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# ExUnit.configure exclude: :pending, trace: true
|
||||||
|
```
|
||||||
|
|
||||||
|
For more detailed information about the Elixir track, please
|
||||||
|
see the [help page](http://exercism.io/languages/elixir).
|
||||||
|
|
||||||
|
## 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.
|
|
@ -0,0 +1,9 @@
|
||||||
|
defmodule HelloWorld do
|
||||||
|
@doc """
|
||||||
|
Simply returns "Hello, World!"
|
||||||
|
"""
|
||||||
|
@spec hello :: String.t()
|
||||||
|
def hello do
|
||||||
|
"Hello, World!"
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,14 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("hello_world.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(trace: true)
|
||||||
|
|
||||||
|
defmodule HelloWorldTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
test "says 'Hello, World!'" do
|
||||||
|
assert HelloWorld.hello() == "Hello, World!"
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,54 @@
|
||||||
|
# Nucleotide Count
|
||||||
|
|
||||||
|
Given a single stranded DNA string, compute how many times each nucleotide occurs in the string.
|
||||||
|
|
||||||
|
The genetic language of every living thing on the planet is DNA.
|
||||||
|
DNA is a large molecule that is built from an extremely long sequence of individual elements called nucleotides.
|
||||||
|
4 types exist in DNA and these differ only slightly and can be represented as the following symbols: 'A' for adenine, 'C' for cytosine, 'G' for guanine, and 'T' thymine.
|
||||||
|
|
||||||
|
Here is an analogy:
|
||||||
|
- twigs are to birds nests as
|
||||||
|
- nucleotides are to DNA as
|
||||||
|
- legos are to lego houses as
|
||||||
|
- words are to sentences as...
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir nucleotide_count_test.exs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pending tests
|
||||||
|
|
||||||
|
In the test suites, all but the first test have been skipped.
|
||||||
|
|
||||||
|
Once you get a test passing, you can unskip the next one by
|
||||||
|
commenting out the relevant `@tag :pending` with a `#` symbol.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# @tag :pending
|
||||||
|
test "shouting" do
|
||||||
|
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, you can enable all the tests by commenting out the
|
||||||
|
`ExUnit.configure` line in the test suite.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# ExUnit.configure exclude: :pending, trace: true
|
||||||
|
```
|
||||||
|
|
||||||
|
For more detailed information about the Elixir track, please
|
||||||
|
see the [help page](http://exercism.io/languages/elixir).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
The Calculating DNA Nucleotides_problem at Rosalind [http://rosalind.info/problems/dna/](http://rosalind.info/problems/dna/)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,32 @@
|
||||||
|
defmodule NucleotideCount do
|
||||||
|
@nucleotides [?A, ?C, ?G, ?T]
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Counts individual nucleotides in a NucleotideCount strand.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> NucleotideCount.count('AATAA', ?A)
|
||||||
|
4
|
||||||
|
|
||||||
|
iex> NucleotideCount.count('AATAA', ?T)
|
||||||
|
1
|
||||||
|
"""
|
||||||
|
@spec count([char], char) :: non_neg_integer
|
||||||
|
def count(strand, nucleotide) do
|
||||||
|
Enum.count(strand, &(&1 == nucleotide))
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Returns a summary of counts by nucleotide.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> NucleotideCount.histogram('AATAA')
|
||||||
|
%{?A => 4, ?T => 1, ?C => 0, ?G => 0}
|
||||||
|
"""
|
||||||
|
@spec histogram([char]) :: map
|
||||||
|
def histogram(strand) do
|
||||||
|
Map.new(@nucleotides, &{&1, count(strand, &1)})
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,44 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("nucleotide_count.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(exclude: :pending, trace: true)
|
||||||
|
|
||||||
|
defmodule NucleotideCountTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "empty dna string has no adenine" do
|
||||||
|
assert NucleotideCount.count('', ?A) == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "repetitive cytosine gets counted" do
|
||||||
|
assert NucleotideCount.count('CCCCC', ?C) == 5
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "counts only thymine" do
|
||||||
|
assert NucleotideCount.count('GGGGGTAACCCGG', ?T) == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "empty dna string has no nucleotides" do
|
||||||
|
expected = %{?A => 0, ?T => 0, ?C => 0, ?G => 0}
|
||||||
|
assert NucleotideCount.histogram('') == expected
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "repetitive sequence has only guanine" do
|
||||||
|
expected = %{?A => 0, ?T => 0, ?C => 0, ?G => 8}
|
||||||
|
assert NucleotideCount.histogram('GGGGGGGG') == expected
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "counts all nucleotides" do
|
||||||
|
s = 'AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGC'
|
||||||
|
expected = %{?A => 20, ?T => 21, ?C => 12, ?G => 17}
|
||||||
|
assert NucleotideCount.histogram(s) == expected
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,83 @@
|
||||||
|
# Protein Translation
|
||||||
|
|
||||||
|
Translate RNA sequences into proteins.
|
||||||
|
|
||||||
|
RNA can be broken into three nucleotide sequences called codons, and then translated to a polypeptide like so:
|
||||||
|
|
||||||
|
RNA: `"AUGUUUUCU"` => translates to
|
||||||
|
|
||||||
|
Codons: `"AUG", "UUU", "UCU"`
|
||||||
|
=> which become a polypeptide with the following sequence =>
|
||||||
|
|
||||||
|
Protein: `"Methionine", "Phenylalanine", "Serine"`
|
||||||
|
|
||||||
|
There are 64 codons which in turn correspond to 20 amino acids; however, all of the codon sequences and resulting amino acids are not important in this exercise. If it works for one codon, the program should work for all of them.
|
||||||
|
However, feel free to expand the list in the test suite to include them all.
|
||||||
|
|
||||||
|
There are also three terminating codons (also known as 'STOP' codons); if any of these codons are encountered (by the ribosome), all translation ends and the protein is terminated.
|
||||||
|
|
||||||
|
All subsequent codons after are ignored, like this:
|
||||||
|
|
||||||
|
RNA: `"AUGUUUUCUUAAAUG"` =>
|
||||||
|
|
||||||
|
Codons: `"AUG", "UUU", "UCU", "UAG", "AUG"` =>
|
||||||
|
|
||||||
|
Protein: `"Methionine", "Phenylalanine", "Serine"`
|
||||||
|
|
||||||
|
Note the stop codon terminates the translation and the final methionine is not translated into the protein sequence.
|
||||||
|
|
||||||
|
Below are the codons and resulting Amino Acids needed for the exercise.
|
||||||
|
|
||||||
|
Codon | Protein
|
||||||
|
:--- | :---
|
||||||
|
AUG | Methionine
|
||||||
|
UUU, UUC | Phenylalanine
|
||||||
|
UUA, UUG | Leucine
|
||||||
|
UCU, UCC, UCA, UCG | Serine
|
||||||
|
UAU, UAC | Tyrosine
|
||||||
|
UGU, UGC | Cysteine
|
||||||
|
UGG | Tryptophan
|
||||||
|
UAA, UAG, UGA | STOP
|
||||||
|
|
||||||
|
Learn more about [protein translation on Wikipedia](http://en.wikipedia.org/wiki/Translation_(biology))
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir protein_translation_test.exs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pending tests
|
||||||
|
|
||||||
|
In the test suites, all but the first test have been skipped.
|
||||||
|
|
||||||
|
Once you get a test passing, you can unskip the next one by
|
||||||
|
commenting out the relevant `@tag :pending` with a `#` symbol.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# @tag :pending
|
||||||
|
test "shouting" do
|
||||||
|
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, you can enable all the tests by commenting out the
|
||||||
|
`ExUnit.configure` line in the test suite.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# ExUnit.configure exclude: :pending, trace: true
|
||||||
|
```
|
||||||
|
|
||||||
|
For more detailed information about the Elixir track, please
|
||||||
|
see the [help page](http://exercism.io/languages/elixir).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Tyler Long
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,33 @@
|
||||||
|
defmodule ProteinTranslation do
|
||||||
|
@doc """
|
||||||
|
Given an RNA string, return a list of proteins specified by codons, in order.
|
||||||
|
"""
|
||||||
|
@spec of_rna(String.t()) :: {atom, list(String.t())}
|
||||||
|
def of_rna(rna) do
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Given a codon, return the corresponding protein
|
||||||
|
|
||||||
|
UGU -> Cysteine
|
||||||
|
UGC -> Cysteine
|
||||||
|
UUA -> Leucine
|
||||||
|
UUG -> Leucine
|
||||||
|
AUG -> Methionine
|
||||||
|
UUU -> Phenylalanine
|
||||||
|
UUC -> Phenylalanine
|
||||||
|
UCU -> Serine
|
||||||
|
UCC -> Serine
|
||||||
|
UCA -> Serine
|
||||||
|
UCG -> Serine
|
||||||
|
UGG -> Tryptophan
|
||||||
|
UAU -> Tyrosine
|
||||||
|
UAC -> Tyrosine
|
||||||
|
UAA -> STOP
|
||||||
|
UAG -> STOP
|
||||||
|
UGA -> STOP
|
||||||
|
"""
|
||||||
|
@spec of_codon(String.t()) :: {atom, String.t()}
|
||||||
|
def of_codon(codon) do
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,92 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("protein_translation.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(exclude: :pending, trace: true)
|
||||||
|
|
||||||
|
defmodule ProteinTranslationTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "AUG translates to methionine" do
|
||||||
|
assert ProteinTranslation.of_codon("AUG") == {:ok, "Methionine"}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "identifies Phenylalanine codons" do
|
||||||
|
assert ProteinTranslation.of_codon("UUU") == {:ok, "Phenylalanine"}
|
||||||
|
assert ProteinTranslation.of_codon("UUC") == {:ok, "Phenylalanine"}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "identifies Leucine codons" do
|
||||||
|
assert ProteinTranslation.of_codon("UUA") == {:ok, "Leucine"}
|
||||||
|
assert ProteinTranslation.of_codon("UUG") == {:ok, "Leucine"}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "identifies Serine codons" do
|
||||||
|
assert ProteinTranslation.of_codon("UCU") == {:ok, "Serine"}
|
||||||
|
assert ProteinTranslation.of_codon("UCC") == {:ok, "Serine"}
|
||||||
|
assert ProteinTranslation.of_codon("UCA") == {:ok, "Serine"}
|
||||||
|
assert ProteinTranslation.of_codon("UCG") == {:ok, "Serine"}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "identifies Tyrosine codons" do
|
||||||
|
assert ProteinTranslation.of_codon("UAU") == {:ok, "Tyrosine"}
|
||||||
|
assert ProteinTranslation.of_codon("UAC") == {:ok, "Tyrosine"}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "identifies Cysteine codons" do
|
||||||
|
assert ProteinTranslation.of_codon("UGU") == {:ok, "Cysteine"}
|
||||||
|
assert ProteinTranslation.of_codon("UGC") == {:ok, "Cysteine"}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "identifies Tryptophan codons" do
|
||||||
|
assert ProteinTranslation.of_codon("UGG") == {:ok, "Tryptophan"}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "identifies stop codons" do
|
||||||
|
assert ProteinTranslation.of_codon("UAA") == {:ok, "STOP"}
|
||||||
|
assert ProteinTranslation.of_codon("UAG") == {:ok, "STOP"}
|
||||||
|
assert ProteinTranslation.of_codon("UGA") == {:ok, "STOP"}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "translates rna strand into correct protein" do
|
||||||
|
strand = "AUGUUUUGG"
|
||||||
|
assert ProteinTranslation.of_rna(strand) == {:ok, ~w(Methionine Phenylalanine Tryptophan)}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "stops translation if stop codon present" do
|
||||||
|
strand = "AUGUUUUAA"
|
||||||
|
assert ProteinTranslation.of_rna(strand) == {:ok, ~w(Methionine Phenylalanine)}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "stops translation of longer strand" do
|
||||||
|
strand = "UGGUGUUAUUAAUGGUUU"
|
||||||
|
assert ProteinTranslation.of_rna(strand) == {:ok, ~w(Tryptophan Cysteine Tyrosine)}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "invalid RNA" do
|
||||||
|
assert ProteinTranslation.of_rna("CARROT") == {:error, "invalid RNA"}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "invalid codon at end of RNA" do
|
||||||
|
assert ProteinTranslation.of_rna("UUUROT") == {:error, "invalid RNA"}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "invalid codon" do
|
||||||
|
assert ProteinTranslation.of_codon("INVALID") == {:error, "invalid codon"}
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,72 @@
|
||||||
|
# Rotational Cipher
|
||||||
|
|
||||||
|
Create an implementation of the rotational cipher, also sometimes called the Caesar cipher.
|
||||||
|
|
||||||
|
The Caesar cipher is a simple shift cipher that relies on
|
||||||
|
transposing all the letters in the alphabet using an integer key
|
||||||
|
between `0` and `26`. Using a key of `0` or `26` will always yield
|
||||||
|
the same output due to modular arithmetic. The letter is shifted
|
||||||
|
for as many values as the value of the key.
|
||||||
|
|
||||||
|
The general notation for rotational ciphers is `ROT + <key>`.
|
||||||
|
The most commonly used rotational cipher is `ROT13`.
|
||||||
|
|
||||||
|
A `ROT13` on the Latin alphabet would be as follows:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Plain: abcdefghijklmnopqrstuvwxyz
|
||||||
|
Cipher: nopqrstuvwxyzabcdefghijklm
|
||||||
|
```
|
||||||
|
|
||||||
|
It is stronger than the Atbash cipher because it has 27 possible keys, and 25 usable keys.
|
||||||
|
|
||||||
|
Ciphertext is written out in the same formatting as the input including spaces and punctuation.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
- ROT5 `omg` gives `trl`
|
||||||
|
- ROT0 `c` gives `c`
|
||||||
|
- ROT26 `Cool` gives `Cool`
|
||||||
|
- ROT13 `The quick brown fox jumps over the lazy dog.` gives `Gur dhvpx oebja sbk whzcf bire gur ynml qbt.`
|
||||||
|
- ROT13 `Gur dhvpx oebja sbk whzcf bire gur ynml qbt.` gives `The quick brown fox jumps over the lazy dog.`
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir rotational_cipher_test.exs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pending tests
|
||||||
|
|
||||||
|
In the test suites, all but the first test have been skipped.
|
||||||
|
|
||||||
|
Once you get a test passing, you can unskip the next one by
|
||||||
|
commenting out the relevant `@tag :pending` with a `#` symbol.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# @tag :pending
|
||||||
|
test "shouting" do
|
||||||
|
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, you can enable all the tests by commenting out the
|
||||||
|
`ExUnit.configure` line in the test suite.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# ExUnit.configure exclude: :pending, trace: true
|
||||||
|
```
|
||||||
|
|
||||||
|
For more detailed information about the Elixir track, please
|
||||||
|
see the [help page](http://exercism.io/languages/elixir).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Wikipedia [https://en.wikipedia.org/wiki/Caesar_cipher](https://en.wikipedia.org/wiki/Caesar_cipher)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,19 @@
|
||||||
|
defmodule RotationalCipher do
|
||||||
|
@doc """
|
||||||
|
Given a plaintext and amount to shift by, return a rotated string.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
iex> RotationalCipher.rotate("Attack at dawn", 13)
|
||||||
|
"Nggnpx ng qnja"
|
||||||
|
"""
|
||||||
|
@spec rotate(text :: String.t(), shift :: integer) :: String.t()
|
||||||
|
def rotate(text, shift) do
|
||||||
|
for <<c <- text>>, into: "" do
|
||||||
|
if Regex.match?(~r/[a-zA-Z]/, <<c>>) do
|
||||||
|
<<rem(c + shift, 26) + ?z>>
|
||||||
|
else
|
||||||
|
<<c>>
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,82 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("rotational_cipher.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(exclude: :pending, trace: true)
|
||||||
|
|
||||||
|
defmodule RotationalCipherTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "rotate a by 1" do
|
||||||
|
plaintext = "a"
|
||||||
|
shift = 1
|
||||||
|
assert RotationalCipher.rotate(plaintext, shift) == "b"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "rotate a by 26, same output as input" do
|
||||||
|
plaintext = "a"
|
||||||
|
shift = 26
|
||||||
|
assert RotationalCipher.rotate(plaintext, shift) == "a"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "rotate a by 0, same output as input" do
|
||||||
|
plaintext = "a"
|
||||||
|
shift = 0
|
||||||
|
assert RotationalCipher.rotate(plaintext, shift) == "a"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "rotate m by 13" do
|
||||||
|
plaintext = "m"
|
||||||
|
shift = 13
|
||||||
|
assert RotationalCipher.rotate(plaintext, shift) == "z"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "rotate n by 13 with wrap around alphabet" do
|
||||||
|
plaintext = "n"
|
||||||
|
shift = 13
|
||||||
|
assert RotationalCipher.rotate(plaintext, shift) == "a"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "rotate capital letters" do
|
||||||
|
plaintext = "OMG"
|
||||||
|
shift = 5
|
||||||
|
assert RotationalCipher.rotate(plaintext, shift) == "TRL"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "rotate spaces" do
|
||||||
|
plaintext = "O M G"
|
||||||
|
shift = 5
|
||||||
|
assert RotationalCipher.rotate(plaintext, shift) == "T R L"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "rotate numbers" do
|
||||||
|
plaintext = "Testing 1 2 3 testing"
|
||||||
|
shift = 4
|
||||||
|
assert RotationalCipher.rotate(plaintext, shift) == "Xiwxmrk 1 2 3 xiwxmrk"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "rotate punctuation" do
|
||||||
|
plaintext = "Let's eat, Grandma!"
|
||||||
|
shift = 21
|
||||||
|
assert RotationalCipher.rotate(plaintext, shift) == "Gzo'n zvo, Bmviyhv!"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "rotate all letters" do
|
||||||
|
plaintext = "The quick brown fox jumps over the lazy dog."
|
||||||
|
shift = 13
|
||||||
|
|
||||||
|
assert RotationalCipher.rotate(plaintext, shift) ==
|
||||||
|
"Gur dhvpx oebja sbk whzcf bire gur ynml qbt."
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,92 @@
|
||||||
|
# Secret Handshake
|
||||||
|
|
||||||
|
> There are 10 types of people in the world: Those who understand
|
||||||
|
> binary, and those who don't.
|
||||||
|
|
||||||
|
You and your fellow cohort of those in the "know" when it comes to
|
||||||
|
binary decide to come up with a secret "handshake".
|
||||||
|
|
||||||
|
```text
|
||||||
|
1 = wink
|
||||||
|
10 = double blink
|
||||||
|
100 = close your eyes
|
||||||
|
1000 = jump
|
||||||
|
|
||||||
|
|
||||||
|
10000 = Reverse the order of the operations in the secret handshake.
|
||||||
|
```
|
||||||
|
|
||||||
|
Given a decimal number, convert it to the appropriate sequence of events for a secret handshake.
|
||||||
|
|
||||||
|
Here's a couple of examples:
|
||||||
|
|
||||||
|
Given the input 3, the function would return the array
|
||||||
|
["wink", "double blink"] because 3 is 11 in binary.
|
||||||
|
|
||||||
|
Given the input 19, the function would return the array
|
||||||
|
["double blink", "wink"] because 19 is 10011 in binary.
|
||||||
|
Notice that the addition of 16 (10000 in binary)
|
||||||
|
has caused the array to be reversed.
|
||||||
|
|
||||||
|
use Bitwise (or div/rem)
|
||||||
|
|
||||||
|
If you use Bitwise, an easy way to see if a particular bit is set is to compare
|
||||||
|
the binary AND (`&&&`) of a set of bits with the particular bit pattern you
|
||||||
|
want to check, and determine if the result is the same as the pattern you're
|
||||||
|
checking.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
Flags: 0b11011
|
||||||
|
Check: 0b11010
|
||||||
|
|
||||||
|
Flags &&& Check: 0b11010 (All checked bits are set)
|
||||||
|
|
||||||
|
Another:
|
||||||
|
|
||||||
|
Flags: 0b11011
|
||||||
|
Check: 0b10110
|
||||||
|
|
||||||
|
Flags &&& Check: 0b10010 (Third bit not set)
|
||||||
|
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir secret_handshake_test.exs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pending tests
|
||||||
|
|
||||||
|
In the test suites, all but the first test have been skipped.
|
||||||
|
|
||||||
|
Once you get a test passing, you can unskip the next one by
|
||||||
|
commenting out the relevant `@tag :pending` with a `#` symbol.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# @tag :pending
|
||||||
|
test "shouting" do
|
||||||
|
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, you can enable all the tests by commenting out the
|
||||||
|
`ExUnit.configure` line in the test suite.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# ExUnit.configure exclude: :pending, trace: true
|
||||||
|
```
|
||||||
|
|
||||||
|
For more detailed information about the Elixir track, please
|
||||||
|
see the [help page](http://exercism.io/languages/elixir).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Bert, in Mary Poppins [http://www.imdb.com/title/tt0058331/quotes/qt0437047](http://www.imdb.com/title/tt0058331/quotes/qt0437047)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,27 @@
|
||||||
|
defmodule SecretHandshake do
|
||||||
|
import Bitwise
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Determine the actions of a secret handshake based on the binary
|
||||||
|
representation of the given `code`.
|
||||||
|
|
||||||
|
If the following bits are set, include the corresponding action in your list
|
||||||
|
of commands, in order from lowest to highest.
|
||||||
|
|
||||||
|
1 = wink
|
||||||
|
10 = double blink
|
||||||
|
100 = close your eyes
|
||||||
|
1000 = jump
|
||||||
|
|
||||||
|
10000 = Reverse the order of the operations in the secret handshake
|
||||||
|
"""
|
||||||
|
@spec commands(code :: integer) :: list(String.t())
|
||||||
|
def commands(code) do
|
||||||
|
[]
|
||||||
|
|> (fn acc -> if (code &&& 1) == 1, do: ["wink" | acc], else: acc end).()
|
||||||
|
|> (fn acc -> if (code &&& 2) == 2, do: ["double blink" | acc], else: acc end).()
|
||||||
|
|> (fn acc -> if (code &&& 4) == 4, do: ["close your eyes" | acc], else: acc end).()
|
||||||
|
|> (fn acc -> if (code &&& 8) == 8, do: ["jump" | acc], else: acc end).()
|
||||||
|
|> (fn acc -> if (code &&& 16) == 16, do: acc, else: Enum.reverse(acc) end).()
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,72 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("secret_handshake.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(trace: true, exclude: :pending)
|
||||||
|
|
||||||
|
defmodule SecretHandshakeTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
describe "Create a handshake for a number" do
|
||||||
|
# @tag :pending
|
||||||
|
test "wink for 1" do
|
||||||
|
assert SecretHandshake.commands(1) == ["wink"]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "double blink for 10" do
|
||||||
|
assert SecretHandshake.commands(2) == ["double blink"]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "close your eyes for 100" do
|
||||||
|
assert SecretHandshake.commands(4) == ["close your eyes"]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "jump for 1000" do
|
||||||
|
assert SecretHandshake.commands(8) == ["jump"]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "combine two actions" do
|
||||||
|
assert SecretHandshake.commands(3) == ["wink", "double blink"]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "reverse two actions" do
|
||||||
|
assert SecretHandshake.commands(19) == ["double blink", "wink"]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "reversing one action gives the same action" do
|
||||||
|
assert SecretHandshake.commands(24) == ["jump"]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "reversing no actions still gives no actions" do
|
||||||
|
assert SecretHandshake.commands(16) == []
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "all possible actions" do
|
||||||
|
assert SecretHandshake.commands(15) == ["wink", "double blink", "close your eyes", "jump"]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "reverse all possible actions" do
|
||||||
|
assert SecretHandshake.commands(31) == ["jump", "close your eyes", "double blink", "wink"]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "do nothing for zero" do
|
||||||
|
assert SecretHandshake.commands(0) == []
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "do nothing if lower 5 bits not set" do
|
||||||
|
assert SecretHandshake.commands(32) == []
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Strain
|
||||||
|
|
||||||
|
Implement the `keep` and `discard` operation on collections. Given a collection
|
||||||
|
and a predicate on the collection's elements, `keep` returns a new collection
|
||||||
|
containing those elements where the predicate is true, while `discard` returns
|
||||||
|
a new collection containing those elements where the predicate is false.
|
||||||
|
|
||||||
|
For example, given the collection of numbers:
|
||||||
|
|
||||||
|
- 1, 2, 3, 4, 5
|
||||||
|
|
||||||
|
And the predicate:
|
||||||
|
|
||||||
|
- is the number even?
|
||||||
|
|
||||||
|
Then your keep operation should produce:
|
||||||
|
|
||||||
|
- 2, 4
|
||||||
|
|
||||||
|
While your discard operation should produce:
|
||||||
|
|
||||||
|
- 1, 3, 5
|
||||||
|
|
||||||
|
Note that the union of keep and discard is all the elements.
|
||||||
|
|
||||||
|
The functions may be called `keep` and `discard`, or they may need different
|
||||||
|
names in order to not clash with existing functions or concepts in your
|
||||||
|
language.
|
||||||
|
|
||||||
|
## Restrictions
|
||||||
|
|
||||||
|
Keep your hands off that filter/reject/whatchamacallit functionality
|
||||||
|
provided by your standard library! Solve this one yourself using other
|
||||||
|
basic tools instead.
|
||||||
|
|
||||||
|
`apply` will let you pass arguments to a function, as will `fun.(args)`
|
||||||
|
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir strain_test.exs
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pending tests
|
||||||
|
|
||||||
|
In the test suites, all but the first test have been skipped.
|
||||||
|
|
||||||
|
Once you get a test passing, you can unskip the next one by
|
||||||
|
commenting out the relevant `@tag :pending` with a `#` symbol.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# @tag :pending
|
||||||
|
test "shouting" do
|
||||||
|
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, you can enable all the tests by commenting out the
|
||||||
|
`ExUnit.configure` line in the test suite.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# ExUnit.configure exclude: :pending, trace: true
|
||||||
|
```
|
||||||
|
|
||||||
|
For more detailed information about the Elixir track, please
|
||||||
|
see the [help page](http://exercism.io/languages/elixir).
|
||||||
|
|
||||||
|
## 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.
|
|
@ -0,0 +1,27 @@
|
||||||
|
defmodule Strain do
|
||||||
|
@doc """
|
||||||
|
Given a `list` of items and a function `fun`, return the list of items where
|
||||||
|
`fun` returns true.
|
||||||
|
|
||||||
|
Do not use `Enum.filter`.
|
||||||
|
"""
|
||||||
|
@spec keep(list :: list(any), fun :: (any -> boolean)) :: list(any)
|
||||||
|
def keep(list, fun) do
|
||||||
|
for item <- list, fun.(item), into: [] do
|
||||||
|
item
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Given a `list` of items and a function `fun`, return the list of items where
|
||||||
|
`fun` returns false.
|
||||||
|
|
||||||
|
Do not use `Enum.reject`.
|
||||||
|
"""
|
||||||
|
@spec discard(list :: list(any), fun :: (any -> boolean)) :: list(any)
|
||||||
|
def discard(list, fun) do
|
||||||
|
for item <- list, not fun.(item), into: [] do
|
||||||
|
item
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,101 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("strain.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(trace: true, exclude: :pending)
|
||||||
|
|
||||||
|
defmodule StrainTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
defp is_odd?(n), do: rem(n, 2) == 1
|
||||||
|
defp is_even?(n), do: rem(n, 2) == 0
|
||||||
|
defp noop(_), do: true
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "empty keep" do
|
||||||
|
assert Strain.keep([], &noop/1) == []
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "keep everything" do
|
||||||
|
assert Strain.keep([1, 2, 3], fn e -> e < 10 end) == [1, 2, 3]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "keep first and last" do
|
||||||
|
assert Strain.keep([1, 2, 3], &is_odd?/1) == [1, 3]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "keep neither first nor last" do
|
||||||
|
assert Strain.keep([1, 2, 3, 4, 5], &is_even?/1) == [2, 4]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "keep strings" do
|
||||||
|
words = ~w(apple zebra banana zombies cherimoya zelot)
|
||||||
|
assert Strain.keep(words, &String.starts_with?(&1, "z")) == ~w(zebra zombies zelot)
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "keep arrays" do
|
||||||
|
rows = [
|
||||||
|
[1, 2, 3],
|
||||||
|
[5, 5, 5],
|
||||||
|
[5, 1, 2],
|
||||||
|
[2, 1, 2],
|
||||||
|
[1, 5, 2],
|
||||||
|
[2, 2, 1],
|
||||||
|
[1, 2, 5]
|
||||||
|
]
|
||||||
|
|
||||||
|
assert Strain.keep(rows, fn row -> 5 in row end) == [
|
||||||
|
[5, 5, 5],
|
||||||
|
[5, 1, 2],
|
||||||
|
[1, 5, 2],
|
||||||
|
[1, 2, 5]
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "empty discard" do
|
||||||
|
assert Strain.discard([], &noop/1) == []
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "discard nothing" do
|
||||||
|
assert Strain.discard([1, 2, 3], fn e -> e > 10 end) == [1, 2, 3]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "discard first and last" do
|
||||||
|
assert Strain.discard([1, 2, 3], &is_odd?/1) == [2]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "discard neither first nor last" do
|
||||||
|
assert Strain.discard([1, 2, 3, 4, 5], &is_even?/1) == [1, 3, 5]
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "discard strings" do
|
||||||
|
words = ~w(apple zebra banana zombies cherimoya zelot)
|
||||||
|
assert Strain.discard(words, &String.starts_with?(&1, "z")) == ~w(apple banana cherimoya)
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "discard arrays" do
|
||||||
|
rows = [
|
||||||
|
[1, 2, 3],
|
||||||
|
[5, 5, 5],
|
||||||
|
[5, 1, 2],
|
||||||
|
[2, 1, 2],
|
||||||
|
[1, 5, 2],
|
||||||
|
[2, 2, 1],
|
||||||
|
[1, 2, 5]
|
||||||
|
]
|
||||||
|
|
||||||
|
assert Strain.discard(rows, fn row -> 5 in row end) == [[1, 2, 3], [2, 1, 2], [2, 2, 1]]
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,454 @@
|
||||||
|
# Originally created by https://www.gitignore.io/api/windows,linux,visualstudio,visualstudiocode,osx,xamarinstudio,f#,monodevelop,vim,emacs,node,bower on 2016-03-19
|
||||||
|
# Last updated: 2016-03-20
|
||||||
|
|
||||||
|
### Windows ###
|
||||||
|
# Windows image file caches
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
|
||||||
|
### Linux ###
|
||||||
|
*~
|
||||||
|
|
||||||
|
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||||
|
.fuse_hidden*
|
||||||
|
|
||||||
|
# KDE directory preferences
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Linux trash folder which might appear on any partition or disk
|
||||||
|
.Trash-*
|
||||||
|
|
||||||
|
|
||||||
|
### VisualStudio ###
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Bb]uild/
|
||||||
|
_[Bb]uild/
|
||||||
|
[Dd]eploy/
|
||||||
|
_[Dd]eploy/
|
||||||
|
|
||||||
|
# Visual Studio 2015 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUNIT
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
TestResults.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# DNX
|
||||||
|
project.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_i.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/packages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/packages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/packages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignoreable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
node_modules/
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# JetBrains Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
|
|
||||||
|
|
||||||
|
### VisualStudioCode ###
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### OSX ###
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
|
||||||
|
### XamarinStudio ###
|
||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
|
||||||
|
### F# ###
|
||||||
|
lib/debug
|
||||||
|
lib/release
|
||||||
|
Debug
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
obj
|
||||||
|
bin
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
|
||||||
|
### MonoDevelop ###
|
||||||
|
#User Specific
|
||||||
|
*.userprefs
|
||||||
|
*.usertasks
|
||||||
|
|
||||||
|
#Mono Project Files
|
||||||
|
*.pidb
|
||||||
|
*.resources
|
||||||
|
test-results/
|
||||||
|
|
||||||
|
|
||||||
|
### Vim ###
|
||||||
|
# swap
|
||||||
|
[._]*.s[a-w][a-z]
|
||||||
|
[._]s[a-w][a-z]
|
||||||
|
# session
|
||||||
|
Session.vim
|
||||||
|
# temporary
|
||||||
|
.netrwhist
|
||||||
|
*~
|
||||||
|
# auto-generated tag files
|
||||||
|
tags
|
||||||
|
|
||||||
|
|
||||||
|
### Emacs ###
|
||||||
|
# -*- mode: gitignore; -*-
|
||||||
|
*~
|
||||||
|
\#*\#
|
||||||
|
/.emacs.desktop
|
||||||
|
/.emacs.desktop.lock
|
||||||
|
*.elc
|
||||||
|
auto-save-list
|
||||||
|
tramp
|
||||||
|
.\#*
|
||||||
|
|
||||||
|
# Org-mode
|
||||||
|
.org-id-locations
|
||||||
|
*_archive
|
||||||
|
|
||||||
|
# flymake-mode
|
||||||
|
*_flymake.*
|
||||||
|
|
||||||
|
# eshell files
|
||||||
|
/eshell/history
|
||||||
|
/eshell/lastdir
|
||||||
|
|
||||||
|
# elpa packages
|
||||||
|
/elpa/
|
||||||
|
|
||||||
|
# reftex files
|
||||||
|
*.rel
|
||||||
|
|
||||||
|
# AUCTeX auto folder
|
||||||
|
/auto/
|
||||||
|
|
||||||
|
# cask packages
|
||||||
|
.cask/
|
||||||
|
|
||||||
|
# Flycheck
|
||||||
|
flycheck_*.el
|
||||||
|
|
||||||
|
# server auth directory
|
||||||
|
/server/
|
||||||
|
|
||||||
|
# projectiles files
|
||||||
|
.projectile
|
||||||
|
|
||||||
|
### Node ###
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules
|
||||||
|
jspm_packages
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
|
||||||
|
### Bower ###
|
||||||
|
bower_components
|
||||||
|
.bower-cache
|
||||||
|
.bower-registry
|
||||||
|
.bower-tmp
|
||||||
|
|
||||||
|
|
||||||
|
### WebSharper ###
|
||||||
|
Scripts/
|
|
@ -0,0 +1,3 @@
|
||||||
|
module Bob
|
||||||
|
|
||||||
|
let response (input: string): string = failwith "You need to implement this function."
|
|
@ -0,0 +1,23 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Bob.fs" />
|
||||||
|
<Compile Include="BobTest.fs" />
|
||||||
|
<Compile Include="Program.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
|
<PackageReference Include="FsUnit.xUnit" Version="3.0.0" />
|
||||||
|
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,109 @@
|
||||||
|
// This file was auto-generated based on version 1.2.0 of the canonical data.
|
||||||
|
|
||||||
|
module BobTest
|
||||||
|
|
||||||
|
open FsUnit.Xunit
|
||||||
|
open Xunit
|
||||||
|
|
||||||
|
open Bob
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``Stating something`` () =
|
||||||
|
response "Tom-ay-to, tom-aaaah-to." |> should equal "Whatever."
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Shouting`` () =
|
||||||
|
response "WATCH OUT!" |> should equal "Whoa, chill out!"
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Shouting gibberish`` () =
|
||||||
|
response "FCECDFCAAB" |> should equal "Whoa, chill out!"
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Asking a question`` () =
|
||||||
|
response "Does this cryogenic chamber make me look fat?" |> should equal "Sure."
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Asking a numeric question`` () =
|
||||||
|
response "You are, what, like 15?" |> should equal "Sure."
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Asking gibberish`` () =
|
||||||
|
response "fffbbcbeab?" |> should equal "Sure."
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Talking forcefully`` () =
|
||||||
|
response "Let's go make out behind the gym!" |> should equal "Whatever."
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Using acronyms in regular speech`` () =
|
||||||
|
response "It's OK if you don't want to go to the DMV." |> should equal "Whatever."
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Forceful question`` () =
|
||||||
|
response "WHAT THE HELL WERE YOU THINKING?" |> should equal "Calm down, I know what I'm doing!"
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Shouting numbers`` () =
|
||||||
|
response "1, 2, 3 GO!" |> should equal "Whoa, chill out!"
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Only numbers`` () =
|
||||||
|
response "1, 2, 3" |> should equal "Whatever."
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Question with only numbers`` () =
|
||||||
|
response "4?" |> should equal "Sure."
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Shouting with special characters`` () =
|
||||||
|
response "ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!" |> should equal "Whoa, chill out!"
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Shouting with no exclamation mark`` () =
|
||||||
|
response "I HATE YOU" |> should equal "Whoa, chill out!"
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Statement containing question mark`` () =
|
||||||
|
response "Ending with ? means a question." |> should equal "Whatever."
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Non-letters with question`` () =
|
||||||
|
response ":) ?" |> should equal "Sure."
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Prattling on`` () =
|
||||||
|
response "Wait! Hang on. Are you going to be OK?" |> should equal "Sure."
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Silence`` () =
|
||||||
|
response "" |> should equal "Fine. Be that way!"
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Prolonged silence`` () =
|
||||||
|
response " " |> should equal "Fine. Be that way!"
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Alternate silence`` () =
|
||||||
|
response "\t\t\t\t\t\t\t\t\t\t" |> should equal "Fine. Be that way!"
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Multiple line question`` () =
|
||||||
|
response "\nDoes this cryogenic chamber make me look fat?\nno" |> should equal "Whatever."
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Starting with whitespace`` () =
|
||||||
|
response " hmmmmmmm..." |> should equal "Whatever."
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Ending with whitespace`` () =
|
||||||
|
response "Okay if like my spacebar quite a bit? " |> should equal "Sure."
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Other whitespace`` () =
|
||||||
|
response "\n\r \t" |> should equal "Fine. Be that way!"
|
||||||
|
|
||||||
|
[<Fact(Skip = "Remove to run test")>]
|
||||||
|
let ``Non-question ending with whitespace`` () =
|
||||||
|
response "This is a statement ending with whitespace " |> should equal "Whatever."
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
module Program = let [<EntryPoint>] main _ = 0
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Bob
|
||||||
|
|
||||||
|
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
|
||||||
|
|
||||||
|
Bob answers 'Sure.' if you ask him a question.
|
||||||
|
|
||||||
|
He answers 'Whoa, chill out!' if you yell at him.
|
||||||
|
|
||||||
|
He answers 'Calm down, I know what I'm doing!' if you yell a question at him.
|
||||||
|
|
||||||
|
He says 'Fine. Be that way!' if you address him without actually saying anything.
|
||||||
|
|
||||||
|
He answers 'Whatever.' to anything else.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. [http://pine.fm/LearnToProgram/?Chapter=06](http://pine.fm/LearnToProgram/?Chapter=06)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,3 @@
|
||||||
|
module HelloWorld
|
||||||
|
|
||||||
|
let hello: string = "Hello, World!"
|
|
@ -0,0 +1,23 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="HelloWorld.fs" />
|
||||||
|
<Compile Include="HelloWorldTest.fs" />
|
||||||
|
<Compile Include="Program.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
|
<PackageReference Include="FsUnit.xUnit" Version="3.0.0" />
|
||||||
|
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,13 @@
|
||||||
|
// This file was auto-generated based on version 1.1.0 of the canonical data.
|
||||||
|
|
||||||
|
module HelloWorldTest
|
||||||
|
|
||||||
|
open FsUnit.Xunit
|
||||||
|
open Xunit
|
||||||
|
|
||||||
|
open HelloWorld
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``Say Hi!`` () =
|
||||||
|
hello |> should equal "Hello, World!"
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
module Program = let [<EntryPoint>] main _ = 0
|
|
@ -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.
|
|
@ -0,0 +1,3 @@
|
||||||
|
module Leap
|
||||||
|
|
||||||
|
let leapYear (year: int): bool = year % 400 = 0 || (year % 4 = 0 && year % 100 <> 0)
|
|
@ -0,0 +1,23 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Leap.fs" />
|
||||||
|
<Compile Include="LeapTest.fs" />
|
||||||
|
<Compile Include="Program.fs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.3.1" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||||
|
<PackageReference Include="FsUnit.xUnit" Version="3.0.0" />
|
||||||
|
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,25 @@
|
||||||
|
// This file was auto-generated based on version 1.3.0 of the canonical data.
|
||||||
|
|
||||||
|
module LeapTest
|
||||||
|
|
||||||
|
open FsUnit.Xunit
|
||||||
|
open Xunit
|
||||||
|
|
||||||
|
open Leap
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``Year not divisible by 4: common year`` () =
|
||||||
|
leapYear 2015 |> should equal false
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``Year divisible by 4, not divisible by 100: leap year`` () =
|
||||||
|
leapYear 1996 |> should equal true
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``Year divisible by 100, not divisible by 400: common year`` () =
|
||||||
|
leapYear 2100 |> should equal false
|
||||||
|
|
||||||
|
[<Fact>]
|
||||||
|
let ``Year divisible by 400: leap year`` () =
|
||||||
|
leapYear 2000 |> should equal true
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
module Program = let [<EntryPoint>] main _ = 0
|
|
@ -0,0 +1,33 @@
|
||||||
|
# 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
|
||||||
|
## 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.
|
|
@ -0,0 +1,50 @@
|
||||||
|
*.gem
|
||||||
|
*.rbc
|
||||||
|
/.config
|
||||||
|
/coverage/
|
||||||
|
/InstalledFiles
|
||||||
|
/pkg/
|
||||||
|
/spec/reports/
|
||||||
|
/spec/examples.txt
|
||||||
|
/test/tmp/
|
||||||
|
/test/version_tmp/
|
||||||
|
/tmp/
|
||||||
|
|
||||||
|
# Used by dotenv library to load environment variables.
|
||||||
|
# .env
|
||||||
|
|
||||||
|
## Specific to RubyMotion:
|
||||||
|
.dat*
|
||||||
|
.repl_history
|
||||||
|
build/
|
||||||
|
*.bridgesupport
|
||||||
|
build-iPhoneOS/
|
||||||
|
build-iPhoneSimulator/
|
||||||
|
|
||||||
|
## Specific to RubyMotion (use of CocoaPods):
|
||||||
|
#
|
||||||
|
# We recommend against adding the Pods directory to your .gitignore. However
|
||||||
|
# you should judge for yourself, the pros and cons are mentioned at:
|
||||||
|
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||||
|
#
|
||||||
|
# vendor/Pods/
|
||||||
|
|
||||||
|
## Documentation cache and generated files:
|
||||||
|
/.yardoc/
|
||||||
|
/_yardoc/
|
||||||
|
/doc/
|
||||||
|
/rdoc/
|
||||||
|
|
||||||
|
## Environment normalization:
|
||||||
|
/.bundle/
|
||||||
|
/vendor/bundle
|
||||||
|
/lib/bundler/man/
|
||||||
|
|
||||||
|
# for a library or gem, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# Gemfile.lock
|
||||||
|
# .ruby-version
|
||||||
|
# .ruby-gemset
|
||||||
|
|
||||||
|
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
||||||
|
.rvmrc
|
|
@ -0,0 +1,43 @@
|
||||||
|
# Difference Of Squares
|
||||||
|
|
||||||
|
Find the difference between the square of the sum and the sum of the squares of the first N natural numbers.
|
||||||
|
|
||||||
|
The square of the sum of the first ten natural numbers is
|
||||||
|
(1 + 2 + ... + 10)² = 55² = 3025.
|
||||||
|
|
||||||
|
The sum of the squares of the first ten natural numbers is
|
||||||
|
1² + 2² + ... + 10² = 385.
|
||||||
|
|
||||||
|
Hence the difference between the square of the sum of the first
|
||||||
|
ten natural numbers and the sum of the squares of the first ten
|
||||||
|
natural numbers is 3025 - 385 = 2640.
|
||||||
|
|
||||||
|
* * * *
|
||||||
|
|
||||||
|
For installation and learning resources, refer to the
|
||||||
|
[exercism help page](http://exercism.io/languages/ruby).
|
||||||
|
|
||||||
|
For running the tests provided, you will need the Minitest gem. Open a
|
||||||
|
terminal window and run the following command to install minitest:
|
||||||
|
|
||||||
|
gem install minitest
|
||||||
|
|
||||||
|
If you would like color output, you can `require 'minitest/pride'` in
|
||||||
|
the test file, or note the alternative instruction, below, for running
|
||||||
|
the test file.
|
||||||
|
|
||||||
|
Run the tests from the exercise directory using the following command:
|
||||||
|
|
||||||
|
ruby difference_of_squares_test.rb
|
||||||
|
|
||||||
|
To include color from the command line:
|
||||||
|
|
||||||
|
ruby -r minitest/pride difference_of_squares_test.rb
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Problem 6 at Project Euler [http://projecteuler.net/problem=6](http://projecteuler.net/problem=6)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,23 @@
|
||||||
|
class Squares
|
||||||
|
@num
|
||||||
|
def initialize(num)
|
||||||
|
@num = num
|
||||||
|
end
|
||||||
|
|
||||||
|
def difference
|
||||||
|
square_of_sum - sum_of_squares
|
||||||
|
end
|
||||||
|
|
||||||
|
def sum_of_squares
|
||||||
|
(1..@num).map{|n| n ** 2}.inject(&:+)
|
||||||
|
end
|
||||||
|
|
||||||
|
def square_of_sum
|
||||||
|
(1..@num).inject(&:+) ** 2
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module BookKeeping
|
||||||
|
VERSION = 4
|
||||||
|
end
|
|
@ -0,0 +1,62 @@
|
||||||
|
require 'minitest/autorun'
|
||||||
|
require_relative 'difference_of_squares'
|
||||||
|
|
||||||
|
# Common test data version: 1.1.0 7a1108b
|
||||||
|
class DifferenceOfSquaresTest < Minitest::Test
|
||||||
|
def test_square_of_sum_1
|
||||||
|
assert_equal 1, Squares.new(1).square_of_sum
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_square_of_sum_5
|
||||||
|
assert_equal 225, Squares.new(5).square_of_sum
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_square_of_sum_100
|
||||||
|
assert_equal 25_502_500, Squares.new(100).square_of_sum
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_sum_of_squares_1
|
||||||
|
assert_equal 1, Squares.new(1).sum_of_squares
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_sum_of_squares_5
|
||||||
|
assert_equal 55, Squares.new(5).sum_of_squares
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_sum_of_squares_100
|
||||||
|
assert_equal 338_350, Squares.new(100).sum_of_squares
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_difference_of_squares_1
|
||||||
|
assert_equal 0, Squares.new(1).difference
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_difference_of_squares_5
|
||||||
|
assert_equal 170, Squares.new(5).difference
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_difference_of_squares_100
|
||||||
|
assert_equal 25_164_150, Squares.new(100).difference
|
||||||
|
end
|
||||||
|
|
||||||
|
# Problems in exercism evolve over time, as we find better ways to ask
|
||||||
|
# questions.
|
||||||
|
# The version number refers to the version of the problem you solved,
|
||||||
|
# not your solution.
|
||||||
|
#
|
||||||
|
# Define a constant named VERSION inside of the top level BookKeeping
|
||||||
|
# module, which may be placed near the end of your file.
|
||||||
|
#
|
||||||
|
# In your file, it will look like this:
|
||||||
|
#
|
||||||
|
# module BookKeeping
|
||||||
|
# VERSION = 1 # Where the version number matches the one in the test.
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# If you are curious, read more about constants on RubyDoc:
|
||||||
|
# http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html
|
||||||
|
|
||||||
|
def test_bookkeeping
|
||||||
|
assert_equal 4, BookKeeping::VERSION
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,35 @@
|
||||||
|
# Gigasecond
|
||||||
|
|
||||||
|
Calculate the moment when someone has lived for 10^9 seconds.
|
||||||
|
|
||||||
|
A gigasecond is 10^9 (1,000,000,000) seconds.
|
||||||
|
|
||||||
|
* * * *
|
||||||
|
|
||||||
|
For installation and learning resources, refer to the
|
||||||
|
[exercism help page](http://exercism.io/languages/ruby).
|
||||||
|
|
||||||
|
For running the tests provided, you will need the Minitest gem. Open a
|
||||||
|
terminal window and run the following command to install minitest:
|
||||||
|
|
||||||
|
gem install minitest
|
||||||
|
|
||||||
|
If you would like color output, you can `require 'minitest/pride'` in
|
||||||
|
the test file, or note the alternative instruction, below, for running
|
||||||
|
the test file.
|
||||||
|
|
||||||
|
Run the tests from the exercise directory using the following command:
|
||||||
|
|
||||||
|
ruby gigasecond_test.rb
|
||||||
|
|
||||||
|
To include color from the command line:
|
||||||
|
|
||||||
|
ruby -r minitest/pride gigasecond_test.rb
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Chapter 9 in Chris Pine's online Learn to Program tutorial. [http://pine.fm/LearnToProgram/?Chapter=09](http://pine.fm/LearnToProgram/?Chapter=09)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,9 @@
|
||||||
|
class Gigasecond
|
||||||
|
def self.from(time)
|
||||||
|
time + 1_000_000_000
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module BookKeeping
|
||||||
|
VERSION = 6
|
||||||
|
end
|
|
@ -0,0 +1,47 @@
|
||||||
|
require 'minitest/autorun'
|
||||||
|
require_relative 'gigasecond'
|
||||||
|
|
||||||
|
# Common test data version: 1.0.0 61e7d70
|
||||||
|
class GigasecondTest < Minitest::Test
|
||||||
|
def test_date_only_specification_of_time
|
||||||
|
# skip
|
||||||
|
assert_equal Time.utc(2043, 1, 1, 1, 46, 40), Gigasecond.from(Time.utc(2011, 4, 25, 0, 0, 0))
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_second_test_for_date_only_specification_of_time
|
||||||
|
assert_equal Time.utc(2009, 2, 19, 1, 46, 40), Gigasecond.from(Time.utc(1977, 6, 13, 0, 0, 0))
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_third_test_for_date_only_specification_of_time
|
||||||
|
assert_equal Time.utc(1991, 3, 27, 1, 46, 40), Gigasecond.from(Time.utc(1959, 7, 19, 0, 0, 0))
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_full_time_specified
|
||||||
|
assert_equal Time.utc(2046, 10, 2, 23, 46, 40), Gigasecond.from(Time.utc(2015, 1, 24, 22, 0, 0))
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_full_time_with_day_roll_over
|
||||||
|
assert_equal Time.utc(2046, 10, 3, 1, 46, 39), Gigasecond.from(Time.utc(2015, 1, 24, 23, 59, 59))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Problems in exercism evolve over time, as we find better ways to ask
|
||||||
|
# questions.
|
||||||
|
# The version number refers to the version of the problem you solved,
|
||||||
|
# not your solution.
|
||||||
|
#
|
||||||
|
# Define a constant named VERSION inside of the top level BookKeeping
|
||||||
|
# module, which may be placed near the end of your file.
|
||||||
|
#
|
||||||
|
# In your file, it will look like this:
|
||||||
|
#
|
||||||
|
# module BookKeeping
|
||||||
|
# VERSION = 1 # Where the version number matches the one in the test.
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# If you are curious, read more about constants on RubyDoc:
|
||||||
|
# http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html
|
||||||
|
|
||||||
|
def test_bookkeeping
|
||||||
|
assert_equal 6, BookKeeping::VERSION
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,57 @@
|
||||||
|
# Grains
|
||||||
|
|
||||||
|
Calculate the number of grains of wheat on a chessboard given that the number
|
||||||
|
on each square doubles.
|
||||||
|
|
||||||
|
There once was a wise servant who saved the life of a prince. The king
|
||||||
|
promised to pay whatever the servant could dream up. Knowing that the
|
||||||
|
king loved chess, the servant told the king he would like to have grains
|
||||||
|
of wheat. One grain on the first square of a chess board. Two grains on
|
||||||
|
the next. Four on the third, and so on.
|
||||||
|
|
||||||
|
There are 64 squares on a chessboard.
|
||||||
|
|
||||||
|
Write code that shows:
|
||||||
|
- how many grains were on each square, and
|
||||||
|
- the total number of grains
|
||||||
|
|
||||||
|
## For bonus points
|
||||||
|
|
||||||
|
Did you get the tests passing and the code clean? If you want to, these
|
||||||
|
are some additional things you could try:
|
||||||
|
|
||||||
|
- Optimize for speed.
|
||||||
|
- Optimize for readability.
|
||||||
|
|
||||||
|
Then please share your thoughts in a comment on the submission. Did this
|
||||||
|
experiment make the code better? Worse? Did you learn anything from it?
|
||||||
|
|
||||||
|
* * * *
|
||||||
|
|
||||||
|
For installation and learning resources, refer to the
|
||||||
|
[exercism help page](http://exercism.io/languages/ruby).
|
||||||
|
|
||||||
|
For running the tests provided, you will need the Minitest gem. Open a
|
||||||
|
terminal window and run the following command to install minitest:
|
||||||
|
|
||||||
|
gem install minitest
|
||||||
|
|
||||||
|
If you would like color output, you can `require 'minitest/pride'` in
|
||||||
|
the test file, or note the alternative instruction, below, for running
|
||||||
|
the test file.
|
||||||
|
|
||||||
|
Run the tests from the exercise directory using the following command:
|
||||||
|
|
||||||
|
ruby grains_test.rb
|
||||||
|
|
||||||
|
To include color from the command line:
|
||||||
|
|
||||||
|
ruby -r minitest/pride grains_test.rb
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
JavaRanch Cattle Drive, exercise 6 [http://www.javaranch.com/grains.jsp](http://www.javaranch.com/grains.jsp)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,14 @@
|
||||||
|
class Grains
|
||||||
|
def self.square(n)
|
||||||
|
raise ArgumentError if n < 1 || n > 64
|
||||||
|
2 ** (n - 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.total
|
||||||
|
(0...64).map{|n| 2 ** n}.inject(&:+)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module BookKeeping
|
||||||
|
VERSION = 1
|
||||||
|
end
|
|
@ -0,0 +1,70 @@
|
||||||
|
require 'minitest/autorun'
|
||||||
|
require_relative 'grains'
|
||||||
|
|
||||||
|
# Common test data version: 1.0.0 2e0e77e
|
||||||
|
class GrainsTest < Minitest::Test
|
||||||
|
def test_1
|
||||||
|
assert_equal 1, Grains.square(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_2
|
||||||
|
assert_equal 2, Grains.square(2)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_3
|
||||||
|
assert_equal 4, Grains.square(3)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_4
|
||||||
|
assert_equal 8, Grains.square(4)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_16
|
||||||
|
assert_equal 32_768, Grains.square(16)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_32
|
||||||
|
assert_equal 2_147_483_648, Grains.square(32)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_64
|
||||||
|
assert_equal 9_223_372_036_854_775_808, Grains.square(64)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_square_0_raises_an_exception
|
||||||
|
assert_raises(ArgumentError) { Grains.square(0) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_negative_square_raises_an_exception
|
||||||
|
assert_raises(ArgumentError) { Grains.square(-1) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_square_greater_than_64_raises_an_exception
|
||||||
|
assert_raises(ArgumentError) { Grains.square(65) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_returns_the_total_number_of_grains_on_the_board
|
||||||
|
assert_equal 18_446_744_073_709_551_615, Grains.total
|
||||||
|
end
|
||||||
|
|
||||||
|
# Problems in exercism evolve over time, as we find better ways to ask
|
||||||
|
# questions.
|
||||||
|
# The version number refers to the version of the problem you solved,
|
||||||
|
# not your solution.
|
||||||
|
#
|
||||||
|
# Define a constant named VERSION inside of the top level BookKeeping
|
||||||
|
# module, which may be placed near the end of your file.
|
||||||
|
#
|
||||||
|
# In your file, it will look like this:
|
||||||
|
#
|
||||||
|
# module BookKeeping
|
||||||
|
# VERSION = 1 # Where the version number matches the one in the test.
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# If you are curious, read more about constants on RubyDoc:
|
||||||
|
# http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html
|
||||||
|
|
||||||
|
def test_bookkeeping
|
||||||
|
assert_equal 1, BookKeeping::VERSION
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,66 @@
|
||||||
|
# Hamming
|
||||||
|
|
||||||
|
Calculate the Hamming difference between two DNA strands.
|
||||||
|
|
||||||
|
A mutation is simply a mistake that occurs during the creation or
|
||||||
|
copying of a nucleic acid, in particular DNA. Because nucleic acids are
|
||||||
|
vital to cellular functions, mutations tend to cause a ripple effect
|
||||||
|
throughout the cell. Although mutations are technically mistakes, a very
|
||||||
|
rare mutation may equip the cell with a beneficial attribute. In fact,
|
||||||
|
the macro effects of evolution are attributable by the accumulated
|
||||||
|
result of beneficial microscopic mutations over many generations.
|
||||||
|
|
||||||
|
The simplest and most common type of nucleic acid mutation is a point
|
||||||
|
mutation, which replaces one base with another at a single nucleotide.
|
||||||
|
|
||||||
|
By counting the number of differences between two homologous DNA strands
|
||||||
|
taken from different genomes with a common ancestor, we get a measure of
|
||||||
|
the minimum number of point mutations that could have occurred on the
|
||||||
|
evolutionary path between the two strands.
|
||||||
|
|
||||||
|
This is called the 'Hamming distance'.
|
||||||
|
|
||||||
|
It is found by comparing two DNA strands and counting how many of the
|
||||||
|
nucleotides are different from their equivalent in the other string.
|
||||||
|
|
||||||
|
GAGCCTACTAACGGGAT
|
||||||
|
CATCGTAATGACGGCCT
|
||||||
|
^ ^ ^ ^ ^ ^^
|
||||||
|
|
||||||
|
The Hamming distance between these two DNA strands is 7.
|
||||||
|
|
||||||
|
# Implementation notes
|
||||||
|
|
||||||
|
The Hamming distance is only defined for sequences of equal length. This means
|
||||||
|
that based on the definition, each language could deal with getting sequences
|
||||||
|
of equal length differently.
|
||||||
|
|
||||||
|
* * * *
|
||||||
|
|
||||||
|
For installation and learning resources, refer to the
|
||||||
|
[exercism help page](http://exercism.io/languages/ruby).
|
||||||
|
|
||||||
|
For running the tests provided, you will need the Minitest gem. Open a
|
||||||
|
terminal window and run the following command to install minitest:
|
||||||
|
|
||||||
|
gem install minitest
|
||||||
|
|
||||||
|
If you would like color output, you can `require 'minitest/pride'` in
|
||||||
|
the test file, or note the alternative instruction, below, for running
|
||||||
|
the test file.
|
||||||
|
|
||||||
|
Run the tests from the exercise directory using the following command:
|
||||||
|
|
||||||
|
ruby hamming_test.rb
|
||||||
|
|
||||||
|
To include color from the command line:
|
||||||
|
|
||||||
|
ruby -r minitest/pride hamming_test.rb
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
The Calculating Point Mutations problem at Rosalind [http://rosalind.info/problems/hamm/](http://rosalind.info/problems/hamm/)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,56 @@
|
||||||
|
# Running Tests
|
||||||
|
|
||||||
|
In order to complete this exercise, and all of the subsequent exercises, you
|
||||||
|
will need to pass multiple tests.
|
||||||
|
|
||||||
|
## Understanding Test Results
|
||||||
|
|
||||||
|
After you have created and saved `hamming.rb`, run the test suite. You should
|
||||||
|
see output like the following:
|
||||||
|
|
||||||
|
# Running:
|
||||||
|
|
||||||
|
SSSSSSESSSSSSSSS
|
||||||
|
|
||||||
|
Finished in 0.002593s, 6170.4588 runs/s, 0.0000 assertions/s.
|
||||||
|
|
||||||
|
1) Error:
|
||||||
|
HammingTest#test_identical_strands:
|
||||||
|
NameError: uninitialized constant HammingTest::Hamming
|
||||||
|
Did you mean? HammingTest
|
||||||
|
../hamming/hamming_test.rb:9:in `test_identical_strands'
|
||||||
|
|
||||||
|
16 runs, 0 assertions, 0 failures, 1 errors, 15 skips
|
||||||
|
|
||||||
|
You have skipped tests. Run with --verbose for details.
|
||||||
|
|
||||||
|
|
||||||
|
The letters `SSSSSSESSSSSSSSS` show that there are sixteen tests altogether,
|
||||||
|
that one of them has an error (`E`), and that the rest of them are skipped (all
|
||||||
|
the `S` letters).
|
||||||
|
|
||||||
|
The tests are run in randomized order, which will cause the letters to display
|
||||||
|
in random order as well.
|
||||||
|
|
||||||
|
The goal is to have all passing tests, which will show in two places:
|
||||||
|
|
||||||
|
1. `SSSSSSESSSSSSSSS` will become a series dots: `................`,
|
||||||
|
|
||||||
|
2. The line at the bottom will read `16 runs, 0 assertions, 0 failures, 0
|
||||||
|
errors, 0 skips`.
|
||||||
|
|
||||||
|
## Passing Tests
|
||||||
|
|
||||||
|
Write enough code to change the Error to Failure, and finally to Passing.
|
||||||
|
|
||||||
|
Open `hamming_test.rb`, and find the word "skip". All but the first test start
|
||||||
|
with "skip", which tells Minitest to ignore the test. This is so that you don't
|
||||||
|
have to deal with all the failures at once.
|
||||||
|
|
||||||
|
To activate the next test, delete the "skip", or comment it out, and run the
|
||||||
|
test suite again.
|
||||||
|
|
||||||
|
## Wash, Rinse, Repeat
|
||||||
|
|
||||||
|
Delete one "skip" at a time, and make each test pass before you move to the
|
||||||
|
next one.
|
|
@ -0,0 +1,6 @@
|
||||||
|
class Hamming
|
||||||
|
def self.compute(a, b)
|
||||||
|
raise ArgumentError unless a.length == b.length
|
||||||
|
(0..a.length).count {|i| a[i] != b[i]}
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,88 @@
|
||||||
|
require 'minitest/autorun'
|
||||||
|
require_relative 'hamming'
|
||||||
|
|
||||||
|
# Common test data version: 2.0.1 f79dfd7
|
||||||
|
class HammingTest < Minitest::Test
|
||||||
|
def test_empty_strands
|
||||||
|
# skip
|
||||||
|
assert_equal 0, Hamming.compute('', '')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_identical_strands
|
||||||
|
assert_equal 0, Hamming.compute('A', 'A')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_long_identical_strands
|
||||||
|
assert_equal 0, Hamming.compute('GGACTGA', 'GGACTGA')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_complete_distance_in_single_nucleotide_strands
|
||||||
|
assert_equal 1, Hamming.compute('A', 'G')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_complete_distance_in_small_strands
|
||||||
|
assert_equal 2, Hamming.compute('AG', 'CT')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_small_distance_in_small_strands
|
||||||
|
assert_equal 1, Hamming.compute('AT', 'CT')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_small_distance
|
||||||
|
assert_equal 1, Hamming.compute('GGACG', 'GGTCG')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_small_distance_in_long_strands
|
||||||
|
assert_equal 2, Hamming.compute('ACCAGGG', 'ACTATGG')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_non_unique_character_in_first_strand
|
||||||
|
assert_equal 1, Hamming.compute('AAG', 'AAA')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_non_unique_character_in_second_strand
|
||||||
|
assert_equal 1, Hamming.compute('AAA', 'AAG')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_same_nucleotides_in_different_positions
|
||||||
|
assert_equal 2, Hamming.compute('TAG', 'GAT')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_large_distance
|
||||||
|
assert_equal 4, Hamming.compute('GATACA', 'GCATAA')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_large_distance_in_off_by_one_strand
|
||||||
|
assert_equal 9, Hamming.compute('GGACGGATTCTG', 'AGGACGGATTCT')
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_disallow_first_strand_longer
|
||||||
|
assert_raises(ArgumentError) { Hamming.compute('AATG', 'AAA') }
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_disallow_second_strand_longer
|
||||||
|
assert_raises(ArgumentError) { Hamming.compute('ATA', 'AGTG') }
|
||||||
|
end
|
||||||
|
|
||||||
|
# Problems in exercism evolve over time, as we find better ways to ask
|
||||||
|
# questions.
|
||||||
|
# The version number refers to the version of the problem you solved,
|
||||||
|
# not your solution.
|
||||||
|
#
|
||||||
|
# Define a constant named VERSION inside of the top level BookKeeping
|
||||||
|
# module, which may be placed near the end of your file.
|
||||||
|
#
|
||||||
|
# In your file, it will look like this:
|
||||||
|
#
|
||||||
|
# module BookKeeping
|
||||||
|
# VERSION = 1 # Where the version number matches the one in the test.
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# If you are curious, read more about constants on RubyDoc:
|
||||||
|
# http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html
|
||||||
|
|
||||||
|
def test_bookkeeping
|
||||||
|
skip
|
||||||
|
assert_equal 3, BookKeeping::VERSION
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,128 @@
|
||||||
|
# Getting Started
|
||||||
|
|
||||||
|
These exercises lean on Test-Driven Development (TDD), but they're not an
|
||||||
|
exact match. If you want a gentle introduction to TDD using minitest in
|
||||||
|
Ruby, see the "Intro to TDD" over at JumpstartLab:
|
||||||
|
http://tutorials.jumpstartlab.com/topics/testing/intro-to-tdd.html
|
||||||
|
|
||||||
|
The following steps assume that you are in the same directory as the test
|
||||||
|
suite.
|
||||||
|
|
||||||
|
You must have the `minitest` gem installed:
|
||||||
|
|
||||||
|
$ gem install minitest
|
||||||
|
|
||||||
|
## Step 1
|
||||||
|
|
||||||
|
Run the test suite. It's written using the Minitest framework, and can be
|
||||||
|
run with ruby:
|
||||||
|
|
||||||
|
$ ruby hello_world_test.rb
|
||||||
|
|
||||||
|
This will fail, complaining that there is no file called `hello_world`.
|
||||||
|
|
||||||
|
To fix the error create an empty file called `hello_world.rb` in the same
|
||||||
|
directory as the `hello_world_test.rb` file.
|
||||||
|
|
||||||
|
## Step 2
|
||||||
|
|
||||||
|
Run the test again. It will give you a new error, since now the file exists,
|
||||||
|
but is empty and does not contain the expected code.
|
||||||
|
|
||||||
|
Depending on what platform you are on, the error will look different, but
|
||||||
|
the way to fix it will be the same.
|
||||||
|
|
||||||
|
On Windows, it will complain about:
|
||||||
|
|
||||||
|
syntax error, unexpected end-of-input, expecting '('
|
||||||
|
|
||||||
|
On OS X and Linux, the error will be something like:
|
||||||
|
|
||||||
|
|
||||||
|
# Running:
|
||||||
|
|
||||||
|
E
|
||||||
|
|
||||||
|
Finished in 0.001328s, 753.0121 runs/s, 0.0000 assertions/s.
|
||||||
|
|
||||||
|
1) Error:
|
||||||
|
HelloWorldTest#test_say_hi:
|
||||||
|
NameError: uninitialized constant HelloWorldTest::HelloWorld
|
||||||
|
Did you mean? HelloWorldTest
|
||||||
|
hello_world_test.rb:19:in `test_say_hi'
|
||||||
|
|
||||||
|
1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
|
||||||
|
|
||||||
|
|
||||||
|
Within the first test, we are referencing a constant named `HelloWorld` when
|
||||||
|
we say `HelloWorld.hello`. When Ruby sees a capitalized name like
|
||||||
|
`HelloWorld`, it looks it up in a big huge list of all the constants it knows about,
|
||||||
|
to see what it points to. It could point to anything, and often in Ruby we have
|
||||||
|
constants that point to definitions of classes or modules.
|
||||||
|
|
||||||
|
When it looks `HelloWorld` up in its list, it doesn't find anything, so we need
|
||||||
|
to make one.
|
||||||
|
|
||||||
|
### Fixing the Error
|
||||||
|
|
||||||
|
To fix it, open up the hello_world.rb file and add the following code:
|
||||||
|
|
||||||
|
class HelloWorld
|
||||||
|
end
|
||||||
|
|
||||||
|
## Step 3
|
||||||
|
|
||||||
|
Run the test again.
|
||||||
|
|
||||||
|
1) Error:
|
||||||
|
HelloWorldTest#test_no_name:
|
||||||
|
NoMethodError: undefined method `hello' for HelloWorld:Class
|
||||||
|
hello_world_test.rb:20:in `test_no_name'
|
||||||
|
|
||||||
|
This time we have a `HelloWorld`, but we're trying tell it to `hello`, and
|
||||||
|
`HelloWorld` doesn't understand that message.
|
||||||
|
|
||||||
|
Open up hello_world.rb and add a method definition inside the class:
|
||||||
|
|
||||||
|
class HelloWorld
|
||||||
|
def self.hello
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
## Step 4
|
||||||
|
|
||||||
|
Run the test again.
|
||||||
|
|
||||||
|
1) Failure:
|
||||||
|
HelloWorldTest#test_no_name [hello_world_test.rb:11]:
|
||||||
|
When given no name, we should greet the world.
|
||||||
|
Expected: "Hello, World!"
|
||||||
|
Actual: nil
|
||||||
|
|
||||||
|
Up until now we've been getting errors, this time we get a failure.
|
||||||
|
|
||||||
|
An error means that Ruby cannot even run properly because of things like missing
|
||||||
|
files or syntax errors, or referring to things that don't exist.
|
||||||
|
|
||||||
|
A failure is different. A failure is when Ruby is running just fine
|
||||||
|
and the test is expecting one outcome, but getting another.
|
||||||
|
|
||||||
|
The test is expecting the `hello` method to return the string `"Hello, World!"`. The easiest way
|
||||||
|
to make it pass, is to simply stick the string `"Hello, World!"` inside the method definition.
|
||||||
|
|
||||||
|
## Step 5
|
||||||
|
|
||||||
|
Run the test again.
|
||||||
|
|
||||||
|
If it fails you're going to need to read the error message carefully to figure
|
||||||
|
out what went wrong, and then try again.
|
||||||
|
|
||||||
|
If it passes, then you're ready to move to the next step.
|
||||||
|
|
||||||
|
## Submit
|
||||||
|
|
||||||
|
When everything is passing, you can submit your code with the following
|
||||||
|
command:
|
||||||
|
|
||||||
|
$ exercism submit hello_world.rb
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
* * * *
|
||||||
|
|
||||||
|
For installation and learning resources, refer to the
|
||||||
|
[exercism help page](http://exercism.io/languages/ruby).
|
||||||
|
|
||||||
|
For running the tests provided, you will need the Minitest gem. Open a
|
||||||
|
terminal window and run the following command to install minitest:
|
||||||
|
|
||||||
|
gem install minitest
|
||||||
|
|
||||||
|
If you would like color output, you can `require 'minitest/pride'` in
|
||||||
|
the test file, or note the alternative instruction, below, for running
|
||||||
|
the test file.
|
||||||
|
|
||||||
|
Run the tests from the exercise directory using the following command:
|
||||||
|
|
||||||
|
ruby hello_world_test.rb
|
||||||
|
|
||||||
|
To include color from the command line:
|
||||||
|
|
||||||
|
ruby -r minitest/pride hello_world_test.rb
|
||||||
|
|
||||||
|
|
||||||
|
## 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.
|
|
@ -0,0 +1,5 @@
|
||||||
|
class HelloWorld
|
||||||
|
def self.hello
|
||||||
|
"Hello, World!"
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,43 @@
|
||||||
|
begin
|
||||||
|
gem 'minitest', '>= 5.0.0'
|
||||||
|
require 'minitest/autorun'
|
||||||
|
require_relative 'hello_world'
|
||||||
|
rescue Gem::LoadError => e
|
||||||
|
puts "\nMissing Dependency:\n#{e.backtrace.first} #{e.message}"
|
||||||
|
puts 'Minitest 5.0 gem must be installed for the Ruby track.'
|
||||||
|
rescue LoadError => e
|
||||||
|
puts "\nError:\n#{e.backtrace.first} #{e.message}"
|
||||||
|
puts DATA.read
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# Common test data version: 1.0.0 4b9ae53
|
||||||
|
class HelloWorldTest < Minitest::Test
|
||||||
|
def test_say_hi
|
||||||
|
# skip
|
||||||
|
assert_equal "Hello, World!", HelloWorld.hello
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
__END__
|
||||||
|
|
||||||
|
*****************************************************
|
||||||
|
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 load such file
|
||||||
|
|
||||||
|
It's looking for a file named hello_world.rb that doesn't
|
||||||
|
exist yet.
|
||||||
|
|
||||||
|
To fix the error, create an empty file named hello_world.rb
|
||||||
|
in the same directory as the hello_world_test.rb file.
|
||||||
|
|
||||||
|
Then run the test again.
|
||||||
|
|
||||||
|
For more guidance as you work on this exercise, see
|
||||||
|
GETTING_STARTED.md.
|
||||||
|
*****************************************************
|
|
@ -0,0 +1,57 @@
|
||||||
|
# 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:
|
||||||
|
|
||||||
|
```text
|
||||||
|
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
|
||||||
|
|
||||||
|
* * * *
|
||||||
|
|
||||||
|
For installation and learning resources, refer to the
|
||||||
|
[exercism help page](http://exercism.io/languages/ruby).
|
||||||
|
|
||||||
|
For running the tests provided, you will need the Minitest gem. Open a
|
||||||
|
terminal window and run the following command to install minitest:
|
||||||
|
|
||||||
|
gem install minitest
|
||||||
|
|
||||||
|
If you would like color output, you can `require 'minitest/pride'` in
|
||||||
|
the test file, or note the alternative instruction, below, for running
|
||||||
|
the test file.
|
||||||
|
|
||||||
|
Run the tests from the exercise directory using the following command:
|
||||||
|
|
||||||
|
ruby leap_test.rb
|
||||||
|
|
||||||
|
To include color from the command line:
|
||||||
|
|
||||||
|
ruby -r minitest/pride leap_test.rb
|
||||||
|
|
||||||
|
|
||||||
|
## 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.
|
|
@ -0,0 +1,9 @@
|
||||||
|
class Year
|
||||||
|
def self.leap?(yr)
|
||||||
|
yr % 400 == 0 || (yr % 4 == 0 && yr % 100 != 0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
module BookKeeping
|
||||||
|
VERSION = 3
|
||||||
|
end
|
|
@ -0,0 +1,51 @@
|
||||||
|
require 'minitest/autorun'
|
||||||
|
require_relative 'leap'
|
||||||
|
|
||||||
|
# Common test data version: 1.1.0 7f4d0d8
|
||||||
|
class Date
|
||||||
|
def leap?
|
||||||
|
raise RuntimeError, "Implement this yourself instead of using Ruby's implementation."
|
||||||
|
end
|
||||||
|
|
||||||
|
alias gregorian_leap? leap?
|
||||||
|
alias julian_leap? leap?
|
||||||
|
end
|
||||||
|
|
||||||
|
class YearTest < Minitest::Test
|
||||||
|
def test_year_not_divisible_by_4_common_year
|
||||||
|
refute Year.leap?(2015), "Expected 'false', 2015 is not a leap year."
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_year_divisible_by_4_not_divisible_by_100_leap_year
|
||||||
|
assert Year.leap?(2020), "Expected 'true', 2020 is a leap year."
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_year_divisible_by_100_not_divisible_by_400_common_year
|
||||||
|
refute Year.leap?(2100), "Expected 'false', 2100 is not a leap year."
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_year_divisible_by_400_leap_year
|
||||||
|
assert Year.leap?(2000), "Expected 'true', 2000 is a leap year."
|
||||||
|
end
|
||||||
|
|
||||||
|
# Problems in exercism evolve over time, as we find better ways to ask
|
||||||
|
# questions.
|
||||||
|
# The version number refers to the version of the problem you solved,
|
||||||
|
# not your solution.
|
||||||
|
#
|
||||||
|
# Define a constant named VERSION inside of the top level BookKeeping
|
||||||
|
# module, which may be placed near the end of your file.
|
||||||
|
#
|
||||||
|
# In your file, it will look like this:
|
||||||
|
#
|
||||||
|
# module BookKeeping
|
||||||
|
# VERSION = 1 # Where the version number matches the one in the test.
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# If you are curious, read more about constants on RubyDoc:
|
||||||
|
# http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html
|
||||||
|
|
||||||
|
def test_bookkeeping
|
||||||
|
assert_equal 3, BookKeeping::VERSION
|
||||||
|
end
|
||||||
|
end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue