lunchtime elixir
This commit is contained in:
parent
ec37071482
commit
04d8892d22
|
@ -0,0 +1,67 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir accumulate_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,22 @@
|
||||||
|
defmodule Accumulate do
|
||||||
|
@doc """
|
||||||
|
Given a list and a function, apply the function to each list item and
|
||||||
|
replace it with the function's return value.
|
||||||
|
|
||||||
|
Returns a list.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> Accumulate.accumulate([], fn(x) -> x * 2 end)
|
||||||
|
[]
|
||||||
|
|
||||||
|
iex> Accumulate.accumulate([1, 2, 3], fn(x) -> x * 2 end)
|
||||||
|
[2, 4, 6]
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
@spec accumulate(list, (any -> any)) :: list
|
||||||
|
def accumulate(list, fun) do
|
||||||
|
for item <- list, into: [], do: fun.(item)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,42 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("accumulate.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(trace: true)
|
||||||
|
|
||||||
|
defmodule AccumulateTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
test "accumulate empty list" do
|
||||||
|
assert Accumulate.accumulate([], fn n -> n * n end) == []
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "accumulate square numbers" do
|
||||||
|
assert Accumulate.accumulate([1, 2, 3], fn n -> n * n end) == [1, 4, 9]
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "accumulate upcased strings" do
|
||||||
|
fun = fn w -> String.upcase(w) end
|
||||||
|
assert Accumulate.accumulate(["hello", "world"], fun) == ["HELLO", "WORLD"]
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "accumulate reversed strings" do
|
||||||
|
fun = fn w -> String.reverse(w) end
|
||||||
|
words = ~w(the quick brown fox etc)
|
||||||
|
expected = ["eht", "kciuq", "nworb", "xof", "cte"]
|
||||||
|
assert Accumulate.accumulate(words, fun) == expected
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "nested accumulate" do
|
||||||
|
chars = ~w(a b c)
|
||||||
|
nums = ~w(1 2 3)
|
||||||
|
fun = fn c -> Accumulate.accumulate(nums, &(c <> &1)) end
|
||||||
|
expected = [["a1", "a2", "a3"], ["b1", "b2", "b3"], ["c1", "c2", "c3"]]
|
||||||
|
assert Accumulate.accumulate(chars, fun) == expected
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,49 @@
|
||||||
|
# Acronym
|
||||||
|
|
||||||
|
Convert a phrase to its acronym.
|
||||||
|
|
||||||
|
Techies love their TLA (Three Letter Acronyms)!
|
||||||
|
|
||||||
|
Help generate some jargon by writing a program that converts a long name
|
||||||
|
like Portable Network Graphics to its acronym (PNG).
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir acronym_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
|
||||||
|
|
||||||
|
Julien Vanier [https://github.com/monkbroc](https://github.com/monkbroc)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,13 @@
|
||||||
|
defmodule Acronym do
|
||||||
|
@doc """
|
||||||
|
Generate an acronym from a string.
|
||||||
|
"This is a string" => "TIAS"
|
||||||
|
"""
|
||||||
|
@spec abbreviate(String.t()) :: String.t()
|
||||||
|
def abbreviate(string) do
|
||||||
|
string
|
||||||
|
|> String.split(~r/(?=\p{Lu})|[ -]/iu, trim: true)
|
||||||
|
|> Enum.map(fn w -> w |> String.first() |> String.upcase() end)
|
||||||
|
|> Enum.join()
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,34 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("acronym.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(trace: true)
|
||||||
|
|
||||||
|
defmodule AcronymTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
test "it produces acronyms from title case" do
|
||||||
|
assert Acronym.abbreviate("Portable Networks Graphic") === "PNG"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "it produces acronyms from lower case" do
|
||||||
|
assert Acronym.abbreviate("Ruby on Rails") === "ROR"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "it produces acronyms from inconsistent case" do
|
||||||
|
assert Acronym.abbreviate("HyperText Markup Language") === "HTML"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "it ignores punctuation" do
|
||||||
|
assert Acronym.abbreviate("First in, First out") === "FIFO"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "it produces acronyms ignoring punctuation and casing" do
|
||||||
|
assert Acronym.abbreviate("Complementary Metal-Oxide semiconductor") === "CMOS"
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,55 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir bob_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
|
||||||
|
|
||||||
|
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,19 @@
|
||||||
|
defmodule Bob do
|
||||||
|
def hey(input) do
|
||||||
|
cond do
|
||||||
|
String.trim(input) in [nil, ""] ->
|
||||||
|
"Fine. Be that way!"
|
||||||
|
|
||||||
|
Regex.match?(~r/[a-zA-Z]/, input) && input == String.upcase(input) ->
|
||||||
|
if String.contains?(input, "?"),
|
||||||
|
do: "Calm down, I know what I'm doing!",
|
||||||
|
else: "Whoa, chill out!"
|
||||||
|
|
||||||
|
input |> String.trim() |> String.ends_with?("?") ->
|
||||||
|
"Sure."
|
||||||
|
|
||||||
|
true ->
|
||||||
|
"Whatever."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,84 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("bob.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(exclude: :pending, trace: true)
|
||||||
|
|
||||||
|
defmodule BobTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
test "stating something" do
|
||||||
|
assert Bob.hey("Tom-ay-to, tom-aaaah-to.") == "Whatever."
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "shouting" do
|
||||||
|
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "asking a question" do
|
||||||
|
assert Bob.hey("Does this cryogenic chamber make me look fat?") == "Sure."
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "talking forcefully" do
|
||||||
|
assert Bob.hey("Let's go make out behind the gym!") == "Whatever."
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "talking in capitals" do
|
||||||
|
assert Bob.hey("This Isn't Shouting!") == "Whatever."
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "asking in capitals" do
|
||||||
|
assert Bob.hey("THIS ISN'T SHOUTING?") == "Calm down, I know what I'm doing!"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "shouting numbers" do
|
||||||
|
assert Bob.hey("1, 2, 3 GO!") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "shouting with special characters" do
|
||||||
|
assert Bob.hey("ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "shouting with no exclamation mark" do
|
||||||
|
assert Bob.hey("I HATE YOU") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "statement containing question mark" do
|
||||||
|
assert Bob.hey("Ending with ? means a question.") == "Whatever."
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "silence" do
|
||||||
|
assert Bob.hey("") == "Fine. Be that way!"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "prolonged silence" do
|
||||||
|
assert Bob.hey(" ") == "Fine. Be that way!"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "only numbers" do
|
||||||
|
assert Bob.hey("1, 2, 3") == "Whatever."
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "question with numbers" do
|
||||||
|
assert Bob.hey("4?") == "Sure."
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "shouting in Russian" do
|
||||||
|
assert Bob.hey("УХОДИ") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,59 @@
|
||||||
|
# Pig Latin
|
||||||
|
|
||||||
|
Implement a program that translates from English to Pig Latin.
|
||||||
|
|
||||||
|
Pig Latin is a made-up children's language that's intended to be
|
||||||
|
confusing. It obeys a few simple rules (below), but when it's spoken
|
||||||
|
quickly it's really difficult for non-children (and non-native speakers)
|
||||||
|
to understand.
|
||||||
|
|
||||||
|
- **Rule 1**: If a word begins with a vowel sound, add an "ay" sound to
|
||||||
|
the end of the word.
|
||||||
|
- **Rule 2**: If a word begins with a consonant sound, move it to the
|
||||||
|
end of the word, and then add an "ay" sound to the end of the word.
|
||||||
|
|
||||||
|
There are a few more rules for edge cases, and there are regional
|
||||||
|
variants too.
|
||||||
|
|
||||||
|
See <http://en.wikipedia.org/wiki/Pig_latin> for more details.
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir pig_latin_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 Pig Latin exercise at Test First Teaching by Ultrasaurus [https://github.com/ultrasaurus/test-first-teaching/blob/master/learn_ruby/pig_latin/](https://github.com/ultrasaurus/test-first-teaching/blob/master/learn_ruby/pig_latin/)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,44 @@
|
||||||
|
defmodule PigLatin do
|
||||||
|
@doc """
|
||||||
|
Given a `phrase`, translate it a word at a time to Pig Latin.
|
||||||
|
|
||||||
|
Words beginning with consonants should have the consonant moved to the end of
|
||||||
|
the word, followed by "ay".
|
||||||
|
|
||||||
|
Words beginning with vowels (aeiou) should have "ay" added to the end of the
|
||||||
|
word.
|
||||||
|
|
||||||
|
Some groups of letters are treated like consonants, including "ch", "qu",
|
||||||
|
"squ", "th", "thr", and "sch".
|
||||||
|
|
||||||
|
Some groups are treated like vowels, including "yt" and "xr".
|
||||||
|
"""
|
||||||
|
@vowels ["a", "e", "i", "o", "u", "xr", "yt"]
|
||||||
|
@clusters ["ch", "sh", "qu", "sq", "th", "pl"]
|
||||||
|
@triple_clusters ["thr", "sch", "squ", "str"]
|
||||||
|
|
||||||
|
@spec translate(phrase :: String.t()) :: String.t()
|
||||||
|
def translate(phrase) do
|
||||||
|
phrase
|
||||||
|
|> String.split()
|
||||||
|
|> Enum.map(fn w ->
|
||||||
|
cond do
|
||||||
|
String.starts_with?(w, @vowels) ->
|
||||||
|
"#{w}ay"
|
||||||
|
|
||||||
|
String.starts_with?(w, @triple_clusters) ->
|
||||||
|
{first, rest} = String.split_at(w, 3)
|
||||||
|
"#{rest}#{first}ay"
|
||||||
|
|
||||||
|
String.starts_with?(w, @clusters) ->
|
||||||
|
{first, rest} = String.split_at(w, 2)
|
||||||
|
"#{rest}#{first}ay"
|
||||||
|
|
||||||
|
true ->
|
||||||
|
{first, rest} = String.split_at(w, 1)
|
||||||
|
"#{rest}#{first}ay"
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|> Enum.join(" ")
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,145 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("pig_latin.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(exclude: :pending, trace: true)
|
||||||
|
|
||||||
|
defmodule PigLatinTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
describe "ay is added to words that start with vowels" do
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with a" do
|
||||||
|
assert PigLatin.translate("apple") == "appleay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with e" do
|
||||||
|
assert PigLatin.translate("ear") == "earay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with i" do
|
||||||
|
assert PigLatin.translate("igloo") == "iglooay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with o" do
|
||||||
|
assert PigLatin.translate("object") == "objectay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with u" do
|
||||||
|
assert PigLatin.translate("under") == "underay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with a vowel and followed by a qu" do
|
||||||
|
assert PigLatin.translate("equal") == "equalay"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "first consonant letters and ay are moved to the end of words that start with consonants" do
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with p" do
|
||||||
|
assert PigLatin.translate("pig") == "igpay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with k" do
|
||||||
|
assert PigLatin.translate("koala") == "oalakay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with y" do
|
||||||
|
assert PigLatin.translate("yellow") == "ellowyay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with x" do
|
||||||
|
assert PigLatin.translate("xenon") == "enonxay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with q without a following u" do
|
||||||
|
assert PigLatin.translate("qat") == "atqay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with two consonants" do
|
||||||
|
assert PigLatin.translate("pleasure") == "easureplay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with three consonants" do
|
||||||
|
assert PigLatin.translate("stringify") == "ingifystray"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with a serie of consonants : aliens speak Pig Latin too" do
|
||||||
|
assert PigLatin.translate("zkrrkrkrkrzzzkewk") == "ewkzkrrkrkrkrzzzkay"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "consecutive consonants are treated like a single consonant" do
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with ch" do
|
||||||
|
assert PigLatin.translate("chair") == "airchay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with qu" do
|
||||||
|
assert PigLatin.translate("queen") == "eenquay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with qu and a preceding consonant" do
|
||||||
|
assert PigLatin.translate("square") == "aresquay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with th" do
|
||||||
|
assert PigLatin.translate("therapy") == "erapythay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with thr" do
|
||||||
|
assert PigLatin.translate("thrush") == "ushthray"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with sch" do
|
||||||
|
assert PigLatin.translate("school") == "oolschay"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "'x' and 'y', when followed by a consonant, are treated like a vowel" do
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with y, followed by a consonant" do
|
||||||
|
assert PigLatin.translate("yttria") == "yttriaay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with y, followed by another consonant" do
|
||||||
|
assert PigLatin.translate("yddria") == "yddriaay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with xr" do
|
||||||
|
assert PigLatin.translate("xray") == "xrayay"
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "word beginning with xb" do
|
||||||
|
assert PigLatin.translate("xbot") == "xbotay"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "phrases are translated" do
|
||||||
|
# @tag :pending
|
||||||
|
test "a whole phrase" do
|
||||||
|
assert PigLatin.translate("quick fast run") == "ickquay astfay unray"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -4,6 +4,18 @@ defmodule ProteinTranslation do
|
||||||
"""
|
"""
|
||||||
@spec of_rna(String.t()) :: {atom, list(String.t())}
|
@spec of_rna(String.t()) :: {atom, list(String.t())}
|
||||||
def of_rna(rna) do
|
def of_rna(rna) do
|
||||||
|
for <<x::binary-3 <- rna>> do
|
||||||
|
of_codon(x)
|
||||||
|
end
|
||||||
|
|> Enum.reduce([], fn c, acc ->
|
||||||
|
case c do
|
||||||
|
{:ok, codon} ->
|
||||||
|
acc ++ codon
|
||||||
|
|
||||||
|
{:error, _msg} ->
|
||||||
|
{:error, "invalid RNA"}
|
||||||
|
end
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -29,5 +41,33 @@ defmodule ProteinTranslation do
|
||||||
"""
|
"""
|
||||||
@spec of_codon(String.t()) :: {atom, String.t()}
|
@spec of_codon(String.t()) :: {atom, String.t()}
|
||||||
def of_codon(codon) do
|
def of_codon(codon) do
|
||||||
|
case codon do
|
||||||
|
n when n in ["UGU", "UGC"] ->
|
||||||
|
{:ok, "Cysteine"}
|
||||||
|
|
||||||
|
n when n in ["UUA", "UUG"] ->
|
||||||
|
{:ok, "Leucine"}
|
||||||
|
|
||||||
|
"AUG" ->
|
||||||
|
{:ok, "Methionine"}
|
||||||
|
|
||||||
|
n when n in ["UUU", "UUC"] ->
|
||||||
|
{:ok, "Phenylalanine"}
|
||||||
|
|
||||||
|
n when n in ["UCU", "UCC", "UCA", "UCG"] ->
|
||||||
|
{:ok, "Serine"}
|
||||||
|
|
||||||
|
"UGG" ->
|
||||||
|
{:ok, "Tryptophan"}
|
||||||
|
|
||||||
|
n when n in ["UAU", "UAC"] ->
|
||||||
|
{:ok, "Tyrosine"}
|
||||||
|
|
||||||
|
n when n in ["UAA", "UAG", "UGA"] ->
|
||||||
|
{:ok, "STOP"}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
{:error, "invalid codon"}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,19 +13,19 @@ defmodule ProteinTranslationTest do
|
||||||
assert ProteinTranslation.of_codon("AUG") == {:ok, "Methionine"}
|
assert ProteinTranslation.of_codon("AUG") == {:ok, "Methionine"}
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "identifies Phenylalanine codons" do
|
test "identifies Phenylalanine codons" do
|
||||||
assert ProteinTranslation.of_codon("UUU") == {:ok, "Phenylalanine"}
|
assert ProteinTranslation.of_codon("UUU") == {:ok, "Phenylalanine"}
|
||||||
assert ProteinTranslation.of_codon("UUC") == {:ok, "Phenylalanine"}
|
assert ProteinTranslation.of_codon("UUC") == {:ok, "Phenylalanine"}
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "identifies Leucine codons" do
|
test "identifies Leucine codons" do
|
||||||
assert ProteinTranslation.of_codon("UUA") == {:ok, "Leucine"}
|
assert ProteinTranslation.of_codon("UUA") == {:ok, "Leucine"}
|
||||||
assert ProteinTranslation.of_codon("UUG") == {:ok, "Leucine"}
|
assert ProteinTranslation.of_codon("UUG") == {:ok, "Leucine"}
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "identifies Serine codons" do
|
test "identifies Serine codons" do
|
||||||
assert ProteinTranslation.of_codon("UCU") == {:ok, "Serine"}
|
assert ProteinTranslation.of_codon("UCU") == {:ok, "Serine"}
|
||||||
assert ProteinTranslation.of_codon("UCC") == {:ok, "Serine"}
|
assert ProteinTranslation.of_codon("UCC") == {:ok, "Serine"}
|
||||||
|
@ -33,59 +33,59 @@ defmodule ProteinTranslationTest do
|
||||||
assert ProteinTranslation.of_codon("UCG") == {:ok, "Serine"}
|
assert ProteinTranslation.of_codon("UCG") == {:ok, "Serine"}
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "identifies Tyrosine codons" do
|
test "identifies Tyrosine codons" do
|
||||||
assert ProteinTranslation.of_codon("UAU") == {:ok, "Tyrosine"}
|
assert ProteinTranslation.of_codon("UAU") == {:ok, "Tyrosine"}
|
||||||
assert ProteinTranslation.of_codon("UAC") == {:ok, "Tyrosine"}
|
assert ProteinTranslation.of_codon("UAC") == {:ok, "Tyrosine"}
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "identifies Cysteine codons" do
|
test "identifies Cysteine codons" do
|
||||||
assert ProteinTranslation.of_codon("UGU") == {:ok, "Cysteine"}
|
assert ProteinTranslation.of_codon("UGU") == {:ok, "Cysteine"}
|
||||||
assert ProteinTranslation.of_codon("UGC") == {:ok, "Cysteine"}
|
assert ProteinTranslation.of_codon("UGC") == {:ok, "Cysteine"}
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "identifies Tryptophan codons" do
|
test "identifies Tryptophan codons" do
|
||||||
assert ProteinTranslation.of_codon("UGG") == {:ok, "Tryptophan"}
|
assert ProteinTranslation.of_codon("UGG") == {:ok, "Tryptophan"}
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "identifies stop codons" do
|
test "identifies stop codons" do
|
||||||
assert ProteinTranslation.of_codon("UAA") == {:ok, "STOP"}
|
assert ProteinTranslation.of_codon("UAA") == {:ok, "STOP"}
|
||||||
assert ProteinTranslation.of_codon("UAG") == {:ok, "STOP"}
|
assert ProteinTranslation.of_codon("UAG") == {:ok, "STOP"}
|
||||||
assert ProteinTranslation.of_codon("UGA") == {:ok, "STOP"}
|
assert ProteinTranslation.of_codon("UGA") == {:ok, "STOP"}
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "translates rna strand into correct protein" do
|
test "translates rna strand into correct protein" do
|
||||||
strand = "AUGUUUUGG"
|
strand = "AUGUUUUGG"
|
||||||
assert ProteinTranslation.of_rna(strand) == {:ok, ~w(Methionine Phenylalanine Tryptophan)}
|
assert ProteinTranslation.of_rna(strand) == {:ok, ~w(Methionine Phenylalanine Tryptophan)}
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "stops translation if stop codon present" do
|
test "stops translation if stop codon present" do
|
||||||
strand = "AUGUUUUAA"
|
strand = "AUGUUUUAA"
|
||||||
assert ProteinTranslation.of_rna(strand) == {:ok, ~w(Methionine Phenylalanine)}
|
assert ProteinTranslation.of_rna(strand) == {:ok, ~w(Methionine Phenylalanine)}
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "stops translation of longer strand" do
|
test "stops translation of longer strand" do
|
||||||
strand = "UGGUGUUAUUAAUGGUUU"
|
strand = "UGGUGUUAUUAAUGGUUU"
|
||||||
assert ProteinTranslation.of_rna(strand) == {:ok, ~w(Tryptophan Cysteine Tyrosine)}
|
assert ProteinTranslation.of_rna(strand) == {:ok, ~w(Tryptophan Cysteine Tyrosine)}
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "invalid RNA" do
|
test "invalid RNA" do
|
||||||
assert ProteinTranslation.of_rna("CARROT") == {:error, "invalid RNA"}
|
assert ProteinTranslation.of_rna("CARROT") == {:error, "invalid RNA"}
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "invalid codon at end of RNA" do
|
test "invalid codon at end of RNA" do
|
||||||
assert ProteinTranslation.of_rna("UUUROT") == {:error, "invalid RNA"}
|
assert ProteinTranslation.of_rna("UUUROT") == {:error, "invalid RNA"}
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "invalid codon" do
|
test "invalid codon" do
|
||||||
assert ProteinTranslation.of_codon("INVALID") == {:error, "invalid codon"}
|
assert ProteinTranslation.of_codon("INVALID") == {:error, "invalid codon"}
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
# 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".
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir raindrops_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
|
||||||
|
|
||||||
|
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,27 @@
|
||||||
|
defmodule Raindrops do
|
||||||
|
@doc """
|
||||||
|
Returns a string based on raindrop factors.
|
||||||
|
|
||||||
|
- If the number contains 3 as a prime factor, output 'Pling'.
|
||||||
|
- If the number contains 5 as a prime factor, output 'Plang'.
|
||||||
|
- If the number contains 7 as a prime factor, output 'Plong'.
|
||||||
|
- If the number does not contain 3, 5, or 7 as a prime factor,
|
||||||
|
just pass the number's digits straight through.
|
||||||
|
"""
|
||||||
|
@spec convert(pos_integer) :: String.t()
|
||||||
|
def convert(number) do
|
||||||
|
if rem(number, 3) != 0 && rem(number, 5) != 0 && rem(number, 7) != 0 do
|
||||||
|
"#{number}"
|
||||||
|
else
|
||||||
|
res = ""
|
||||||
|
|
||||||
|
res = res <> if rem(number, 3) == 0, do: "Pling", else: ""
|
||||||
|
|
||||||
|
res = res <> if rem(number, 5) == 0, do: "Plang", else: ""
|
||||||
|
|
||||||
|
res = res <> if rem(number, 7) == 0, do: "Plong", else: ""
|
||||||
|
|
||||||
|
res
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,90 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("raindrops.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(trace: true)
|
||||||
|
|
||||||
|
defmodule RaindropsTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "1" do
|
||||||
|
assert Raindrops.convert(1) == "1"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "3" do
|
||||||
|
assert Raindrops.convert(3) == "Pling"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "5" do
|
||||||
|
assert Raindrops.convert(5) == "Plang"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "7" do
|
||||||
|
assert Raindrops.convert(7) == "Plong"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "6" do
|
||||||
|
assert Raindrops.convert(6) == "Pling"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "9" do
|
||||||
|
assert Raindrops.convert(9) == "Pling"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "10" do
|
||||||
|
assert Raindrops.convert(10) == "Plang"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "14" do
|
||||||
|
assert Raindrops.convert(14) == "Plong"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "15" do
|
||||||
|
assert Raindrops.convert(15) == "PlingPlang"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "21" do
|
||||||
|
assert Raindrops.convert(21) == "PlingPlong"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "25" do
|
||||||
|
assert Raindrops.convert(25) == "Plang"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "35" do
|
||||||
|
assert Raindrops.convert(35) == "PlangPlong"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "49" do
|
||||||
|
assert Raindrops.convert(49) == "Plong"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "52" do
|
||||||
|
assert Raindrops.convert(52) == "52"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "105" do
|
||||||
|
assert Raindrops.convert(105) == "PlingPlangPlong"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "12121" do
|
||||||
|
assert Raindrops.convert(12121) == "12121"
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Run Length Encoding
|
||||||
|
|
||||||
|
Implement run-length encoding and decoding.
|
||||||
|
|
||||||
|
Run-length encoding (RLE) is a simple form of data compression, where runs
|
||||||
|
(consecutive data elements) are replaced by just one data value and count.
|
||||||
|
|
||||||
|
For example we can represent the original 53 characters with only 13.
|
||||||
|
|
||||||
|
```text
|
||||||
|
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB" -> "12WB12W3B24WB"
|
||||||
|
```
|
||||||
|
|
||||||
|
RLE allows the original data to be perfectly reconstructed from
|
||||||
|
the compressed data, which makes it a lossless data compression.
|
||||||
|
|
||||||
|
```text
|
||||||
|
"AABCCCDEEEE" -> "2AB3CD4E" -> "AABCCCDEEEE"
|
||||||
|
```
|
||||||
|
|
||||||
|
For simplicity, you can assume that the unencoded string will only contain
|
||||||
|
the letters A through Z (either lower or upper case) and whitespace. This way
|
||||||
|
data to be encoded will never contain any numbers and numbers inside data to
|
||||||
|
be decoded always represent the count for the following character.
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir run_length_encoding_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/Run-length_encoding](https://en.wikipedia.org/wiki/Run-length_encoding)
|
||||||
|
|
||||||
|
## 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 RunLengthEncoder do
|
||||||
|
@doc """
|
||||||
|
Generates a string where consecutive elements are represented as a data value and count.
|
||||||
|
"AABBBCCCC" => "2A3B4C"
|
||||||
|
For this example, assume all input are strings, that are all uppercase letters.
|
||||||
|
It should also be able to reconstruct the data into its original form.
|
||||||
|
"2A3B4C" => "AABBBCCCC"
|
||||||
|
"""
|
||||||
|
@spec encode(String.t()) :: String.t()
|
||||||
|
def encode(string) do
|
||||||
|
string
|
||||||
|
|> String.graphemes()
|
||||||
|
|> Enum.chunk_by(& &1)
|
||||||
|
|> Enum.map_join(fn e ->
|
||||||
|
if length(e) < 2, do: List.first(e), else: "#{length(e)}#{List.first(e)}"
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec decode(String.t()) :: String.t()
|
||||||
|
def decode(string) do
|
||||||
|
Regex.replace(~r/([0-9]+)(.)/, string, fn _, num, letter ->
|
||||||
|
num
|
||||||
|
|> String.to_integer()
|
||||||
|
|> (&String.duplicate(letter, &1)).()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,78 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("rle.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(trace: true)
|
||||||
|
|
||||||
|
defmodule RunLengthEncoderTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
test "encode empty string" do
|
||||||
|
assert RunLengthEncoder.encode("") === ""
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "encode single characters only are encoded without count" do
|
||||||
|
assert RunLengthEncoder.encode("XYZ") === "XYZ"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "encode string with no single characters" do
|
||||||
|
assert RunLengthEncoder.encode("AABBBCCCC") == "2A3B4C"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "encode single characters mixed with repeated characters" do
|
||||||
|
assert RunLengthEncoder.encode("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB") ===
|
||||||
|
"12WB12W3B24WB"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "encode multiple whitespace mixed in string" do
|
||||||
|
assert RunLengthEncoder.encode(" hsqq qww ") === "2 hs2q q2w2 "
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "encode lowercase characters" do
|
||||||
|
assert RunLengthEncoder.encode("aabbbcccc") === "2a3b4c"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "decode empty string" do
|
||||||
|
assert RunLengthEncoder.decode("") === ""
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "decode single characters only" do
|
||||||
|
assert RunLengthEncoder.decode("XYZ") === "XYZ"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "decode string with no single characters" do
|
||||||
|
assert RunLengthEncoder.decode("2A3B4C") == "AABBBCCCC"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "decode single characters with repeated characters" do
|
||||||
|
assert RunLengthEncoder.decode("12WB12W3B24WB") ===
|
||||||
|
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "decode multiple whitespace mixed in string" do
|
||||||
|
assert RunLengthEncoder.decode("2 hs2q q2w2 ") === " hsqq qww "
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "decode lower case string" do
|
||||||
|
assert RunLengthEncoder.decode("2a3b4c") === "aabbbcccc"
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "encode followed by decode gives original string" do
|
||||||
|
original = "zzz ZZ zZ"
|
||||||
|
encoded = RunLengthEncoder.encode(original)
|
||||||
|
assert RunLengthEncoder.decode(encoded) === original
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,62 @@
|
||||||
|
# Series
|
||||||
|
|
||||||
|
Given a string of digits, output all the contiguous substrings of length `n` in
|
||||||
|
that string.
|
||||||
|
|
||||||
|
For example, the string "49142" has the following 3-digit series:
|
||||||
|
|
||||||
|
- 491
|
||||||
|
- 914
|
||||||
|
- 142
|
||||||
|
|
||||||
|
And the following 4-digit series:
|
||||||
|
|
||||||
|
- 4914
|
||||||
|
- 9142
|
||||||
|
|
||||||
|
And if you ask for a 6-digit series from a 5-digit string, you deserve
|
||||||
|
whatever you get.
|
||||||
|
|
||||||
|
Note that these series are only required to occupy *adjacent positions*
|
||||||
|
in the input; the digits need not be *numerically consecutive*.
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir series_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
|
||||||
|
|
||||||
|
A subset of the Problem 8 at Project Euler [http://projecteuler.net/problem=8](http://projecteuler.net/problem=8)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,18 @@
|
||||||
|
defmodule StringSeries do
|
||||||
|
@doc """
|
||||||
|
Given a string `s` and a positive integer `size`, return all substrings
|
||||||
|
of that size. If `size` is greater than the length of `s`, or less than 1,
|
||||||
|
return an empty list.
|
||||||
|
"""
|
||||||
|
@spec slices(s :: String.t(), size :: integer) :: list(String.t())
|
||||||
|
def slices(s, size) do
|
||||||
|
if size < 1 do
|
||||||
|
[]
|
||||||
|
else
|
||||||
|
s
|
||||||
|
|> String.codepoints()
|
||||||
|
|> Enum.chunk_every(size, 1, :discard)
|
||||||
|
|> Enum.map(&Enum.join/1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,52 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("series.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(trace: true)
|
||||||
|
|
||||||
|
defmodule StringSeriesTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "slices of size 1" do
|
||||||
|
assert StringSeries.slices("01234", 1) == ["0", "1", "2", "3", "4"]
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "slices of size 2" do
|
||||||
|
assert StringSeries.slices("01234", 2) == ["01", "12", "23", "34"]
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "slices of size 3" do
|
||||||
|
assert StringSeries.slices("01234", 3) == ["012", "123", "234"]
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "slices of size 4" do
|
||||||
|
assert StringSeries.slices("01234", 4) == ["0123", "1234"]
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "slices same size as string" do
|
||||||
|
assert StringSeries.slices("01234", 5) == ["01234"]
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "Unicode characters count as a single character" do
|
||||||
|
assert StringSeries.slices("José", 1) == ["J", "o", "s", "é"]
|
||||||
|
assert StringSeries.slices("José", 2) == ["Jo", "os", "sé"]
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "slices with size longer than string return empty list" do
|
||||||
|
assert StringSeries.slices("01234", 6) == []
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "slices with size zero or negative return empty list" do
|
||||||
|
assert StringSeries.slices("01234", -1) == []
|
||||||
|
assert StringSeries.slices("01234", 0) == []
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,59 @@
|
||||||
|
# Space Age
|
||||||
|
|
||||||
|
Given an age in seconds, calculate how old someone would be on:
|
||||||
|
|
||||||
|
- Earth: orbital period 365.25 Earth days, or 31557600 seconds
|
||||||
|
- Mercury: orbital period 0.2408467 Earth years
|
||||||
|
- Venus: orbital period 0.61519726 Earth years
|
||||||
|
- Mars: orbital period 1.8808158 Earth years
|
||||||
|
- Jupiter: orbital period 11.862615 Earth years
|
||||||
|
- Saturn: orbital period 29.447498 Earth years
|
||||||
|
- Uranus: orbital period 84.016846 Earth years
|
||||||
|
- Neptune: orbital period 164.79132 Earth years
|
||||||
|
|
||||||
|
So if you were told someone were 1,000,000,000 seconds old, you should
|
||||||
|
be able to say that they're 31.69 Earth-years old.
|
||||||
|
|
||||||
|
If you're wondering why Pluto didn't make the cut, go watch [this
|
||||||
|
youtube video](http://www.youtube.com/watch?v=Z_2gbGXzFbs).
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir space_age_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
|
||||||
|
|
||||||
|
Partially inspired by Chapter 1 in Chris Pine's online Learn to Program tutorial. [http://pine.fm/LearnToProgram/?Chapter=01](http://pine.fm/LearnToProgram/?Chapter=01)
|
||||||
|
|
||||||
|
## 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 @@
|
||||||
|
defmodule SpaceAge do
|
||||||
|
@type planet ::
|
||||||
|
:mercury
|
||||||
|
| :venus
|
||||||
|
| :earth
|
||||||
|
| :mars
|
||||||
|
| :jupiter
|
||||||
|
| :saturn
|
||||||
|
| :uranus
|
||||||
|
| :neptune
|
||||||
|
|
||||||
|
@earth_yr_in_secs 31_557_600
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Return the number of years a person that has lived for 'seconds' seconds is
|
||||||
|
aged on 'planet'.
|
||||||
|
|
||||||
|
- Earth: orbital period 365.25 Earth days, or 31557600 seconds
|
||||||
|
- Mercury: orbital period 0.2408467 Earth years
|
||||||
|
- Venus: orbital period 0.61519726 Earth years
|
||||||
|
- Mars: orbital period 1.8808158 Earth years
|
||||||
|
- Jupiter: orbital period 11.862615 Earth years
|
||||||
|
- Saturn: orbital period 29.447498 Earth years
|
||||||
|
- Uranus: orbital period 84.016846 Earth years
|
||||||
|
- Neptune: orbital period 164.79132 Earth years
|
||||||
|
"""
|
||||||
|
@spec age_on(planet, pos_integer) :: float
|
||||||
|
def age_on(planet, seconds) do
|
||||||
|
seconds / @earth_yr_in_secs /
|
||||||
|
case planet do
|
||||||
|
:mercury ->
|
||||||
|
0.2408467
|
||||||
|
|
||||||
|
:venus ->
|
||||||
|
0.61519726
|
||||||
|
|
||||||
|
:earth ->
|
||||||
|
1.0
|
||||||
|
|
||||||
|
:mars ->
|
||||||
|
1.8808158
|
||||||
|
|
||||||
|
:jupiter ->
|
||||||
|
11.862615
|
||||||
|
|
||||||
|
:saturn ->
|
||||||
|
29.447498
|
||||||
|
|
||||||
|
:uranus ->
|
||||||
|
84.016846
|
||||||
|
|
||||||
|
:neptune ->
|
||||||
|
164.79132
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,69 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("space_age.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(exclude: :pending, trace: true)
|
||||||
|
|
||||||
|
# You need to define a SpaceAge module containing a function age_on that given a
|
||||||
|
# planet (:earth, :saturn, etc) and a number of seconds returns the age in years
|
||||||
|
# on that planet as a floating point number.
|
||||||
|
|
||||||
|
defmodule SpageAgeTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "age on Earth" do
|
||||||
|
input = 1_000_000_000
|
||||||
|
assert_in_delta 31.69, SpaceAge.age_on(:earth, input), 0.005
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "age on Mercury" do
|
||||||
|
input = 2_134_835_688
|
||||||
|
assert_in_delta 67.65, SpaceAge.age_on(:earth, input), 0.005
|
||||||
|
assert_in_delta 280.88, SpaceAge.age_on(:mercury, input), 0.005
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "age on Venus" do
|
||||||
|
input = 189_839_836
|
||||||
|
assert_in_delta 6.02, SpaceAge.age_on(:earth, input), 0.005
|
||||||
|
assert_in_delta 9.78, SpaceAge.age_on(:venus, input), 0.005
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "age on Mars" do
|
||||||
|
input = 2_329_871_239
|
||||||
|
assert_in_delta 73.83, SpaceAge.age_on(:earth, input), 0.005
|
||||||
|
assert_in_delta 39.25, SpaceAge.age_on(:mars, input), 0.005
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "age on Jupiter" do
|
||||||
|
input = 901_876_382
|
||||||
|
assert_in_delta 28.58, SpaceAge.age_on(:earth, input), 0.005
|
||||||
|
assert_in_delta 2.41, SpaceAge.age_on(:jupiter, input), 0.005
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "age on Saturn" do
|
||||||
|
input = 3_000_000_000
|
||||||
|
assert_in_delta 95.06, SpaceAge.age_on(:earth, input), 0.005
|
||||||
|
assert_in_delta 3.23, SpaceAge.age_on(:saturn, input), 0.005
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "age on Uranus" do
|
||||||
|
input = 3_210_123_456
|
||||||
|
assert_in_delta 101.72, SpaceAge.age_on(:earth, input), 0.005
|
||||||
|
assert_in_delta 1.21, SpaceAge.age_on(:uranus, input), 0.005
|
||||||
|
end
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "age on Neptune" do
|
||||||
|
input = 8_210_123_456
|
||||||
|
assert_in_delta 260.16, SpaceAge.age_on(:earth, input), 0.005
|
||||||
|
assert_in_delta 1.58, SpaceAge.age_on(:neptune, input), 0.005
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Sublist
|
||||||
|
|
||||||
|
Given two lists determine if the first list is contained within the second
|
||||||
|
list, if the second list is contained within the first list, if both lists are
|
||||||
|
contained within each other or if none of these are true.
|
||||||
|
|
||||||
|
Specifically, a list A is a sublist of list B if by dropping 0 or more elements
|
||||||
|
from the front of B and 0 or more elements from the back of B you get a list
|
||||||
|
that's completely equal to A.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
* A = [1, 2, 3], B = [1, 2, 3, 4, 5], A is a sublist of B
|
||||||
|
* A = [3, 4, 5], B = [1, 2, 3, 4, 5], A is a sublist of B
|
||||||
|
* A = [3, 4], B = [1, 2, 3, 4, 5], A is a sublist of B
|
||||||
|
* A = [1, 2, 3], B = [1, 2, 3], A is equal to B
|
||||||
|
* A = [1, 2, 3, 4, 5], B = [2, 3, 4], A is a superlist of B
|
||||||
|
* A = [1, 2, 4], B = [1, 2, 3, 4, 5], A is not a superlist of, sublist of or equal to B
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir sublist_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).
|
||||||
|
|
||||||
|
## 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 @@
|
||||||
|
defmodule Sublist do
|
||||||
|
@doc """
|
||||||
|
Returns whether the first list is a sublist or a superlist of the second list
|
||||||
|
and if not whether it is equal or unequal to the second list.
|
||||||
|
"""
|
||||||
|
def compare(a, b) do
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,110 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("sublist.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(exclude: :pending, trace: true)
|
||||||
|
|
||||||
|
defmodule SublistTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
test "empty equals empty" do
|
||||||
|
assert Sublist.compare([], []) == :equal
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "empty is a sublist of anything" do
|
||||||
|
assert Sublist.compare([], [nil]) == :sublist
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "anything is a superlist of empty" do
|
||||||
|
assert Sublist.compare([nil], []) == :superlist
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "1 is not 2" do
|
||||||
|
assert Sublist.compare([1], [2]) == :unequal
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "comparing massive equal lists" do
|
||||||
|
l = Enum.to_list(1..1_000_000)
|
||||||
|
assert Sublist.compare(l, l) == :equal
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "sublist at start" do
|
||||||
|
assert Sublist.compare([1, 2, 3], [1, 2, 3, 4, 5]) == :sublist
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "sublist in middle" do
|
||||||
|
assert Sublist.compare([4, 3, 2], [5, 4, 3, 2, 1]) == :sublist
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "sublist at end" do
|
||||||
|
assert Sublist.compare([3, 4, 5], [1, 2, 3, 4, 5]) == :sublist
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "partially matching sublist at start" do
|
||||||
|
assert Sublist.compare([1, 1, 2], [1, 1, 1, 2]) == :sublist
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "sublist early in huge list" do
|
||||||
|
assert Sublist.compare([3, 4, 5], Enum.to_list(1..1_000_000)) == :sublist
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "huge sublist not in huge list" do
|
||||||
|
assert Sublist.compare(Enum.to_list(10..1_000_001), Enum.to_list(1..1_000_000)) == :unequal
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "superlist at start" do
|
||||||
|
assert Sublist.compare([1, 2, 3, 4, 5], [1, 2, 3]) == :superlist
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "superlist in middle" do
|
||||||
|
assert Sublist.compare([5, 4, 3, 2, 1], [4, 3, 2]) == :superlist
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "superlist at end" do
|
||||||
|
assert Sublist.compare([1, 2, 3, 4, 5], [3, 4, 5]) == :superlist
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "1 and 2 does not contain 3" do
|
||||||
|
assert Sublist.compare([1, 2], [3]) == :unequal
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "partially matching superlist at start" do
|
||||||
|
assert Sublist.compare([1, 1, 1, 2], [1, 1, 2]) == :superlist
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "superlist early in huge list" do
|
||||||
|
assert Sublist.compare(Enum.to_list(1..1_000_000), [3, 4, 5]) == :superlist
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "strict equality needed" do
|
||||||
|
assert Sublist.compare([1], [1.0, 2]) == :unequal
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "recurring values sublist" do
|
||||||
|
assert Sublist.compare([1, 2, 1, 2, 3], [1, 2, 3, 1, 2, 1, 2, 3, 2, 1]) == :sublist
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "recurring values unequal" do
|
||||||
|
assert Sublist.compare([1, 2, 1, 2, 3], [1, 2, 3, 1, 2, 3, 2, 3, 2, 1]) == :unequal
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,70 @@
|
||||||
|
# Twelve Days
|
||||||
|
|
||||||
|
Output the lyrics to 'The Twelve Days of Christmas'.
|
||||||
|
|
||||||
|
```text
|
||||||
|
On the first day of Christmas my true love gave to me, a Partridge in a Pear Tree.
|
||||||
|
|
||||||
|
On the second day of Christmas my true love gave to me, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
|
||||||
|
On the third day of Christmas my true love gave to me, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
|
||||||
|
On the fourth day of Christmas my true love gave to me, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
|
||||||
|
On the fifth day of Christmas my true love gave to me, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
|
||||||
|
On the sixth day of Christmas my true love gave to me, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
|
||||||
|
On the seventh day of Christmas my true love gave to me, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
|
||||||
|
On the eighth day of Christmas my true love gave to me, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
|
||||||
|
On the ninth day of Christmas my true love gave to me, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
|
||||||
|
On the tenth day of Christmas my true love gave to me, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
|
||||||
|
On the eleventh day of Christmas my true love gave to me, eleven Pipers Piping, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
|
||||||
|
On the twelfth day of Christmas my true love gave to me, twelve Drummers Drumming, eleven Pipers Piping, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir twelve_days_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 [http://en.wikipedia.org/wiki/The_Twelve_Days_of_Christmas_(song)](http://en.wikipedia.org/wiki/The_Twelve_Days_of_Christmas_(song))
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,44 @@
|
||||||
|
defmodule TwelveDays do
|
||||||
|
@verses [
|
||||||
|
"On the first day of Christmas my true love gave to me, a Partridge in a Pear Tree.",
|
||||||
|
"On the second day of Christmas my true love gave to me, two Turtle Doves, and a Partridge in a Pear Tree.",
|
||||||
|
"On the third day of Christmas my true love gave to me, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.",
|
||||||
|
"On the fourth day of Christmas my true love gave to me, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.",
|
||||||
|
"On the fifth day of Christmas my true love gave to me, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.",
|
||||||
|
"On the sixth day of Christmas my true love gave to me, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.",
|
||||||
|
"On the seventh day of Christmas my true love gave to me, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.",
|
||||||
|
"On the eighth day of Christmas my true love gave to me, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.",
|
||||||
|
"On the ninth day of Christmas my true love gave to me, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.",
|
||||||
|
"On the tenth day of Christmas my true love gave to me, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.",
|
||||||
|
"On the eleventh day of Christmas my true love gave to me, eleven Pipers Piping, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.",
|
||||||
|
"On the twelfth day of Christmas my true love gave to me, twelve Drummers Drumming, eleven Pipers Piping, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree."
|
||||||
|
]
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Given a `number`, return the song's verse for that specific day, including
|
||||||
|
all gifts for previous days in the same line.
|
||||||
|
"""
|
||||||
|
@spec verse(number :: integer) :: String.t()
|
||||||
|
def verse(number) do
|
||||||
|
@verses |> Enum.at(number - 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Given a `starting_verse` and an `ending_verse`, return the verses for each
|
||||||
|
included day, one per line.
|
||||||
|
"""
|
||||||
|
@spec verses(starting_verse :: integer, ending_verse :: integer) :: String.t()
|
||||||
|
def verses(starting_verse, ending_verse) do
|
||||||
|
@verses
|
||||||
|
|> Enum.slice(starting_verse - 1, ending_verse - starting_verse + 1)
|
||||||
|
|> Enum.join("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Sing all 12 verses, in order, one verse per line.
|
||||||
|
"""
|
||||||
|
@spec sing() :: String.t()
|
||||||
|
def sing do
|
||||||
|
@verses |> Enum.join("\n")
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,97 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("twelve_days.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
# , exclude: :pending)
|
||||||
|
ExUnit.configure(trace: true)
|
||||||
|
|
||||||
|
defmodule TwelveDaysTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
describe "verse" do
|
||||||
|
# @tag :pending
|
||||||
|
test "first verse" do
|
||||||
|
assert TwelveDays.verse(1) ==
|
||||||
|
"On the first day of Christmas my true love gave to me, a Partridge in a Pear Tree."
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "sixth verse" do
|
||||||
|
assert TwelveDays.verse(6) ==
|
||||||
|
"On the sixth day of Christmas my true love gave to me, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree."
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "last verse" do
|
||||||
|
assert TwelveDays.verse(12) ==
|
||||||
|
"On the twelfth day of Christmas my true love gave to me, twelve Drummers Drumming, eleven Pipers Piping, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "verses" do
|
||||||
|
@tag :pending
|
||||||
|
test "1-3" do
|
||||||
|
assert TwelveDays.verses(1, 3) ==
|
||||||
|
"""
|
||||||
|
On the first day of Christmas my true love gave to me, a Partridge in a Pear Tree.
|
||||||
|
On the second day of Christmas my true love gave to me, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the third day of Christmas my true love gave to me, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
"""
|
||||||
|
|> String.trim()
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "4-6" do
|
||||||
|
assert TwelveDays.verses(4, 6) ==
|
||||||
|
"""
|
||||||
|
On the fourth day of Christmas my true love gave to me, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the fifth day of Christmas my true love gave to me, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the sixth day of Christmas my true love gave to me, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
"""
|
||||||
|
|> String.trim()
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "1-12" do
|
||||||
|
assert TwelveDays.verses(1, 12) ==
|
||||||
|
"""
|
||||||
|
On the first day of Christmas my true love gave to me, a Partridge in a Pear Tree.
|
||||||
|
On the second day of Christmas my true love gave to me, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the third day of Christmas my true love gave to me, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the fourth day of Christmas my true love gave to me, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the fifth day of Christmas my true love gave to me, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the sixth day of Christmas my true love gave to me, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the seventh day of Christmas my true love gave to me, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the eighth day of Christmas my true love gave to me, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the ninth day of Christmas my true love gave to me, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the tenth day of Christmas my true love gave to me, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the eleventh day of Christmas my true love gave to me, eleven Pipers Piping, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the twelfth day of Christmas my true love gave to me, twelve Drummers Drumming, eleven Pipers Piping, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
"""
|
||||||
|
|> String.trim()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "sing" do
|
||||||
|
@tag :pending
|
||||||
|
test "all 12 verses" do
|
||||||
|
assert TwelveDays.sing() ==
|
||||||
|
"""
|
||||||
|
On the first day of Christmas my true love gave to me, a Partridge in a Pear Tree.
|
||||||
|
On the second day of Christmas my true love gave to me, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the third day of Christmas my true love gave to me, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the fourth day of Christmas my true love gave to me, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the fifth day of Christmas my true love gave to me, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the sixth day of Christmas my true love gave to me, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the seventh day of Christmas my true love gave to me, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the eighth day of Christmas my true love gave to me, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the ninth day of Christmas my true love gave to me, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the tenth day of Christmas my true love gave to me, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the eleventh day of Christmas my true love gave to me, eleven Pipers Piping, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
On the twelfth day of Christmas my true love gave to me, twelve Drummers Drumming, eleven Pipers Piping, ten Lords-a-Leaping, nine Ladies Dancing, eight Maids-a-Milking, seven Swans-a-Swimming, six Geese-a-Laying, five Gold Rings, four Calling Birds, three French Hens, two Turtle Doves, and a Partridge in a Pear Tree.
|
||||||
|
"""
|
||||||
|
|> String.trim()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,53 @@
|
||||||
|
# Word Count
|
||||||
|
|
||||||
|
Given a phrase, count the occurrences of each word in that phrase.
|
||||||
|
|
||||||
|
For example for the input `"olly olly in come free"`
|
||||||
|
|
||||||
|
```text
|
||||||
|
olly: 2
|
||||||
|
in: 1
|
||||||
|
come: 1
|
||||||
|
free: 1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir word_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
|
||||||
|
|
||||||
|
This is a classic toy problem, but we were reminded of it by seeing it in the Go Tour.
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,12 @@
|
||||||
|
defmodule Words do
|
||||||
|
@doc """
|
||||||
|
Count the number of words in the sentence.
|
||||||
|
|
||||||
|
Words are compared case-insensitively.
|
||||||
|
"""
|
||||||
|
@spec count(String.t()) :: map
|
||||||
|
def count(sentence) do
|
||||||
|
String.split(Regex.replace(~r/[^[:alnum:]-]/u, String.downcase(sentence), " "))
|
||||||
|
|> Enum.reduce(%{}, fn w, acc -> Map.update(acc, w, 1, &(&1 + 1)) end)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,62 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("word_count.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(trace: true)
|
||||||
|
|
||||||
|
defmodule WordsTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
test "count one word" do
|
||||||
|
assert Words.count("word") == %{"word" => 1}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "count one of each" do
|
||||||
|
expected = %{"one" => 1, "of" => 1, "each" => 1}
|
||||||
|
assert Words.count("one of each") == expected
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "count multiple occurrences" do
|
||||||
|
expected = %{"one" => 1, "fish" => 4, "two" => 1, "red" => 1, "blue" => 1}
|
||||||
|
assert Words.count("one fish two fish red fish blue fish") == expected
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "ignore punctuation" do
|
||||||
|
expected = %{"car" => 1, "carpet" => 1, "as" => 1, "java" => 1, "javascript" => 1}
|
||||||
|
assert Words.count("car : carpet as java : javascript!!&@$%^&") == expected
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "include numbers" do
|
||||||
|
expected = %{"testing" => 2, "1" => 1, "2" => 1}
|
||||||
|
assert Words.count("testing, 1, 2 testing") == expected
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "hyphens" do
|
||||||
|
expected = %{"co-operative" => 1}
|
||||||
|
assert Words.count("co-operative") == expected
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "ignore underscores" do
|
||||||
|
expected = %{"two" => 1, "words" => 1}
|
||||||
|
assert Words.count("two_words") == expected
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "normalize case" do
|
||||||
|
expected = %{"go" => 3}
|
||||||
|
assert Words.count("go Go GO") == expected
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "German" do
|
||||||
|
expected = %{"götterfunken" => 1, "schöner" => 1, "freude" => 1}
|
||||||
|
assert Words.count("Freude schöner Götterfunken") == expected
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,5 @@
|
||||||
|
module HelloWorld exposing (..)
|
||||||
|
|
||||||
|
helloWorld : Maybe String -> String
|
||||||
|
helloWorld name =
|
||||||
|
"Hello, World!"
|
|
@ -0,0 +1,51 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
## Elm Installation
|
||||||
|
|
||||||
|
Refer to the [Exercism help page](http://exercism.io/languages/elm) for Elm
|
||||||
|
installation and learning resources.
|
||||||
|
|
||||||
|
## Writing the Code
|
||||||
|
|
||||||
|
The first time you start an exercise, you'll need to ensure you have the
|
||||||
|
appropriate dependencies installed.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
Automatically run tests again when you save changes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm run watch
|
||||||
|
```
|
||||||
|
|
||||||
|
As you work your way through the test suite, be sure to remove the `skip <|`
|
||||||
|
calls from each test until you get them all passing!
|
||||||
|
|
||||||
|
## 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,15 @@
|
||||||
|
{
|
||||||
|
"version": "3.0.0",
|
||||||
|
"summary": "Exercism problems in Elm.",
|
||||||
|
"repository": "https://github.com/exercism/elm.git",
|
||||||
|
"license": "BSD3",
|
||||||
|
"source-directories": [
|
||||||
|
"."
|
||||||
|
],
|
||||||
|
"exposed-modules": [],
|
||||||
|
"dependencies": {
|
||||||
|
"elm-lang/core": "5.0.0 <= v < 6.0.0"
|
||||||
|
},
|
||||||
|
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"description": "Exercism/Elm",
|
||||||
|
"repository": "https://github.com/exercism/elm.git",
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"postinstall": "elm-package install -y",
|
||||||
|
"watch": "elm-test --watch",
|
||||||
|
"test": "elm-test"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"elm": "0.18.0",
|
||||||
|
"elm-test": "0.18.3"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
module Tests exposing (..)
|
||||||
|
|
||||||
|
import Expect
|
||||||
|
import HelloWorld exposing (helloWorld)
|
||||||
|
import Test exposing (..)
|
||||||
|
|
||||||
|
|
||||||
|
tests : Test
|
||||||
|
tests =
|
||||||
|
describe "Hello, World!"
|
||||||
|
[ test "Hello with no name" <|
|
||||||
|
\() ->
|
||||||
|
Expect.equal "Hello, World!" (helloWorld Nothing)
|
||||||
|
|
||||||
|
-- Once you get the first test passing, remove the
|
||||||
|
-- `skip <|` (just leave the comma) on the next two
|
||||||
|
-- lines to continue!
|
||||||
|
, skip <|
|
||||||
|
test "Hello to a sample name" <|
|
||||||
|
\() ->
|
||||||
|
Expect.equal "Hello, Alice!" (helloWorld (Just "Alice"))
|
||||||
|
, skip <|
|
||||||
|
test "Hello to another sample name" <|
|
||||||
|
\() ->
|
||||||
|
Expect.equal "Hello, Bob!" (helloWorld (Just "Bob"))
|
||||||
|
]
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"version": "3.0.0",
|
||||||
|
"summary": "Exercism problems in Elm.",
|
||||||
|
"repository": "https://github.com/exercism/elm.git",
|
||||||
|
"license": "BSD3",
|
||||||
|
"source-directories": [
|
||||||
|
".",
|
||||||
|
".."
|
||||||
|
],
|
||||||
|
"exposed-modules": [],
|
||||||
|
"dependencies": {
|
||||||
|
"elm-lang/core": "5.0.0 <= v < 6.0.0",
|
||||||
|
"elm-community/elm-test": "4.0.0 <= v < 5.0.0"
|
||||||
|
},
|
||||||
|
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Gigasecond
|
||||||
|
|
||||||
|
Calculate the moment when someone has lived for 10^9 seconds.
|
||||||
|
|
||||||
|
A gigasecond is 10^9 (1,000,000,000) seconds.
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
To run the tests run the command `go test` from within the exercise directory.
|
||||||
|
|
||||||
|
If the test suite contains benchmarks, you can run these with the `-bench`
|
||||||
|
flag:
|
||||||
|
|
||||||
|
go test -bench .
|
||||||
|
|
||||||
|
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||||
|
different specs, so the results from these benchmark tests may vary.
|
||||||
|
|
||||||
|
## Further information
|
||||||
|
|
||||||
|
For more detailed information about the Go track, including how to get help if
|
||||||
|
you're having trouble, please visit the exercism.io [Go language page](http://exercism.io/languages/go/about).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
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,38 @@
|
||||||
|
package gigasecond
|
||||||
|
|
||||||
|
// Source: exercism/problem-specifications
|
||||||
|
// Commit: 5506bac gigasecond: Apply new "input" policy
|
||||||
|
// Problem Specifications Version: 1.1.0
|
||||||
|
|
||||||
|
// Add one gigasecond to the input.
|
||||||
|
var addCases = []struct {
|
||||||
|
description string
|
||||||
|
in string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"date only specification of time",
|
||||||
|
"2011-04-25",
|
||||||
|
"2043-01-01T01:46:40",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"second test for date only specification of time",
|
||||||
|
"1977-06-13",
|
||||||
|
"2009-02-19T01:46:40",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"third test for date only specification of time",
|
||||||
|
"1959-07-19",
|
||||||
|
"1991-03-27T01:46:40",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"full time specified",
|
||||||
|
"2015-01-24T22:00:00",
|
||||||
|
"2046-10-02T23:46:40",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"full time with day roll-over",
|
||||||
|
"2015-01-24T23:59:59",
|
||||||
|
"2046-10-03T01:46:39",
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
// This is a "stub" file. It's a little start on your solution.
|
||||||
|
// It's not a complete solution though; you have to write some code.
|
||||||
|
|
||||||
|
// Package gigasecond should have a package comment that summarizes what it's about.
|
||||||
|
// https://golang.org/doc/effective_go.html#commentary
|
||||||
|
package gigasecond
|
||||||
|
|
||||||
|
// import path for the time package from the standard library
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// AddGigasecond should have a comment documenting it.
|
||||||
|
func AddGigasecond(t time.Time) time.Time {
|
||||||
|
// Write some code here to pass the test suite.
|
||||||
|
// Then remove all the stock comments.
|
||||||
|
// They're here to help you get started but they only clutter a finished solution.
|
||||||
|
// If you leave them in, reviewers may protest!
|
||||||
|
return t
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package gigasecond
|
||||||
|
|
||||||
|
// Write a function AddGigasecond that works with time.Time.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// date formats used in test data
|
||||||
|
const (
|
||||||
|
fmtD = "2006-01-02"
|
||||||
|
fmtDT = "2006-01-02T15:04:05"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAddGigasecond(t *testing.T) {
|
||||||
|
for _, tc := range addCases {
|
||||||
|
in := parse(tc.in, t)
|
||||||
|
want := parse(tc.want, t)
|
||||||
|
got := AddGigasecond(in)
|
||||||
|
if !got.Equal(want) {
|
||||||
|
t.Fatalf(`FAIL: %s
|
||||||
|
AddGigasecond(%s)
|
||||||
|
= %s
|
||||||
|
want %s`, tc.description, in, got, want)
|
||||||
|
}
|
||||||
|
t.Log("PASS:", tc.description)
|
||||||
|
}
|
||||||
|
t.Log("Tested", len(addCases), "cases.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse(s string, t *testing.T) time.Time {
|
||||||
|
tt, err := time.Parse(fmtDT, s) // try full date time format first
|
||||||
|
if err != nil {
|
||||||
|
tt, err = time.Parse(fmtD, s) // also allow just date
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
// can't run tests if input won't parse. if this seems to be a
|
||||||
|
// development or ci environment, raise an error. if this condition
|
||||||
|
// makes it to the solver though, ask for a bug report.
|
||||||
|
_, statErr := os.Stat("example_gen.go")
|
||||||
|
if statErr == nil || os.Getenv("TRAVIS_GO_VERSION") > "" {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
t.Log(err)
|
||||||
|
t.Skip("(This is not your fault, and is unexpected. " +
|
||||||
|
"Please file an issue at https://github.com/exercism/go.)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tt
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAddGigasecond(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
AddGigasecond(time.Time{})
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
## Tutorial
|
||||||
|
|
||||||
|
This exercise has two files:
|
||||||
|
|
||||||
|
- hello-world.js
|
||||||
|
- hello-world.spec.js
|
||||||
|
|
||||||
|
The first file is where you will write your code.
|
||||||
|
The second is where the tests are defined.
|
||||||
|
|
||||||
|
The tests will check whether your code is doing the right thing.
|
||||||
|
You don't need to be able to write a test suite from scratch,
|
||||||
|
but it helps to understand what a test looks like, and what
|
||||||
|
it is doing.
|
||||||
|
|
||||||
|
Open up the test file, hello-world.spec.js.
|
||||||
|
There is one test inside:
|
||||||
|
|
||||||
|
it('says hello world', function() {
|
||||||
|
expect(helloWorld.hello()).toEqual('Hello, World!');
|
||||||
|
});
|
||||||
|
|
||||||
|
Run the test now, with the following command on the command-line:
|
||||||
|
|
||||||
|
jasmine hello-world.spec.js
|
||||||
|
|
||||||
|
The test fails, which makes sense since you've not written any code yet.
|
||||||
|
|
||||||
|
The failure looks like this:
|
||||||
|
|
||||||
|
1) Hello World says hello world
|
||||||
|
Message:
|
||||||
|
Expected undefined to equal 'Hello, World!'.
|
||||||
|
|
||||||
|
There's more, but this is the most important part.
|
||||||
|
|
||||||
|
Take a look at that first line:
|
||||||
|
|
||||||
|
1) Hello World says hello world
|
||||||
|
|
||||||
|
Now look at the test definition again:
|
||||||
|
|
||||||
|
it('says hello world', function() {
|
||||||
|
// ... more code here ...
|
||||||
|
});
|
||||||
|
|
||||||
|
The text 'says hello world' is repeated.
|
||||||
|
This is how you know the test failed.
|
||||||
|
|
||||||
|
The failure message explains what is wrong:
|
||||||
|
|
||||||
|
Expected undefined to equal 'Hello, World!'.
|
||||||
|
|
||||||
|
This comes from the part of the test definition that says "expect":
|
||||||
|
|
||||||
|
expect(helloWorld.hello()).toEqual('Hello, World!');
|
||||||
|
|
||||||
|
It's comparing two values. It is calling
|
||||||
|
|
||||||
|
helloWorld.hello()
|
||||||
|
|
||||||
|
and comparing the result to a hard-coded string.
|
||||||
|
|
||||||
|
'Hello, World!'.
|
||||||
|
|
||||||
|
So if you look at the failure message again, the hello function
|
||||||
|
is returning undefined.
|
||||||
|
|
||||||
|
Try changing the function in hello-world.js so that it says
|
||||||
|
|
||||||
|
HelloWorld.prototype.hello = function(input) {
|
||||||
|
return "chocolate";
|
||||||
|
};
|
||||||
|
|
||||||
|
Then run the tests again from the command-line:
|
||||||
|
|
||||||
|
jasmine hello-world.spec.js
|
||||||
|
|
||||||
|
Notice how it changes the failure message.
|
||||||
|
|
||||||
|
Then change the implementation in hello-world.js again, this time to make the test pass.
|
||||||
|
|
||||||
|
When you are done, submit your solution to exercism:
|
||||||
|
|
||||||
|
exercism submit hello-world.js
|
||||||
|
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Go through the setup instructions for JavaScript to install the
|
||||||
|
necessary dependencies:
|
||||||
|
|
||||||
|
http://exercism.io/languages/javascript/installation
|
||||||
|
|
||||||
|
## Running the test suite
|
||||||
|
|
||||||
|
The provided test suite uses [Jasmine](https://jasmine.github.io/).
|
||||||
|
You can install it by opening a terminal window and running the
|
||||||
|
following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install -g jasmine
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the test suite from the exercise directory with:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
jasmine hello-world.spec.js
|
||||||
|
```
|
||||||
|
|
||||||
|
In many test suites all but the first test have been marked "pending".
|
||||||
|
Once you get a test passing, activate the next one by changing `xit` 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,15 @@
|
||||||
|
//
|
||||||
|
// This is a stub file for the 'Hello World' exercise. It's been provided as a
|
||||||
|
// convenience to get you started writing code faster.
|
||||||
|
// Make sure to look at hello-world.spec.js--that should give you some hints about what is
|
||||||
|
// expected here.
|
||||||
|
|
||||||
|
var HelloWorld = function () {};
|
||||||
|
|
||||||
|
HelloWorld.prototype.hello = function () {
|
||||||
|
//
|
||||||
|
// YOUR CODE GOES HERE
|
||||||
|
//
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = HelloWorld;
|
|
@ -0,0 +1,9 @@
|
||||||
|
var HelloWorld = require('./hello-world');
|
||||||
|
|
||||||
|
describe('Hello World', function () {
|
||||||
|
var helloWorld = new HelloWorld();
|
||||||
|
|
||||||
|
it('says hello world', function () {
|
||||||
|
expect(helloWorld.hello()).toEqual('Hello, World!');
|
||||||
|
});
|
||||||
|
});
|
|
@ -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.
|
||||||
|
|
||||||
|
## Exception messages
|
||||||
|
|
||||||
|
Sometimes it is necessary to raise an exception. When you do this, you should include a meaningful error message to
|
||||||
|
indicate what the source of the error is. This makes your code more readable and helps significantly with debugging. Not
|
||||||
|
every exercise will require you to raise an exception, but for those that do, the tests will only pass if you include
|
||||||
|
a message.
|
||||||
|
|
||||||
|
To raise a message with an exception, just write it as an argument to the exception type. For example, instead of
|
||||||
|
`raise Exception`, you shold write:
|
||||||
|
|
||||||
|
```python
|
||||||
|
raise Exception("Meaningful message indicating the source of the error")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Submitting Exercises
|
||||||
|
|
||||||
|
Note that, when trying to submit an exercise, make sure the solution is in the `$EXERCISM_WORKSPACE/python/hello-world` directory.
|
||||||
|
|
||||||
|
You can find your Exercism workspace by running `exercism debug` and looking for the line that starts with `Workspace`.
|
||||||
|
|
||||||
|
For more detailed information about running tests, code style and linting,
|
||||||
|
please see the [help page](http://exercism.io/languages/python).
|
||||||
|
|
||||||
|
## 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,2 @@
|
||||||
|
def hello(name=''):
|
||||||
|
return "Hello, World!"
|
Binary file not shown.
|
@ -0,0 +1,14 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import hello_world
|
||||||
|
|
||||||
|
|
||||||
|
# Tests adapted from `problem-specifications//canonical-data.json` @ v1.1.0
|
||||||
|
|
||||||
|
class HelloWorldTests(unittest.TestCase):
|
||||||
|
def test_hello(self):
|
||||||
|
self.assertEqual(hello_world.hello(), 'Hello, World!')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
|
@ -0,0 +1,44 @@
|
||||||
|
# Isogram
|
||||||
|
|
||||||
|
Determine if a word or phrase is an isogram.
|
||||||
|
|
||||||
|
An isogram (also known as a "nonpattern word") is a word or phrase without a repeating letter, however spaces and hyphens are allowed to appear multiple times.
|
||||||
|
|
||||||
|
Examples of isograms:
|
||||||
|
|
||||||
|
- lumberjacks
|
||||||
|
- background
|
||||||
|
- downstream
|
||||||
|
- six-year-old
|
||||||
|
|
||||||
|
The word *isograms*, however, is not an isogram, because the s repeats.
|
||||||
|
|
||||||
|
## Exception messages
|
||||||
|
|
||||||
|
Sometimes it is necessary to raise an exception. When you do this, you should include a meaningful error message to
|
||||||
|
indicate what the source of the error is. This makes your code more readable and helps significantly with debugging. Not
|
||||||
|
every exercise will require you to raise an exception, but for those that do, the tests will only pass if you include
|
||||||
|
a message.
|
||||||
|
|
||||||
|
To raise a message with an exception, just write it as an argument to the exception type. For example, instead of
|
||||||
|
`raise Exception`, you shold write:
|
||||||
|
|
||||||
|
```python
|
||||||
|
raise Exception("Meaningful message indicating the source of the error")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Submitting Exercises
|
||||||
|
|
||||||
|
Note that, when trying to submit an exercise, make sure the solution is in the `$EXERCISM_WORKSPACE/python/isogram` directory.
|
||||||
|
|
||||||
|
You can find your Exercism workspace by running `exercism debug` and looking for the line that starts with `Workspace`.
|
||||||
|
|
||||||
|
For more detailed information about running tests, code style and linting,
|
||||||
|
please see the [help page](http://exercism.io/languages/python).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Wikipedia [https://en.wikipedia.org/wiki/Isogram](https://en.wikipedia.org/wiki/Isogram)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,2 @@
|
||||||
|
def is_isogram(string):
|
||||||
|
pass
|
|
@ -0,0 +1,44 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from isogram import is_isogram
|
||||||
|
|
||||||
|
|
||||||
|
# Tests adapted from `problem-specifications//canonical-data.json` @ v1.2.0
|
||||||
|
|
||||||
|
class TestIsogram(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_empty_string(self):
|
||||||
|
self.assertIs(is_isogram(""), True)
|
||||||
|
|
||||||
|
def test_isogram_with_only_lower_case_characters(self):
|
||||||
|
self.assertIs(is_isogram("isogram"), True)
|
||||||
|
|
||||||
|
def test_word_with_one_duplicated_character(self):
|
||||||
|
self.assertIs(is_isogram("eleven"), False)
|
||||||
|
|
||||||
|
def test_longest_reported_english_isogram(self):
|
||||||
|
self.assertIs(is_isogram("subdermatoglyphic"), True)
|
||||||
|
|
||||||
|
def test_word_with_duplicated_character_in_mixed_case(self):
|
||||||
|
self.assertIs(is_isogram("Alphabet"), False)
|
||||||
|
|
||||||
|
def test_hypothetical_isogrammic_word_with_hyphen(self):
|
||||||
|
self.assertIs(is_isogram("thumbscrew-japingly"), True)
|
||||||
|
|
||||||
|
def test_isogram_with_duplicated_hyphen(self):
|
||||||
|
self.assertIs(is_isogram("six-year-old"), True)
|
||||||
|
|
||||||
|
def test_made_up_name_that_is_an_isogram(self):
|
||||||
|
self.assertIs(is_isogram("Emily Jung Schwartzkopf"), True)
|
||||||
|
|
||||||
|
def test_duplicated_character_in_the_middle(self):
|
||||||
|
self.assertIs(is_isogram("accentor"), False)
|
||||||
|
|
||||||
|
# Additional tests for this track
|
||||||
|
|
||||||
|
def test_isogram_with_duplicated_letter_and_nonletter_character(self):
|
||||||
|
self.assertIs(is_isogram("Aleph Bot Chap"), False)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
|
@ -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
|
||||||
|
|
||||||
|
## Exception messages
|
||||||
|
|
||||||
|
Sometimes it is necessary to raise an exception. When you do this, you should include a meaningful error message to
|
||||||
|
indicate what the source of the error is. This makes your code more readable and helps significantly with debugging. Not
|
||||||
|
every exercise will require you to raise an exception, but for those that do, the tests will only pass if you include
|
||||||
|
a message.
|
||||||
|
|
||||||
|
To raise a message with an exception, just write it as an argument to the exception type. For example, instead of
|
||||||
|
`raise Exception`, you shold write:
|
||||||
|
|
||||||
|
```python
|
||||||
|
raise Exception("Meaningful message indicating the source of the error")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Submitting Exercises
|
||||||
|
|
||||||
|
Note that, when trying to submit an exercise, make sure the solution is in the `$EXERCISM_WORKSPACE/python/leap` directory.
|
||||||
|
|
||||||
|
You can find your Exercism workspace by running `exercism debug` and looking for the line that starts with `Workspace`.
|
||||||
|
|
||||||
|
For more detailed information about running tests, code style and linting,
|
||||||
|
please see the [help page](http://exercism.io/languages/python).
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
JavaRanch Cattle Drive, exercise 3 [http://www.javaranch.com/leap.jsp](http://www.javaranch.com/leap.jsp)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,2 @@
|
||||||
|
def is_leap_year(year):
|
||||||
|
return year % 400 == 0 or (year % 4 == 0 and year % 100 != 0);
|
Binary file not shown.
|
@ -0,0 +1,23 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from leap import is_leap_year
|
||||||
|
|
||||||
|
|
||||||
|
# Tests adapted from `problem-specifications//canonical-data.json` @ v1.3.0
|
||||||
|
|
||||||
|
class YearTest(unittest.TestCase):
|
||||||
|
def test_year_not_divisible_by_4(self):
|
||||||
|
self.assertIs(is_leap_year(2015), False)
|
||||||
|
|
||||||
|
def test_year_divisible_by_4_not_divisible_by_100(self):
|
||||||
|
self.assertIs(is_leap_year(1996), True)
|
||||||
|
|
||||||
|
def test_year_divisible_by_100_not_divisible_by_400(self):
|
||||||
|
self.assertIs(is_leap_year(2100), False)
|
||||||
|
|
||||||
|
def test_year_divisible_by_400(self):
|
||||||
|
self.assertIs(is_leap_year(2000), True)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Reverse String
|
||||||
|
|
||||||
|
Reverse a string
|
||||||
|
|
||||||
|
For example:
|
||||||
|
input: "cool"
|
||||||
|
output: "looc"
|
||||||
|
|
||||||
|
## Exception messages
|
||||||
|
|
||||||
|
Sometimes it is necessary to raise an exception. When you do this, you should include a meaningful error message to
|
||||||
|
indicate what the source of the error is. This makes your code more readable and helps significantly with debugging. Not
|
||||||
|
every exercise will require you to raise an exception, but for those that do, the tests will only pass if you include
|
||||||
|
a message.
|
||||||
|
|
||||||
|
To raise a message with an exception, just write it as an argument to the exception type. For example, instead of
|
||||||
|
`raise Exception`, you shold write:
|
||||||
|
|
||||||
|
```python
|
||||||
|
raise Exception("Meaningful message indicating the source of the error")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Submitting Exercises
|
||||||
|
|
||||||
|
Note that, when trying to submit an exercise, make sure the solution is in the `$EXERCISM_WORKSPACE/python/reverse-string` directory.
|
||||||
|
|
||||||
|
You can find your Exercism workspace by running `exercism debug` and looking for the line that starts with `Workspace`.
|
||||||
|
|
||||||
|
For more detailed information about running tests, code style and linting,
|
||||||
|
please see the [help page](http://exercism.io/languages/python).
|
||||||
|
|
||||||
|
## 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,2 @@
|
||||||
|
def reverse(input=''):
|
||||||
|
return input[::-1]
|
Binary file not shown.
|
@ -0,0 +1,26 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from reverse_string import reverse
|
||||||
|
|
||||||
|
|
||||||
|
# Tests adapted from `problem-specifications//canonical-data.json` @ v1.1.0
|
||||||
|
|
||||||
|
class ReverseStringTests(unittest.TestCase):
|
||||||
|
def test_empty_string(self):
|
||||||
|
self.assertEqual(reverse(''), '')
|
||||||
|
|
||||||
|
def test_a_word(self):
|
||||||
|
self.assertEqual(reverse('robot'), 'tobor')
|
||||||
|
|
||||||
|
def test_a_capitalized_word(self):
|
||||||
|
self.assertEqual(reverse('Ramen'), 'nemaR')
|
||||||
|
|
||||||
|
def test_a_sentence_with_punctuation(self):
|
||||||
|
self.assertEqual(reverse('I\'m hungry!'), '!yrgnuh m\'I')
|
||||||
|
|
||||||
|
def test_a_palindrome(self):
|
||||||
|
self.assertEqual(reverse('racecar'), 'racecar')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Loading…
Reference in New Issue