From 04d8892d229f0c966f8c3c6cd67b028a45c9c4bd Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Mon, 5 Mar 2018 14:40:19 -0500 Subject: [PATCH] lunchtime elixir --- elixir/accumulate/README.md | 67 ++++++++ elixir/accumulate/accumulate.exs | 22 +++ elixir/accumulate/accumulate_test.exs | 42 +++++ elixir/acronym/README.md | 49 ++++++ elixir/acronym/acronym.exs | 13 ++ elixir/acronym/acronym_test.exs | 34 ++++ elixir/bob/README.md | 55 +++++++ elixir/bob/bob.exs | 19 +++ elixir/bob/bob_test.exs | 84 ++++++++++ elixir/pig-latin/README.md | 59 +++++++ elixir/pig-latin/pig_latin.exs | 44 ++++++ elixir/pig-latin/pig_latin_test.exs | 145 ++++++++++++++++++ .../protein_translation.exs | 40 +++++ .../protein_translation_test.exs | 26 ++-- elixir/raindrops/README.md | 59 +++++++ elixir/raindrops/raindrops.exs | 27 ++++ elixir/raindrops/raindrops_test.exs | 90 +++++++++++ elixir/run-length-encoding/README.md | 65 ++++++++ elixir/run-length-encoding/rle.exs | 27 ++++ elixir/run-length-encoding/rle_test.exs | 78 ++++++++++ elixir/series/README.md | 62 ++++++++ elixir/series/series.exs | 18 +++ elixir/series/series_test.exs | 52 +++++++ elixir/space-age/README.md | 59 +++++++ elixir/space-age/space_age.exs | 56 +++++++ elixir/space-age/space_age_test.exs | 69 +++++++++ elixir/sublist/README.md | 55 +++++++ elixir/sublist/sublist.exs | 8 + elixir/sublist/sublist_test.exs | 110 +++++++++++++ elixir/twelve-days/README.md | 70 +++++++++ elixir/twelve-days/twelve_days.exs | 44 ++++++ elixir/twelve-days/twelve_days_test.exs | 97 ++++++++++++ elixir/word-count/README.md | 53 +++++++ elixir/word-count/word_count.exs | 12 ++ elixir/word-count/word_count_test.exs | 62 ++++++++ elm/hello-world/HelloWorld.elm | 5 + elm/hello-world/README.md | 51 ++++++ elm/hello-world/elm-package.json | 15 ++ elm/hello-world/package.json | 14 ++ elm/hello-world/tests/Tests.elm | 26 ++++ elm/hello-world/tests/elm-package.json | 16 ++ go/gigasecond/README.md | 29 ++++ go/gigasecond/cases_test.go | 38 +++++ go/gigasecond/gigasecond.go | 18 +++ go/gigasecond/gigasecond_test.go | 58 +++++++ javascript/hello-world/README.md | 135 ++++++++++++++++ javascript/hello-world/hello-world.js | 15 ++ javascript/hello-world/hello-world.spec.js | 9 ++ python/hello-world/README.md | 45 ++++++ python/hello-world/hello_world.py | 2 + python/hello-world/hello_world.pyc | Bin 0 -> 332 bytes python/hello-world/hello_world_test.py | 14 ++ python/isogram/README.md | 44 ++++++ python/isogram/isogram.py | 2 + python/isogram/isogram_test.py | 44 ++++++ python/leap/README.md | 57 +++++++ python/leap/leap.py | 2 + python/leap/leap.pyc | Bin 0 -> 347 bytes python/leap/leap_test.py | 23 +++ python/reverse-string/README.md | 37 +++++ python/reverse-string/reverse_string.py | 2 + python/reverse-string/reverse_string.pyc | Bin 0 -> 347 bytes python/reverse-string/reverse_string_test.py | 26 ++++ 63 files changed, 2586 insertions(+), 13 deletions(-) create mode 100644 elixir/accumulate/README.md create mode 100644 elixir/accumulate/accumulate.exs create mode 100644 elixir/accumulate/accumulate_test.exs create mode 100644 elixir/acronym/README.md create mode 100644 elixir/acronym/acronym.exs create mode 100644 elixir/acronym/acronym_test.exs create mode 100644 elixir/bob/README.md create mode 100644 elixir/bob/bob.exs create mode 100644 elixir/bob/bob_test.exs create mode 100644 elixir/pig-latin/README.md create mode 100644 elixir/pig-latin/pig_latin.exs create mode 100644 elixir/pig-latin/pig_latin_test.exs create mode 100644 elixir/raindrops/README.md create mode 100644 elixir/raindrops/raindrops.exs create mode 100644 elixir/raindrops/raindrops_test.exs create mode 100644 elixir/run-length-encoding/README.md create mode 100644 elixir/run-length-encoding/rle.exs create mode 100644 elixir/run-length-encoding/rle_test.exs create mode 100644 elixir/series/README.md create mode 100644 elixir/series/series.exs create mode 100644 elixir/series/series_test.exs create mode 100644 elixir/space-age/README.md create mode 100644 elixir/space-age/space_age.exs create mode 100644 elixir/space-age/space_age_test.exs create mode 100644 elixir/sublist/README.md create mode 100644 elixir/sublist/sublist.exs create mode 100644 elixir/sublist/sublist_test.exs create mode 100644 elixir/twelve-days/README.md create mode 100644 elixir/twelve-days/twelve_days.exs create mode 100644 elixir/twelve-days/twelve_days_test.exs create mode 100644 elixir/word-count/README.md create mode 100644 elixir/word-count/word_count.exs create mode 100644 elixir/word-count/word_count_test.exs create mode 100644 elm/hello-world/HelloWorld.elm create mode 100644 elm/hello-world/README.md create mode 100644 elm/hello-world/elm-package.json create mode 100644 elm/hello-world/package.json create mode 100644 elm/hello-world/tests/Tests.elm create mode 100644 elm/hello-world/tests/elm-package.json create mode 100644 go/gigasecond/README.md create mode 100644 go/gigasecond/cases_test.go create mode 100644 go/gigasecond/gigasecond.go create mode 100644 go/gigasecond/gigasecond_test.go create mode 100644 javascript/hello-world/README.md create mode 100644 javascript/hello-world/hello-world.js create mode 100644 javascript/hello-world/hello-world.spec.js create mode 100644 python/hello-world/README.md create mode 100644 python/hello-world/hello_world.py create mode 100644 python/hello-world/hello_world.pyc create mode 100644 python/hello-world/hello_world_test.py create mode 100644 python/isogram/README.md create mode 100644 python/isogram/isogram.py create mode 100644 python/isogram/isogram_test.py create mode 100644 python/leap/README.md create mode 100644 python/leap/leap.py create mode 100644 python/leap/leap.pyc create mode 100644 python/leap/leap_test.py create mode 100644 python/reverse-string/README.md create mode 100644 python/reverse-string/reverse_string.py create mode 100644 python/reverse-string/reverse_string.pyc create mode 100644 python/reverse-string/reverse_string_test.py diff --git a/elixir/accumulate/README.md b/elixir/accumulate/README.md new file mode 100644 index 0000000..67e3c38 --- /dev/null +++ b/elixir/accumulate/README.md @@ -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. diff --git a/elixir/accumulate/accumulate.exs b/elixir/accumulate/accumulate.exs new file mode 100644 index 0000000..ec5226c --- /dev/null +++ b/elixir/accumulate/accumulate.exs @@ -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 diff --git a/elixir/accumulate/accumulate_test.exs b/elixir/accumulate/accumulate_test.exs new file mode 100644 index 0000000..501d158 --- /dev/null +++ b/elixir/accumulate/accumulate_test.exs @@ -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 diff --git a/elixir/acronym/README.md b/elixir/acronym/README.md new file mode 100644 index 0000000..0801391 --- /dev/null +++ b/elixir/acronym/README.md @@ -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. diff --git a/elixir/acronym/acronym.exs b/elixir/acronym/acronym.exs new file mode 100644 index 0000000..2c84521 --- /dev/null +++ b/elixir/acronym/acronym.exs @@ -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 diff --git a/elixir/acronym/acronym_test.exs b/elixir/acronym/acronym_test.exs new file mode 100644 index 0000000..7a5ed46 --- /dev/null +++ b/elixir/acronym/acronym_test.exs @@ -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 diff --git a/elixir/bob/README.md b/elixir/bob/README.md new file mode 100644 index 0000000..137607a --- /dev/null +++ b/elixir/bob/README.md @@ -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. diff --git a/elixir/bob/bob.exs b/elixir/bob/bob.exs new file mode 100644 index 0000000..6a21f48 --- /dev/null +++ b/elixir/bob/bob.exs @@ -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 diff --git a/elixir/bob/bob_test.exs b/elixir/bob/bob_test.exs new file mode 100644 index 0000000..f5d3341 --- /dev/null +++ b/elixir/bob/bob_test.exs @@ -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 diff --git a/elixir/pig-latin/README.md b/elixir/pig-latin/README.md new file mode 100644 index 0000000..1564107 --- /dev/null +++ b/elixir/pig-latin/README.md @@ -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 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. diff --git a/elixir/pig-latin/pig_latin.exs b/elixir/pig-latin/pig_latin.exs new file mode 100644 index 0000000..de9910f --- /dev/null +++ b/elixir/pig-latin/pig_latin.exs @@ -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 diff --git a/elixir/pig-latin/pig_latin_test.exs b/elixir/pig-latin/pig_latin_test.exs new file mode 100644 index 0000000..f93603d --- /dev/null +++ b/elixir/pig-latin/pig_latin_test.exs @@ -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 diff --git a/elixir/protein-translation/protein_translation.exs b/elixir/protein-translation/protein_translation.exs index 401b205..1a816cf 100644 --- a/elixir/protein-translation/protein_translation.exs +++ b/elixir/protein-translation/protein_translation.exs @@ -4,6 +4,18 @@ defmodule ProteinTranslation do """ @spec of_rna(String.t()) :: {atom, list(String.t())} def of_rna(rna) do + for <> 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 @doc """ @@ -29,5 +41,33 @@ defmodule ProteinTranslation do """ @spec of_codon(String.t()) :: {atom, String.t()} 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 diff --git a/elixir/protein-translation/protein_translation_test.exs b/elixir/protein-translation/protein_translation_test.exs index a9363a4..a65cc21 100644 --- a/elixir/protein-translation/protein_translation_test.exs +++ b/elixir/protein-translation/protein_translation_test.exs @@ -13,19 +13,19 @@ defmodule ProteinTranslationTest do assert ProteinTranslation.of_codon("AUG") == {:ok, "Methionine"} end - @tag :pending + # @tag :pending test "identifies Phenylalanine codons" do assert ProteinTranslation.of_codon("UUU") == {:ok, "Phenylalanine"} assert ProteinTranslation.of_codon("UUC") == {:ok, "Phenylalanine"} end - @tag :pending + # @tag :pending test "identifies Leucine codons" do assert ProteinTranslation.of_codon("UUA") == {:ok, "Leucine"} assert ProteinTranslation.of_codon("UUG") == {:ok, "Leucine"} end - @tag :pending + # @tag :pending test "identifies Serine codons" do assert ProteinTranslation.of_codon("UCU") == {:ok, "Serine"} assert ProteinTranslation.of_codon("UCC") == {:ok, "Serine"} @@ -33,59 +33,59 @@ defmodule ProteinTranslationTest do assert ProteinTranslation.of_codon("UCG") == {:ok, "Serine"} end - @tag :pending + # @tag :pending test "identifies Tyrosine codons" do assert ProteinTranslation.of_codon("UAU") == {:ok, "Tyrosine"} assert ProteinTranslation.of_codon("UAC") == {:ok, "Tyrosine"} end - @tag :pending + # @tag :pending test "identifies Cysteine codons" do assert ProteinTranslation.of_codon("UGU") == {:ok, "Cysteine"} assert ProteinTranslation.of_codon("UGC") == {:ok, "Cysteine"} end - @tag :pending + # @tag :pending test "identifies Tryptophan codons" do assert ProteinTranslation.of_codon("UGG") == {:ok, "Tryptophan"} end - @tag :pending + # @tag :pending test "identifies stop codons" do assert ProteinTranslation.of_codon("UAA") == {:ok, "STOP"} assert ProteinTranslation.of_codon("UAG") == {:ok, "STOP"} assert ProteinTranslation.of_codon("UGA") == {:ok, "STOP"} end - @tag :pending + # @tag :pending test "translates rna strand into correct protein" do strand = "AUGUUUUGG" assert ProteinTranslation.of_rna(strand) == {:ok, ~w(Methionine Phenylalanine Tryptophan)} end - @tag :pending + # @tag :pending test "stops translation if stop codon present" do strand = "AUGUUUUAA" assert ProteinTranslation.of_rna(strand) == {:ok, ~w(Methionine Phenylalanine)} end - @tag :pending + # @tag :pending test "stops translation of longer strand" do strand = "UGGUGUUAUUAAUGGUUU" assert ProteinTranslation.of_rna(strand) == {:ok, ~w(Tryptophan Cysteine Tyrosine)} end - @tag :pending + # @tag :pending test "invalid RNA" do assert ProteinTranslation.of_rna("CARROT") == {:error, "invalid RNA"} end - @tag :pending + # @tag :pending test "invalid codon at end of RNA" do assert ProteinTranslation.of_rna("UUUROT") == {:error, "invalid RNA"} end - @tag :pending + # @tag :pending test "invalid codon" do assert ProteinTranslation.of_codon("INVALID") == {:error, "invalid codon"} end diff --git a/elixir/raindrops/README.md b/elixir/raindrops/README.md new file mode 100644 index 0000000..7f66fb7 --- /dev/null +++ b/elixir/raindrops/README.md @@ -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. diff --git a/elixir/raindrops/raindrops.exs b/elixir/raindrops/raindrops.exs new file mode 100644 index 0000000..16f3d5d --- /dev/null +++ b/elixir/raindrops/raindrops.exs @@ -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 diff --git a/elixir/raindrops/raindrops_test.exs b/elixir/raindrops/raindrops_test.exs new file mode 100644 index 0000000..cd743fe --- /dev/null +++ b/elixir/raindrops/raindrops_test.exs @@ -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 diff --git a/elixir/run-length-encoding/README.md b/elixir/run-length-encoding/README.md new file mode 100644 index 0000000..ef1c70b --- /dev/null +++ b/elixir/run-length-encoding/README.md @@ -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. diff --git a/elixir/run-length-encoding/rle.exs b/elixir/run-length-encoding/rle.exs new file mode 100644 index 0000000..0c6ef83 --- /dev/null +++ b/elixir/run-length-encoding/rle.exs @@ -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 diff --git a/elixir/run-length-encoding/rle_test.exs b/elixir/run-length-encoding/rle_test.exs new file mode 100644 index 0000000..bfa99fc --- /dev/null +++ b/elixir/run-length-encoding/rle_test.exs @@ -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 diff --git a/elixir/series/README.md b/elixir/series/README.md new file mode 100644 index 0000000..e0fad86 --- /dev/null +++ b/elixir/series/README.md @@ -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. diff --git a/elixir/series/series.exs b/elixir/series/series.exs new file mode 100644 index 0000000..113a389 --- /dev/null +++ b/elixir/series/series.exs @@ -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 diff --git a/elixir/series/series_test.exs b/elixir/series/series_test.exs new file mode 100644 index 0000000..a927405 --- /dev/null +++ b/elixir/series/series_test.exs @@ -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 diff --git a/elixir/space-age/README.md b/elixir/space-age/README.md new file mode 100644 index 0000000..e759140 --- /dev/null +++ b/elixir/space-age/README.md @@ -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. diff --git a/elixir/space-age/space_age.exs b/elixir/space-age/space_age.exs new file mode 100644 index 0000000..6618da8 --- /dev/null +++ b/elixir/space-age/space_age.exs @@ -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 diff --git a/elixir/space-age/space_age_test.exs b/elixir/space-age/space_age_test.exs new file mode 100644 index 0000000..561f09f --- /dev/null +++ b/elixir/space-age/space_age_test.exs @@ -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 diff --git a/elixir/sublist/README.md b/elixir/sublist/README.md new file mode 100644 index 0000000..4a5ee72 --- /dev/null +++ b/elixir/sublist/README.md @@ -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. diff --git a/elixir/sublist/sublist.exs b/elixir/sublist/sublist.exs new file mode 100644 index 0000000..b490ec7 --- /dev/null +++ b/elixir/sublist/sublist.exs @@ -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 diff --git a/elixir/sublist/sublist_test.exs b/elixir/sublist/sublist_test.exs new file mode 100644 index 0000000..1f3e061 --- /dev/null +++ b/elixir/sublist/sublist_test.exs @@ -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 diff --git a/elixir/twelve-days/README.md b/elixir/twelve-days/README.md new file mode 100644 index 0000000..82335d3 --- /dev/null +++ b/elixir/twelve-days/README.md @@ -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. diff --git a/elixir/twelve-days/twelve_days.exs b/elixir/twelve-days/twelve_days.exs new file mode 100644 index 0000000..2cd0770 --- /dev/null +++ b/elixir/twelve-days/twelve_days.exs @@ -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 diff --git a/elixir/twelve-days/twelve_days_test.exs b/elixir/twelve-days/twelve_days_test.exs new file mode 100644 index 0000000..112336c --- /dev/null +++ b/elixir/twelve-days/twelve_days_test.exs @@ -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 diff --git a/elixir/word-count/README.md b/elixir/word-count/README.md new file mode 100644 index 0000000..5da9856 --- /dev/null +++ b/elixir/word-count/README.md @@ -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. diff --git a/elixir/word-count/word_count.exs b/elixir/word-count/word_count.exs new file mode 100644 index 0000000..bce5286 --- /dev/null +++ b/elixir/word-count/word_count.exs @@ -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 diff --git a/elixir/word-count/word_count_test.exs b/elixir/word-count/word_count_test.exs new file mode 100644 index 0000000..e066e52 --- /dev/null +++ b/elixir/word-count/word_count_test.exs @@ -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 diff --git a/elm/hello-world/HelloWorld.elm b/elm/hello-world/HelloWorld.elm new file mode 100644 index 0000000..95847fd --- /dev/null +++ b/elm/hello-world/HelloWorld.elm @@ -0,0 +1,5 @@ +module HelloWorld exposing (..) + +helloWorld : Maybe String -> String +helloWorld name = + "Hello, World!" diff --git a/elm/hello-world/README.md b/elm/hello-world/README.md new file mode 100644 index 0000000..d1fe144 --- /dev/null +++ b/elm/hello-world/README.md @@ -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. diff --git a/elm/hello-world/elm-package.json b/elm/hello-world/elm-package.json new file mode 100644 index 0000000..8f73600 --- /dev/null +++ b/elm/hello-world/elm-package.json @@ -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" +} + diff --git a/elm/hello-world/package.json b/elm/hello-world/package.json new file mode 100644 index 0000000..31d6fb3 --- /dev/null +++ b/elm/hello-world/package.json @@ -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" + } +} diff --git a/elm/hello-world/tests/Tests.elm b/elm/hello-world/tests/Tests.elm new file mode 100644 index 0000000..f679dd2 --- /dev/null +++ b/elm/hello-world/tests/Tests.elm @@ -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")) + ] diff --git a/elm/hello-world/tests/elm-package.json b/elm/hello-world/tests/elm-package.json new file mode 100644 index 0000000..3e92515 --- /dev/null +++ b/elm/hello-world/tests/elm-package.json @@ -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" +} diff --git a/go/gigasecond/README.md b/go/gigasecond/README.md new file mode 100644 index 0000000..168a5ea --- /dev/null +++ b/go/gigasecond/README.md @@ -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. diff --git a/go/gigasecond/cases_test.go b/go/gigasecond/cases_test.go new file mode 100644 index 0000000..ba6c58c --- /dev/null +++ b/go/gigasecond/cases_test.go @@ -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", + }, +} diff --git a/go/gigasecond/gigasecond.go b/go/gigasecond/gigasecond.go new file mode 100644 index 0000000..97ba5b9 --- /dev/null +++ b/go/gigasecond/gigasecond.go @@ -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 +} diff --git a/go/gigasecond/gigasecond_test.go b/go/gigasecond/gigasecond_test.go new file mode 100644 index 0000000..ae90d69 --- /dev/null +++ b/go/gigasecond/gigasecond_test.go @@ -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{}) + } +} diff --git a/javascript/hello-world/README.md b/javascript/hello-world/README.md new file mode 100644 index 0000000..3a36a6b --- /dev/null +++ b/javascript/hello-world/README.md @@ -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. diff --git a/javascript/hello-world/hello-world.js b/javascript/hello-world/hello-world.js new file mode 100644 index 0000000..000d959 --- /dev/null +++ b/javascript/hello-world/hello-world.js @@ -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; diff --git a/javascript/hello-world/hello-world.spec.js b/javascript/hello-world/hello-world.spec.js new file mode 100644 index 0000000..2d1a820 --- /dev/null +++ b/javascript/hello-world/hello-world.spec.js @@ -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!'); + }); +}); diff --git a/python/hello-world/README.md b/python/hello-world/README.md new file mode 100644 index 0000000..885d3b5 --- /dev/null +++ b/python/hello-world/README.md @@ -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. diff --git a/python/hello-world/hello_world.py b/python/hello-world/hello_world.py new file mode 100644 index 0000000..e24f8a4 --- /dev/null +++ b/python/hello-world/hello_world.py @@ -0,0 +1,2 @@ +def hello(name=''): + return "Hello, World!" diff --git a/python/hello-world/hello_world.pyc b/python/hello-world/hello_world.pyc new file mode 100644 index 0000000000000000000000000000000000000000..abba5ac57c2bcc495285e192f8c9d26bc3799ad3 GIT binary patch literal 332 zcmZSn%*&-QWo}e50~9a;X$K%K761|{K*Y$WH2!VYcK-^OMsXmnGs09urrWd z%mO5Uii0&kCioTe0!fe5oSb|eh4B2MoD@Y3pa6pgNJ|MwXob7KlBOEU8FVlqJH>6U|xgRtYlY(1bfD^NdJ8e~B+ k$O#OLeqh^zKpcckU>3#JaRAM<$<0qG%}KQb+X%7{083Fx?EnA( literal 0 HcmV?d00001 diff --git a/python/hello-world/hello_world_test.py b/python/hello-world/hello_world_test.py new file mode 100644 index 0000000..c1bcd6c --- /dev/null +++ b/python/hello-world/hello_world_test.py @@ -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() diff --git a/python/isogram/README.md b/python/isogram/README.md new file mode 100644 index 0000000..edb8898 --- /dev/null +++ b/python/isogram/README.md @@ -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. diff --git a/python/isogram/isogram.py b/python/isogram/isogram.py new file mode 100644 index 0000000..98b31c5 --- /dev/null +++ b/python/isogram/isogram.py @@ -0,0 +1,2 @@ +def is_isogram(string): + pass diff --git a/python/isogram/isogram_test.py b/python/isogram/isogram_test.py new file mode 100644 index 0000000..175ec92 --- /dev/null +++ b/python/isogram/isogram_test.py @@ -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() diff --git a/python/leap/README.md b/python/leap/README.md new file mode 100644 index 0000000..9b65afb --- /dev/null +++ b/python/leap/README.md @@ -0,0 +1,57 @@ +# Leap + +Given a year, report if it is a leap year. + +The tricky thing here is that a leap year in the Gregorian calendar occurs: + +```text +on every year that is evenly divisible by 4 + except every year that is evenly divisible by 100 + unless the year is also evenly divisible by 400 +``` + +For example, 1997 is not a leap year, but 1996 is. 1900 is not a leap +year, but 2000 is. + +If your language provides a method in the standard library that does +this look-up, pretend it doesn't exist and implement it yourself. + +## Notes + +Though our exercise adopts some very simple rules, there is more to +learn! + +For a delightful, four minute explanation of the whole leap year +phenomenon, go watch [this youtube video][video]. + +[video]: http://www.youtube.com/watch?v=xX96xng7sAE + +## 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. diff --git a/python/leap/leap.py b/python/leap/leap.py new file mode 100644 index 0000000..84d2dc2 --- /dev/null +++ b/python/leap/leap.py @@ -0,0 +1,2 @@ +def is_leap_year(year): + return year % 400 == 0 or (year % 4 == 0 and year % 100 != 0); diff --git a/python/leap/leap.pyc b/python/leap/leap.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d6d4c52ba28c6c546ad005062e616247fbf96283 GIT binary patch literal 347 zcmbVGK?=e!5Zty3BKGRR7xbbJ5D}sG9uzMUklF?sY;DO_Q1Ivje1N{v4>+3&-VN+z zXEr;N;2jPp&(|)a@9}W2P#gksqC3$JjYpfvhmy%$N=S_28Q|t#jB}rkJ~dOv1N!p1 zn& zMa3~m8Hq(jnZ+@w6{$tZnZ>y=1(hWk`FSx#sbxUvRNdl|qRhN>7&jim)dMPG2buy^ o1hT0ZWIY3;AK2O;5C>r+m_;RPIe;eHm-;{X5v literal 0 HcmV?d00001 diff --git a/python/reverse-string/reverse_string_test.py b/python/reverse-string/reverse_string_test.py new file mode 100644 index 0000000..5dec7aa --- /dev/null +++ b/python/reverse-string/reverse_string_test.py @@ -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()