Initial commit

This commit is contained in:
2023-12-17 00:26:14 -05:00
commit 59d97be20c
89 changed files with 3184 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
{
"authors": [
"neenjaw"
],
"contributors": [
"fireproofsocks"
],
"files": {
"solution": [
"lib/language_list.ex"
],
"test": [
"test/language_list_test.exs"
],
"exemplar": [
".meta/exemplar.ex"
]
},
"language_versions": ">=1.10",
"forked_from": [
"clojure/tracks-on-tracks-on-tracks"
],
"blurb": "Learn about lists by keeping track of the programming languages you're currently learning on Exercism."
}

View File

@@ -0,0 +1 @@
{"track":"elixir","exercise":"language-list","id":"1fc6fd5b991141188a10438edd755faa","url":"https://exercism.org/tracks/elixir/exercises/language-list","handle":"negrienko","is_requester":true,"auto_approve":false}

View File

@@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]

24
elixir/language-list/.gitignore vendored Normal file
View 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").
strings-*.tar

View 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/language_list.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.

View File

@@ -0,0 +1,35 @@
# Hints
## General
- Use the built-in [(linked) list type][list].
## 1. Define a function to return an empty language list
- The function needs to return `[]`.
## 2. Define a function to add a language to the list
- An element can be prepended to a list using `|`.
## 3. Define a function to remove a language from the list
- Elixir [provides a function][tl] to return a list with the first item removed.
## 4. Define a function to return the first item in the list
- Elixir [provides a function][hd] to get the first item from a list.
## 5. Define a function to return how many languages are in the list
- Elixir [provides a function][length] to count the length of a list.
## 6. Define a function to determine if the list includes a functional language
- Your function should return a boolean value indicating whether `"Elixir"` is a member of the list. Elixir [provides a function][in] to test list membership.
[list]: https://elixir-lang.org/getting-started/basic-types.html#linked-lists
[hd]: https://hexdocs.pm/elixir/Kernel.html#hd/1
[tl]: https://hexdocs.pm/elixir/Kernel.html#tl/1
[length]: https://hexdocs.pm/elixir/Kernel.html#length/1
[in]: https://hexdocs.pm/elixir/Kernel.html#in/2

View File

@@ -0,0 +1,140 @@
# Language List
Welcome to Language List 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
## Lists
Lists are built-in to the Elixir language. They are considered a basic type, denoted by square brackets. Lists may be empty or hold any number of items of any type. For example:
```elixir
empty_list = []
one_item_list = [1]
two_item_list = [1, 2]
multiple_type_list = [1, :pi, 3.14, "four"]
```
Elixir implements lists as a linked list, where each node stores two values: the first item and another list with all the remaining items. The first item in the list is referred to as the _head_ and the remaining list of items is called the _tail_. We can use this notation in code:
```elixir
# [1] represented in [head | tail] notation
[1 | []]
# [1, 2, 3] represented in [head | tail] notation
[1 | [2 | [3 | []]]]
```
We can use _`[head | tail]`_ notation to prepend elements to a list:
```elixir
# Suppose
list = [2, 1]
[3, 2, 1] == [3 | list]
# => true
```
There are several functions in the `Kernel` module for working with lists, as well as the whole `List` module.
```elixir
# Check if 1 is a member of the list
1 in [1, 2, 3, 4]
# => true
```
## Instructions
In this exercise you need to implement some functions to manipulate a list of programming languages.
## 1. Define a function to return an empty language list
Define the `new/0` function that takes no arguments and returns an empty list.
```elixir
LanguageList.new()
# => []
```
## 2. Define a function to add a language to the list
Define the `add/2` function that takes 2 arguments (a _language list_ and a string literal of a _language_). It should return the resulting list with the new language prepended to the given list.
```elixir
language_list = LanguageList.new()
# => []
language_list = LanguageList.add(language_list, "Clojure")
# => ["Clojure"]
language_list = LanguageList.add(language_list, "Haskell")
# => ["Haskell", "Clojure"]
```
## 3. Define a function to remove a language from the list
Define the `remove/1` function that takes 1 argument (a _language list_). It should return the list without the first item. Assume the list will always have at least one item.
```elixir
language_list = LanguageList.new()
# => []
language_list = LanguageList.add(language_list, "Clojure")
# => ["Clojure"]
language_list = LanguageList.add(language_list, "Haskell")
# => ["Haskell", "Clojure"]
language_list = LanguageList.remove(language_list)
# => ["Clojure"]
```
## 4. Define a function to return the first item in the list
Define the `first/1` function that takes 1 argument (a _language list_). It should return the first language in the list. Assume the list will always have at least one item.
```elixir
language_list = LanguageList.new()
# => []
language_list = LanguageList.add(language_list, "Elm")
# => ["Elm"]
language_list = LanguageList.add(language_list, "Prolog")
# => ["Prolog", "Elm"]
LanguageList.first(language_list)
# => "Prolog"
```
## 5. Define a function to return how many languages are in the list
Define the `count/1` function that takes 1 argument (a _language list_). It should return the number of languages in the list.
```elixir
language_list = LanguageList.new()
# => []
language_list = LanguageList.add(language_list, "Elm")
# => ["Elm"]
language_list = LanguageList.add(language_list, "Prolog")
# => ["Prolog", "Elm"]
LanguageList.count(language_list)
# => 2
```
## 6. Define a function to determine if the list includes a functional language
Define the `functional_list?/1` function which takes 1 argument (a _language list_). It should return a boolean value. It should return true if _"Elixir"_ is one of the languages in the list.
```elixir
language_list = LanguageList.new()
# => []
language_list = LanguageList.add(language_list, "Elixir")
# => ["Elixir"]
LanguageList.functional_list?(language_list)
# => true
```
## Source
### Created by
- @neenjaw
### Contributed to by
- @fireproofsocks

View File

@@ -0,0 +1,13 @@
defmodule LanguageList do
def new(), do: []
def add(list, language), do: [language | list]
def remove(list), do: tl(list)
def first(list), do: hd(list)
def count(list), do: length(list)
def functional_list?(list), do: "Elixir" in list
end

View File

@@ -0,0 +1,28 @@
defmodule LanguageList.MixProject do
use Mix.Project
def project do
[
app: :language_list,
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

View File

@@ -0,0 +1,116 @@
defmodule LanguageListTest do
use ExUnit.Case
describe "new/0" do
@tag task_id: 1
test "new list" do
assert LanguageList.new() == []
end
end
describe "add/2" do
@tag task_id: 2
test "add a language to a list" do
language = "Elixir"
list = [language]
assert LanguageList.new() |> LanguageList.add(language) == list
end
@tag task_id: 2
test "add several languages to a list" do
list =
LanguageList.new()
|> LanguageList.add("Clojure")
|> LanguageList.add("Haskell")
|> LanguageList.add("Erlang")
|> LanguageList.add("F#")
|> LanguageList.add("Elixir")
assert list == ["Elixir", "F#", "Erlang", "Haskell", "Clojure"]
end
end
describe "remove/1" do
@tag task_id: 3
test "add then remove results in empty list" do
list =
LanguageList.new()
|> LanguageList.add("Elixir")
|> LanguageList.remove()
assert list == []
end
@tag task_id: 3
test "adding two languages, when removed, removes first item" do
list =
LanguageList.new()
|> LanguageList.add("F#")
|> LanguageList.add("Elixir")
|> LanguageList.remove()
assert list == ["F#"]
end
end
describe "first/1" do
@tag task_id: 4
test "add one language, then get the first" do
assert LanguageList.new() |> LanguageList.add("Elixir") |> LanguageList.first() == "Elixir"
end
@tag task_id: 4
test "add a few languages, then get the first" do
first =
LanguageList.new()
|> LanguageList.add("Elixir")
|> LanguageList.add("Prolog")
|> LanguageList.add("F#")
|> LanguageList.first()
assert first == "F#"
end
end
describe "count/1" do
@tag task_id: 5
test "the count of a new list is 0" do
assert LanguageList.new() |> LanguageList.count() == 0
end
@tag task_id: 5
test "the count of a one-language list is 1" do
count =
LanguageList.new()
|> LanguageList.add("Elixir")
|> LanguageList.count()
assert count == 1
end
@tag task_id: 5
test "the count of a multiple-item list is equal to its length" do
count =
LanguageList.new()
|> LanguageList.add("Elixir")
|> LanguageList.add("Prolog")
|> LanguageList.add("F#")
|> LanguageList.count()
assert count == 3
end
end
describe "functional_list?/1" do
@tag task_id: 6
test "a functional language list" do
assert LanguageList.functional_list?(["Clojure", "Haskell", "Erlang", "F#", "Elixir"])
end
@tag task_id: 6
test "not a functional language list" do
refute LanguageList.functional_list?(["Java", "C", "JavaScript"])
end
end
end

View File

@@ -0,0 +1,2 @@
ExUnit.start()
ExUnit.configure(exclude: :pending, trace: true, seed: 0)