resistor_color_trio

This commit is contained in:
Danil Negrienko 2024-08-21 13:22:25 -04:00
parent 7856986097
commit 64030231bf
10 changed files with 381 additions and 0 deletions

View File

@ -0,0 +1,22 @@
{
"authors": [
"jiegillet"
],
"contributors": [
"angelikatyborska"
],
"files": {
"solution": [
"lib/resistor_color_trio.ex"
],
"test": [
"test/resistor_color_trio_test.exs"
],
"example": [
".meta/example.ex"
]
},
"blurb": "Convert color codes, as used on resistors, to a human-readable label.",
"source": "Maud de Vries, Erik Schierboom",
"source_url": "https://github.com/exercism/problem-specifications/issues/1549"
}

View File

@ -0,0 +1 @@
{"track":"elixir","exercise":"resistor-color-trio","id":"3c05c38d4119449a8cb120483b347a29","url":"https://exercism.org/tracks/elixir/exercises/resistor-color-trio","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/resistor-color-trio/.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").
resistor_color_trio-*.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/resistor_color_trio.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,75 @@
# Resistor Color Trio
Welcome to Resistor Color Trio on Exercism's Elixir Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
## Instructions
If you want to build something using a Raspberry Pi, you'll probably use _resistors_.
For this exercise, you need to know only three things about them:
- Each resistor has a resistance value.
- Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read.
To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values.
- Each band acts as a digit of a number.
For example, if they printed a brown band (value 1) followed by a green band (value 5), it would translate to the number 15.
In this exercise, you are going to create a helpful program so that you don't have to remember the values of the bands.
The program will take 3 colors as input, and outputs the correct value, in ohms.
The color bands are encoded as follows:
- black: 0
- brown: 1
- red: 2
- orange: 3
- yellow: 4
- green: 5
- blue: 6
- violet: 7
- grey: 8
- white: 9
In Resistor Color Duo you decoded the first two colors.
For instance: orange-orange got the main value `33`.
The third color stands for how many zeros need to be added to the main value.
The main value plus the zeros gives us a value in ohms.
For the exercise it doesn't matter what ohms really are.
For example:
- orange-orange-black would be 33 and no zeros, which becomes 33 ohms.
- orange-orange-red would be 33 and 2 zeros, which becomes 3300 ohms.
- orange-orange-orange would be 33 and 3 zeros, which becomes 33000 ohms.
(If Math is your thing, you may want to think of the zeros as exponents of 10.
If Math is not your thing, go with the zeros.
It really is the same thing, just in plain English instead of Math lingo.)
This exercise is about translating the colors into a label:
> "... ohms"
So an input of `"orange", "orange", "black"` should return:
> "33 ohms"
When we get to larger resistors, a [metric prefix][metric-prefix] is used to indicate a larger magnitude of ohms, such as "kiloohms".
That is similar to saying "2 kilometers" instead of "2000 meters", or "2 kilograms" for "2000 grams".
For example, an input of `"orange", "orange", "orange"` should return:
> "33 kiloohms"
[metric-prefix]: https://en.wikipedia.org/wiki/Metric_prefix
## Source
### Created by
- @jiegillet
### Contributed to by
- @angelikatyborska
### Based on
Maud de Vries, Erik Schierboom - https://github.com/exercism/problem-specifications/issues/1549

View File

@ -0,0 +1,43 @@
defmodule ResistorColorTrio do
@type color :: :black | :brown | :red | :orange | :yellow | :green | :blue | :violet | :grey | :white
@type colors :: [color]
@type unit :: :ohms | :kiloohms | :megaohms | :gigaohms
defguardp is_giga(value) when value >= 1_000_000_000
defguardp is_mega(value) when value >= 1_000_000
defguardp is_kilo(value) when value >= 1_000
@doc """
Calculate the resistance value in ohms from resistor colors
"""
@spec label(colors) :: {number, unit}
def label(colors) do
colors
|> Enum.take(2)
|> Enum.map(&code/1)
|> Kernel.++(zeros(Enum.at(colors, 2)))
|> Integer.undigits()
|> with_unit()
end
@spec code(color) :: integer()
defp code(:black), do: 0
defp code(:brown), do: 1
defp code(:red), do: 2
defp code(:orange), do: 3
defp code(:yellow), do: 4
defp code(:green), do: 5
defp code(:blue), do: 6
defp code(:violet), do: 7
defp code(:grey), do: 8
defp code(:white), do: 9
@spec zeros(color) :: list()
defp zeros(color), do: List.duplicate(0, code(color))
@spec with_unit(integer) :: {integer, unit}
defp with_unit(value) when is_giga(value), do: {div(value, 1_000_000_000), :gigaohms}
defp with_unit(value) when is_mega(value), do: {div(value, 1_000_000), :megaohms}
defp with_unit(value) when is_kilo(value), do: {div(value, 1_000), :kiloohms}
defp with_unit(value), do: {value, :ohms}
end

View File

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

View File

@ -0,0 +1,107 @@
defmodule ResistorColorTrioTest do
use ExUnit.Case
test "Orange and orange and black" do
colors = [:orange, :orange, :black]
output = ResistorColorTrio.label(colors)
expected = {33, :ohms}
assert output == expected
end
test "Blue and grey and brown" do
colors = [:blue, :grey, :brown]
output = ResistorColorTrio.label(colors)
expected = {680, :ohms}
assert output == expected
end
test "Red and black and red" do
colors = [:red, :black, :red]
output = ResistorColorTrio.label(colors)
expected = {2, :kiloohms}
assert output == expected
end
test "Green and brown and orange" do
colors = [:green, :brown, :orange]
output = ResistorColorTrio.label(colors)
expected = {51, :kiloohms}
assert output == expected
end
test "Yellow and violet and yellow" do
colors = [:yellow, :violet, :yellow]
output = ResistorColorTrio.label(colors)
expected = {470, :kiloohms}
assert output == expected
end
test "Blue and violet and blue" do
colors = [:blue, :violet, :blue]
output = ResistorColorTrio.label(colors)
expected = {67, :megaohms}
assert output == expected
end
test "Minimum possible value" do
colors = [:black, :black, :black]
output = ResistorColorTrio.label(colors)
expected = {0, :ohms}
assert output == expected
end
test "Maximum possible value" do
colors = [:white, :white, :white]
output = ResistorColorTrio.label(colors)
expected = {99, :gigaohms}
assert output == expected
end
test "First two colors make an invalid octal number" do
colors = [:black, :grey, :black]
output = ResistorColorTrio.label(colors)
expected = {8, :ohms}
assert output == expected
end
test "Ignore extra colors" do
colors = [:blue, :green, :yellow, :orange]
output = ResistorColorTrio.label(colors)
expected = {650, :kiloohms}
assert output == expected
end
test "Kilo value" do
colors = [:brown, :black, :red]
output = ResistorColorTrio.label(colors)
expected = {1, :kiloohms}
assert output == expected
end
test "Mega value" do
colors = [:brown, :black, :green]
output = ResistorColorTrio.label(colors)
expected = {1, :megaohms}
assert output == expected
end
test "Giga value" do
colors = [:brown, :black, :grey]
output = ResistorColorTrio.label(colors)
expected = {1, :gigaohms}
assert output == expected
end
end

View File

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