Compare commits
98 Commits
b8a7845967
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 95c9a93dec | |||
| cbeda5d38b | |||
| 5f594b12e3 | |||
| ab3508e9fc | |||
| a33fa3295c | |||
| 2cb2de4caf | |||
| 79f77f009a | |||
| 1a4c55bdaf | |||
| 6bcb4db837 | |||
| d9bc141e51 | |||
| d00a9787f9 | |||
| 2b764143c4 | |||
| b21db6b2f9 | |||
| 64030231bf | |||
| 7856986097 | |||
| 4e5b4dceeb | |||
| 00a1a882dd | |||
| 58eac331ab | |||
| 44ca0cb19b | |||
| 34e04eff6a | |||
| 22d545194e | |||
| 379e523c04 | |||
| 0c3373b87e | |||
| 1224cca405 | |||
| 7b3e6d3216 | |||
| 2eb14fcd40 | |||
| 643a41d53c | |||
| 2b1e10247b | |||
| 81b389528e | |||
| 721b4e4ed6 | |||
| c2e651cd5a | |||
| 0aef8da6d9 | |||
| e0d8231e91 | |||
| 1610d6caf3 | |||
| 66f0e9c6f8 | |||
| 9425fd5368 | |||
| 15ab62c4f1 | |||
| 1ae69450e8 | |||
| 320bdc1286 | |||
| 780dc17b36 | |||
| 6e761f7041 | |||
| 8fbd81ed9d | |||
| dad68cb89f | |||
| 8d8a30b39c | |||
| 9adeef7c61 | |||
| 26a8976b52 | |||
| 8a0b02049f | |||
| c7b7989ccd | |||
| 146d1d3f89 | |||
| b5a8d35513 | |||
| 15f39c5c5b | |||
| 79c17a8c59 | |||
| 140299f646 | |||
| fcc4ddb61c | |||
| eb76c60826 | |||
| 10cfc2215b | |||
| b62fcbc5ea | |||
| 4c3da6abe4 | |||
| fd86d9545f | |||
| e0c8beb31f | |||
| 22b46519fd | |||
| d46a9b8e9a | |||
| 4265743d75 | |||
| af9641f4e9 | |||
| e950cc6d90 | |||
| c625ecedd6 | |||
| 3c7f1d64f5 | |||
| bb65cd30cc | |||
| def44c9d46 | |||
| 5203753bd5 | |||
| 3ab71444f5 | |||
| b4e1570ba6 | |||
| 5704073c97 | |||
| 8a0a02f996 | |||
| ed251fd37d | |||
| 7ae168f5ea | |||
| d1b894006c | |||
| 0c15aedc09 | |||
| c62233f40f | |||
| eab9b54f20 | |||
| af3b5c40f8 | |||
| e2e3430ef8 | |||
| cd5d83851d | |||
| 3b19351ce4 | |||
| 42bdf9694e | |||
| 776a104f19 | |||
| 833fe9c0f5 | |||
| ec644472b3 | |||
| f324155864 | |||
| 2465a18235 | |||
| db731118fc | |||
| 9d03ff01dc | |||
| 3001618707 | |||
| 53d94ff371 | |||
| 7332230435 | |||
| b69dc97356 | |||
| a4a5085d00 | |||
| 5f3aa01e4d |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -24,3 +24,5 @@ Icon
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
.vscode
|
||||
35
elixir/acronym/.exercism/config.json
Normal file
35
elixir/acronym/.exercism/config.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"authors": [
|
||||
"Teapane"
|
||||
],
|
||||
"contributors": [
|
||||
"angelikatyborska",
|
||||
"Cohen-Carlisle",
|
||||
"dalexj",
|
||||
"devonestes",
|
||||
"gmile",
|
||||
"henrik",
|
||||
"jwworth",
|
||||
"lpil",
|
||||
"martinsvalin",
|
||||
"neenjaw",
|
||||
"parkerl",
|
||||
"rubysolo",
|
||||
"sotojuan",
|
||||
"waiting-for-dev"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"lib/acronym.ex"
|
||||
],
|
||||
"test": [
|
||||
"test/acronym_test.exs"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.ex"
|
||||
]
|
||||
},
|
||||
"blurb": "Convert a long phrase to its acronym.",
|
||||
"source": "Julien Vanier",
|
||||
"source_url": "https://github.com/monkbroc"
|
||||
}
|
||||
1
elixir/acronym/.exercism/metadata.json
Normal file
1
elixir/acronym/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
||||
{"track":"elixir","exercise":"acronym","id":"6e61a6a0f47e4396aad6d4854fe80fb4","url":"https://exercism.org/tracks/elixir/exercises/acronym","handle":"negrienko","is_requester":true,"auto_approve":false}
|
||||
4
elixir/acronym/.formatter.exs
Normal file
4
elixir/acronym/.formatter.exs
Normal file
@@ -0,0 +1,4 @@
|
||||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
||||
24
elixir/acronym/.gitignore
vendored
Normal file
24
elixir/acronym/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
acronym-*.tar
|
||||
|
||||
75
elixir/acronym/HELP.md
Normal file
75
elixir/acronym/HELP.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
From the terminal, change to the base directory of the exercise then execute the tests with:
|
||||
|
||||
```bash
|
||||
$ mix test
|
||||
```
|
||||
|
||||
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs`
|
||||
|
||||
Documentation:
|
||||
|
||||
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html)
|
||||
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html)
|
||||
|
||||
## Pending tests
|
||||
|
||||
In test suites of practice exercises, all but the first test have been tagged to be 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
|
||||
```
|
||||
|
||||
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command:
|
||||
|
||||
```bash
|
||||
$ mix test --include pending
|
||||
```
|
||||
|
||||
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`.
|
||||
|
||||
```elixir
|
||||
# ExUnit.configure(exclude: :pending, trace: true)
|
||||
```
|
||||
|
||||
## Useful `mix test` options
|
||||
|
||||
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM`
|
||||
* `--failed` - runs only tests that failed the last time they ran
|
||||
* `--max-failures` - the suite stops evaluating tests when this number of test failures
|
||||
is reached
|
||||
* `--seed 0` - disables randomization so the tests in a single file will always be ran
|
||||
in the same order they were defined in
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit lib/acronym.ex` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir)
|
||||
- The [Elixir track's programming category on the forum](https://forum.exercism.org/c/programming/elixir)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found.
|
||||
49
elixir/acronym/README.md
Normal file
49
elixir/acronym/README.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Acronym
|
||||
|
||||
Welcome to Acronym on Exercism's Elixir Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
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).
|
||||
|
||||
Punctuation is handled as follows: hyphens are word separators (like whitespace); all other punctuation can be removed from the input.
|
||||
|
||||
For example:
|
||||
|
||||
| Input | Output |
|
||||
| ------------------------- | ------ |
|
||||
| As Soon As Possible | ASAP |
|
||||
| Liquid-crystal display | LCD |
|
||||
| Thank George It's Friday! | TGIF |
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @Teapane
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @angelikatyborska
|
||||
- @Cohen-Carlisle
|
||||
- @dalexj
|
||||
- @devonestes
|
||||
- @gmile
|
||||
- @henrik
|
||||
- @jwworth
|
||||
- @lpil
|
||||
- @martinsvalin
|
||||
- @neenjaw
|
||||
- @parkerl
|
||||
- @rubysolo
|
||||
- @sotojuan
|
||||
- @waiting-for-dev
|
||||
|
||||
### Based on
|
||||
|
||||
Julien Vanier - https://github.com/monkbroc
|
||||
14
elixir/acronym/lib/acronym.ex
Normal file
14
elixir/acronym/lib/acronym.ex
Normal file
@@ -0,0 +1,14 @@
|
||||
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([" ", "-", "_"], trim: true)
|
||||
|> Enum.map(&String.first/1)
|
||||
|> Enum.join()
|
||||
|> String.upcase()
|
||||
end
|
||||
end
|
||||
28
elixir/acronym/mix.exs
Normal file
28
elixir/acronym/mix.exs
Normal file
@@ -0,0 +1,28 @@
|
||||
defmodule Acronym.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :acronym,
|
||||
version: "0.1.0",
|
||||
# elixir: "~> 1.8",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications.
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
# {:dep_from_hexpm, "~> 0.3.0"},
|
||||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||
]
|
||||
end
|
||||
end
|
||||
49
elixir/acronym/test/acronym_test.exs
Normal file
49
elixir/acronym/test/acronym_test.exs
Normal file
@@ -0,0 +1,49 @@
|
||||
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 ignores punctuation" do
|
||||
assert Acronym.abbreviate("First in, First out") === "FIFO"
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "it produces acronyms from phrases with acronyms" do
|
||||
assert Acronym.abbreviate("GNU Image Manipulation Program") === "GIMP"
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "it produces acronyms ignoring punctuation and casing" do
|
||||
assert Acronym.abbreviate("Complementary Metal-Oxide semiconductor") === "CMOS"
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "it produces a very long abbreviation" do
|
||||
assert Acronym.abbreviate(
|
||||
"Rolling On The Floor Laughing So Hard That My Dogs Came Over And Licked Me"
|
||||
) === "ROTFLSHTMDCOALM"
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "it produces acronyms from phrases with consecutive delimiters" do
|
||||
assert Acronym.abbreviate("Something - I made up from thin air") === "SIMUFTA"
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "it produces acronyms from phrases with apostrophes" do
|
||||
assert Acronym.abbreviate("Halley's Comet") === "HC"
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "it produces acronyms from phrases with underscore emphasis" do
|
||||
assert Acronym.abbreviate("The Road _Not_ Taken") === "TRNT"
|
||||
end
|
||||
end
|
||||
2
elixir/acronym/test/test_helper.exs
Normal file
2
elixir/acronym/test/test_helper.exs
Normal file
@@ -0,0 +1,2 @@
|
||||
ExUnit.start()
|
||||
ExUnit.configure(exclude: :pending, trace: true)
|
||||
27
elixir/all-your-base/.exercism/config.json
Normal file
27
elixir/all-your-base/.exercism/config.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"authors": [
|
||||
"ananthamapod"
|
||||
],
|
||||
"contributors": [
|
||||
"angelikatyborska",
|
||||
"ChristianTovar",
|
||||
"Cohen-Carlisle",
|
||||
"devonestes",
|
||||
"neenjaw",
|
||||
"parkerl",
|
||||
"sotojuan",
|
||||
"ybod"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"lib/all_your_base.ex"
|
||||
],
|
||||
"test": [
|
||||
"test/all_your_base_test.exs"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.ex"
|
||||
]
|
||||
},
|
||||
"blurb": "Convert a number, represented as a sequence of digits in one base, to any other base."
|
||||
}
|
||||
1
elixir/all-your-base/.exercism/metadata.json
Normal file
1
elixir/all-your-base/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
||||
{"track":"elixir","exercise":"all-your-base","id":"98d3bf453a6d4f1383988013aadb22c0","url":"https://exercism.org/tracks/elixir/exercises/all-your-base","handle":"negrienko","is_requester":true,"auto_approve":false}
|
||||
4
elixir/all-your-base/.formatter.exs
Normal file
4
elixir/all-your-base/.formatter.exs
Normal file
@@ -0,0 +1,4 @@
|
||||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
||||
24
elixir/all-your-base/.gitignore
vendored
Normal file
24
elixir/all-your-base/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
all_your_base-*.tar
|
||||
|
||||
75
elixir/all-your-base/HELP.md
Normal file
75
elixir/all-your-base/HELP.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
From the terminal, change to the base directory of the exercise then execute the tests with:
|
||||
|
||||
```bash
|
||||
$ mix test
|
||||
```
|
||||
|
||||
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs`
|
||||
|
||||
Documentation:
|
||||
|
||||
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html)
|
||||
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html)
|
||||
|
||||
## Pending tests
|
||||
|
||||
In test suites of practice exercises, all but the first test have been tagged to be 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
|
||||
```
|
||||
|
||||
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command:
|
||||
|
||||
```bash
|
||||
$ mix test --include pending
|
||||
```
|
||||
|
||||
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`.
|
||||
|
||||
```elixir
|
||||
# ExUnit.configure(exclude: :pending, trace: true)
|
||||
```
|
||||
|
||||
## Useful `mix test` options
|
||||
|
||||
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM`
|
||||
* `--failed` - runs only tests that failed the last time they ran
|
||||
* `--max-failures` - the suite stops evaluating tests when this number of test failures
|
||||
is reached
|
||||
* `--seed 0` - disables randomization so the tests in a single file will always be ran
|
||||
in the same order they were defined in
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit lib/all_your_base.ex` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir)
|
||||
- The [Elixir track's programming category on the forum](https://forum.exercism.org/c/programming/elixir)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found.
|
||||
55
elixir/all-your-base/README.md
Normal file
55
elixir/all-your-base/README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# All Your Base
|
||||
|
||||
Welcome to All Your Base on Exercism's Elixir Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
Convert a number, represented as a sequence of digits in one base, to any other base.
|
||||
|
||||
Implement general base conversion.
|
||||
Given a number in base **a**, represented as a sequence of digits, convert it to base **b**.
|
||||
|
||||
## Note
|
||||
|
||||
- Try to implement the conversion yourself.
|
||||
Do not use something else to perform the conversion for you.
|
||||
|
||||
## About [Positional Notation][positional-notation]
|
||||
|
||||
In positional notation, a number in base **b** can be understood as a linear combination of powers of **b**.
|
||||
|
||||
The number 42, _in base 10_, means:
|
||||
|
||||
`(4 * 10^1) + (2 * 10^0)`
|
||||
|
||||
The number 101010, _in base 2_, means:
|
||||
|
||||
`(1 * 2^5) + (0 * 2^4) + (1 * 2^3) + (0 * 2^2) + (1 * 2^1) + (0 * 2^0)`
|
||||
|
||||
The number 1120, _in base 3_, means:
|
||||
|
||||
`(1 * 3^3) + (1 * 3^2) + (2 * 3^1) + (0 * 3^0)`
|
||||
|
||||
I think you got the idea!
|
||||
|
||||
_Yes. Those three numbers above are exactly the same. Congratulations!_
|
||||
|
||||
[positional-notation]: https://en.wikipedia.org/wiki/Positional_notation
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @ananthamapod
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @angelikatyborska
|
||||
- @ChristianTovar
|
||||
- @Cohen-Carlisle
|
||||
- @devonestes
|
||||
- @neenjaw
|
||||
- @parkerl
|
||||
- @sotojuan
|
||||
- @ybod
|
||||
31
elixir/all-your-base/lib/all_your_base.ex
Normal file
31
elixir/all-your-base/lib/all_your_base.ex
Normal file
@@ -0,0 +1,31 @@
|
||||
defmodule AllYourBase do
|
||||
@doc """
|
||||
Given a number in input base, represented as a sequence of digits, converts it to output base,
|
||||
or returns an error tuple if either of the bases are less than 2
|
||||
"""
|
||||
|
||||
@spec convert(list, integer, integer) :: {:ok, list} | {:error, String.t()}
|
||||
def convert(_digits, input_base, _output_base) when input_base < 2,
|
||||
do: {:error, "input base must be >= 2"}
|
||||
|
||||
def convert(_digits, _input_base, output_base) when output_base < 2,
|
||||
do: {:error, "output base must be >= 2"}
|
||||
|
||||
def convert([0 | digits], input_base, output_base), do: convert(digits, input_base, output_base)
|
||||
|
||||
def convert(digits, input_base, output_base) do
|
||||
unless Enum.all?(digits, &valid_digit?(&1, input_base)) do
|
||||
{:error, "all digits must be >= 0 and < input base"}
|
||||
else
|
||||
result =
|
||||
digits
|
||||
|> Integer.undigits(input_base)
|
||||
|> Integer.digits(output_base)
|
||||
|
||||
{:ok, result}
|
||||
end
|
||||
end
|
||||
|
||||
defp valid_digit?(digit, base) when digit >= 0 and digit < base, do: true
|
||||
defp valid_digit?(_digit, _base), do: false
|
||||
end
|
||||
28
elixir/all-your-base/mix.exs
Normal file
28
elixir/all-your-base/mix.exs
Normal file
@@ -0,0 +1,28 @@
|
||||
defmodule AllYourBase.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :all_your_base,
|
||||
version: "0.1.0",
|
||||
# elixir: "~> 1.8",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications.
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
# {:dep_from_hexpm, "~> 0.3.0"},
|
||||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||
]
|
||||
end
|
||||
end
|
||||
109
elixir/all-your-base/test/all_your_base_test.exs
Normal file
109
elixir/all-your-base/test/all_your_base_test.exs
Normal file
@@ -0,0 +1,109 @@
|
||||
defmodule AllYourBaseTest do
|
||||
use ExUnit.Case
|
||||
|
||||
test "convert single bit one to decimal" do
|
||||
assert AllYourBase.convert([1], 2, 10) == {:ok, [1]}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert binary to single decimal" do
|
||||
assert AllYourBase.convert([1, 0, 1], 2, 10) == {:ok, [5]}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert single decimal to binary" do
|
||||
assert AllYourBase.convert([5], 10, 2) == {:ok, [1, 0, 1]}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert binary to multiple decimal" do
|
||||
assert AllYourBase.convert([1, 0, 1, 0, 1, 0], 2, 10) == {:ok, [4, 2]}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert decimal to binary" do
|
||||
assert AllYourBase.convert([4, 2], 10, 2) == {:ok, [1, 0, 1, 0, 1, 0]}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert trinary to hexadecimal" do
|
||||
assert AllYourBase.convert([1, 1, 2, 0], 3, 16) == {:ok, [2, 10]}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert hexadecimal to trinary" do
|
||||
assert AllYourBase.convert([2, 10], 16, 3) == {:ok, [1, 1, 2, 0]}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert 15-bit integer" do
|
||||
assert AllYourBase.convert([3, 46, 60], 97, 73) == {:ok, [6, 10, 45]}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert empty list" do
|
||||
assert AllYourBase.convert([], 2, 10) == {:ok, [0]}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert single zero" do
|
||||
assert AllYourBase.convert([0], 10, 2) == {:ok, [0]}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert multiple zeros" do
|
||||
assert AllYourBase.convert([0, 0, 0], 10, 2) == {:ok, [0]}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert leading zeros" do
|
||||
assert AllYourBase.convert([0, 6, 0], 7, 10) == {:ok, [4, 2]}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert first base is one" do
|
||||
assert AllYourBase.convert([0], 1, 10) == {:error, "input base must be >= 2"}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert first base is zero" do
|
||||
assert AllYourBase.convert([], 0, 10) == {:error, "input base must be >= 2"}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert first base is negative" do
|
||||
assert AllYourBase.convert([1], -2, 10) == {:error, "input base must be >= 2"}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert negative digit" do
|
||||
assert AllYourBase.convert([1, -1, 1, 0, 1, 0], 2, 10) ==
|
||||
{:error, "all digits must be >= 0 and < input base"}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert invalid positive digit" do
|
||||
assert AllYourBase.convert([1, 2, 1, 0, 1, 0], 2, 10) ==
|
||||
{:error, "all digits must be >= 0 and < input base"}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert second base is one" do
|
||||
assert AllYourBase.convert([1, 0, 1, 0, 1, 0], 2, 1) == {:error, "output base must be >= 2"}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert second base is zero" do
|
||||
assert AllYourBase.convert([7], 10, 0) == {:error, "output base must be >= 2"}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert second base is negative" do
|
||||
assert AllYourBase.convert([1], 2, -7) == {:error, "output base must be >= 2"}
|
||||
end
|
||||
|
||||
# @tag :pending
|
||||
test "convert both bases are negative" do
|
||||
assert AllYourBase.convert([1], -2, -7) == {:error, "input base must be >= 2"}
|
||||
end
|
||||
end
|
||||
2
elixir/all-your-base/test/test_helper.exs
Normal file
2
elixir/all-your-base/test/test_helper.exs
Normal file
@@ -0,0 +1,2 @@
|
||||
ExUnit.start()
|
||||
ExUnit.configure(exclude: :pending, trace: true)
|
||||
37
elixir/allergies/.exercism/config.json
Normal file
37
elixir/allergies/.exercism/config.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"authors": [
|
||||
"rubysolo"
|
||||
],
|
||||
"contributors": [
|
||||
"andrewsardone",
|
||||
"angelikatyborska",
|
||||
"Cohen-Carlisle",
|
||||
"dalexj",
|
||||
"devonestes",
|
||||
"ggpasqualino",
|
||||
"jinyeow",
|
||||
"lpil",
|
||||
"martinsvalin",
|
||||
"meadsteve",
|
||||
"montague",
|
||||
"neenjaw",
|
||||
"parkerl",
|
||||
"sotojuan",
|
||||
"Teapane",
|
||||
"waiting-for-dev"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"lib/allergies.ex"
|
||||
],
|
||||
"test": [
|
||||
"test/allergies_test.exs"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.ex"
|
||||
]
|
||||
},
|
||||
"blurb": "Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies.",
|
||||
"source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.",
|
||||
"source_url": "https://turing.edu"
|
||||
}
|
||||
1
elixir/allergies/.exercism/metadata.json
Normal file
1
elixir/allergies/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
||||
{"track":"elixir","exercise":"allergies","id":"0f056a8c570349d4b0832bbf025c5c86","url":"https://exercism.org/tracks/elixir/exercises/allergies","handle":"negrienko","is_requester":true,"auto_approve":false}
|
||||
4
elixir/allergies/.formatter.exs
Normal file
4
elixir/allergies/.formatter.exs
Normal file
@@ -0,0 +1,4 @@
|
||||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
||||
24
elixir/allergies/.gitignore
vendored
Normal file
24
elixir/allergies/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
allergies-*.tar
|
||||
|
||||
75
elixir/allergies/HELP.md
Normal file
75
elixir/allergies/HELP.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
From the terminal, change to the base directory of the exercise then execute the tests with:
|
||||
|
||||
```bash
|
||||
$ mix test
|
||||
```
|
||||
|
||||
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs`
|
||||
|
||||
Documentation:
|
||||
|
||||
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html)
|
||||
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html)
|
||||
|
||||
## Pending tests
|
||||
|
||||
In test suites of practice exercises, all but the first test have been tagged to be 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
|
||||
```
|
||||
|
||||
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command:
|
||||
|
||||
```bash
|
||||
$ mix test --include pending
|
||||
```
|
||||
|
||||
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`.
|
||||
|
||||
```elixir
|
||||
# ExUnit.configure(exclude: :pending, trace: true)
|
||||
```
|
||||
|
||||
## Useful `mix test` options
|
||||
|
||||
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM`
|
||||
* `--failed` - runs only tests that failed the last time they ran
|
||||
* `--max-failures` - the suite stops evaluating tests when this number of test failures
|
||||
is reached
|
||||
* `--seed 0` - disables randomization so the tests in a single file will always be ran
|
||||
in the same order they were defined in
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit lib/allergies.ex` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir)
|
||||
- The [Elixir track's programming category on the forum](https://forum.exercism.org/c/programming/elixir)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found.
|
||||
61
elixir/allergies/README.md
Normal file
61
elixir/allergies/README.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Allergies
|
||||
|
||||
Welcome to Allergies on Exercism's Elixir Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
Given a person's allergy score, determine whether or not they're allergic to a given item, and their full list of allergies.
|
||||
|
||||
An allergy test produces a single numeric score which contains the information about all the allergies the person has (that they were tested for).
|
||||
|
||||
The list of items (and their value) that were tested are:
|
||||
|
||||
- eggs (1)
|
||||
- peanuts (2)
|
||||
- shellfish (4)
|
||||
- strawberries (8)
|
||||
- tomatoes (16)
|
||||
- chocolate (32)
|
||||
- pollen (64)
|
||||
- cats (128)
|
||||
|
||||
So if Tom is allergic to peanuts and chocolate, he gets a score of 34.
|
||||
|
||||
Now, given just that score of 34, your program should be able to say:
|
||||
|
||||
- Whether Tom is allergic to any one of those allergens listed above.
|
||||
- All the allergens Tom is allergic to.
|
||||
|
||||
Note: a given score may include allergens **not** listed above (i.e. allergens that score 256, 512, 1024, etc.).
|
||||
Your program should ignore those components of the score.
|
||||
For example, if the allergy score is 257, your program should only report the eggs (1) allergy.
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @rubysolo
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @andrewsardone
|
||||
- @angelikatyborska
|
||||
- @Cohen-Carlisle
|
||||
- @dalexj
|
||||
- @devonestes
|
||||
- @ggpasqualino
|
||||
- @jinyeow
|
||||
- @lpil
|
||||
- @martinsvalin
|
||||
- @meadsteve
|
||||
- @montague
|
||||
- @neenjaw
|
||||
- @parkerl
|
||||
- @sotojuan
|
||||
- @Teapane
|
||||
- @waiting-for-dev
|
||||
|
||||
### Based on
|
||||
|
||||
Exercise by the JumpstartLab team for students at The Turing School of Software and Design. - https://turing.edu
|
||||
27
elixir/allergies/lib/allergies.ex
Normal file
27
elixir/allergies/lib/allergies.ex
Normal file
@@ -0,0 +1,27 @@
|
||||
defmodule Allergies do
|
||||
@allergens %{
|
||||
"eggs" => 1,
|
||||
"peanuts" => 2,
|
||||
"shellfish" => 4,
|
||||
"strawberries" => 8,
|
||||
"tomatoes" => 16,
|
||||
"chocolate" => 32,
|
||||
"pollen" => 64,
|
||||
"cats" => 128
|
||||
}
|
||||
|
||||
@doc """
|
||||
List the allergies for which the corresponding flag bit is true.
|
||||
"""
|
||||
@spec list(non_neg_integer) :: [String.t()]
|
||||
def list(flags) do
|
||||
for {allergen, mask} <- @allergens, allergic_to?(mask, flags), do: allergen
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns whether the corresponding flag bit in 'flags' is set for the item.
|
||||
"""
|
||||
@spec allergic_to?(non_neg_integer, String.t() | non_neg_integer) :: boolean
|
||||
def allergic_to?(flags, mask) when is_integer(mask), do: Bitwise.band(mask, flags) > 0
|
||||
def allergic_to?(flags, allergen) when is_binary(allergen), do: allergic_to?(@allergens[allergen], flags)
|
||||
end
|
||||
28
elixir/allergies/mix.exs
Normal file
28
elixir/allergies/mix.exs
Normal file
@@ -0,0 +1,28 @@
|
||||
defmodule Allergies.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :allergies,
|
||||
version: "0.1.0",
|
||||
# elixir: "~> 1.8",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications.
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
# {:dep_from_hexpm, "~> 0.3.0"},
|
||||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||
]
|
||||
end
|
||||
end
|
||||
241
elixir/allergies/test/allergies_test.exs
Normal file
241
elixir/allergies/test/allergies_test.exs
Normal file
@@ -0,0 +1,241 @@
|
||||
defmodule AllergiesTest do
|
||||
use ExUnit.Case
|
||||
|
||||
defp assert_is_a_set_containing(list, to_contain) do
|
||||
set = Enum.into(list, MapSet.new())
|
||||
|
||||
same_contents =
|
||||
to_contain
|
||||
|> Enum.into(MapSet.new())
|
||||
|> MapSet.equal?(set)
|
||||
|
||||
assert same_contents,
|
||||
"Expected a set with: #{inspect(to_contain)} got #{inspect(set |> MapSet.to_list())}"
|
||||
end
|
||||
|
||||
describe "allergy list against expected allergens -" do
|
||||
test "no allergies at all" do
|
||||
Allergies.list(0) |> assert_is_a_set_containing([])
|
||||
end
|
||||
|
||||
test "allergic to just eggs" do
|
||||
Allergies.list(1) |> assert_is_a_set_containing(~w[eggs])
|
||||
end
|
||||
|
||||
test "allergic to just peanuts" do
|
||||
Allergies.list(2) |> assert_is_a_set_containing(~w[peanuts])
|
||||
end
|
||||
|
||||
test "allergic to just strawberries" do
|
||||
Allergies.list(8) |> assert_is_a_set_containing(~w[strawberries])
|
||||
end
|
||||
|
||||
test "allergic to eggs and peanuts" do
|
||||
Allergies.list(3) |> assert_is_a_set_containing(~w[eggs peanuts])
|
||||
end
|
||||
|
||||
test "allergic to more than eggs but not peanuts" do
|
||||
Allergies.list(5) |> assert_is_a_set_containing(~w[eggs shellfish])
|
||||
end
|
||||
|
||||
test "allergic to lots of stuff" do
|
||||
Allergies.list(248)
|
||||
|> assert_is_a_set_containing(~w[strawberries tomatoes chocolate pollen cats])
|
||||
end
|
||||
|
||||
test "allergic to everything" do
|
||||
Allergies.list(255)
|
||||
|> assert_is_a_set_containing(
|
||||
~w[eggs peanuts shellfish strawberries tomatoes chocolate pollen cats]
|
||||
)
|
||||
end
|
||||
|
||||
test "ignore non allergen score parts" do
|
||||
Allergies.list(509)
|
||||
|> assert_is_a_set_containing(
|
||||
~w[eggs shellfish strawberries tomatoes chocolate pollen cats]
|
||||
)
|
||||
end
|
||||
|
||||
test "ignore non allergen score parts without highest valid score" do
|
||||
Allergies.list(257)
|
||||
|> assert_is_a_set_containing(~w[eggs])
|
||||
end
|
||||
end
|
||||
|
||||
describe "score for egg allergies -" do
|
||||
test "not allergic to eggs" do
|
||||
refute Allergies.allergic_to?(0, "eggs")
|
||||
end
|
||||
|
||||
test "is allergic to only eggs" do
|
||||
assert Allergies.allergic_to?(1, "eggs")
|
||||
end
|
||||
|
||||
test "is allergic to eggs and something else" do
|
||||
assert Allergies.allergic_to?(3, "eggs")
|
||||
end
|
||||
|
||||
test "is allergic to something, but not eggs" do
|
||||
refute Allergies.allergic_to?(2, "eggs")
|
||||
end
|
||||
|
||||
test "is allergic to everything (including eggs)" do
|
||||
assert Allergies.allergic_to?(255, "eggs")
|
||||
end
|
||||
end
|
||||
|
||||
describe "score for peanuts allergies -" do
|
||||
test "not allergic to peanuts" do
|
||||
refute Allergies.allergic_to?(0, "peanuts")
|
||||
end
|
||||
|
||||
test "is allergic to only peanuts" do
|
||||
assert Allergies.allergic_to?(2, "peanuts")
|
||||
end
|
||||
|
||||
test "is allergic to peanuts and something else" do
|
||||
assert Allergies.allergic_to?(7, "peanuts")
|
||||
end
|
||||
|
||||
test "is allergic to something, but not peanuts" do
|
||||
refute Allergies.allergic_to?(5, "peanuts")
|
||||
end
|
||||
|
||||
test "is allergic to everything (including peanuts)" do
|
||||
assert Allergies.allergic_to?(255, "peanuts")
|
||||
end
|
||||
end
|
||||
|
||||
describe "score for shellfish allergies -" do
|
||||
test "not allergic to shellfish" do
|
||||
refute Allergies.allergic_to?(0, "shellfish")
|
||||
end
|
||||
|
||||
test "is allergic to only shellfish" do
|
||||
assert Allergies.allergic_to?(4, "shellfish")
|
||||
end
|
||||
|
||||
test "is allergic to shellfish and something else" do
|
||||
assert Allergies.allergic_to?(14, "shellfish")
|
||||
end
|
||||
|
||||
test "is allergic to something, but not shellfish" do
|
||||
refute Allergies.allergic_to?(10, "shellfish")
|
||||
end
|
||||
|
||||
test "is allergic to everything (including shellfish)" do
|
||||
assert Allergies.allergic_to?(255, "shellfish")
|
||||
end
|
||||
end
|
||||
|
||||
describe "score for strawberries allergies -" do
|
||||
test "not allergic to strawberries" do
|
||||
refute Allergies.allergic_to?(0, "strawberries")
|
||||
end
|
||||
|
||||
test "is allergic to only strawberries" do
|
||||
assert Allergies.allergic_to?(8, "strawberries")
|
||||
end
|
||||
|
||||
test "is allergic to strawberries and something else" do
|
||||
assert Allergies.allergic_to?(28, "strawberries")
|
||||
end
|
||||
|
||||
test "is allergic to something, but not strawberries" do
|
||||
refute Allergies.allergic_to?(20, "strawberries")
|
||||
end
|
||||
|
||||
test "is allergic to everything (including strawberries)" do
|
||||
assert Allergies.allergic_to?(255, "strawberries")
|
||||
end
|
||||
end
|
||||
|
||||
describe "score for tomatoes allergies -" do
|
||||
test "not allergic to tomatoes" do
|
||||
refute Allergies.allergic_to?(0, "tomatoes")
|
||||
end
|
||||
|
||||
test "is allergic to only tomatoes" do
|
||||
assert Allergies.allergic_to?(16, "tomatoes")
|
||||
end
|
||||
|
||||
test "is allergic to tomatoes and something else" do
|
||||
assert Allergies.allergic_to?(56, "tomatoes")
|
||||
end
|
||||
|
||||
test "is allergic to something, but not tomatoes" do
|
||||
refute Allergies.allergic_to?(40, "tomatoes")
|
||||
end
|
||||
|
||||
test "is allergic to everything (including tomatoes)" do
|
||||
assert Allergies.allergic_to?(255, "tomatoes")
|
||||
end
|
||||
end
|
||||
|
||||
describe "score for chocolate allergies -" do
|
||||
test "not allergic to chocolate" do
|
||||
refute Allergies.allergic_to?(0, "chocolate")
|
||||
end
|
||||
|
||||
test "is allergic to only chocolate" do
|
||||
assert Allergies.allergic_to?(32, "chocolate")
|
||||
end
|
||||
|
||||
test "is allergic to chocolate and something else" do
|
||||
assert Allergies.allergic_to?(112, "chocolate")
|
||||
end
|
||||
|
||||
test "is allergic to something, but not chocolate" do
|
||||
refute Allergies.allergic_to?(80, "chocolate")
|
||||
end
|
||||
|
||||
test "is allergic to everything (including chocolate)" do
|
||||
assert Allergies.allergic_to?(255, "chocolate")
|
||||
end
|
||||
end
|
||||
|
||||
describe "score for pollen allergies -" do
|
||||
test "not allergic to pollen" do
|
||||
refute Allergies.allergic_to?(0, "pollen")
|
||||
end
|
||||
|
||||
test "is allergic to only pollen" do
|
||||
assert Allergies.allergic_to?(64, "pollen")
|
||||
end
|
||||
|
||||
test "is allergic to pollen and something else" do
|
||||
assert Allergies.allergic_to?(224, "pollen")
|
||||
end
|
||||
|
||||
test "is allergic to something, but not pollen" do
|
||||
refute Allergies.allergic_to?(160, "pollen")
|
||||
end
|
||||
|
||||
test "is allergic to everything (including pollen)" do
|
||||
assert Allergies.allergic_to?(255, "pollen")
|
||||
end
|
||||
end
|
||||
|
||||
describe "score for cats allergies -" do
|
||||
test "not allergic to cats" do
|
||||
refute Allergies.allergic_to?(0, "cats")
|
||||
end
|
||||
|
||||
test "is allergic to only cats" do
|
||||
assert Allergies.allergic_to?(128, "cats")
|
||||
end
|
||||
|
||||
test "is allergic to cats and something else" do
|
||||
assert Allergies.allergic_to?(192, "cats")
|
||||
end
|
||||
|
||||
test "is allergic to something, but not cats" do
|
||||
refute Allergies.allergic_to?(64, "cats")
|
||||
end
|
||||
|
||||
test "is allergic to everything (including cats)" do
|
||||
assert Allergies.allergic_to?(255, "cats")
|
||||
end
|
||||
end
|
||||
end
|
||||
2
elixir/allergies/test/test_helper.exs
Normal file
2
elixir/allergies/test/test_helper.exs
Normal file
@@ -0,0 +1,2 @@
|
||||
ExUnit.start()
|
||||
ExUnit.configure(exclude: :pending, trace: true)
|
||||
41
elixir/anagram/.exercism/config.json
Normal file
41
elixir/anagram/.exercism/config.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"authors": [
|
||||
"rubysolo"
|
||||
],
|
||||
"contributors": [
|
||||
"andrewsardone",
|
||||
"angelikatyborska",
|
||||
"Br1ght0ne",
|
||||
"Cohen-Carlisle",
|
||||
"crazymykl",
|
||||
"dalexj",
|
||||
"devonestes",
|
||||
"henrik",
|
||||
"jeremy-w",
|
||||
"jinyeow",
|
||||
"kytrinyx",
|
||||
"lpil",
|
||||
"markijbema",
|
||||
"neenjaw",
|
||||
"parkerl",
|
||||
"pminten",
|
||||
"sotojuan",
|
||||
"Teapane",
|
||||
"tjcelaya",
|
||||
"waiting-for-dev"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"lib/anagram.ex"
|
||||
],
|
||||
"test": [
|
||||
"test/anagram_test.exs"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.ex"
|
||||
]
|
||||
},
|
||||
"blurb": "Given a word and a list of possible anagrams, select the correct sublist.",
|
||||
"source": "Inspired by the Extreme Startup game",
|
||||
"source_url": "https://github.com/rchatley/extreme_startup"
|
||||
}
|
||||
1
elixir/anagram/.exercism/metadata.json
Normal file
1
elixir/anagram/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
||||
{"track":"elixir","exercise":"anagram","id":"0ffb252576fd4b4fad8cdd024185d2be","url":"https://exercism.org/tracks/elixir/exercises/anagram","handle":"negrienko","is_requester":true,"auto_approve":false}
|
||||
4
elixir/anagram/.formatter.exs
Normal file
4
elixir/anagram/.formatter.exs
Normal file
@@ -0,0 +1,4 @@
|
||||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
||||
24
elixir/anagram/.gitignore
vendored
Normal file
24
elixir/anagram/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
anagram-*.tar
|
||||
|
||||
75
elixir/anagram/HELP.md
Normal file
75
elixir/anagram/HELP.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
From the terminal, change to the base directory of the exercise then execute the tests with:
|
||||
|
||||
```bash
|
||||
$ mix test
|
||||
```
|
||||
|
||||
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs`
|
||||
|
||||
Documentation:
|
||||
|
||||
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html)
|
||||
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html)
|
||||
|
||||
## Pending tests
|
||||
|
||||
In test suites of practice exercises, all but the first test have been tagged to be 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
|
||||
```
|
||||
|
||||
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command:
|
||||
|
||||
```bash
|
||||
$ mix test --include pending
|
||||
```
|
||||
|
||||
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`.
|
||||
|
||||
```elixir
|
||||
# ExUnit.configure(exclude: :pending, trace: true)
|
||||
```
|
||||
|
||||
## Useful `mix test` options
|
||||
|
||||
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM`
|
||||
* `--failed` - runs only tests that failed the last time they ran
|
||||
* `--max-failures` - the suite stops evaluating tests when this number of test failures
|
||||
is reached
|
||||
* `--seed 0` - disables randomization so the tests in a single file will always be ran
|
||||
in the same order they were defined in
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit lib/anagram.ex` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir)
|
||||
- The [Elixir track's programming category on the forum](https://forum.exercism.org/c/programming/elixir)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found.
|
||||
64
elixir/anagram/README.md
Normal file
64
elixir/anagram/README.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Anagram
|
||||
|
||||
Welcome to Anagram on Exercism's Elixir Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Introduction
|
||||
|
||||
At a garage sale, you find a lovely vintage typewriter at a bargain price!
|
||||
Excitedly, you rush home, insert a sheet of paper, and start typing away.
|
||||
However, your excitement wanes when you examine the output: all words are garbled!
|
||||
For example, it prints "stop" instead of "post" and "least" instead of "stale."
|
||||
Carefully, you try again, but now it prints "spot" and "slate."
|
||||
After some experimentation, you find there is a random delay before each letter is printed, which messes up the order.
|
||||
You now understand why they sold it for so little money!
|
||||
|
||||
You realize this quirk allows you to generate anagrams, which are words formed by rearranging the letters of another word.
|
||||
Pleased with your finding, you spend the rest of the day generating hundreds of anagrams.
|
||||
|
||||
## Instructions
|
||||
|
||||
Your task is to, given a target word and a set of candidate words, to find the subset of the candidates that are anagrams of the target.
|
||||
|
||||
An anagram is a rearrangement of letters to form a new word: for example `"owns"` is an anagram of `"snow"`.
|
||||
A word is _not_ its own anagram: for example, `"stop"` is not an anagram of `"stop"`.
|
||||
|
||||
The target and candidates are words of one or more ASCII alphabetic characters (`A`-`Z` and `a`-`z`).
|
||||
Lowercase and uppercase characters are equivalent: for example, `"PoTS"` is an anagram of `"sTOp"`, but `StoP` is not an anagram of `sTOp`.
|
||||
The anagram set is the subset of the candidate set that are anagrams of the target (in any order).
|
||||
Words in the anagram set should have the same letter case as in the candidate set.
|
||||
|
||||
Given the target `"stone"` and candidates `"stone"`, `"tones"`, `"banana"`, `"tons"`, `"notes"`, `"Seton"`, the anagram set is `"tones"`, `"notes"`, `"Seton"`.
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @rubysolo
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @andrewsardone
|
||||
- @angelikatyborska
|
||||
- @Br1ght0ne
|
||||
- @Cohen-Carlisle
|
||||
- @crazymykl
|
||||
- @dalexj
|
||||
- @devonestes
|
||||
- @henrik
|
||||
- @jeremy-w
|
||||
- @jinyeow
|
||||
- @kytrinyx
|
||||
- @lpil
|
||||
- @markijbema
|
||||
- @neenjaw
|
||||
- @parkerl
|
||||
- @pminten
|
||||
- @sotojuan
|
||||
- @Teapane
|
||||
- @tjcelaya
|
||||
- @waiting-for-dev
|
||||
|
||||
### Based on
|
||||
|
||||
Inspired by the Extreme Startup game - https://github.com/rchatley/extreme_startup
|
||||
21
elixir/anagram/lib/anagram.ex
Normal file
21
elixir/anagram/lib/anagram.ex
Normal file
@@ -0,0 +1,21 @@
|
||||
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
|
||||
candidates
|
||||
|> Enum.filter(&anagram?(normalize(base), normalize(&1)))
|
||||
end
|
||||
|
||||
defp anagram?(base, base), do: false
|
||||
defp anagram?(base, candidate), do: hash(base) == hash(candidate)
|
||||
|
||||
@spec normalize(String.t()) :: String.t()
|
||||
defp normalize(string), do: string |> String.downcase() |> String.graphemes()
|
||||
|
||||
@spec hash(String.t()) :: Map.t()
|
||||
defp hash(string) do
|
||||
Enum.reduce(string, %{}, fn char, acc -> Map.update(acc, char, 1, &(&1 + 1)) end)
|
||||
end
|
||||
end
|
||||
28
elixir/anagram/mix.exs
Normal file
28
elixir/anagram/mix.exs
Normal file
@@ -0,0 +1,28 @@
|
||||
defmodule Anagram.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :anagram,
|
||||
version: "0.1.0",
|
||||
# elixir: "~> 1.8",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications.
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
# {:dep_from_hexpm, "~> 0.3.0"},
|
||||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||
]
|
||||
end
|
||||
end
|
||||
100
elixir/anagram/test/anagram_test.exs
Normal file
100
elixir/anagram/test/anagram_test.exs
Normal file
@@ -0,0 +1,100 @@
|
||||
defmodule AnagramTest do
|
||||
use ExUnit.Case
|
||||
|
||||
test "no matches" do
|
||||
matches = Anagram.match("diaper", ~w(hello world zombies pants))
|
||||
assert matches == []
|
||||
end
|
||||
|
||||
test "detects two anagrams" do
|
||||
matches = Anagram.match("solemn", ~w(lemons cherry melons))
|
||||
assert matches == ~w(lemons melons)
|
||||
end
|
||||
|
||||
test "does not detect anagram subsets" do
|
||||
matches = Anagram.match("good", ~w(dog goody))
|
||||
assert matches == []
|
||||
end
|
||||
|
||||
test "detects anagram" do
|
||||
matches = Anagram.match("listen", ~w(enlists google inlets banana))
|
||||
assert matches == ~w(inlets)
|
||||
end
|
||||
|
||||
test "detects three anagrams" do
|
||||
matches = Anagram.match("allergy", ~w(gallery ballerina regally clergy largely leading))
|
||||
assert matches == ~w(gallery regally largely)
|
||||
end
|
||||
|
||||
test "detects multiple anagrams with different case" do
|
||||
matches = Anagram.match("nose", ~w(Eons ONES))
|
||||
assert matches == ~w(Eons ONES)
|
||||
end
|
||||
|
||||
test "does not detect non-anagrams with identical checksum" do
|
||||
matches = Anagram.match("mass", ~w(last))
|
||||
assert matches == []
|
||||
end
|
||||
|
||||
test "detect anagrams case-insensitively" do
|
||||
matches = Anagram.match("orchestra", ~w(cashregister Carthorse radishes))
|
||||
assert matches == ~w(Carthorse)
|
||||
end
|
||||
|
||||
test "detects anagrams using case-insensitive subject" do
|
||||
matches = Anagram.match("Orchestra", ~w(cashregister carthorse radishes))
|
||||
assert matches == ~w(carthorse)
|
||||
end
|
||||
|
||||
test "detects anagrams using case-insensitive possible matches" do
|
||||
matches = Anagram.match("orchestra", ~w(cashregister Carthorse radishes))
|
||||
assert matches == ~w(Carthorse)
|
||||
end
|
||||
|
||||
test "does not detect an anagram if the original word is repeated" do
|
||||
matches = Anagram.match("go", ~w(goGoGO))
|
||||
assert matches == []
|
||||
end
|
||||
|
||||
test "anagrams must use all letters exactly once" do
|
||||
matches = Anagram.match("tapper", ~w(patter))
|
||||
assert matches == []
|
||||
end
|
||||
|
||||
test "words are not anagrams of themselves" do
|
||||
matches = Anagram.match("BANANA", ~w(BANANA))
|
||||
assert matches == []
|
||||
end
|
||||
|
||||
test "words are not anagrams of themselves even if letter case is partially different" do
|
||||
matches = Anagram.match("BANANA", ~w(Banana))
|
||||
assert matches == []
|
||||
end
|
||||
|
||||
test "words are not anagrams of themselves even if letter case is completely different" do
|
||||
matches = Anagram.match("BANANA", ~w(banana))
|
||||
assert matches == []
|
||||
end
|
||||
|
||||
test "words other than themselves can be anagrams" do
|
||||
matches = Anagram.match("LISTEN", ~w(Silent LISTEN))
|
||||
assert matches == ~w(Silent)
|
||||
end
|
||||
|
||||
test "handles case of greek letters" do
|
||||
matches = Anagram.match("ΑΒΓ", ~w(ΒΓΑ ΒΓΔ γβα αβγ))
|
||||
assert matches == ~w(ΒΓΑ γβα)
|
||||
end
|
||||
|
||||
test "different characters may have the same bytes" do
|
||||
matches =
|
||||
Anagram.match(
|
||||
# binary representation: <<0x61, 0xE2, 0xAC, 0x82>>
|
||||
"a⬂",
|
||||
# binary representation: <<0xE2, 0x82, 0xAC, 0x61>>
|
||||
["€a"]
|
||||
)
|
||||
|
||||
assert matches == []
|
||||
end
|
||||
end
|
||||
2
elixir/anagram/test/test_helper.exs
Normal file
2
elixir/anagram/test/test_helper.exs
Normal file
@@ -0,0 +1,2 @@
|
||||
ExUnit.start()
|
||||
ExUnit.configure(exclude: :pending, trace: true)
|
||||
27
elixir/armstrong-numbers/.exercism/config.json
Normal file
27
elixir/armstrong-numbers/.exercism/config.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"authors": [
|
||||
"Bscruz19"
|
||||
],
|
||||
"contributors": [
|
||||
"angelikatyborska",
|
||||
"Br1ght0ne",
|
||||
"Cohen-Carlisle",
|
||||
"devonestes",
|
||||
"neenjaw",
|
||||
"tsuka"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"lib/armstrong_number.ex"
|
||||
],
|
||||
"test": [
|
||||
"test/armstrong_number_test.exs"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.ex"
|
||||
]
|
||||
},
|
||||
"blurb": "Determine if a number is an Armstrong number.",
|
||||
"source": "Wikipedia",
|
||||
"source_url": "https://en.wikipedia.org/wiki/Narcissistic_number"
|
||||
}
|
||||
1
elixir/armstrong-numbers/.exercism/metadata.json
Normal file
1
elixir/armstrong-numbers/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
||||
{"track":"elixir","exercise":"armstrong-numbers","id":"87b5aa5429664271a572c9f3ac0722d1","url":"https://exercism.org/tracks/elixir/exercises/armstrong-numbers","handle":"negrienko","is_requester":true,"auto_approve":false}
|
||||
4
elixir/armstrong-numbers/.formatter.exs
Normal file
4
elixir/armstrong-numbers/.formatter.exs
Normal file
@@ -0,0 +1,4 @@
|
||||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
||||
24
elixir/armstrong-numbers/.gitignore
vendored
Normal file
24
elixir/armstrong-numbers/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
armstrong_numbers-*.tar
|
||||
|
||||
75
elixir/armstrong-numbers/HELP.md
Normal file
75
elixir/armstrong-numbers/HELP.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
From the terminal, change to the base directory of the exercise then execute the tests with:
|
||||
|
||||
```bash
|
||||
$ mix test
|
||||
```
|
||||
|
||||
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs`
|
||||
|
||||
Documentation:
|
||||
|
||||
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html)
|
||||
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html)
|
||||
|
||||
## Pending tests
|
||||
|
||||
In test suites of practice exercises, all but the first test have been tagged to be 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
|
||||
```
|
||||
|
||||
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command:
|
||||
|
||||
```bash
|
||||
$ mix test --include pending
|
||||
```
|
||||
|
||||
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`.
|
||||
|
||||
```elixir
|
||||
# ExUnit.configure(exclude: :pending, trace: true)
|
||||
```
|
||||
|
||||
## Useful `mix test` options
|
||||
|
||||
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM`
|
||||
* `--failed` - runs only tests that failed the last time they ran
|
||||
* `--max-failures` - the suite stops evaluating tests when this number of test failures
|
||||
is reached
|
||||
* `--seed 0` - disables randomization so the tests in a single file will always be ran
|
||||
in the same order they were defined in
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit lib/armstrong_number.ex` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir)
|
||||
- The [Elixir track's programming category on the forum](https://forum.exercism.org/c/programming/elixir)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found.
|
||||
38
elixir/armstrong-numbers/README.md
Normal file
38
elixir/armstrong-numbers/README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Armstrong Numbers
|
||||
|
||||
Welcome to Armstrong Numbers on Exercism's Elixir Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
An [Armstrong number][armstrong-number] is a number that is the sum of its own digits each raised to the power of the number of digits.
|
||||
|
||||
For example:
|
||||
|
||||
- 9 is an Armstrong number, because `9 = 9^1 = 9`
|
||||
- 10 is _not_ an Armstrong number, because `10 != 1^2 + 0^2 = 1`
|
||||
- 153 is an Armstrong number, because: `153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153`
|
||||
- 154 is _not_ an Armstrong number, because: `154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190`
|
||||
|
||||
Write some code to determine whether a number is an Armstrong number.
|
||||
|
||||
[armstrong-number]: https://en.wikipedia.org/wiki/Narcissistic_number
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @Bscruz19
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @angelikatyborska
|
||||
- @Br1ght0ne
|
||||
- @Cohen-Carlisle
|
||||
- @devonestes
|
||||
- @neenjaw
|
||||
- @tsuka
|
||||
|
||||
### Based on
|
||||
|
||||
Wikipedia - https://en.wikipedia.org/wiki/Narcissistic_number
|
||||
13
elixir/armstrong-numbers/lib/armstrong_number.ex
Normal file
13
elixir/armstrong-numbers/lib/armstrong_number.ex
Normal file
@@ -0,0 +1,13 @@
|
||||
defmodule ArmstrongNumber do
|
||||
@moduledoc """
|
||||
Provides a way to validate whether or not a number is an Armstrong number
|
||||
"""
|
||||
|
||||
@spec valid?(integer) :: boolean
|
||||
def valid?(number) do
|
||||
digits = Integer.digits(number)
|
||||
power = length(digits)
|
||||
|
||||
Enum.reduce(digits, 0, &(&1 ** power + &2)) == number
|
||||
end
|
||||
end
|
||||
28
elixir/armstrong-numbers/mix.exs
Normal file
28
elixir/armstrong-numbers/mix.exs
Normal file
@@ -0,0 +1,28 @@
|
||||
defmodule ArmstrongNumber.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :armstrong_number,
|
||||
version: "0.1.0",
|
||||
# elixir: "~> 1.8",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications.
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
# {:dep_from_hexpm, "~> 0.3.0"},
|
||||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||
]
|
||||
end
|
||||
end
|
||||
47
elixir/armstrong-numbers/test/armstrong_number_test.exs
Normal file
47
elixir/armstrong-numbers/test/armstrong_number_test.exs
Normal file
@@ -0,0 +1,47 @@
|
||||
defmodule ArmstrongNumberTest do
|
||||
use ExUnit.Case
|
||||
|
||||
test "Zero is an Armstrong number" do
|
||||
assert ArmstrongNumber.valid?(0)
|
||||
end
|
||||
|
||||
test "Single digit numbers are Armstrong numbers" do
|
||||
assert ArmstrongNumber.valid?(5)
|
||||
end
|
||||
|
||||
test "There are no two-digit Armstrong Numbers" do
|
||||
refute ArmstrongNumber.valid?(10)
|
||||
end
|
||||
|
||||
test "Three-digit number that is an Armstrong number" do
|
||||
assert ArmstrongNumber.valid?(153)
|
||||
end
|
||||
|
||||
test "Three-digit number that is not an Armstrong number" do
|
||||
refute ArmstrongNumber.valid?(100)
|
||||
end
|
||||
|
||||
test "Four-digit number that is an Armstrong number" do
|
||||
assert ArmstrongNumber.valid?(9474)
|
||||
end
|
||||
|
||||
test "Four-digit number that is not an Armstrong number" do
|
||||
refute ArmstrongNumber.valid?(9475)
|
||||
end
|
||||
|
||||
test "Seven-digit number that is an Armstrong number" do
|
||||
assert ArmstrongNumber.valid?(9_926_315)
|
||||
end
|
||||
|
||||
test "Seven-digit number that is not an Armstrong number" do
|
||||
refute ArmstrongNumber.valid?(9_926_134)
|
||||
end
|
||||
|
||||
test "Armstrong number containing seven zeroes" do
|
||||
assert ArmstrongNumber.valid?(186_709_961_001_538_790_100_634_132_976_990)
|
||||
end
|
||||
|
||||
test "The largest and last Armstrong number" do
|
||||
assert ArmstrongNumber.valid?(115_132_219_018_763_992_565_095_597_973_971_522_401)
|
||||
end
|
||||
end
|
||||
2
elixir/armstrong-numbers/test/test_helper.exs
Normal file
2
elixir/armstrong-numbers/test/test_helper.exs
Normal file
@@ -0,0 +1,2 @@
|
||||
ExUnit.start()
|
||||
ExUnit.configure(exclude: :pending, trace: true)
|
||||
36
elixir/atbash-cipher/.exercism/config.json
Normal file
36
elixir/atbash-cipher/.exercism/config.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"authors": [
|
||||
"rubysolo"
|
||||
],
|
||||
"contributors": [
|
||||
"andrewsardone",
|
||||
"angelikatyborska",
|
||||
"Br1ght0ne",
|
||||
"Cohen-Carlisle",
|
||||
"dalexj",
|
||||
"devonestes",
|
||||
"jinyeow",
|
||||
"kytrinyx",
|
||||
"lpil",
|
||||
"mhinz",
|
||||
"neenjaw",
|
||||
"parkerl",
|
||||
"sotojuan",
|
||||
"Teapane",
|
||||
"waiting-for-dev"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"lib/atbash.ex"
|
||||
],
|
||||
"test": [
|
||||
"test/atbash_test.exs"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.ex"
|
||||
]
|
||||
},
|
||||
"blurb": "Create an implementation of the atbash cipher, an ancient encryption system created in the Middle East.",
|
||||
"source": "Wikipedia",
|
||||
"source_url": "https://en.wikipedia.org/wiki/Atbash"
|
||||
}
|
||||
1
elixir/atbash-cipher/.exercism/metadata.json
Normal file
1
elixir/atbash-cipher/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
||||
{"track":"elixir","exercise":"atbash-cipher","id":"156913b0379c4b8886dff7de48ab370e","url":"https://exercism.org/tracks/elixir/exercises/atbash-cipher","handle":"negrienko","is_requester":true,"auto_approve":false}
|
||||
4
elixir/atbash-cipher/.formatter.exs
Normal file
4
elixir/atbash-cipher/.formatter.exs
Normal file
@@ -0,0 +1,4 @@
|
||||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
||||
24
elixir/atbash-cipher/.gitignore
vendored
Normal file
24
elixir/atbash-cipher/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
atbash_cipher-*.tar
|
||||
|
||||
75
elixir/atbash-cipher/HELP.md
Normal file
75
elixir/atbash-cipher/HELP.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
From the terminal, change to the base directory of the exercise then execute the tests with:
|
||||
|
||||
```bash
|
||||
$ mix test
|
||||
```
|
||||
|
||||
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs`
|
||||
|
||||
Documentation:
|
||||
|
||||
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html)
|
||||
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html)
|
||||
|
||||
## Pending tests
|
||||
|
||||
In test suites of practice exercises, all but the first test have been tagged to be 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
|
||||
```
|
||||
|
||||
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command:
|
||||
|
||||
```bash
|
||||
$ mix test --include pending
|
||||
```
|
||||
|
||||
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`.
|
||||
|
||||
```elixir
|
||||
# ExUnit.configure(exclude: :pending, trace: true)
|
||||
```
|
||||
|
||||
## Useful `mix test` options
|
||||
|
||||
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM`
|
||||
* `--failed` - runs only tests that failed the last time they ran
|
||||
* `--max-failures` - the suite stops evaluating tests when this number of test failures
|
||||
is reached
|
||||
* `--seed 0` - disables randomization so the tests in a single file will always be ran
|
||||
in the same order they were defined in
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit lib/atbash.ex` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir)
|
||||
- The [Elixir track's programming category on the forum](https://forum.exercism.org/c/programming/elixir)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found.
|
||||
60
elixir/atbash-cipher/README.md
Normal file
60
elixir/atbash-cipher/README.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# Atbash Cipher
|
||||
|
||||
Welcome to Atbash Cipher on Exercism's Elixir Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
Create an implementation of the atbash cipher, an ancient encryption system created in the Middle East.
|
||||
|
||||
The Atbash cipher is a simple substitution cipher that relies on transposing all the letters in the alphabet such that the resulting alphabet is backwards.
|
||||
The first letter is replaced with the last letter, the second with the second-last, and so on.
|
||||
|
||||
An Atbash cipher for the Latin alphabet would be as follows:
|
||||
|
||||
```text
|
||||
Plain: abcdefghijklmnopqrstuvwxyz
|
||||
Cipher: zyxwvutsrqponmlkjihgfedcba
|
||||
```
|
||||
|
||||
It is a very weak cipher because it only has one possible key, and it is a simple mono-alphabetic substitution cipher.
|
||||
However, this may not have been an issue in the cipher's time.
|
||||
|
||||
Ciphertext is written out in groups of fixed length, the traditional group size being 5 letters, leaving numbers unchanged, and punctuation is excluded.
|
||||
This is to make it harder to guess things based on word boundaries.
|
||||
All text will be encoded as lowercase letters.
|
||||
|
||||
## Examples
|
||||
|
||||
- Encoding `test` gives `gvhg`
|
||||
- Encoding `x123 yes` gives `c123b vh`
|
||||
- Decoding `gvhg` gives `test`
|
||||
- Decoding `gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt` gives `thequickbrownfoxjumpsoverthelazydog`
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @rubysolo
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @andrewsardone
|
||||
- @angelikatyborska
|
||||
- @Br1ght0ne
|
||||
- @Cohen-Carlisle
|
||||
- @dalexj
|
||||
- @devonestes
|
||||
- @jinyeow
|
||||
- @kytrinyx
|
||||
- @lpil
|
||||
- @mhinz
|
||||
- @neenjaw
|
||||
- @parkerl
|
||||
- @sotojuan
|
||||
- @Teapane
|
||||
- @waiting-for-dev
|
||||
|
||||
### Based on
|
||||
|
||||
Wikipedia - https://en.wikipedia.org/wiki/Atbash
|
||||
48
elixir/atbash-cipher/lib/atbash.ex
Normal file
48
elixir/atbash-cipher/lib/atbash.ex
Normal file
@@ -0,0 +1,48 @@
|
||||
defmodule Atbash do
|
||||
@letters ?a..?z
|
||||
|> Enum.to_list
|
||||
|> to_string
|
||||
|> String.graphemes()
|
||||
|
||||
@digits ?0..?9
|
||||
|> Enum.to_list
|
||||
|> to_string
|
||||
|> String.graphemes()
|
||||
|
||||
@table Map.new(Enum.zip(@letters, Enum.reverse(@letters)))
|
||||
|
||||
defguardp is_letter(char) when char in @letters
|
||||
defguardp is_digit(char) when char in @digits
|
||||
|
||||
@doc """
|
||||
Encode a given plaintext to the corresponding ciphertext
|
||||
|
||||
## Examples
|
||||
|
||||
iex> Atbash.encode("completely insecure")
|
||||
"xlnko vgvob rmhvx fiv"
|
||||
"""
|
||||
@spec encode(String.t()) :: String.t()
|
||||
def encode(plaintext) do
|
||||
plaintext
|
||||
|> transpose()
|
||||
|> String.graphemes()
|
||||
|> Enum.chunk_every(5)
|
||||
|> Enum.join(" ")
|
||||
end
|
||||
|
||||
@spec decode(String.t()) :: String.t()
|
||||
def decode(cipher), do: transpose(cipher)
|
||||
|
||||
defp transpose(string) do
|
||||
string
|
||||
|> String.downcase()
|
||||
|> String.graphemes()
|
||||
|> Enum.map(&code/1)
|
||||
|> Enum.join()
|
||||
end
|
||||
|
||||
defp code(char) when is_digit(char), do: char
|
||||
defp code(char) when is_letter(char), do: @table[char]
|
||||
defp code(_char), do: nil
|
||||
end
|
||||
28
elixir/atbash-cipher/mix.exs
Normal file
28
elixir/atbash-cipher/mix.exs
Normal file
@@ -0,0 +1,28 @@
|
||||
defmodule Atbash.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :atbash,
|
||||
version: "0.1.0",
|
||||
# elixir: "~> 1.8",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications.
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
# {:dep_from_hexpm, "~> 0.3.0"},
|
||||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||
]
|
||||
end
|
||||
end
|
||||
77
elixir/atbash-cipher/test/atbash_test.exs
Normal file
77
elixir/atbash-cipher/test/atbash_test.exs
Normal file
@@ -0,0 +1,77 @@
|
||||
defmodule AtbashTest do
|
||||
use ExUnit.Case
|
||||
|
||||
describe "encode" do
|
||||
test "yes" do
|
||||
assert Atbash.encode("yes") == "bvh"
|
||||
end
|
||||
|
||||
test "no" do
|
||||
assert Atbash.encode("no") == "ml"
|
||||
end
|
||||
|
||||
test "OMG" do
|
||||
assert Atbash.encode("OMG") == "lnt"
|
||||
end
|
||||
|
||||
test "O M G" do
|
||||
assert Atbash.encode("O M G") == "lnt"
|
||||
end
|
||||
|
||||
test "mindblowingly" do
|
||||
assert Atbash.encode("mindblowingly") == "nrmwy oldrm tob"
|
||||
end
|
||||
|
||||
test "numbers" do
|
||||
assert Atbash.encode("Testing, 1 2 3, testing.") == "gvhgr mt123 gvhgr mt"
|
||||
end
|
||||
|
||||
test "deep thought" do
|
||||
assert Atbash.encode("Truth is fiction.") == "gifgs rhurx grlm"
|
||||
end
|
||||
|
||||
test "all the letters" do
|
||||
plaintext = "The quick brown fox jumps over the lazy dog."
|
||||
cipher = "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt"
|
||||
assert Atbash.encode(plaintext) == cipher
|
||||
end
|
||||
end
|
||||
|
||||
describe "decode" do
|
||||
test "exercism" do
|
||||
cipher = "vcvix rhn"
|
||||
plaintext = "exercism"
|
||||
assert Atbash.decode(cipher) == plaintext
|
||||
end
|
||||
|
||||
test "a sentence" do
|
||||
cipher = "zmlyh gzxov rhlug vmzhg vkkrm thglm v"
|
||||
plaintext = "anobstacleisoftenasteppingstone"
|
||||
assert Atbash.decode(cipher) == plaintext
|
||||
end
|
||||
|
||||
test "numbers" do
|
||||
cipher = "gvhgr mt123 gvhgr mt"
|
||||
plaintext = "testing123testing"
|
||||
assert Atbash.decode(cipher) == plaintext
|
||||
end
|
||||
|
||||
test "all the letters" do
|
||||
cipher = "gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt"
|
||||
plaintext = "thequickbrownfoxjumpsoverthelazydog"
|
||||
assert Atbash.decode(cipher) == plaintext
|
||||
end
|
||||
|
||||
test "with too many spaces" do
|
||||
cipher = "vc vix r hn"
|
||||
plaintext = "exercism"
|
||||
assert Atbash.decode(cipher) == plaintext
|
||||
end
|
||||
|
||||
test "with no spaces" do
|
||||
cipher = "zmlyhgzxovrhlugvmzhgvkkrmthglmv"
|
||||
plaintext = "anobstacleisoftenasteppingstone"
|
||||
assert Atbash.decode(cipher) == plaintext
|
||||
end
|
||||
end
|
||||
end
|
||||
2
elixir/atbash-cipher/test/test_helper.exs
Normal file
2
elixir/atbash-cipher/test/test_helper.exs
Normal file
@@ -0,0 +1,2 @@
|
||||
ExUnit.start()
|
||||
ExUnit.configure(exclude: :pending, trace: true)
|
||||
22
elixir/basketball-website/.exercism/config.json
Normal file
22
elixir/basketball-website/.exercism/config.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"authors": [
|
||||
"neenjaw"
|
||||
],
|
||||
"contributors": [
|
||||
"angelikatyborska",
|
||||
"NobbZ"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"lib/basketball_website.ex"
|
||||
],
|
||||
"test": [
|
||||
"test/basketball_website_test.exs"
|
||||
],
|
||||
"exemplar": [
|
||||
".meta/exemplar.ex"
|
||||
]
|
||||
},
|
||||
"language_versions": ">=1.10",
|
||||
"blurb": "Learn about Access Behaviour by helping extract deeply nested data for the basketball team's website."
|
||||
}
|
||||
1
elixir/basketball-website/.exercism/metadata.json
Normal file
1
elixir/basketball-website/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
||||
{"track":"elixir","exercise":"basketball-website","id":"740e1842211445898b26c211cbf40f0c","url":"https://exercism.org/tracks/elixir/exercises/basketball-website","handle":"negrienko","is_requester":true,"auto_approve":false}
|
||||
4
elixir/basketball-website/.formatter.exs
Normal file
4
elixir/basketball-website/.formatter.exs
Normal file
@@ -0,0 +1,4 @@
|
||||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
||||
24
elixir/basketball-website/.gitignore
vendored
Normal file
24
elixir/basketball-website/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
access-*.tar
|
||||
|
||||
75
elixir/basketball-website/HELP.md
Normal file
75
elixir/basketball-website/HELP.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
From the terminal, change to the base directory of the exercise then execute the tests with:
|
||||
|
||||
```bash
|
||||
$ mix test
|
||||
```
|
||||
|
||||
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs`
|
||||
|
||||
Documentation:
|
||||
|
||||
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html)
|
||||
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html)
|
||||
|
||||
## Pending tests
|
||||
|
||||
In test suites of practice exercises, all but the first test have been tagged to be 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
|
||||
```
|
||||
|
||||
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command:
|
||||
|
||||
```bash
|
||||
$ mix test --include pending
|
||||
```
|
||||
|
||||
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`.
|
||||
|
||||
```elixir
|
||||
# ExUnit.configure(exclude: :pending, trace: true)
|
||||
```
|
||||
|
||||
## Useful `mix test` options
|
||||
|
||||
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM`
|
||||
* `--failed` - runs only tests that failed the last time they ran
|
||||
* `--max-failures` - the suite stops evaluating tests when this number of test failures
|
||||
is reached
|
||||
* `--seed 0` - disables randomization so the tests in a single file will always be ran
|
||||
in the same order they were defined in
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit lib/basketball_website.ex` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir)
|
||||
- The [Elixir track's programming category on the forum](https://forum.exercism.org/c/programming/elixir)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found.
|
||||
18
elixir/basketball-website/HINTS.md
Normal file
18
elixir/basketball-website/HINTS.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Hints
|
||||
|
||||
## General
|
||||
|
||||
- Read about the [`Access` behaviour][access-behaviour] in the documentation.
|
||||
|
||||
## 1. Extract data from a nested map structure
|
||||
|
||||
- First tokenize the string path to a usable state. You can make use of [`String` module functions][string-module].
|
||||
- Write a recursive function to traverse the nested-map structure to retrieve the value or return `nil`.
|
||||
|
||||
## 2. Refactor using included functions
|
||||
|
||||
- Read through the various [`Kernel` module functions][kernel-module], to find one that might shorten/simplify your approach.
|
||||
|
||||
[kernel-module]: https://hexdocs.pm/elixir/Kernel.html#functions
|
||||
[string-module]: https://hexdocs.pm/elixir/String.html#functions
|
||||
[access-behaviour]: https://hexdocs.pm/elixir/Access.html
|
||||
82
elixir/basketball-website/README.md
Normal file
82
elixir/basketball-website/README.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Basketball Website
|
||||
|
||||
Welcome to Basketball Website on Exercism's Elixir Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
|
||||
|
||||
## Introduction
|
||||
|
||||
## Access Behaviour
|
||||
|
||||
Elixir uses code _Behaviours_ to provide common generic interfaces while facilitating specific implementations for each module which implements it. One such common example is the _Access Behaviour_.
|
||||
|
||||
The _Access Behaviour_ provides a common interface for retrieving data from a key-based data structure. The _Access Behaviour_ is implemented for maps and keyword lists, but let's look at its use for maps to get a feel for it. _Access Behaviour_ specifies that when you have a map, you may follow it with _square brackets_ and then use the key to retrieve the value associated with that key.
|
||||
|
||||
```elixir
|
||||
# Suppose we have these two maps defined (note the difference in the key type)
|
||||
my_map = %{key: "my value"}
|
||||
your_map = %{"key" => "your value"}
|
||||
|
||||
# Obtain the value using the Access Behaviour
|
||||
my_map[:key] == "my value"
|
||||
your_map[:key] == nil
|
||||
your_map["key"] == "your value"
|
||||
```
|
||||
|
||||
If the key does not exist in the data structure, then `nil` is returned. This can be a source of unintended behavior, because it does not raise an error. Note that `nil` itself implements the Access Behaviour and always returns `nil` for any key.
|
||||
|
||||
## Instructions
|
||||
|
||||
You are working with a web development team to maintain a website for a local basketball team. The web development team is less familiar with Elixir and is asking for a function to be able to extract data from a series of nested maps to facilitate rapid development.
|
||||
|
||||
## 1. Extract data from a nested map structure
|
||||
|
||||
Implement the `extract_from_path/2` function to take two arguments:
|
||||
|
||||
- `data`: a nested map structure with data about the basketball team.
|
||||
- `path`: a string consisting of period-delimited keys to obtain the value associated with the last key.
|
||||
|
||||
If the value or the key does not exist at any point in the path, `nil` should be returned
|
||||
|
||||
```elixir
|
||||
data = %{
|
||||
"team_mascot" => %{
|
||||
"animal" => "bear",
|
||||
"actor" => %{
|
||||
"first_name" => "Noel"
|
||||
}
|
||||
}
|
||||
}
|
||||
BasketballWebsite.extract_from_path(data, "team_mascot.animal")
|
||||
# => "bear"
|
||||
BasketballWebsite.extract_from_path(data, "team_mascot.colors")
|
||||
# => nil
|
||||
```
|
||||
|
||||
Use the _Access Behaviour_ when implementing this function.
|
||||
|
||||
Do not use any `Map` or `Kernel` module functions for working with the nested map data structure.
|
||||
|
||||
## 2. Refactor using included functions
|
||||
|
||||
Your coworker reviewing your code tells you about a `Kernel` module function which does something very similar to your implementation.
|
||||
|
||||
Implement `get_in_path/2` to use this `Kernel` module function.
|
||||
|
||||
The arguments expected are the same as part 1.
|
||||
|
||||
```elixir
|
||||
BasketballWebsite.get_in_path(data, "team_mascot.actor.first_name")
|
||||
# => "Noel"
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @neenjaw
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @angelikatyborska
|
||||
- @NobbZ
|
||||
15
elixir/basketball-website/lib/basketball_website.ex
Normal file
15
elixir/basketball-website/lib/basketball_website.ex
Normal file
@@ -0,0 +1,15 @@
|
||||
defmodule BasketballWebsite do
|
||||
def extract_from_path(data, path) do
|
||||
path
|
||||
|> String.split(".")
|
||||
|> get_path(data)
|
||||
end
|
||||
|
||||
defp get_path(_list, nil), do: nil
|
||||
defp get_path([], data), do: data
|
||||
defp get_path([head | tail], data), do: get_path(tail, data[head])
|
||||
|
||||
def get_in_path(data, path) do
|
||||
get_in(data, String.split(path, "."))
|
||||
end
|
||||
end
|
||||
28
elixir/basketball-website/mix.exs
Normal file
28
elixir/basketball-website/mix.exs
Normal file
@@ -0,0 +1,28 @@
|
||||
defmodule BasketballWebsite.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :basketball_website,
|
||||
version: "0.1.0",
|
||||
# elixir: "~> 1.10",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications.
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
# {:dep_from_hexpm, "~> 0.3.0"},
|
||||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||
]
|
||||
end
|
||||
end
|
||||
335
elixir/basketball-website/test/basketball_website_test.exs
Normal file
335
elixir/basketball-website/test/basketball_website_test.exs
Normal file
@@ -0,0 +1,335 @@
|
||||
defmodule BasketballWebsiteTest do
|
||||
use ExUnit.Case
|
||||
|
||||
describe "extract_from_path retrieves from" do
|
||||
@tag task_id: 1
|
||||
test "first layer" do
|
||||
team_data = %{
|
||||
"coach" => %{},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.extract_from_path(team_data, "team_name") == "Hoop Masters"
|
||||
end
|
||||
|
||||
@tag task_id: 1
|
||||
test "second layer" do
|
||||
team_data = %{
|
||||
"coach" => %{
|
||||
"first_name" => "Jane",
|
||||
"last_name" => "Brown"
|
||||
},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.extract_from_path(team_data, "coach.first_name") == "Jane"
|
||||
end
|
||||
|
||||
@tag task_id: 1
|
||||
test "third layer" do
|
||||
team_data = %{
|
||||
"coach" => %{},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{
|
||||
"99" => %{
|
||||
"first_name" => "Amalee",
|
||||
"last_name" => "Tynemouth",
|
||||
"email" => "atynemouth0@yellowpages.com",
|
||||
"statistics" => %{}
|
||||
},
|
||||
"98" => %{
|
||||
"first_name" => "Tiffie",
|
||||
"last_name" => "Derle",
|
||||
"email" => "tderle1@vimeo.com",
|
||||
"statistics" => %{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.extract_from_path(team_data, "players.99.first_name") == "Amalee"
|
||||
end
|
||||
|
||||
@tag task_id: 1
|
||||
test "fourth layer" do
|
||||
team_data = %{
|
||||
"coach" => %{},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{
|
||||
"42" => %{
|
||||
"first_name" => "Conchita",
|
||||
"last_name" => "Elham",
|
||||
"email" => "celham4@wikia.com",
|
||||
"statistics" => %{
|
||||
"average_points_per_game" => 4.6,
|
||||
"free_throws_made" => 7,
|
||||
"free_throws_attempted" => 10
|
||||
}
|
||||
},
|
||||
"61" => %{
|
||||
"first_name" => "Noel",
|
||||
"last_name" => "Fawlkes",
|
||||
"email" => "nfawlkes5@yahoo.co.jp",
|
||||
"statistics" => %{
|
||||
"average_points_per_game" => 5.0,
|
||||
"free_throws_made" => 5,
|
||||
"free_throws_attempted" => 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.extract_from_path(
|
||||
team_data,
|
||||
"players.61.statistics.average_points_per_game"
|
||||
) === 5.0
|
||||
end
|
||||
end
|
||||
|
||||
describe "extract_from_path returns nil from nonexistent last key in" do
|
||||
@tag task_id: 1
|
||||
test "first layer" do
|
||||
team_data = %{
|
||||
"coach" => %{},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.extract_from_path(team_data, "team_song") == nil
|
||||
end
|
||||
|
||||
@tag task_id: 1
|
||||
test "second layer" do
|
||||
team_data = %{
|
||||
"coach" => %{
|
||||
"first_name" => "Jane",
|
||||
"last_name" => "Brown"
|
||||
},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.extract_from_path(team_data, "coach.age") == nil
|
||||
end
|
||||
|
||||
@tag task_id: 1
|
||||
test "third layer" do
|
||||
team_data = %{
|
||||
"coach" => %{},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{
|
||||
"32" => %{
|
||||
"first_name" => "Deni",
|
||||
"last_name" => "Lidster",
|
||||
"email" => nil,
|
||||
"statistics" => %{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.extract_from_path(team_data, "players.32.height") == nil
|
||||
end
|
||||
|
||||
@tag task_id: 1
|
||||
test "fourth layer" do
|
||||
team_data = %{
|
||||
"coach" => %{},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{
|
||||
"12" => %{
|
||||
"first_name" => "Andy",
|
||||
"last_name" => "Napoli",
|
||||
"email" => "anapoli7@goodreads.com",
|
||||
"statistics" => %{
|
||||
"average_points_per_game" => 7
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.extract_from_path(
|
||||
team_data,
|
||||
"players.12.statistics.personal_fouls"
|
||||
) == nil
|
||||
end
|
||||
end
|
||||
|
||||
@tag task_id: 1
|
||||
test "extract_from_path returns nil from nonexistent path" do
|
||||
team_data = %{
|
||||
"coach" => %{},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.extract_from_path(
|
||||
team_data,
|
||||
"support_personnel.physiotherapy.first_name"
|
||||
) == nil
|
||||
end
|
||||
|
||||
describe "get_in_path retrieves from" do
|
||||
@tag task_id: 2
|
||||
test "first layer" do
|
||||
team_data = %{
|
||||
"coach" => %{},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.get_in_path(team_data, "team_name") == "Hoop Masters"
|
||||
end
|
||||
|
||||
@tag task_id: 2
|
||||
test "second layer" do
|
||||
team_data = %{
|
||||
"coach" => %{
|
||||
"first_name" => "Jane",
|
||||
"last_name" => "Brown"
|
||||
},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.get_in_path(team_data, "coach.first_name") == "Jane"
|
||||
end
|
||||
|
||||
@tag task_id: 2
|
||||
test "third layer" do
|
||||
team_data = %{
|
||||
"coach" => %{},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{
|
||||
"99" => %{
|
||||
"first_name" => "Amalee",
|
||||
"last_name" => "Tynemouth",
|
||||
"email" => "atynemouth0@yellowpages.com",
|
||||
"statistics" => %{}
|
||||
},
|
||||
"98" => %{
|
||||
"first_name" => "Tiffie",
|
||||
"last_name" => "Derle",
|
||||
"email" => "tderle1@vimeo.com",
|
||||
"statistics" => %{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.get_in_path(team_data, "players.99.first_name") == "Amalee"
|
||||
end
|
||||
|
||||
@tag task_id: 2
|
||||
test "fourth layer" do
|
||||
team_data = %{
|
||||
"coach" => %{},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{
|
||||
"42" => %{
|
||||
"first_name" => "Conchita",
|
||||
"last_name" => "Elham",
|
||||
"email" => "celham4@wikia.com",
|
||||
"statistics" => %{
|
||||
"average_points_per_game" => 4.6,
|
||||
"free_throws_made" => 7,
|
||||
"free_throws_attempted" => 10
|
||||
}
|
||||
},
|
||||
"61" => %{
|
||||
"first_name" => "Noel",
|
||||
"last_name" => "Fawlkes",
|
||||
"email" => "nfawlkes5@yahoo.co.jp",
|
||||
"statistics" => %{
|
||||
"average_points_per_game" => 5.0,
|
||||
"free_throws_made" => 5,
|
||||
"free_throws_attempted" => 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.get_in_path(
|
||||
team_data,
|
||||
"players.61.statistics.average_points_per_game"
|
||||
) === 5.0
|
||||
end
|
||||
end
|
||||
|
||||
describe "get_in_path returns nil from nonexistent last key in" do
|
||||
@tag task_id: 2
|
||||
test "first layer" do
|
||||
team_data = %{
|
||||
"coach" => %{},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.get_in_path(team_data, "team_song") == nil
|
||||
end
|
||||
|
||||
@tag task_id: 2
|
||||
test "second layer" do
|
||||
team_data = %{
|
||||
"coach" => %{
|
||||
"first_name" => "Jane",
|
||||
"last_name" => "Brown"
|
||||
},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.get_in_path(team_data, "coach.age") == nil
|
||||
end
|
||||
|
||||
@tag task_id: 2
|
||||
test "third layer" do
|
||||
team_data = %{
|
||||
"coach" => %{},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{
|
||||
"32" => %{
|
||||
"first_name" => "Deni",
|
||||
"last_name" => "Lidster",
|
||||
"email" => nil,
|
||||
"statistics" => %{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.get_in_path(team_data, "players.32.height") == nil
|
||||
end
|
||||
|
||||
@tag task_id: 2
|
||||
test "fourth layer" do
|
||||
team_data = %{
|
||||
"coach" => %{},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{
|
||||
"12" => %{
|
||||
"first_name" => "Andy",
|
||||
"last_name" => "Napoli",
|
||||
"email" => "anapoli7@goodreads.com",
|
||||
"statistics" => %{
|
||||
"average_points_per_game" => 7
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.get_in_path(team_data, "players.12.statistics.personal_fouls") ==
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@tag task_id: 2
|
||||
test "get_in_path returns nil from nonexistent path" do
|
||||
team_data = %{
|
||||
"coach" => %{},
|
||||
"team_name" => "Hoop Masters",
|
||||
"players" => %{}
|
||||
}
|
||||
|
||||
assert BasketballWebsite.get_in_path(team_data, "support_personnel.physiotherapy.first_name") ==
|
||||
nil
|
||||
end
|
||||
end
|
||||
2
elixir/basketball-website/test/test_helper.exs
Normal file
2
elixir/basketball-website/test/test_helper.exs
Normal file
@@ -0,0 +1,2 @@
|
||||
ExUnit.start()
|
||||
ExUnit.configure(exclude: :pending, trace: true, seed: 0)
|
||||
25
elixir/binary-search-tree/.exercism/config.json
Normal file
25
elixir/binary-search-tree/.exercism/config.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"authors": [
|
||||
"sngeth"
|
||||
],
|
||||
"contributors": [
|
||||
"angelikatyborska",
|
||||
"Cohen-Carlisle",
|
||||
"devonestes",
|
||||
"neenjaw",
|
||||
"sotojuan"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"lib/binary_search_tree.ex"
|
||||
],
|
||||
"test": [
|
||||
"test/binary_search_tree_test.exs"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.ex"
|
||||
]
|
||||
},
|
||||
"blurb": "Insert and search for numbers in a binary tree.",
|
||||
"source": "Josh Cheek"
|
||||
}
|
||||
1
elixir/binary-search-tree/.exercism/metadata.json
Normal file
1
elixir/binary-search-tree/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
||||
{"track":"elixir","exercise":"binary-search-tree","id":"fc6ed3ee9f82408eb78d0f9df5e506bf","url":"https://exercism.org/tracks/elixir/exercises/binary-search-tree","handle":"negrienko","is_requester":true,"auto_approve":false}
|
||||
4
elixir/binary-search-tree/.formatter.exs
Normal file
4
elixir/binary-search-tree/.formatter.exs
Normal file
@@ -0,0 +1,4 @@
|
||||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
||||
24
elixir/binary-search-tree/.gitignore
vendored
Normal file
24
elixir/binary-search-tree/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
binary_search_tree-*.tar
|
||||
|
||||
75
elixir/binary-search-tree/HELP.md
Normal file
75
elixir/binary-search-tree/HELP.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
From the terminal, change to the base directory of the exercise then execute the tests with:
|
||||
|
||||
```bash
|
||||
$ mix test
|
||||
```
|
||||
|
||||
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs`
|
||||
|
||||
Documentation:
|
||||
|
||||
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html)
|
||||
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html)
|
||||
|
||||
## Pending tests
|
||||
|
||||
In test suites of practice exercises, all but the first test have been tagged to be 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
|
||||
```
|
||||
|
||||
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command:
|
||||
|
||||
```bash
|
||||
$ mix test --include pending
|
||||
```
|
||||
|
||||
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`.
|
||||
|
||||
```elixir
|
||||
# ExUnit.configure(exclude: :pending, trace: true)
|
||||
```
|
||||
|
||||
## Useful `mix test` options
|
||||
|
||||
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM`
|
||||
* `--failed` - runs only tests that failed the last time they ran
|
||||
* `--max-failures` - the suite stops evaluating tests when this number of test failures
|
||||
is reached
|
||||
* `--seed 0` - disables randomization so the tests in a single file will always be ran
|
||||
in the same order they were defined in
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit lib/binary_search_tree.ex` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir)
|
||||
- The [Elixir track's programming category on the forum](https://forum.exercism.org/c/programming/elixir)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found.
|
||||
70
elixir/binary-search-tree/README.md
Normal file
70
elixir/binary-search-tree/README.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Binary Search Tree
|
||||
|
||||
Welcome to Binary Search Tree on Exercism's Elixir Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Instructions
|
||||
|
||||
Insert and search for numbers in a binary tree.
|
||||
|
||||
When we need to represent sorted data, an array does not make a good data structure.
|
||||
|
||||
Say we have the array `[1, 3, 4, 5]`, and we add 2 to it so it becomes `[1, 3, 4, 5, 2]`.
|
||||
Now we must sort the entire array again!
|
||||
We can improve on this by realizing that we only need to make space for the new item `[1, nil, 3, 4, 5]`, and then adding the item in the space we added.
|
||||
But this still requires us to shift many elements down by one.
|
||||
|
||||
Binary Search Trees, however, can operate on sorted data much more efficiently.
|
||||
|
||||
A binary search tree consists of a series of connected nodes.
|
||||
Each node contains a piece of data (e.g. the number 3), a variable named `left`, and a variable named `right`.
|
||||
The `left` and `right` variables point at `nil`, or other nodes.
|
||||
Since these other nodes in turn have other nodes beneath them, we say that the left and right variables are pointing at subtrees.
|
||||
All data in the left subtree is less than or equal to the current node's data, and all data in the right subtree is greater than the current node's data.
|
||||
|
||||
For example, if we had a node containing the data 4, and we added the data 2, our tree would look like this:
|
||||
|
||||
4
|
||||
/
|
||||
2
|
||||
|
||||
If we then added 6, it would look like this:
|
||||
|
||||
4
|
||||
/ \
|
||||
2 6
|
||||
|
||||
If we then added 3, it would look like this
|
||||
|
||||
4
|
||||
/ \
|
||||
2 6
|
||||
\
|
||||
3
|
||||
|
||||
And if we then added 1, 5, and 7, it would look like this
|
||||
|
||||
4
|
||||
/ \
|
||||
/ \
|
||||
2 6
|
||||
/ \ / \
|
||||
1 3 5 7
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @sngeth
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @angelikatyborska
|
||||
- @Cohen-Carlisle
|
||||
- @devonestes
|
||||
- @neenjaw
|
||||
- @sotojuan
|
||||
|
||||
### Based on
|
||||
|
||||
Josh Cheek
|
||||
26
elixir/binary-search-tree/lib/binary_search_tree.ex
Normal file
26
elixir/binary-search-tree/lib/binary_search_tree.ex
Normal file
@@ -0,0 +1,26 @@
|
||||
defmodule BinarySearchTree do
|
||||
@type bst_node :: %{data: any, left: bst_node | nil, right: bst_node | nil}
|
||||
|
||||
@doc """
|
||||
Create a new Binary Search Tree with root's value as the given 'data'
|
||||
"""
|
||||
@spec new(any) :: bst_node
|
||||
def new(data), do: %{data: data, left: nil, right: nil}
|
||||
|
||||
@doc """
|
||||
Creates and inserts a node with its value as 'data' into the tree.
|
||||
"""
|
||||
@spec insert(bst_node, any) :: bst_node
|
||||
def insert(nil, data), do: new(data)
|
||||
def insert(tree, data) when data <= tree.data, do:
|
||||
%{tree | left: insert(tree.left, data)}
|
||||
def insert(tree, data), do:
|
||||
%{tree | right: insert(tree.right, data)}
|
||||
|
||||
@doc """
|
||||
Traverses the Binary Search Tree in order and returns a list of each node's data.
|
||||
"""
|
||||
@spec in_order(bst_node) :: [any]
|
||||
def in_order(nil), do: []
|
||||
def in_order(tree), do: in_order(tree.left) ++ [tree.data | in_order(tree.right)]
|
||||
end
|
||||
28
elixir/binary-search-tree/mix.exs
Normal file
28
elixir/binary-search-tree/mix.exs
Normal file
@@ -0,0 +1,28 @@
|
||||
defmodule BinarySearchTree.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :binary_search_tree,
|
||||
version: "0.1.0",
|
||||
# elixir: "~> 1.8",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications.
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
# {:dep_from_hexpm, "~> 0.3.0"},
|
||||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||
]
|
||||
end
|
||||
end
|
||||
119
elixir/binary-search-tree/test/binary_search_tree_test.exs
Normal file
119
elixir/binary-search-tree/test/binary_search_tree_test.exs
Normal file
@@ -0,0 +1,119 @@
|
||||
defmodule BinarySearchTreeTest do
|
||||
use ExUnit.Case
|
||||
|
||||
test "data is retained" do
|
||||
root = BinarySearchTree.new(4)
|
||||
assert root.data == 4
|
||||
assert root.left == nil
|
||||
assert root.right == nil
|
||||
end
|
||||
|
||||
describe "insert data at proper node" do
|
||||
test "smaller number at left node" do
|
||||
root =
|
||||
BinarySearchTree.new(4)
|
||||
|> BinarySearchTree.insert(2)
|
||||
|
||||
assert root.data == 4
|
||||
assert root.left.data == 2
|
||||
assert root.left.left == nil
|
||||
assert root.left.right == nil
|
||||
assert root.right == nil
|
||||
end
|
||||
|
||||
test "same number at left node" do
|
||||
root =
|
||||
BinarySearchTree.new(4)
|
||||
|> BinarySearchTree.insert(4)
|
||||
|
||||
assert root.data == 4
|
||||
assert root.left.data == 4
|
||||
assert root.left.left == nil
|
||||
assert root.left.right == nil
|
||||
assert root.right == nil
|
||||
end
|
||||
|
||||
test "greater number at right node" do
|
||||
root =
|
||||
BinarySearchTree.new(4)
|
||||
|> BinarySearchTree.insert(5)
|
||||
|
||||
assert root.data == 4
|
||||
assert root.left == nil
|
||||
assert root.right.data == 5
|
||||
assert root.right.left == nil
|
||||
assert root.right.right == nil
|
||||
end
|
||||
end
|
||||
|
||||
test "can create complex tree" do
|
||||
root =
|
||||
BinarySearchTree.new(4)
|
||||
|> BinarySearchTree.insert(2)
|
||||
|> BinarySearchTree.insert(6)
|
||||
|> BinarySearchTree.insert(1)
|
||||
|> BinarySearchTree.insert(3)
|
||||
|> BinarySearchTree.insert(5)
|
||||
|> BinarySearchTree.insert(7)
|
||||
|
||||
assert root.data == 4
|
||||
assert root.left.data == 2
|
||||
assert root.left.left.data == 1
|
||||
assert root.left.left.left == nil
|
||||
assert root.left.left.right == nil
|
||||
assert root.left.right.data == 3
|
||||
assert root.left.right.left == nil
|
||||
assert root.left.right.right == nil
|
||||
assert root.right.data == 6
|
||||
assert root.right.left.data == 5
|
||||
assert root.right.left.left == nil
|
||||
assert root.right.left.right == nil
|
||||
assert root.right.right.data == 7
|
||||
assert root.right.right.left == nil
|
||||
assert root.right.right.right == nil
|
||||
end
|
||||
|
||||
describe "can sort data" do
|
||||
test "can sort single number" do
|
||||
root = BinarySearchTree.new(2)
|
||||
|
||||
assert [2] == BinarySearchTree.in_order(root)
|
||||
end
|
||||
|
||||
test "can sort if second number is smaller than first" do
|
||||
root =
|
||||
BinarySearchTree.new(2)
|
||||
|> BinarySearchTree.insert(1)
|
||||
|
||||
assert [1, 2] == BinarySearchTree.in_order(root)
|
||||
end
|
||||
|
||||
test "can sort if second number is the same as the first" do
|
||||
root =
|
||||
BinarySearchTree.new(2)
|
||||
|> BinarySearchTree.insert(2)
|
||||
|
||||
assert [2, 2] == BinarySearchTree.in_order(root)
|
||||
end
|
||||
|
||||
test "can sort if second number is greater than the first" do
|
||||
root =
|
||||
BinarySearchTree.new(2)
|
||||
|> BinarySearchTree.insert(3)
|
||||
|
||||
assert [2, 3] == BinarySearchTree.in_order(root)
|
||||
end
|
||||
|
||||
test "can sort complex tree" do
|
||||
root =
|
||||
BinarySearchTree.new(2)
|
||||
|> BinarySearchTree.insert(1)
|
||||
|> BinarySearchTree.insert(3)
|
||||
|> BinarySearchTree.insert(6)
|
||||
|> BinarySearchTree.insert(7)
|
||||
|> BinarySearchTree.insert(5)
|
||||
|
||||
assert [1, 2, 3, 5, 6, 7] == BinarySearchTree.in_order(root)
|
||||
end
|
||||
end
|
||||
end
|
||||
2
elixir/binary-search-tree/test/test_helper.exs
Normal file
2
elixir/binary-search-tree/test/test_helper.exs
Normal file
@@ -0,0 +1,2 @@
|
||||
ExUnit.start()
|
||||
ExUnit.configure(exclude: :pending, trace: true)
|
||||
31
elixir/binary-search/.exercism/config.json
Normal file
31
elixir/binary-search/.exercism/config.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"authors": [
|
||||
"bernardoamc"
|
||||
],
|
||||
"contributors": [
|
||||
"angelikatyborska",
|
||||
"Cohen-Carlisle",
|
||||
"devonestes",
|
||||
"lpil",
|
||||
"martinsvalin",
|
||||
"neenjaw",
|
||||
"parkerl",
|
||||
"screamingjungle",
|
||||
"sotojuan",
|
||||
"waiting-for-dev"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"lib/binary_search.ex"
|
||||
],
|
||||
"test": [
|
||||
"test/binary_search_test.exs"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.ex"
|
||||
]
|
||||
},
|
||||
"blurb": "Implement a binary search algorithm.",
|
||||
"source": "Wikipedia",
|
||||
"source_url": "https://en.wikipedia.org/wiki/Binary_search_algorithm"
|
||||
}
|
||||
1
elixir/binary-search/.exercism/metadata.json
Normal file
1
elixir/binary-search/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
||||
{"track":"elixir","exercise":"binary-search","id":"46907374d6fd43e0815717c10201d2e0","url":"https://exercism.org/tracks/elixir/exercises/binary-search","handle":"negrienko","is_requester":true,"auto_approve":false}
|
||||
4
elixir/binary-search/.formatter.exs
Normal file
4
elixir/binary-search/.formatter.exs
Normal file
@@ -0,0 +1,4 @@
|
||||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
||||
24
elixir/binary-search/.gitignore
vendored
Normal file
24
elixir/binary-search/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
binary_search-*.tar
|
||||
|
||||
75
elixir/binary-search/HELP.md
Normal file
75
elixir/binary-search/HELP.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
From the terminal, change to the base directory of the exercise then execute the tests with:
|
||||
|
||||
```bash
|
||||
$ mix test
|
||||
```
|
||||
|
||||
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs`
|
||||
|
||||
Documentation:
|
||||
|
||||
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html)
|
||||
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html)
|
||||
|
||||
## Pending tests
|
||||
|
||||
In test suites of practice exercises, all but the first test have been tagged to be 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
|
||||
```
|
||||
|
||||
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command:
|
||||
|
||||
```bash
|
||||
$ mix test --include pending
|
||||
```
|
||||
|
||||
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`.
|
||||
|
||||
```elixir
|
||||
# ExUnit.configure(exclude: :pending, trace: true)
|
||||
```
|
||||
|
||||
## Useful `mix test` options
|
||||
|
||||
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM`
|
||||
* `--failed` - runs only tests that failed the last time they ran
|
||||
* `--max-failures` - the suite stops evaluating tests when this number of test failures
|
||||
is reached
|
||||
* `--seed 0` - disables randomization so the tests in a single file will always be ran
|
||||
in the same order they were defined in
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit lib/binary_search.ex` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir)
|
||||
- The [Elixir track's programming category on the forum](https://forum.exercism.org/c/programming/elixir)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found.
|
||||
71
elixir/binary-search/README.md
Normal file
71
elixir/binary-search/README.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Binary Search
|
||||
|
||||
Welcome to Binary Search on Exercism's Elixir Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Introduction
|
||||
|
||||
You have stumbled upon a group of mathematicians who are also singer-songwriters.
|
||||
They have written a song for each of their favorite numbers, and, as you can imagine, they have a lot of favorite numbers (like [0][zero] or [73][seventy-three] or [6174][kaprekars-constant]).
|
||||
|
||||
You are curious to hear the song for your favorite number, but with so many songs to wade through, finding the right song could take a while.
|
||||
Fortunately, they have organized their songs in a playlist sorted by the title — which is simply the number that the song is about.
|
||||
|
||||
You realize that you can use a binary search algorithm to quickly find a song given the title.
|
||||
|
||||
[zero]: https://en.wikipedia.org/wiki/0
|
||||
[seventy-three]: https://en.wikipedia.org/wiki/73_(number)
|
||||
[kaprekars-constant]: https://en.wikipedia.org/wiki/6174_(number)
|
||||
|
||||
## Instructions
|
||||
|
||||
Your task is to implement a binary search algorithm.
|
||||
|
||||
A binary search algorithm finds an item in a list by repeatedly splitting it in half, only keeping the half which contains the item we're looking for.
|
||||
It allows us to quickly narrow down the possible locations of our item until we find it, or until we've eliminated all possible locations.
|
||||
|
||||
~~~~exercism/caution
|
||||
Binary search only works when a list has been sorted.
|
||||
~~~~
|
||||
|
||||
The algorithm looks like this:
|
||||
|
||||
- Find the middle element of a _sorted_ list and compare it with the item we're looking for.
|
||||
- If the middle element is our item, then we're done!
|
||||
- If the middle element is greater than our item, we can eliminate that element and all the elements **after** it.
|
||||
- If the middle element is less than our item, we can eliminate that element and all the elements **before** it.
|
||||
- If every element of the list has been eliminated then the item is not in the list.
|
||||
- Otherwise, repeat the process on the part of the list that has not been eliminated.
|
||||
|
||||
Here's an example:
|
||||
|
||||
Let's say we're looking for the number 23 in the following sorted list: `[4, 8, 12, 16, 23, 28, 32]`.
|
||||
|
||||
- We start by comparing 23 with the middle element, 16.
|
||||
- Since 23 is greater than 16, we can eliminate the left half of the list, leaving us with `[23, 28, 32]`.
|
||||
- We then compare 23 with the new middle element, 28.
|
||||
- Since 23 is less than 28, we can eliminate the right half of the list: `[23]`.
|
||||
- We've found our item.
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @bernardoamc
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @angelikatyborska
|
||||
- @Cohen-Carlisle
|
||||
- @devonestes
|
||||
- @lpil
|
||||
- @martinsvalin
|
||||
- @neenjaw
|
||||
- @parkerl
|
||||
- @screamingjungle
|
||||
- @sotojuan
|
||||
- @waiting-for-dev
|
||||
|
||||
### Based on
|
||||
|
||||
Wikipedia - https://en.wikipedia.org/wiki/Binary_search_algorithm
|
||||
34
elixir/binary-search/lib/binary_search.ex
Normal file
34
elixir/binary-search/lib/binary_search.ex
Normal file
@@ -0,0 +1,34 @@
|
||||
defmodule BinarySearch do
|
||||
@doc """
|
||||
Searches for a key in the tuple using the binary search algorithm.
|
||||
It returns :not_found if the key is not in the tuple.
|
||||
Otherwise returns {:ok, index}.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> BinarySearch.search({}, 2)
|
||||
:not_found
|
||||
|
||||
iex> BinarySearch.search({1, 3, 5}, 2)
|
||||
:not_found
|
||||
|
||||
iex> BinarySearch.search({1, 3, 5}, 5)
|
||||
{:ok, 2}
|
||||
|
||||
"""
|
||||
|
||||
@spec search(tuple, integer) :: {:ok, integer} | :not_found
|
||||
def search({}, _value), do: :not_found
|
||||
def search(numbers, value), do: do_search(numbers, value, 0, tuple_size(numbers) - 1)
|
||||
|
||||
defp do_search(_numbers, _value, from, to) when from > to, do: :not_found
|
||||
defp do_search(numbers, value, from, to) do
|
||||
middle = div(from + to, 2)
|
||||
element = elem(numbers, middle)
|
||||
cond do
|
||||
value == element -> {:ok, middle}
|
||||
value < element -> do_search(numbers, value, from, middle - 1)
|
||||
value > element -> do_search(numbers, value, middle + 1, to)
|
||||
end
|
||||
end
|
||||
end
|
||||
28
elixir/binary-search/mix.exs
Normal file
28
elixir/binary-search/mix.exs
Normal file
@@ -0,0 +1,28 @@
|
||||
defmodule BinarySearch.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :binary_search,
|
||||
version: "0.1.0",
|
||||
# elixir: "~> 1.8",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications.
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
# {:dep_from_hexpm, "~> 0.3.0"},
|
||||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||
]
|
||||
end
|
||||
end
|
||||
57
elixir/binary-search/test/binary_search_test.exs
Normal file
57
elixir/binary-search/test/binary_search_test.exs
Normal file
@@ -0,0 +1,57 @@
|
||||
defmodule BinarySearchTest do
|
||||
use ExUnit.Case
|
||||
|
||||
test "finds a value in a tuple with one element" do
|
||||
assert BinarySearch.search({6}, 6) == {:ok, 0}
|
||||
assert BinarySearch.search({3}, 3) == {:ok, 0}
|
||||
end
|
||||
|
||||
test "finds a value in the middle of a tuple" do
|
||||
assert BinarySearch.search({1, 2, 4, 5, 6}, 4) == {:ok, 2}
|
||||
assert BinarySearch.search({1, 3, 4, 6, 8, 9, 11}, 6) == {:ok, 3}
|
||||
end
|
||||
|
||||
test "finds a value at the beginning of a tuple" do
|
||||
assert BinarySearch.search({1, 2, 4, 5, 6}, 1) == {:ok, 0}
|
||||
assert BinarySearch.search({1, 3, 4, 5, 8, 9, 11}, 1) == {:ok, 0}
|
||||
end
|
||||
|
||||
test "finds a value at the end of a tuple" do
|
||||
assert BinarySearch.search({1, 2, 4, 5, 6}, 6) == {:ok, 4}
|
||||
assert BinarySearch.search({1, 3, 4, 5, 8, 9, 11}, 11) == {:ok, 6}
|
||||
end
|
||||
|
||||
test "finds a value in a tuple of odd length" do
|
||||
tuple = {1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 634}
|
||||
assert BinarySearch.search(tuple, 144) == {:ok, 9}
|
||||
end
|
||||
|
||||
test "finds a value in a tuple of even length" do
|
||||
tuple = {1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377}
|
||||
assert BinarySearch.search(tuple, 21) == {:ok, 5}
|
||||
assert BinarySearch.search(tuple, 34) == {:ok, 6}
|
||||
end
|
||||
|
||||
test "identifies that a value is not included in the tuple" do
|
||||
assert BinarySearch.search({2, 4, 6}, 3) == :not_found
|
||||
assert BinarySearch.search({1, 3, 4, 6, 8, 9, 11}, 7) == :not_found
|
||||
end
|
||||
|
||||
test "a value smaller than the tuple's smallest value is not found" do
|
||||
assert BinarySearch.search({2, 4, 6}, 1) == :not_found
|
||||
assert BinarySearch.search({1, 3, 4, 6, 8, 9, 11}, 0) == :not_found
|
||||
end
|
||||
|
||||
test "a value larger than the tuple's largest value is not found" do
|
||||
assert BinarySearch.search({2, 4, 6}, 9) == :not_found
|
||||
assert BinarySearch.search({1, 3, 4, 6, 8, 9, 11}, 13) == :not_found
|
||||
end
|
||||
|
||||
test "nothing is found in an empty tuple" do
|
||||
assert BinarySearch.search({}, 1) == :not_found
|
||||
end
|
||||
|
||||
test "nothing is found when the left and right bounds cross" do
|
||||
assert BinarySearch.search({1, 2}, 0) == :not_found
|
||||
end
|
||||
end
|
||||
2
elixir/binary-search/test/test_helper.exs
Normal file
2
elixir/binary-search/test/test_helper.exs
Normal file
@@ -0,0 +1,2 @@
|
||||
ExUnit.start()
|
||||
ExUnit.configure(exclude: :pending, trace: true)
|
||||
46
elixir/bob/.exercism/config.json
Normal file
46
elixir/bob/.exercism/config.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"authors": [
|
||||
"rubysolo"
|
||||
],
|
||||
"contributors": [
|
||||
"andrewsardone",
|
||||
"angelikatyborska",
|
||||
"austinlyons",
|
||||
"cbliard",
|
||||
"Cohen-Carlisle",
|
||||
"dalexj",
|
||||
"devonestes",
|
||||
"digitalronin",
|
||||
"doncruse",
|
||||
"etrepum",
|
||||
"ghajba",
|
||||
"kytrinyx",
|
||||
"lpil",
|
||||
"neenjaw",
|
||||
"parkerl",
|
||||
"pminten",
|
||||
"rsslldnphy",
|
||||
"seeflanigan",
|
||||
"sotojuan",
|
||||
"Teapane",
|
||||
"tjcelaya",
|
||||
"Tonkpils",
|
||||
"victorpre",
|
||||
"vladimir-tikhonov",
|
||||
"waiting-for-dev"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"lib/bob.ex"
|
||||
],
|
||||
"test": [
|
||||
"test/bob_test.exs"
|
||||
],
|
||||
"example": [
|
||||
".meta/example.ex"
|
||||
]
|
||||
},
|
||||
"blurb": "Bob is a lackadaisical teenager. In conversation, his responses are very limited.",
|
||||
"source": "Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial.",
|
||||
"source_url": "https://pine.fm/LearnToProgram/?Chapter=06"
|
||||
}
|
||||
1
elixir/bob/.exercism/metadata.json
Normal file
1
elixir/bob/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
||||
{"track":"elixir","exercise":"bob","id":"7c75c2cb7c6d4f808ec6412bbc842f86","url":"https://exercism.org/tracks/elixir/exercises/bob","handle":"negrienko","is_requester":true,"auto_approve":false}
|
||||
4
elixir/bob/.formatter.exs
Normal file
4
elixir/bob/.formatter.exs
Normal file
@@ -0,0 +1,4 @@
|
||||
# Used by "mix format"
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
||||
24
elixir/bob/.gitignore
vendored
Normal file
24
elixir/bob/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
bob-*.tar
|
||||
|
||||
75
elixir/bob/HELP.md
Normal file
75
elixir/bob/HELP.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
From the terminal, change to the base directory of the exercise then execute the tests with:
|
||||
|
||||
```bash
|
||||
$ mix test
|
||||
```
|
||||
|
||||
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs`
|
||||
|
||||
Documentation:
|
||||
|
||||
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html)
|
||||
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html)
|
||||
|
||||
## Pending tests
|
||||
|
||||
In test suites of practice exercises, all but the first test have been tagged to be 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
|
||||
```
|
||||
|
||||
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command:
|
||||
|
||||
```bash
|
||||
$ mix test --include pending
|
||||
```
|
||||
|
||||
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`.
|
||||
|
||||
```elixir
|
||||
# ExUnit.configure(exclude: :pending, trace: true)
|
||||
```
|
||||
|
||||
## Useful `mix test` options
|
||||
|
||||
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM`
|
||||
* `--failed` - runs only tests that failed the last time they ran
|
||||
* `--max-failures` - the suite stops evaluating tests when this number of test failures
|
||||
is reached
|
||||
* `--seed 0` - disables randomization so the tests in a single file will always be ran
|
||||
in the same order they were defined in
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit lib/bob.ex` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir)
|
||||
- The [Elixir track's programming category on the forum](https://forum.exercism.org/c/programming/elixir)
|
||||
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found.
|
||||
73
elixir/bob/README.md
Normal file
73
elixir/bob/README.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Bob
|
||||
|
||||
Welcome to Bob on Exercism's Elixir Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
|
||||
## Introduction
|
||||
|
||||
Bob is a [lackadaisical][] teenager.
|
||||
He likes to think that he's very cool.
|
||||
And he definitely doesn't get excited about things.
|
||||
That wouldn't be cool.
|
||||
|
||||
When people talk to him, his responses are pretty limited.
|
||||
|
||||
[lackadaisical]: https://www.collinsdictionary.com/dictionary/english/lackadaisical
|
||||
|
||||
## Instructions
|
||||
|
||||
Your task is to determine what Bob will reply to someone when they say something to him or ask him a question.
|
||||
|
||||
Bob only ever answers one of five things:
|
||||
|
||||
- **"Sure."**
|
||||
This is his response if you ask him a question, such as "How are you?"
|
||||
The convention used for questions is that it ends with a question mark.
|
||||
- **"Whoa, chill out!"**
|
||||
This is his answer if you YELL AT HIM.
|
||||
The convention used for yelling is ALL CAPITAL LETTERS.
|
||||
- **"Calm down, I know what I'm doing!"**
|
||||
This is what he says if you yell a question at him.
|
||||
- **"Fine. Be that way!"**
|
||||
This is how he responds to silence.
|
||||
The convention used for silence is nothing, or various combinations of whitespace characters.
|
||||
- **"Whatever."**
|
||||
This is what he answers to anything else.
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @rubysolo
|
||||
|
||||
### Contributed to by
|
||||
|
||||
- @andrewsardone
|
||||
- @angelikatyborska
|
||||
- @austinlyons
|
||||
- @cbliard
|
||||
- @Cohen-Carlisle
|
||||
- @dalexj
|
||||
- @devonestes
|
||||
- @digitalronin
|
||||
- @doncruse
|
||||
- @etrepum
|
||||
- @ghajba
|
||||
- @kytrinyx
|
||||
- @lpil
|
||||
- @neenjaw
|
||||
- @parkerl
|
||||
- @pminten
|
||||
- @rsslldnphy
|
||||
- @seeflanigan
|
||||
- @sotojuan
|
||||
- @Teapane
|
||||
- @tjcelaya
|
||||
- @Tonkpils
|
||||
- @victorpre
|
||||
- @vladimir-tikhonov
|
||||
- @waiting-for-dev
|
||||
|
||||
### Based on
|
||||
|
||||
Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. - https://pine.fm/LearnToProgram/?Chapter=06
|
||||
23
elixir/bob/lib/bob.ex
Normal file
23
elixir/bob/lib/bob.ex
Normal file
@@ -0,0 +1,23 @@
|
||||
defmodule Bob do
|
||||
@spec hey(String.t()) :: String.t()
|
||||
def hey(input) do
|
||||
trimmed = String.trim(input)
|
||||
|
||||
is_yell? = String.upcase(trimmed) == trimmed and String.downcase(trimmed) != trimmed
|
||||
is_question? = String.ends_with?(trimmed, "?")
|
||||
is_silence? = trimmed == ""
|
||||
|
||||
cond do
|
||||
is_silence? ->
|
||||
"Fine. Be that way!"
|
||||
is_yell? and is_question? ->
|
||||
"Calm down, I know what I'm doing!"
|
||||
is_question? ->
|
||||
"Sure."
|
||||
is_yell? ->
|
||||
"Whoa, chill out!"
|
||||
true ->
|
||||
"Whatever."
|
||||
end
|
||||
end
|
||||
end
|
||||
28
elixir/bob/mix.exs
Normal file
28
elixir/bob/mix.exs
Normal file
@@ -0,0 +1,28 @@
|
||||
defmodule Bob.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :bob,
|
||||
version: "0.1.0",
|
||||
# elixir: "~> 1.8",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help compile.app" to learn about applications.
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
# {:dep_from_hexpm, "~> 0.3.0"},
|
||||
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||
]
|
||||
end
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user