exercism/elixir/resistor-color-trio/lib/resistor_color_trio.ex

44 lines
1.4 KiB
Elixir

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