From 73be23d8789bc27b1ee816432f27f34966c9aa70 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Fri, 9 Mar 2018 09:40:18 -0500 Subject: [PATCH] didn't commit after last solution --- elixir/anagram/README.md | 48 +++++++++++ elixir/anagram/anagram.exs | 16 ++++ elixir/anagram/anagram_test.exs | 76 +++++++++++++++++ elixir/matrix/README.md | 82 +++++++++++++++++++ elixir/matrix/matrix.exs | 47 +++++++++++ elixir/matrix/matrix_test.exs | 58 +++++++++++++ elixir/simple-linked-list/linked_list.exs | 38 +++++++-- .../simple-linked-list/linked_list_test.exs | 2 +- 8 files changed, 357 insertions(+), 10 deletions(-) create mode 100644 elixir/anagram/README.md create mode 100644 elixir/anagram/anagram.exs create mode 100644 elixir/anagram/anagram_test.exs create mode 100644 elixir/matrix/README.md create mode 100644 elixir/matrix/matrix.exs create mode 100644 elixir/matrix/matrix_test.exs diff --git a/elixir/anagram/README.md b/elixir/anagram/README.md new file mode 100644 index 0000000..69127ad --- /dev/null +++ b/elixir/anagram/README.md @@ -0,0 +1,48 @@ +# Anagram + +Given a word and a list of possible anagrams, select the correct sublist. + +Given `"listen"` and a list of candidates like `"enlists" "google" +"inlets" "banana"` the program should return a list containing +`"inlets"`. + +## Running tests + +Execute the tests with: + +```bash +$ elixir anagram_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 Extreme Startup game [https://github.com/rchatley/extreme_startup](https://github.com/rchatley/extreme_startup) + +## 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/anagram/anagram.exs b/elixir/anagram/anagram.exs new file mode 100644 index 0000000..581473f --- /dev/null +++ b/elixir/anagram/anagram.exs @@ -0,0 +1,16 @@ +defmodule Anagram do + @doc """ + Returns all candidates that are anagrams of, but not equal to, 'base'. + """ + @spec match(String.t(), [String.t()]) :: [String.t()] + def match(base, candidates) do + b = String.downcase(base) + + Enum.filter(candidates, fn w -> + w = String.downcase(w) + + Enum.sort(String.graphemes(w)) == Enum.sort(String.graphemes(b)) && + String.length(b) == String.length(w) && b != w + end) + end +end diff --git a/elixir/anagram/anagram_test.exs b/elixir/anagram/anagram_test.exs new file mode 100644 index 0000000..2c37022 --- /dev/null +++ b/elixir/anagram/anagram_test.exs @@ -0,0 +1,76 @@ +if !System.get_env("EXERCISM_TEST_EXAMPLES") do + Code.load_file("anagram.exs", __DIR__) +end + +ExUnit.start() +ExUnit.configure(trace: true) + +defmodule AnagramTest do + use ExUnit.Case + + # @tag :pending + test "no matches" do + matches = Anagram.match("diaper", ["hello", "world", "zombies", "pants"]) + assert matches == [] + end + + @tag :pending + test "detect simple anagram" do + matches = Anagram.match("ant", ["tan", "stand", "at"]) + assert matches == ["tan"] + end + + @tag :pending + test "detect multiple anagrams" do + matches = Anagram.match("master", ["stream", "pigeon", "maters"]) + assert matches == ["stream", "maters"] + end + + @tag :pending + test "do not detect anagram subsets" do + matches = Anagram.match("good", ~w(dog goody)) + assert matches == [] + end + + @tag :pending + test "detect anagram" do + matches = Anagram.match("listen", ~w(enlists google inlets banana)) + assert matches == ["inlets"] + end + + @tag :pending + test "multiple anagrams" do + matches = Anagram.match("allergy", ~w(gallery ballerina regally clergy largely leading)) + assert matches == ["gallery", "regally", "largely"] + end + + @tag :pending + test "anagrams must use all letters exactly once" do + matches = Anagram.match("patter", ["tapper"]) + assert matches == [] + end + + @tag :pending + test "detect anagrams with case-insensitive subject" do + matches = Anagram.match("Orchestra", ~w(cashregister carthorse radishes)) + assert matches == ["carthorse"] + end + + @tag :pending + test "detect anagrams with case-insensitive candidate" do + matches = Anagram.match("orchestra", ~w(cashregister Carthorse radishes)) + assert matches == ["Carthorse"] + end + + @tag :pending + test "anagrams must not be the source word" do + matches = Anagram.match("corn", ["corn", "dark", "Corn", "rank", "CORN", "cron", "park"]) + assert matches == ["cron"] + end + + @tag :pending + test "do not detect words based on checksum" do + matches = Anagram.match("mass", ["last"]) + assert matches == [] + end +end diff --git a/elixir/matrix/README.md b/elixir/matrix/README.md new file mode 100644 index 0000000..3b4743d --- /dev/null +++ b/elixir/matrix/README.md @@ -0,0 +1,82 @@ +# Matrix + +Given a string representing a matrix of numbers, return the rows and columns of +that matrix. + +So given a string with embedded newlines like: + +```text +9 8 7 +5 3 2 +6 6 7 +``` + +representing this matrix: + +```text + 0 1 2 + |--------- +0 | 9 8 7 +1 | 5 3 2 +2 | 6 6 7 +``` + +your code should be able to spit out: + +- A list of the rows, reading each row left-to-right while moving + top-to-bottom across the rows, +- A list of the columns, reading each column top-to-bottom while moving + from left-to-right. + +The rows for our example matrix: + +- 9, 8, 7 +- 5, 3, 2 +- 6, 6, 7 + +And its columns: + +- 9, 5, 6 +- 8, 3, 6 +- 7, 2, 7 + +## Running tests + +Execute the tests with: + +```bash +$ elixir matrix_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 + +Warmup to the `saddle-points` warmup. [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/matrix/matrix.exs b/elixir/matrix/matrix.exs new file mode 100644 index 0000000..dc499c0 --- /dev/null +++ b/elixir/matrix/matrix.exs @@ -0,0 +1,47 @@ +defmodule Matrix do + defstruct matrix: nil + + @doc """ + Convert an `input` string, with rows separated by newlines and values + separated by single spaces, into a `Matrix` struct. + """ + @spec from_string(input :: String.t()) :: %Matrix{} + def from_string(input) do + end + + @doc """ + Write the `matrix` out as a string, with rows separated by newlines and + values separated by single spaces. + """ + @spec to_string(matrix :: %Matrix{}) :: String.t() + def to_string(matrix) do + end + + @doc """ + Given a `matrix`, return its rows as a list of lists of integers. + """ + @spec rows(matrix :: %Matrix{}) :: list(list(integer)) + def rows(matrix) do + end + + @doc """ + Given a `matrix` and `index`, return the row at `index`. + """ + @spec row(matrix :: %Matrix{}, index :: integer) :: list(integer) + def row(matrix, index) do + end + + @doc """ + Given a `matrix`, return its columns as a list of lists of integers. + """ + @spec columns(matrix :: %Matrix{}) :: list(list(integer)) + def columns(matrix) do + end + + @doc """ + Given a `matrix` and `index`, return the column at `index`. + """ + @spec column(matrix :: %Matrix{}, index :: integer) :: list(integer) + def column(matrix, index) do + end +end diff --git a/elixir/matrix/matrix_test.exs b/elixir/matrix/matrix_test.exs new file mode 100644 index 0000000..4220de6 --- /dev/null +++ b/elixir/matrix/matrix_test.exs @@ -0,0 +1,58 @@ +if !System.get_env("EXERCISM_TEST_EXAMPLES") do + Code.load_file("matrix.exs", __DIR__) +end + +ExUnit.start() +ExUnit.configure(trace: true) + +defmodule MatrixTest do + use ExUnit.Case + + @input "1 2 3\n4 5 6\n7 8 9" + + # @tag :pending + test "reading from and writing to string" do + matrix = Matrix.from_string(@input) + assert Matrix.to_string(matrix) == @input + end + + @tag :pending + test "rows should return nested lists regardless of internal structure" do + matrix = Matrix.from_string(@input) + + assert Matrix.rows(matrix) == [ + [1, 2, 3], + [4, 5, 6], + [7, 8, 9] + ] + end + + @tag :pending + test "row should return list at index" do + matrix = Matrix.from_string(@input) + + assert Matrix.row(matrix, 0) == [1, 2, 3] + assert Matrix.row(matrix, 1) == [4, 5, 6] + assert Matrix.row(matrix, 2) == [7, 8, 9] + end + + @tag :pending + test "columns should return nested lists regardless of internal structure" do + matrix = Matrix.from_string(@input) + + assert Matrix.columns(matrix) == [ + [1, 4, 7], + [2, 5, 8], + [3, 6, 9] + ] + end + + @tag :pending + test "column should return list at index" do + matrix = Matrix.from_string(@input) + + assert Matrix.column(matrix, 0) == [1, 4, 7] + assert Matrix.column(matrix, 1) == [2, 5, 8] + assert Matrix.column(matrix, 2) == [3, 6, 9] + end +end diff --git a/elixir/simple-linked-list/linked_list.exs b/elixir/simple-linked-list/linked_list.exs index 45485d0..c34aa29 100644 --- a/elixir/simple-linked-list/linked_list.exs +++ b/elixir/simple-linked-list/linked_list.exs @@ -6,7 +6,7 @@ defmodule LinkedList do """ @spec new() :: t def new() do - # Your implementation here... + [] end @doc """ @@ -14,7 +14,7 @@ defmodule LinkedList do """ @spec push(t, any()) :: t def push(list, elem) do - # Your implementation here... + [elem | list] end @doc """ @@ -22,7 +22,7 @@ defmodule LinkedList do """ @spec length(t) :: non_neg_integer() def length(list) do - # Your implementation here... + Enum.count(list) end @doc """ @@ -30,7 +30,7 @@ defmodule LinkedList do """ @spec empty?(t) :: boolean() def empty?(list) do - # Your implementation here... + Enum.empty?(list) end @doc """ @@ -38,7 +38,13 @@ defmodule LinkedList do """ @spec peek(t) :: {:ok, any()} | {:error, :empty_list} def peek(list) do - # Your implementation here... + cond do + empty?(list) -> + {:error, :empty_list} + + true -> + {:ok, hd(list)} + end end @doc """ @@ -46,7 +52,13 @@ defmodule LinkedList do """ @spec tail(t) :: {:ok, t} | {:error, :empty_list} def tail(list) do - # Your implementation here... + cond do + empty?(list) -> + {:error, :empty_list} + + true -> + {:ok, tl(list)} + end end @doc """ @@ -54,7 +66,14 @@ defmodule LinkedList do """ @spec pop(t) :: {:ok, any(), t} | {:error, :empty_list} def pop(list) do - # Your implementation here... + cond do + empty?(list) -> + {:error, :empty_list} + + true -> + [hd | tail] = list + {:ok, hd, tail} + end end @doc """ @@ -62,7 +81,7 @@ defmodule LinkedList do """ @spec from_list(list()) :: t def from_list(list) do - # Your implementation here... + list end @doc """ @@ -70,7 +89,7 @@ defmodule LinkedList do """ @spec to_list(t) :: list() def to_list(list) do - # Your implementation here... + Enum.to_list(list) end @doc """ @@ -79,5 +98,6 @@ defmodule LinkedList do @spec reverse(t) :: t def reverse(list) do # Your implementation here... + Enum.reverse(list) end end diff --git a/elixir/simple-linked-list/linked_list_test.exs b/elixir/simple-linked-list/linked_list_test.exs index 4a8f4dd..0308fdf 100644 --- a/elixir/simple-linked-list/linked_list_test.exs +++ b/elixir/simple-linked-list/linked_list_test.exs @@ -3,7 +3,7 @@ if !System.get_env("EXERCISM_TEST_EXAMPLES") do end ExUnit.start() -ExUnit.configure(exclude: :pending, trace: true) +ExUnit.configure(trace: true) defmodule LinkedListTest do use ExUnit.Case