lunchtime elixir
This commit is contained in:
parent
6864077c0a
commit
035b8a2561
|
@ -0,0 +1,50 @@
|
||||||
|
# Pangram
|
||||||
|
|
||||||
|
Determine if a sentence is a pangram. A pangram (Greek: παν γράμμα, pan gramma,
|
||||||
|
"every letter") is a sentence using every letter of the alphabet at least once.
|
||||||
|
The best known English pangram is:
|
||||||
|
> The quick brown fox jumps over the lazy dog.
|
||||||
|
|
||||||
|
The alphabet used consists of ASCII letters `a` to `z`, inclusive, and is case
|
||||||
|
insensitive. Input will not contain non-ASCII symbols.
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir pangram_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/Pangram](https://en.wikipedia.org/wiki/Pangram)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,19 @@
|
||||||
|
defmodule Pangram do
|
||||||
|
@doc """
|
||||||
|
Determines if a word or sentence is a pangram.
|
||||||
|
A pangram is a sentence using every letter of the alphabet at least once.
|
||||||
|
|
||||||
|
Returns a boolean.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
iex> Pangram.pangram?("the quick brown fox jumps over the lazy dog")
|
||||||
|
true
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
@spec pangram?(String.t()) :: boolean
|
||||||
|
def pangram?(sentence) do
|
||||||
|
Enum.all?(?a..?z, fn c -> c in String.to_charlist(String.downcase(sentence)) end)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,62 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("pangram.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(trace: true)
|
||||||
|
|
||||||
|
defmodule PangramTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "empty sentence" do
|
||||||
|
refute Pangram.pangram?("")
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "pangram with only lower case" do
|
||||||
|
assert Pangram.pangram?("the quick brown fox jumps over the lazy dog")
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "missing character 'x'" do
|
||||||
|
refute Pangram.pangram?("a quick movement of the enemy will jeopardize five gunboats")
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "another missing character 'x'" do
|
||||||
|
refute Pangram.pangram?("the quick brown fish jumps over the lazy dog")
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "pangram with underscores" do
|
||||||
|
assert Pangram.pangram?("the_quick_brown_fox_jumps_over_the_lazy_dog")
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "pangram with numbers" do
|
||||||
|
assert Pangram.pangram?("the 1 quick brown fox jumps over the 2 lazy dogs")
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "missing letters replaced by numbers" do
|
||||||
|
refute Pangram.pangram?("7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog")
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "pangram with mixed case and punctuation" do
|
||||||
|
assert Pangram.pangram?("Five quacking Zephyrs jolt my wax bed.")
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "pangram with non ascii characters" do
|
||||||
|
assert Pangram.pangram?("Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich.")
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "pangram in alphabet other than ASCII" do
|
||||||
|
refute Pangram.pangram?(
|
||||||
|
"Широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства."
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,81 @@
|
||||||
|
# Scrabble Score
|
||||||
|
|
||||||
|
Given a word, compute the scrabble score for that word.
|
||||||
|
|
||||||
|
## Letter Values
|
||||||
|
|
||||||
|
You'll need these:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Letter Value
|
||||||
|
A, E, I, O, U, L, N, R, S, T 1
|
||||||
|
D, G 2
|
||||||
|
B, C, M, P 3
|
||||||
|
F, H, V, W, Y 4
|
||||||
|
K 5
|
||||||
|
J, X 8
|
||||||
|
Q, Z 10
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
"cabbage" should be scored as worth 14 points:
|
||||||
|
|
||||||
|
- 3 points for C
|
||||||
|
- 1 point for A, twice
|
||||||
|
- 3 points for B, twice
|
||||||
|
- 2 points for G
|
||||||
|
- 1 point for E
|
||||||
|
|
||||||
|
And to total:
|
||||||
|
|
||||||
|
- `3 + 2*1 + 2*3 + 2 + 1`
|
||||||
|
- = `3 + 2 + 6 + 3`
|
||||||
|
- = `5 + 9`
|
||||||
|
- = 14
|
||||||
|
|
||||||
|
## Extensions
|
||||||
|
|
||||||
|
- You can play a double or a triple letter.
|
||||||
|
- You can play a double or a triple word.
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir scrabble_score_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.
|
|
@ -0,0 +1,40 @@
|
||||||
|
defmodule Scrabble do
|
||||||
|
@doc """
|
||||||
|
Calculate the scrabble score for the word.
|
||||||
|
"""
|
||||||
|
@spec score(String.t()) :: non_neg_integer
|
||||||
|
def score(word) do
|
||||||
|
word
|
||||||
|
|> String.upcase()
|
||||||
|
|> String.to_charlist()
|
||||||
|
|> Enum.reduce(0, fn c, acc -> acc + letter_score(c) end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp letter_score(letter) do
|
||||||
|
case letter do
|
||||||
|
c when c in [?A, ?E, ?I, ?O, ?U, ?L, ?N, ?R, ?S, ?T] ->
|
||||||
|
1
|
||||||
|
|
||||||
|
c when c in [?D, ?G] ->
|
||||||
|
2
|
||||||
|
|
||||||
|
c when c in [?B, ?C, ?M, ?P] ->
|
||||||
|
3
|
||||||
|
|
||||||
|
c when c in [?F, ?H, ?V, ?W, ?Y] ->
|
||||||
|
4
|
||||||
|
|
||||||
|
c when c in [?K] ->
|
||||||
|
5
|
||||||
|
|
||||||
|
c when c in [?J, ?X] ->
|
||||||
|
8
|
||||||
|
|
||||||
|
c when c in [?Q, ?Z] ->
|
||||||
|
10
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,50 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("scrabble.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(trace: true)
|
||||||
|
|
||||||
|
defmodule ScrabbleScoreTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "empty word scores zero" do
|
||||||
|
assert Scrabble.score("") == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "whitespace scores zero" do
|
||||||
|
assert Scrabble.score(" \t\n") == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "scores very short word" do
|
||||||
|
assert Scrabble.score("a") == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "scores other very short word" do
|
||||||
|
assert Scrabble.score("f") == 4
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "simple word scores the number of letters" do
|
||||||
|
assert Scrabble.score("street") == 6
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "complicated word scores more" do
|
||||||
|
assert Scrabble.score("quirky") == 22
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "scores are case insensitive" do
|
||||||
|
assert Scrabble.score("OXYPHENBUTAZONE") == 41
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "convenient scoring" do
|
||||||
|
assert Scrabble.score("alacrity") == 13
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,63 @@
|
||||||
|
# Simple Linked List
|
||||||
|
|
||||||
|
Write a simple linked list implementation that uses Elements and a List.
|
||||||
|
|
||||||
|
The linked list is a fundamental data structure in computer science,
|
||||||
|
often used in the implementation of other data structures. They're
|
||||||
|
pervasive in functional programming languages, such as Clojure, Erlang,
|
||||||
|
or Haskell, but far less common in imperative languages such as Ruby or
|
||||||
|
Python.
|
||||||
|
|
||||||
|
The simplest kind of linked list is a singly linked list. Each element in the
|
||||||
|
list contains data and a "next" field pointing to the next element in the list
|
||||||
|
of elements.
|
||||||
|
|
||||||
|
This variant of linked lists is often used to represent sequences or
|
||||||
|
push-down stacks (also called a LIFO stack; Last In, First Out).
|
||||||
|
|
||||||
|
As a first take, lets create a singly linked list to contain the range (1..10),
|
||||||
|
and provide functions to reverse a linked list and convert to and from arrays.
|
||||||
|
|
||||||
|
When implementing this in a language with built-in linked lists,
|
||||||
|
implement your own abstract data type.
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir simple_linked_list_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 'Data Structures and Algorithms with Object-Oriented Design Patterns in Ruby', singly linked-lists. [http://www.brpreiss.com/books/opus8/html/page96.html#SECTION004300000000000000000](http://www.brpreiss.com/books/opus8/html/page96.html#SECTION004300000000000000000)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,83 @@
|
||||||
|
defmodule LinkedList do
|
||||||
|
@opaque t :: tuple()
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Construct a new LinkedList
|
||||||
|
"""
|
||||||
|
@spec new() :: t
|
||||||
|
def new() do
|
||||||
|
# Your implementation here...
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Push an item onto a LinkedList
|
||||||
|
"""
|
||||||
|
@spec push(t, any()) :: t
|
||||||
|
def push(list, elem) do
|
||||||
|
# Your implementation here...
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Calculate the length of a LinkedList
|
||||||
|
"""
|
||||||
|
@spec length(t) :: non_neg_integer()
|
||||||
|
def length(list) do
|
||||||
|
# Your implementation here...
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Determine if a LinkedList is empty
|
||||||
|
"""
|
||||||
|
@spec empty?(t) :: boolean()
|
||||||
|
def empty?(list) do
|
||||||
|
# Your implementation here...
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Get the value of a head of the LinkedList
|
||||||
|
"""
|
||||||
|
@spec peek(t) :: {:ok, any()} | {:error, :empty_list}
|
||||||
|
def peek(list) do
|
||||||
|
# Your implementation here...
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Get tail of a LinkedList
|
||||||
|
"""
|
||||||
|
@spec tail(t) :: {:ok, t} | {:error, :empty_list}
|
||||||
|
def tail(list) do
|
||||||
|
# Your implementation here...
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Remove the head from a LinkedList
|
||||||
|
"""
|
||||||
|
@spec pop(t) :: {:ok, any(), t} | {:error, :empty_list}
|
||||||
|
def pop(list) do
|
||||||
|
# Your implementation here...
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Construct a LinkedList from a stdlib List
|
||||||
|
"""
|
||||||
|
@spec from_list(list()) :: t
|
||||||
|
def from_list(list) do
|
||||||
|
# Your implementation here...
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Construct a stdlib List LinkedList from a LinkedList
|
||||||
|
"""
|
||||||
|
@spec to_list(t) :: list()
|
||||||
|
def to_list(list) do
|
||||||
|
# Your implementation here...
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Reverse a LinkedList
|
||||||
|
"""
|
||||||
|
@spec reverse(t) :: t
|
||||||
|
def reverse(list) do
|
||||||
|
# Your implementation here...
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,157 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("linked_list.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(exclude: :pending, trace: true)
|
||||||
|
|
||||||
|
defmodule LinkedListTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
test "length/1 of new list" do
|
||||||
|
list = LinkedList.new()
|
||||||
|
assert LinkedList.length(list) == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "empty?/1 of new list" do
|
||||||
|
list = LinkedList.new()
|
||||||
|
assert LinkedList.empty?(list)
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "length/1 of list of 1 datum" do
|
||||||
|
list = LinkedList.new() |> LinkedList.push(10)
|
||||||
|
assert LinkedList.length(list) == 1
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "empty?/1 of list of 1 datum" do
|
||||||
|
list = LinkedList.new() |> LinkedList.push(20)
|
||||||
|
refute LinkedList.empty?(list)
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "peek/1 of list of 1 datum" do
|
||||||
|
list = LinkedList.new() |> LinkedList.push(20)
|
||||||
|
assert LinkedList.peek(list) == {:ok, 20}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "peek/1 of list of empty list" do
|
||||||
|
list = LinkedList.new()
|
||||||
|
assert LinkedList.peek(list) == {:error, :empty_list}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "tail/1 of empty list" do
|
||||||
|
list = LinkedList.new()
|
||||||
|
assert {:error, :empty_list} = LinkedList.tail(list)
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "tail/1 of list of 1 datum" do
|
||||||
|
list = LinkedList.new() |> LinkedList.push(:hello)
|
||||||
|
assert {:ok, tail} = LinkedList.tail(list)
|
||||||
|
assert LinkedList.peek(tail) == {:error, :empty_list}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "pushed items are stacked" do
|
||||||
|
list =
|
||||||
|
LinkedList.new()
|
||||||
|
|> LinkedList.push(:a)
|
||||||
|
|> LinkedList.push(:b)
|
||||||
|
|
||||||
|
assert LinkedList.peek(list) == {:ok, :b}
|
||||||
|
assert {:ok, list} = LinkedList.tail(list)
|
||||||
|
assert LinkedList.peek(list) == {:ok, :a}
|
||||||
|
assert {:ok, list} = LinkedList.tail(list)
|
||||||
|
assert LinkedList.peek(list) == {:error, :empty_list}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "push 10 times" do
|
||||||
|
list = Enum.reduce(1..10, LinkedList.new(), &LinkedList.push(&2, &1))
|
||||||
|
assert LinkedList.peek(list) == {:ok, 10}
|
||||||
|
assert LinkedList.length(list) == 10
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "pop/1 of list of 1 datum" do
|
||||||
|
list = LinkedList.new() |> LinkedList.push(:a)
|
||||||
|
assert {:ok, :a, tail} = LinkedList.pop(list)
|
||||||
|
assert LinkedList.length(tail) == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "popping frenzy" do
|
||||||
|
list = Enum.reduce(11..20, LinkedList.new(), &LinkedList.push(&2, &1))
|
||||||
|
assert LinkedList.length(list) == 10
|
||||||
|
assert {:ok, 20, list} = LinkedList.pop(list)
|
||||||
|
assert {:ok, 19, list} = LinkedList.pop(list)
|
||||||
|
assert {:ok, 18, list} = LinkedList.pop(list)
|
||||||
|
assert {:ok, 17, list} = LinkedList.pop(list)
|
||||||
|
assert {:ok, 16, list} = LinkedList.pop(list)
|
||||||
|
assert {:ok, 15} = LinkedList.peek(list)
|
||||||
|
assert LinkedList.length(list) == 5
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "from_list/1 of empty list" do
|
||||||
|
list = LinkedList.from_list([])
|
||||||
|
assert LinkedList.length(list) == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "from_list/1 of 2 element list" do
|
||||||
|
list = LinkedList.from_list([:a, :b])
|
||||||
|
assert LinkedList.length(list) == 2
|
||||||
|
assert {:ok, :a, list} = LinkedList.pop(list)
|
||||||
|
assert {:ok, :b, list} = LinkedList.pop(list)
|
||||||
|
assert {:error, :empty_list} = LinkedList.pop(list)
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "to_list/1 of empty list" do
|
||||||
|
list = LinkedList.new()
|
||||||
|
assert LinkedList.to_list(list) == []
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "to_list/1 of list of 1 datum" do
|
||||||
|
list = LinkedList.from_list([:mon])
|
||||||
|
assert LinkedList.to_list(list) == [:mon]
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "to_list/1 of list of 2 datum" do
|
||||||
|
list = LinkedList.from_list([:mon, :tues])
|
||||||
|
assert LinkedList.to_list(list) == [:mon, :tues]
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "reverse/1 of list of 2 datum" do
|
||||||
|
list = LinkedList.from_list([1, 2, 3]) |> LinkedList.reverse()
|
||||||
|
assert LinkedList.to_list(list) == [3, 2, 1]
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "reverse/1 of list of 200 datum" do
|
||||||
|
list = Enum.to_list(1..200)
|
||||||
|
linked_list = LinkedList.from_list(list) |> LinkedList.reverse()
|
||||||
|
assert LinkedList.to_list(linked_list) == Enum.reverse(list)
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "reverse/1 round trip" do
|
||||||
|
list = Enum.to_list(1..200)
|
||||||
|
|
||||||
|
linked_list =
|
||||||
|
LinkedList.from_list(list)
|
||||||
|
|> LinkedList.reverse()
|
||||||
|
|> LinkedList.reverse()
|
||||||
|
|
||||||
|
assert LinkedList.to_list(linked_list) == list
|
||||||
|
end
|
||||||
|
end
|
|
@ -4,5 +4,32 @@ defmodule Sublist do
|
||||||
and if not whether it is equal or unequal to the second list.
|
and if not whether it is equal or unequal to the second list.
|
||||||
"""
|
"""
|
||||||
def compare(a, b) do
|
def compare(a, b) do
|
||||||
|
cond do
|
||||||
|
a === b ->
|
||||||
|
:equal
|
||||||
|
|
||||||
|
length(a) == length(b) && a !== b ->
|
||||||
|
:unequal
|
||||||
|
|
||||||
|
is_sublist?(a, b) ->
|
||||||
|
:superlist
|
||||||
|
|
||||||
|
is_sublist?(b, a) ->
|
||||||
|
:sublist
|
||||||
|
|
||||||
|
true ->
|
||||||
|
:unequal
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp is_sublist?(_, []), do: true
|
||||||
|
defp is_sublist?([], _), do: false
|
||||||
|
|
||||||
|
defp is_sublist?(a = [head | rest], b) do
|
||||||
|
if head === hd(b) && Enum.take(a, Enum.count(b)) == b do
|
||||||
|
true
|
||||||
|
else
|
||||||
|
is_sublist?(rest, b)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,98 +12,98 @@ defmodule SublistTest do
|
||||||
assert Sublist.compare([], []) == :equal
|
assert Sublist.compare([], []) == :equal
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "empty is a sublist of anything" do
|
test "empty is a sublist of anything" do
|
||||||
assert Sublist.compare([], [nil]) == :sublist
|
assert Sublist.compare([], [nil]) == :sublist
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "anything is a superlist of empty" do
|
test "anything is a superlist of empty" do
|
||||||
assert Sublist.compare([nil], []) == :superlist
|
assert Sublist.compare([nil], []) == :superlist
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "1 is not 2" do
|
test "1 is not 2" do
|
||||||
assert Sublist.compare([1], [2]) == :unequal
|
assert Sublist.compare([1], [2]) == :unequal
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "comparing massive equal lists" do
|
test "comparing massive equal lists" do
|
||||||
l = Enum.to_list(1..1_000_000)
|
l = Enum.to_list(1..1_000_000)
|
||||||
assert Sublist.compare(l, l) == :equal
|
assert Sublist.compare(l, l) == :equal
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "sublist at start" do
|
test "sublist at start" do
|
||||||
assert Sublist.compare([1, 2, 3], [1, 2, 3, 4, 5]) == :sublist
|
assert Sublist.compare([1, 2, 3], [1, 2, 3, 4, 5]) == :sublist
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "sublist in middle" do
|
test "sublist in middle" do
|
||||||
assert Sublist.compare([4, 3, 2], [5, 4, 3, 2, 1]) == :sublist
|
assert Sublist.compare([4, 3, 2], [5, 4, 3, 2, 1]) == :sublist
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "sublist at end" do
|
test "sublist at end" do
|
||||||
assert Sublist.compare([3, 4, 5], [1, 2, 3, 4, 5]) == :sublist
|
assert Sublist.compare([3, 4, 5], [1, 2, 3, 4, 5]) == :sublist
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "partially matching sublist at start" do
|
test "partially matching sublist at start" do
|
||||||
assert Sublist.compare([1, 1, 2], [1, 1, 1, 2]) == :sublist
|
assert Sublist.compare([1, 1, 2], [1, 1, 1, 2]) == :sublist
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "sublist early in huge list" do
|
test "sublist early in huge list" do
|
||||||
assert Sublist.compare([3, 4, 5], Enum.to_list(1..1_000_000)) == :sublist
|
assert Sublist.compare([3, 4, 5], Enum.to_list(1..1_000_000)) == :sublist
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "huge sublist not in huge list" do
|
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
|
assert Sublist.compare(Enum.to_list(10..1_000_001), Enum.to_list(1..1_000_000)) == :unequal
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "superlist at start" do
|
test "superlist at start" do
|
||||||
assert Sublist.compare([1, 2, 3, 4, 5], [1, 2, 3]) == :superlist
|
assert Sublist.compare([1, 2, 3, 4, 5], [1, 2, 3]) == :superlist
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "superlist in middle" do
|
test "superlist in middle" do
|
||||||
assert Sublist.compare([5, 4, 3, 2, 1], [4, 3, 2]) == :superlist
|
assert Sublist.compare([5, 4, 3, 2, 1], [4, 3, 2]) == :superlist
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "superlist at end" do
|
test "superlist at end" do
|
||||||
assert Sublist.compare([1, 2, 3, 4, 5], [3, 4, 5]) == :superlist
|
assert Sublist.compare([1, 2, 3, 4, 5], [3, 4, 5]) == :superlist
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "1 and 2 does not contain 3" do
|
test "1 and 2 does not contain 3" do
|
||||||
assert Sublist.compare([1, 2], [3]) == :unequal
|
assert Sublist.compare([1, 2], [3]) == :unequal
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "partially matching superlist at start" do
|
test "partially matching superlist at start" do
|
||||||
assert Sublist.compare([1, 1, 1, 2], [1, 1, 2]) == :superlist
|
assert Sublist.compare([1, 1, 1, 2], [1, 1, 2]) == :superlist
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "superlist early in huge list" do
|
test "superlist early in huge list" do
|
||||||
assert Sublist.compare(Enum.to_list(1..1_000_000), [3, 4, 5]) == :superlist
|
assert Sublist.compare(Enum.to_list(1..1_000_000), [3, 4, 5]) == :superlist
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "strict equality needed" do
|
test "strict equality needed" do
|
||||||
assert Sublist.compare([1], [1.0, 2]) == :unequal
|
assert Sublist.compare([1], [1.0, 2]) == :unequal
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "recurring values sublist" do
|
test "recurring values sublist" do
|
||||||
assert Sublist.compare([1, 2, 1, 2, 3], [1, 2, 3, 1, 2, 1, 2, 3, 2, 1]) == :sublist
|
assert Sublist.compare([1, 2, 1, 2, 3], [1, 2, 3, 1, 2, 1, 2, 3, 2, 1]) == :sublist
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :pending
|
# @tag :pending
|
||||||
test "recurring values unequal" do
|
test "recurring values unequal" do
|
||||||
assert Sublist.compare([1, 2, 1, 2, 3], [1, 2, 3, 1, 2, 3, 2, 3, 2, 1]) == :unequal
|
assert Sublist.compare([1, 2, 1, 2, 3], [1, 2, 3, 1, 2, 3, 2, 3, 2, 1]) == :unequal
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Sum Of Multiples
|
||||||
|
|
||||||
|
Given a number, find the sum of all the unique multiples of particular numbers up to
|
||||||
|
but not including that number.
|
||||||
|
|
||||||
|
If we list all the natural numbers below 20 that are multiples of 3 or 5,
|
||||||
|
we get 3, 5, 6, 9, 10, 12, 15, and 18.
|
||||||
|
|
||||||
|
The sum of these multiples is 78.
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ elixir sum_of_multiples_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 Problem 1 at Project Euler [http://projecteuler.net/problem=1](http://projecteuler.net/problem=1)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
|
@ -0,0 +1,11 @@
|
||||||
|
defmodule SumOfMultiples do
|
||||||
|
@doc """
|
||||||
|
Adds up all numbers from 1 to a given end number that are multiples of the factors provided.
|
||||||
|
"""
|
||||||
|
@spec to(non_neg_integer, [non_neg_integer]) :: non_neg_integer
|
||||||
|
def to(limit, factors) do
|
||||||
|
0..(limit - 1)
|
||||||
|
|> Enum.filter(fn c -> Enum.any?(factors, fn m -> rem(c, m) == 0 end) end)
|
||||||
|
|> Enum.sum()
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,64 @@
|
||||||
|
if !System.get_env("EXERCISM_TEST_EXAMPLES") do
|
||||||
|
Code.load_file("sum_of_multiples.exs", __DIR__)
|
||||||
|
end
|
||||||
|
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(trace: true)
|
||||||
|
|
||||||
|
defmodule SumOfMultiplesTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
# @tag :pending
|
||||||
|
test "sum to 1" do
|
||||||
|
assert SumOfMultiples.to(1, [3, 5]) == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "sum to 3" do
|
||||||
|
assert SumOfMultiples.to(4, [3, 5]) == 3
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "sum to 10" do
|
||||||
|
assert SumOfMultiples.to(10, [3, 5]) == 23
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "sum to 20" do
|
||||||
|
assert SumOfMultiples.to(20, [3, 5]) == 78
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "sum to 100" do
|
||||||
|
assert SumOfMultiples.to(100, [3, 5]) == 2318
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "sum to 1000" do
|
||||||
|
assert SumOfMultiples.to(1000, [3, 5]) == 233_168
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "configurable 7, 13, 17 to 20" do
|
||||||
|
multiples = [7, 13, 17]
|
||||||
|
assert SumOfMultiples.to(20, multiples) == 51
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "configurable 4, 6 to 15" do
|
||||||
|
multiples = [4, 6]
|
||||||
|
assert SumOfMultiples.to(15, multiples) == 30
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "configurable 5, 6, 8 to 150" do
|
||||||
|
multiples = [5, 6, 8]
|
||||||
|
assert SumOfMultiples.to(150, multiples) == 4419
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :pending
|
||||||
|
test "configurable 43, 47 to 10000" do
|
||||||
|
multiples = [43, 47]
|
||||||
|
assert SumOfMultiples.to(10000, multiples) == 2_203_160
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue