diff --git a/elixir/beer-song/README.md b/elixir/beer-song/README.md new file mode 100644 index 0000000..914f4e2 --- /dev/null +++ b/elixir/beer-song/README.md @@ -0,0 +1,362 @@ +# Beer Song + +Recite the lyrics to that beloved classic, that field-trip favorite: 99 Bottles of Beer on the Wall. + +Note that not all verses are identical. + +```text +99 bottles of beer on the wall, 99 bottles of beer. +Take one down and pass it around, 98 bottles of beer on the wall. + +98 bottles of beer on the wall, 98 bottles of beer. +Take one down and pass it around, 97 bottles of beer on the wall. + +97 bottles of beer on the wall, 97 bottles of beer. +Take one down and pass it around, 96 bottles of beer on the wall. + +96 bottles of beer on the wall, 96 bottles of beer. +Take one down and pass it around, 95 bottles of beer on the wall. + +95 bottles of beer on the wall, 95 bottles of beer. +Take one down and pass it around, 94 bottles of beer on the wall. + +94 bottles of beer on the wall, 94 bottles of beer. +Take one down and pass it around, 93 bottles of beer on the wall. + +93 bottles of beer on the wall, 93 bottles of beer. +Take one down and pass it around, 92 bottles of beer on the wall. + +92 bottles of beer on the wall, 92 bottles of beer. +Take one down and pass it around, 91 bottles of beer on the wall. + +91 bottles of beer on the wall, 91 bottles of beer. +Take one down and pass it around, 90 bottles of beer on the wall. + +90 bottles of beer on the wall, 90 bottles of beer. +Take one down and pass it around, 89 bottles of beer on the wall. + +89 bottles of beer on the wall, 89 bottles of beer. +Take one down and pass it around, 88 bottles of beer on the wall. + +88 bottles of beer on the wall, 88 bottles of beer. +Take one down and pass it around, 87 bottles of beer on the wall. + +87 bottles of beer on the wall, 87 bottles of beer. +Take one down and pass it around, 86 bottles of beer on the wall. + +86 bottles of beer on the wall, 86 bottles of beer. +Take one down and pass it around, 85 bottles of beer on the wall. + +85 bottles of beer on the wall, 85 bottles of beer. +Take one down and pass it around, 84 bottles of beer on the wall. + +84 bottles of beer on the wall, 84 bottles of beer. +Take one down and pass it around, 83 bottles of beer on the wall. + +83 bottles of beer on the wall, 83 bottles of beer. +Take one down and pass it around, 82 bottles of beer on the wall. + +82 bottles of beer on the wall, 82 bottles of beer. +Take one down and pass it around, 81 bottles of beer on the wall. + +81 bottles of beer on the wall, 81 bottles of beer. +Take one down and pass it around, 80 bottles of beer on the wall. + +80 bottles of beer on the wall, 80 bottles of beer. +Take one down and pass it around, 79 bottles of beer on the wall. + +79 bottles of beer on the wall, 79 bottles of beer. +Take one down and pass it around, 78 bottles of beer on the wall. + +78 bottles of beer on the wall, 78 bottles of beer. +Take one down and pass it around, 77 bottles of beer on the wall. + +77 bottles of beer on the wall, 77 bottles of beer. +Take one down and pass it around, 76 bottles of beer on the wall. + +76 bottles of beer on the wall, 76 bottles of beer. +Take one down and pass it around, 75 bottles of beer on the wall. + +75 bottles of beer on the wall, 75 bottles of beer. +Take one down and pass it around, 74 bottles of beer on the wall. + +74 bottles of beer on the wall, 74 bottles of beer. +Take one down and pass it around, 73 bottles of beer on the wall. + +73 bottles of beer on the wall, 73 bottles of beer. +Take one down and pass it around, 72 bottles of beer on the wall. + +72 bottles of beer on the wall, 72 bottles of beer. +Take one down and pass it around, 71 bottles of beer on the wall. + +71 bottles of beer on the wall, 71 bottles of beer. +Take one down and pass it around, 70 bottles of beer on the wall. + +70 bottles of beer on the wall, 70 bottles of beer. +Take one down and pass it around, 69 bottles of beer on the wall. + +69 bottles of beer on the wall, 69 bottles of beer. +Take one down and pass it around, 68 bottles of beer on the wall. + +68 bottles of beer on the wall, 68 bottles of beer. +Take one down and pass it around, 67 bottles of beer on the wall. + +67 bottles of beer on the wall, 67 bottles of beer. +Take one down and pass it around, 66 bottles of beer on the wall. + +66 bottles of beer on the wall, 66 bottles of beer. +Take one down and pass it around, 65 bottles of beer on the wall. + +65 bottles of beer on the wall, 65 bottles of beer. +Take one down and pass it around, 64 bottles of beer on the wall. + +64 bottles of beer on the wall, 64 bottles of beer. +Take one down and pass it around, 63 bottles of beer on the wall. + +63 bottles of beer on the wall, 63 bottles of beer. +Take one down and pass it around, 62 bottles of beer on the wall. + +62 bottles of beer on the wall, 62 bottles of beer. +Take one down and pass it around, 61 bottles of beer on the wall. + +61 bottles of beer on the wall, 61 bottles of beer. +Take one down and pass it around, 60 bottles of beer on the wall. + +60 bottles of beer on the wall, 60 bottles of beer. +Take one down and pass it around, 59 bottles of beer on the wall. + +59 bottles of beer on the wall, 59 bottles of beer. +Take one down and pass it around, 58 bottles of beer on the wall. + +58 bottles of beer on the wall, 58 bottles of beer. +Take one down and pass it around, 57 bottles of beer on the wall. + +57 bottles of beer on the wall, 57 bottles of beer. +Take one down and pass it around, 56 bottles of beer on the wall. + +56 bottles of beer on the wall, 56 bottles of beer. +Take one down and pass it around, 55 bottles of beer on the wall. + +55 bottles of beer on the wall, 55 bottles of beer. +Take one down and pass it around, 54 bottles of beer on the wall. + +54 bottles of beer on the wall, 54 bottles of beer. +Take one down and pass it around, 53 bottles of beer on the wall. + +53 bottles of beer on the wall, 53 bottles of beer. +Take one down and pass it around, 52 bottles of beer on the wall. + +52 bottles of beer on the wall, 52 bottles of beer. +Take one down and pass it around, 51 bottles of beer on the wall. + +51 bottles of beer on the wall, 51 bottles of beer. +Take one down and pass it around, 50 bottles of beer on the wall. + +50 bottles of beer on the wall, 50 bottles of beer. +Take one down and pass it around, 49 bottles of beer on the wall. + +49 bottles of beer on the wall, 49 bottles of beer. +Take one down and pass it around, 48 bottles of beer on the wall. + +48 bottles of beer on the wall, 48 bottles of beer. +Take one down and pass it around, 47 bottles of beer on the wall. + +47 bottles of beer on the wall, 47 bottles of beer. +Take one down and pass it around, 46 bottles of beer on the wall. + +46 bottles of beer on the wall, 46 bottles of beer. +Take one down and pass it around, 45 bottles of beer on the wall. + +45 bottles of beer on the wall, 45 bottles of beer. +Take one down and pass it around, 44 bottles of beer on the wall. + +44 bottles of beer on the wall, 44 bottles of beer. +Take one down and pass it around, 43 bottles of beer on the wall. + +43 bottles of beer on the wall, 43 bottles of beer. +Take one down and pass it around, 42 bottles of beer on the wall. + +42 bottles of beer on the wall, 42 bottles of beer. +Take one down and pass it around, 41 bottles of beer on the wall. + +41 bottles of beer on the wall, 41 bottles of beer. +Take one down and pass it around, 40 bottles of beer on the wall. + +40 bottles of beer on the wall, 40 bottles of beer. +Take one down and pass it around, 39 bottles of beer on the wall. + +39 bottles of beer on the wall, 39 bottles of beer. +Take one down and pass it around, 38 bottles of beer on the wall. + +38 bottles of beer on the wall, 38 bottles of beer. +Take one down and pass it around, 37 bottles of beer on the wall. + +37 bottles of beer on the wall, 37 bottles of beer. +Take one down and pass it around, 36 bottles of beer on the wall. + +36 bottles of beer on the wall, 36 bottles of beer. +Take one down and pass it around, 35 bottles of beer on the wall. + +35 bottles of beer on the wall, 35 bottles of beer. +Take one down and pass it around, 34 bottles of beer on the wall. + +34 bottles of beer on the wall, 34 bottles of beer. +Take one down and pass it around, 33 bottles of beer on the wall. + +33 bottles of beer on the wall, 33 bottles of beer. +Take one down and pass it around, 32 bottles of beer on the wall. + +32 bottles of beer on the wall, 32 bottles of beer. +Take one down and pass it around, 31 bottles of beer on the wall. + +31 bottles of beer on the wall, 31 bottles of beer. +Take one down and pass it around, 30 bottles of beer on the wall. + +30 bottles of beer on the wall, 30 bottles of beer. +Take one down and pass it around, 29 bottles of beer on the wall. + +29 bottles of beer on the wall, 29 bottles of beer. +Take one down and pass it around, 28 bottles of beer on the wall. + +28 bottles of beer on the wall, 28 bottles of beer. +Take one down and pass it around, 27 bottles of beer on the wall. + +27 bottles of beer on the wall, 27 bottles of beer. +Take one down and pass it around, 26 bottles of beer on the wall. + +26 bottles of beer on the wall, 26 bottles of beer. +Take one down and pass it around, 25 bottles of beer on the wall. + +25 bottles of beer on the wall, 25 bottles of beer. +Take one down and pass it around, 24 bottles of beer on the wall. + +24 bottles of beer on the wall, 24 bottles of beer. +Take one down and pass it around, 23 bottles of beer on the wall. + +23 bottles of beer on the wall, 23 bottles of beer. +Take one down and pass it around, 22 bottles of beer on the wall. + +22 bottles of beer on the wall, 22 bottles of beer. +Take one down and pass it around, 21 bottles of beer on the wall. + +21 bottles of beer on the wall, 21 bottles of beer. +Take one down and pass it around, 20 bottles of beer on the wall. + +20 bottles of beer on the wall, 20 bottles of beer. +Take one down and pass it around, 19 bottles of beer on the wall. + +19 bottles of beer on the wall, 19 bottles of beer. +Take one down and pass it around, 18 bottles of beer on the wall. + +18 bottles of beer on the wall, 18 bottles of beer. +Take one down and pass it around, 17 bottles of beer on the wall. + +17 bottles of beer on the wall, 17 bottles of beer. +Take one down and pass it around, 16 bottles of beer on the wall. + +16 bottles of beer on the wall, 16 bottles of beer. +Take one down and pass it around, 15 bottles of beer on the wall. + +15 bottles of beer on the wall, 15 bottles of beer. +Take one down and pass it around, 14 bottles of beer on the wall. + +14 bottles of beer on the wall, 14 bottles of beer. +Take one down and pass it around, 13 bottles of beer on the wall. + +13 bottles of beer on the wall, 13 bottles of beer. +Take one down and pass it around, 12 bottles of beer on the wall. + +12 bottles of beer on the wall, 12 bottles of beer. +Take one down and pass it around, 11 bottles of beer on the wall. + +11 bottles of beer on the wall, 11 bottles of beer. +Take one down and pass it around, 10 bottles of beer on the wall. + +10 bottles of beer on the wall, 10 bottles of beer. +Take one down and pass it around, 9 bottles of beer on the wall. + +9 bottles of beer on the wall, 9 bottles of beer. +Take one down and pass it around, 8 bottles of beer on the wall. + +8 bottles of beer on the wall, 8 bottles of beer. +Take one down and pass it around, 7 bottles of beer on the wall. + +7 bottles of beer on the wall, 7 bottles of beer. +Take one down and pass it around, 6 bottles of beer on the wall. + +6 bottles of beer on the wall, 6 bottles of beer. +Take one down and pass it around, 5 bottles of beer on the wall. + +5 bottles of beer on the wall, 5 bottles of beer. +Take one down and pass it around, 4 bottles of beer on the wall. + +4 bottles of beer on the wall, 4 bottles of beer. +Take one down and pass it around, 3 bottles of beer on the wall. + +3 bottles of beer on the wall, 3 bottles of beer. +Take one down and pass it around, 2 bottles of beer on the wall. + +2 bottles of beer on the wall, 2 bottles of beer. +Take one down and pass it around, 1 bottle of beer on the wall. + +1 bottle of beer on the wall, 1 bottle of beer. +Take it down and pass it around, no more bottles of beer on the wall. + +No more bottles of beer on the wall, no more bottles of beer. +Go to the store and buy some more, 99 bottles of beer on the wall. +``` + +## For bonus points + +Did you get the tests passing and the code clean? If you want to, these +are some additional things you could try: + +* Remove as much duplication as you possibly can. +* Optimize for readability, even if it means introducing duplication. +* If you've removed all the duplication, do you have a lot of + conditionals? Try replacing the conditionals with polymorphism, if it + applies in this language. How readable is it? + +Then please share your thoughts in a comment on the submission. Did this +experiment make the code better? Worse? Did you learn anything from it? + +## Running tests + +Execute the tests with: + +```bash +$ elixir beer_song_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 + +Learn to Program by Chris Pine [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/beer-song/beer_song.exs b/elixir/beer-song/beer_song.exs new file mode 100644 index 0000000..490f93b --- /dev/null +++ b/elixir/beer-song/beer_song.exs @@ -0,0 +1,40 @@ +defmodule BeerSong do + @doc """ + Get a single verse of the beer song + """ + @spec verse(integer) :: String.t() + def verse(number) do + """ + #{String.capitalize(bottle_num(number))} of beer on the wall, #{bottle_num(number)} of beer. + #{action(number)}, #{bottle_num(number - 1)} of beer on the wall. + """ + end + + defp bottle_num(num) do + case num do + 1 -> "1 bottle" + 0 -> "no more bottles" + n when n < 0 -> "99 bottles" + _ -> "#{num} bottles" + end + end + + defp action(num) do + if num == 0 do + "Go to the store and buy some more" + else + article = if num == 1, do: "it", else: "one" + "Take #{article} down and pass it around" + end + end + + @doc """ + Get the entire beer song for a given range of numbers of bottles. + """ + @spec lyrics(Range.t()) :: String.t() + def lyrics(range \\ 99..0) do + range + |> Enum.map(&verse/1) + |> Enum.join("\n") + end +end diff --git a/elixir/beer-song/beer_song_test.exs b/elixir/beer-song/beer_song_test.exs new file mode 100644 index 0000000..d606e87 --- /dev/null +++ b/elixir/beer-song/beer_song_test.exs @@ -0,0 +1,363 @@ +if !System.get_env("EXERCISM_TEST_EXAMPLES") do + Code.load_file("beer_song.exs", __DIR__) +end + +ExUnit.start() +ExUnit.configure(trace: true) + +defmodule BeerSongTest do + use ExUnit.Case + + test "getting the first verse (99 bottles)" do + assert BeerSong.verse(99) == """ + 99 bottles of beer on the wall, 99 bottles of beer. + Take one down and pass it around, 98 bottles of beer on the wall. + """ + end + + @tag :pending + test "getting the second verse (98 bottles)" do + assert BeerSong.verse(98) == """ + 98 bottles of beer on the wall, 98 bottles of beer. + Take one down and pass it around, 97 bottles of beer on the wall. + """ + end + + @tag :pending + test "getting just the penultimate verse" do + assert BeerSong.verse(1) == """ + 1 bottle of beer on the wall, 1 bottle of beer. + Take it down and pass it around, no more bottles of beer on the wall. + """ + end + + @tag :pending + test "getting just the last verse" do + assert BeerSong.verse(0) == """ + No more bottles of beer on the wall, no more bottles of beer. + Go to the store and buy some more, 99 bottles of beer on the wall. + """ + end + + @tag :pending + test "getting the last 4 verses" do + assert BeerSong.lyrics(3..0) == """ + 3 bottles of beer on the wall, 3 bottles of beer. + Take one down and pass it around, 2 bottles of beer on the wall. + + 2 bottles of beer on the wall, 2 bottles of beer. + Take one down and pass it around, 1 bottle of beer on the wall. + + 1 bottle of beer on the wall, 1 bottle of beer. + Take it down and pass it around, no more bottles of beer on the wall. + + No more bottles of beer on the wall, no more bottles of beer. + Go to the store and buy some more, 99 bottles of beer on the wall. + """ + end + + @tag :pending + test "getting the whole song" do + assert BeerSong.lyrics() == """ + 99 bottles of beer on the wall, 99 bottles of beer. + Take one down and pass it around, 98 bottles of beer on the wall. + + 98 bottles of beer on the wall, 98 bottles of beer. + Take one down and pass it around, 97 bottles of beer on the wall. + + 97 bottles of beer on the wall, 97 bottles of beer. + Take one down and pass it around, 96 bottles of beer on the wall. + + 96 bottles of beer on the wall, 96 bottles of beer. + Take one down and pass it around, 95 bottles of beer on the wall. + + 95 bottles of beer on the wall, 95 bottles of beer. + Take one down and pass it around, 94 bottles of beer on the wall. + + 94 bottles of beer on the wall, 94 bottles of beer. + Take one down and pass it around, 93 bottles of beer on the wall. + + 93 bottles of beer on the wall, 93 bottles of beer. + Take one down and pass it around, 92 bottles of beer on the wall. + + 92 bottles of beer on the wall, 92 bottles of beer. + Take one down and pass it around, 91 bottles of beer on the wall. + + 91 bottles of beer on the wall, 91 bottles of beer. + Take one down and pass it around, 90 bottles of beer on the wall. + + 90 bottles of beer on the wall, 90 bottles of beer. + Take one down and pass it around, 89 bottles of beer on the wall. + + 89 bottles of beer on the wall, 89 bottles of beer. + Take one down and pass it around, 88 bottles of beer on the wall. + + 88 bottles of beer on the wall, 88 bottles of beer. + Take one down and pass it around, 87 bottles of beer on the wall. + + 87 bottles of beer on the wall, 87 bottles of beer. + Take one down and pass it around, 86 bottles of beer on the wall. + + 86 bottles of beer on the wall, 86 bottles of beer. + Take one down and pass it around, 85 bottles of beer on the wall. + + 85 bottles of beer on the wall, 85 bottles of beer. + Take one down and pass it around, 84 bottles of beer on the wall. + + 84 bottles of beer on the wall, 84 bottles of beer. + Take one down and pass it around, 83 bottles of beer on the wall. + + 83 bottles of beer on the wall, 83 bottles of beer. + Take one down and pass it around, 82 bottles of beer on the wall. + + 82 bottles of beer on the wall, 82 bottles of beer. + Take one down and pass it around, 81 bottles of beer on the wall. + + 81 bottles of beer on the wall, 81 bottles of beer. + Take one down and pass it around, 80 bottles of beer on the wall. + + 80 bottles of beer on the wall, 80 bottles of beer. + Take one down and pass it around, 79 bottles of beer on the wall. + + 79 bottles of beer on the wall, 79 bottles of beer. + Take one down and pass it around, 78 bottles of beer on the wall. + + 78 bottles of beer on the wall, 78 bottles of beer. + Take one down and pass it around, 77 bottles of beer on the wall. + + 77 bottles of beer on the wall, 77 bottles of beer. + Take one down and pass it around, 76 bottles of beer on the wall. + + 76 bottles of beer on the wall, 76 bottles of beer. + Take one down and pass it around, 75 bottles of beer on the wall. + + 75 bottles of beer on the wall, 75 bottles of beer. + Take one down and pass it around, 74 bottles of beer on the wall. + + 74 bottles of beer on the wall, 74 bottles of beer. + Take one down and pass it around, 73 bottles of beer on the wall. + + 73 bottles of beer on the wall, 73 bottles of beer. + Take one down and pass it around, 72 bottles of beer on the wall. + + 72 bottles of beer on the wall, 72 bottles of beer. + Take one down and pass it around, 71 bottles of beer on the wall. + + 71 bottles of beer on the wall, 71 bottles of beer. + Take one down and pass it around, 70 bottles of beer on the wall. + + 70 bottles of beer on the wall, 70 bottles of beer. + Take one down and pass it around, 69 bottles of beer on the wall. + + 69 bottles of beer on the wall, 69 bottles of beer. + Take one down and pass it around, 68 bottles of beer on the wall. + + 68 bottles of beer on the wall, 68 bottles of beer. + Take one down and pass it around, 67 bottles of beer on the wall. + + 67 bottles of beer on the wall, 67 bottles of beer. + Take one down and pass it around, 66 bottles of beer on the wall. + + 66 bottles of beer on the wall, 66 bottles of beer. + Take one down and pass it around, 65 bottles of beer on the wall. + + 65 bottles of beer on the wall, 65 bottles of beer. + Take one down and pass it around, 64 bottles of beer on the wall. + + 64 bottles of beer on the wall, 64 bottles of beer. + Take one down and pass it around, 63 bottles of beer on the wall. + + 63 bottles of beer on the wall, 63 bottles of beer. + Take one down and pass it around, 62 bottles of beer on the wall. + + 62 bottles of beer on the wall, 62 bottles of beer. + Take one down and pass it around, 61 bottles of beer on the wall. + + 61 bottles of beer on the wall, 61 bottles of beer. + Take one down and pass it around, 60 bottles of beer on the wall. + + 60 bottles of beer on the wall, 60 bottles of beer. + Take one down and pass it around, 59 bottles of beer on the wall. + + 59 bottles of beer on the wall, 59 bottles of beer. + Take one down and pass it around, 58 bottles of beer on the wall. + + 58 bottles of beer on the wall, 58 bottles of beer. + Take one down and pass it around, 57 bottles of beer on the wall. + + 57 bottles of beer on the wall, 57 bottles of beer. + Take one down and pass it around, 56 bottles of beer on the wall. + + 56 bottles of beer on the wall, 56 bottles of beer. + Take one down and pass it around, 55 bottles of beer on the wall. + + 55 bottles of beer on the wall, 55 bottles of beer. + Take one down and pass it around, 54 bottles of beer on the wall. + + 54 bottles of beer on the wall, 54 bottles of beer. + Take one down and pass it around, 53 bottles of beer on the wall. + + 53 bottles of beer on the wall, 53 bottles of beer. + Take one down and pass it around, 52 bottles of beer on the wall. + + 52 bottles of beer on the wall, 52 bottles of beer. + Take one down and pass it around, 51 bottles of beer on the wall. + + 51 bottles of beer on the wall, 51 bottles of beer. + Take one down and pass it around, 50 bottles of beer on the wall. + + 50 bottles of beer on the wall, 50 bottles of beer. + Take one down and pass it around, 49 bottles of beer on the wall. + + 49 bottles of beer on the wall, 49 bottles of beer. + Take one down and pass it around, 48 bottles of beer on the wall. + + 48 bottles of beer on the wall, 48 bottles of beer. + Take one down and pass it around, 47 bottles of beer on the wall. + + 47 bottles of beer on the wall, 47 bottles of beer. + Take one down and pass it around, 46 bottles of beer on the wall. + + 46 bottles of beer on the wall, 46 bottles of beer. + Take one down and pass it around, 45 bottles of beer on the wall. + + 45 bottles of beer on the wall, 45 bottles of beer. + Take one down and pass it around, 44 bottles of beer on the wall. + + 44 bottles of beer on the wall, 44 bottles of beer. + Take one down and pass it around, 43 bottles of beer on the wall. + + 43 bottles of beer on the wall, 43 bottles of beer. + Take one down and pass it around, 42 bottles of beer on the wall. + + 42 bottles of beer on the wall, 42 bottles of beer. + Take one down and pass it around, 41 bottles of beer on the wall. + + 41 bottles of beer on the wall, 41 bottles of beer. + Take one down and pass it around, 40 bottles of beer on the wall. + + 40 bottles of beer on the wall, 40 bottles of beer. + Take one down and pass it around, 39 bottles of beer on the wall. + + 39 bottles of beer on the wall, 39 bottles of beer. + Take one down and pass it around, 38 bottles of beer on the wall. + + 38 bottles of beer on the wall, 38 bottles of beer. + Take one down and pass it around, 37 bottles of beer on the wall. + + 37 bottles of beer on the wall, 37 bottles of beer. + Take one down and pass it around, 36 bottles of beer on the wall. + + 36 bottles of beer on the wall, 36 bottles of beer. + Take one down and pass it around, 35 bottles of beer on the wall. + + 35 bottles of beer on the wall, 35 bottles of beer. + Take one down and pass it around, 34 bottles of beer on the wall. + + 34 bottles of beer on the wall, 34 bottles of beer. + Take one down and pass it around, 33 bottles of beer on the wall. + + 33 bottles of beer on the wall, 33 bottles of beer. + Take one down and pass it around, 32 bottles of beer on the wall. + + 32 bottles of beer on the wall, 32 bottles of beer. + Take one down and pass it around, 31 bottles of beer on the wall. + + 31 bottles of beer on the wall, 31 bottles of beer. + Take one down and pass it around, 30 bottles of beer on the wall. + + 30 bottles of beer on the wall, 30 bottles of beer. + Take one down and pass it around, 29 bottles of beer on the wall. + + 29 bottles of beer on the wall, 29 bottles of beer. + Take one down and pass it around, 28 bottles of beer on the wall. + + 28 bottles of beer on the wall, 28 bottles of beer. + Take one down and pass it around, 27 bottles of beer on the wall. + + 27 bottles of beer on the wall, 27 bottles of beer. + Take one down and pass it around, 26 bottles of beer on the wall. + + 26 bottles of beer on the wall, 26 bottles of beer. + Take one down and pass it around, 25 bottles of beer on the wall. + + 25 bottles of beer on the wall, 25 bottles of beer. + Take one down and pass it around, 24 bottles of beer on the wall. + + 24 bottles of beer on the wall, 24 bottles of beer. + Take one down and pass it around, 23 bottles of beer on the wall. + + 23 bottles of beer on the wall, 23 bottles of beer. + Take one down and pass it around, 22 bottles of beer on the wall. + + 22 bottles of beer on the wall, 22 bottles of beer. + Take one down and pass it around, 21 bottles of beer on the wall. + + 21 bottles of beer on the wall, 21 bottles of beer. + Take one down and pass it around, 20 bottles of beer on the wall. + + 20 bottles of beer on the wall, 20 bottles of beer. + Take one down and pass it around, 19 bottles of beer on the wall. + + 19 bottles of beer on the wall, 19 bottles of beer. + Take one down and pass it around, 18 bottles of beer on the wall. + + 18 bottles of beer on the wall, 18 bottles of beer. + Take one down and pass it around, 17 bottles of beer on the wall. + + 17 bottles of beer on the wall, 17 bottles of beer. + Take one down and pass it around, 16 bottles of beer on the wall. + + 16 bottles of beer on the wall, 16 bottles of beer. + Take one down and pass it around, 15 bottles of beer on the wall. + + 15 bottles of beer on the wall, 15 bottles of beer. + Take one down and pass it around, 14 bottles of beer on the wall. + + 14 bottles of beer on the wall, 14 bottles of beer. + Take one down and pass it around, 13 bottles of beer on the wall. + + 13 bottles of beer on the wall, 13 bottles of beer. + Take one down and pass it around, 12 bottles of beer on the wall. + + 12 bottles of beer on the wall, 12 bottles of beer. + Take one down and pass it around, 11 bottles of beer on the wall. + + 11 bottles of beer on the wall, 11 bottles of beer. + Take one down and pass it around, 10 bottles of beer on the wall. + + 10 bottles of beer on the wall, 10 bottles of beer. + Take one down and pass it around, 9 bottles of beer on the wall. + + 9 bottles of beer on the wall, 9 bottles of beer. + Take one down and pass it around, 8 bottles of beer on the wall. + + 8 bottles of beer on the wall, 8 bottles of beer. + Take one down and pass it around, 7 bottles of beer on the wall. + + 7 bottles of beer on the wall, 7 bottles of beer. + Take one down and pass it around, 6 bottles of beer on the wall. + + 6 bottles of beer on the wall, 6 bottles of beer. + Take one down and pass it around, 5 bottles of beer on the wall. + + 5 bottles of beer on the wall, 5 bottles of beer. + Take one down and pass it around, 4 bottles of beer on the wall. + + 4 bottles of beer on the wall, 4 bottles of beer. + Take one down and pass it around, 3 bottles of beer on the wall. + + 3 bottles of beer on the wall, 3 bottles of beer. + Take one down and pass it around, 2 bottles of beer on the wall. + + 2 bottles of beer on the wall, 2 bottles of beer. + Take one down and pass it around, 1 bottle of beer on the wall. + + 1 bottle of beer on the wall, 1 bottle of beer. + Take it down and pass it around, no more bottles of beer on the wall. + + No more bottles of beer on the wall, no more bottles of beer. + Go to the store and buy some more, 99 bottles of beer on the wall. + """ + end +end diff --git a/elixir/grade-school/README.md b/elixir/grade-school/README.md new file mode 100644 index 0000000..629cd32 --- /dev/null +++ b/elixir/grade-school/README.md @@ -0,0 +1,76 @@ +# Grade School + +Given students' names along with the grade that they are in, create a roster +for the school. + +In the end, you should be able to: + +- Add a student's name to the roster for a grade + - "Add Jim to grade 2." + - "OK." +- Get a list of all students enrolled in a grade + - "Which students are in grade 2?" + - "We've only got Jim just now." +- Get a sorted list of all students in all grades. Grades should sort + as 1, 2, 3, etc., and students within a grade should be sorted + alphabetically by name. + - "Who all is enrolled in school right now?" + - "Grade 1: Anna, Barb, and Charlie. Grade 2: Alex, Peter, and Zoe. + Grade 3…" + +Note that all our students only have one name. (It's a small town, what +do you want?) + +## For bonus points + +Did you get the tests passing and the code clean? If you want to, these +are some additional things you could try: + +- If you're working in a language with mutable data structures and your + implementation allows outside code to mutate the school's internal DB + directly, see if you can prevent this. Feel free to introduce additional + tests. + +Then please share your thoughts in a comment on the submission. Did this +experiment make the code better? Worse? Did you learn anything from it? + +## Running tests + +Execute the tests with: + +```bash +$ elixir grade_school_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 pairing session with Phil Battos at gSchool [http://gschool.it](http://gschool.it) + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/elixir/grade-school/grade_school_test.exs b/elixir/grade-school/grade_school_test.exs new file mode 100644 index 0000000..441f29e --- /dev/null +++ b/elixir/grade-school/grade_school_test.exs @@ -0,0 +1,75 @@ +if !System.get_env("EXERCISM_TEST_EXAMPLES") do + Code.load_file("school.exs", __DIR__) +end + +ExUnit.start() +ExUnit.configure(trace: true) + +defmodule SchoolTest do + use ExUnit.Case + + @db %{} + + test "add student" do + actual = School.add(@db, "Aimee", 2) + assert actual == %{2 => ["Aimee"]} + end + + @tag :pending + test "add more students in same class" do + actual = + @db + |> School.add("James", 2) + |> School.add("Blair", 2) + |> School.add("Paul", 2) + + assert Enum.sort(actual[2]) == ["Blair", "James", "Paul"] + end + + @tag :pending + test "add students to different grades" do + actual = + @db + |> School.add("Chelsea", 3) + |> School.add("Logan", 7) + + assert actual == %{3 => ["Chelsea"], 7 => ["Logan"]} + end + + @tag :pending + test "get students in a grade" do + actual = + @db + |> School.add("Bradley", 5) + |> School.add("Franklin", 5) + |> School.add("Jeff", 1) + |> School.grade(5) + + assert Enum.sort(actual) == ["Bradley", "Franklin"] + end + + @tag :pending + test "get students in a non existent grade" do + assert [] == School.grade(@db, 1) + end + + @tag :pending + test "sort school by grade and by student name" do + actual = + @db + |> School.add("Bart", 4) + |> School.add("Jennifer", 4) + |> School.add("Christopher", 4) + |> School.add("Kareem", 6) + |> School.add("Kyle", 3) + |> School.sort() + + expected = [ + {3, ["Kyle"]}, + {4, ["Bart", "Christopher", "Jennifer"]}, + {6, ["Kareem"]} + ] + + assert expected == actual + end +end diff --git a/elixir/grade-school/school.exs b/elixir/grade-school/school.exs new file mode 100644 index 0000000..4f20c59 --- /dev/null +++ b/elixir/grade-school/school.exs @@ -0,0 +1,28 @@ +defmodule School do + @moduledoc """ + Simulate students in a school. + + Each student is in a grade. + """ + + @doc """ + Add a student to a particular grade in school. + """ + @spec add(map, String.t(), integer) :: map + def add(db, name, grade) do + end + + @doc """ + Return the names of the students in a particular grade. + """ + @spec grade(map, integer) :: [String.t()] + def grade(db, grade) do + end + + @doc """ + Sorts the school by grade and name. + """ + @spec sort(map) :: [{integer, [String.t()]}] + def sort(db) do + end +end diff --git a/elixir/isogram/README.md b/elixir/isogram/README.md new file mode 100644 index 0000000..e231732 --- /dev/null +++ b/elixir/isogram/README.md @@ -0,0 +1,55 @@ +# 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. + +## Running tests + +Execute the tests with: + +```bash +$ elixir isogram_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/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/elixir/isogram/isogram.exs b/elixir/isogram/isogram.exs new file mode 100644 index 0000000..c106682 --- /dev/null +++ b/elixir/isogram/isogram.exs @@ -0,0 +1,10 @@ +defmodule Isogram do + @doc """ + Determines if a word or sentence is an isogram + """ + @spec isogram?(String.t()) :: boolean + def isogram?(sentence) do + letters = Regex.scan(~r/[a-z]/, String.downcase(sentence)) + Enum.uniq(letters) == letters + end +end diff --git a/elixir/isogram/isogram_test.exs b/elixir/isogram/isogram_test.exs new file mode 100644 index 0000000..b900fcc --- /dev/null +++ b/elixir/isogram/isogram_test.exs @@ -0,0 +1,49 @@ +if !System.get_env("EXERCISM_TEST_EXAMPLES") do + Code.load_file("isogram.exs", __DIR__) +end + +ExUnit.start() +ExUnit.configure(trace: true) + +defmodule IsogramTest do + use ExUnit.Case + + test "isogram lowercase" do + assert Isogram.isogram?("subdermatoglyphic") + end + + @tag :pending + test "not isogram lowercase " do + refute Isogram.isogram?("eleven") + end + + @tag :pending + test "isogram uppercase" do + assert Isogram.isogram?("DEMONSTRABLY") + end + + @tag :pending + test "not isogram uppercase" do + refute Isogram.isogram?("ALPHABET") + end + + @tag :pending + test "isogram with dash" do + assert Isogram.isogram?("hjelmqvist-gryb-zock-pfund-wax") + end + + @tag :pending + test "not isogram with dash" do + refute Isogram.isogram?("twenty-five") + end + + @tag :pending + test "phrase is isogram" do + assert Isogram.isogram?("emily jung schwartzkopf") + end + + @tag :pending + test "phrase is not isogram" do + refute Isogram.isogram?("the quick brown fox") + end +end diff --git a/elixir/triangle/README.md b/elixir/triangle/README.md new file mode 100644 index 0000000..f201e92 --- /dev/null +++ b/elixir/triangle/README.md @@ -0,0 +1,64 @@ +# Triangle + +Determine if a triangle is equilateral, isosceles, or scalene. + +An _equilateral_ triangle has all three sides the same length. + +An _isosceles_ triangle has at least two sides the same length. (It is sometimes +specified as having exactly two sides the same length, but for the purposes of +this exercise we'll say at least two.) + +A _scalene_ triangle has all sides of different lengths. + +## Note + +For a shape to be a triangle at all, all sides have to be of length > 0, and +the sum of the lengths of any two sides must be greater than or equal to the +length of the third side. See [Triangle Inequality](https://en.wikipedia.org/wiki/Triangle_inequality). + +## Dig Deeper + +The case where the sum of the lengths of two sides _equals_ that of the +third is known as a _degenerate_ triangle - it has zero area and looks like +a single line. Feel free to add your own code/tests to check for degenerate triangles. + +## Running tests + +Execute the tests with: + +```bash +$ elixir triangle_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 Ruby Koans triangle project, parts 1 & 2 [http://rubykoans.com](http://rubykoans.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/triangle/triangle.exs b/elixir/triangle/triangle.exs new file mode 100644 index 0000000..16ee550 --- /dev/null +++ b/elixir/triangle/triangle.exs @@ -0,0 +1,28 @@ +defmodule Triangle do + @type kind :: :equilateral | :isosceles | :scalene + + @doc """ + Return the kind of triangle of a triangle with 'a', 'b' and 'c' as lengths. + """ + @spec kind(number, number, number) :: {:ok, kind} | {:error, String.t()} + def kind(a, b, c) when a <= 0 or b <= 0 or c <= 0 do + {:error, "all side lengths must be positive"} + end + + def kind(a, b, c) when a + b <= c or b + c <= a or c + a <= b do + {:error, "side lengths violate triangle inequality"} + end + + def kind(a, b, c) do + cond do + a == b && b == c -> + {:ok, :equilateral} + + a == b || b == c || a == c -> + {:ok, :isosceles} + + true -> + {:ok, :scalene} + end + end +end diff --git a/elixir/triangle/triangle_test.exs b/elixir/triangle/triangle_test.exs new file mode 100644 index 0000000..467591e --- /dev/null +++ b/elixir/triangle/triangle_test.exs @@ -0,0 +1,85 @@ +if !System.get_env("EXERCISM_TEST_EXAMPLES") do + Code.load_file("triangle.exs", __DIR__) +end + +ExUnit.start() +ExUnit.configure(trace: true) + +defmodule TriangleTest do + use ExUnit.Case + + # @tag :pending + test "equilateral triangles have equal sides" do + assert Triangle.kind(2, 2, 2) == {:ok, :equilateral} + end + + @tag :pending + test "larger equilateral triangles also have equal sides" do + assert Triangle.kind(10, 10, 10) == {:ok, :equilateral} + end + + @tag :pending + test "isosceles triangles have last two sides equal" do + assert Triangle.kind(3, 4, 4) == {:ok, :isosceles} + end + + @tag :pending + test "isosceles triangles have first and last sides equal" do + assert Triangle.kind(4, 3, 4) == {:ok, :isosceles} + end + + @tag :pending + test "isosceles triangles have two first sides equal" do + assert Triangle.kind(4, 4, 3) == {:ok, :isosceles} + end + + @tag :pending + test "isosceles triangles have in fact exactly two sides equal" do + assert Triangle.kind(10, 10, 2) == {:ok, :isosceles} + end + + @tag :pending + test "scalene triangles have no equal sides" do + assert Triangle.kind(3, 4, 5) == {:ok, :scalene} + end + + @tag :pending + test "scalene triangles have no equal sides at a larger scale too" do + assert Triangle.kind(10, 11, 12) == {:ok, :scalene} + end + + @tag :pending + test "scalene triangles have no equal sides in descending order either" do + assert Triangle.kind(5, 4, 2) == {:ok, :scalene} + end + + @tag :pending + test "very small triangles are legal" do + assert Triangle.kind(0.4, 0.6, 0.3) == {:ok, :scalene} + end + + @tag :pending + test "triangles with no size are illegal" do + assert Triangle.kind(0, 0, 0) == {:error, "all side lengths must be positive"} + end + + @tag :pending + test "triangles with negative sides are illegal" do + assert Triangle.kind(3, 4, -5) == {:error, "all side lengths must be positive"} + end + + @tag :pending + test "triangles violating triangle inequality are illegal" do + assert Triangle.kind(1, 1, 3) == {:error, "side lengths violate triangle inequality"} + end + + @tag :pending + test "triangles violating triangle inequality are illegal 2" do + assert Triangle.kind(2, 4, 2) == {:error, "side lengths violate triangle inequality"} + end + + @tag :pending + test "triangles violating triangle inequality are illegal 3" do + assert Triangle.kind(7, 3, 2) == {:error, "side lengths violate triangle inequality"} + end +end