호두나무 공방/Exercism in Elixir

Resistor Color Trio - Exercism in Elixir

2022. 4. 22. 23:14

문제 보기

Register Color Duo에서 한 단계 더 나가, 저항의 세 번째 값을 10의 거듭제곱으로 해석하여 최종 저항 값을 계산하고, 1000으로 나누어 떨어지는 경우 옴 대신 킬로옴 단위로 출력하도록 하는 문제였다. 구현 자체는 쉬운데, 깔끔한 코드를 짜기가 쉽지 않았다. labelvalue에서는 함수 파라미터 정의부를 바꿔 들어오는 리스트의 길이를 제한했고, format에서는 패턴 매칭을 쓰면 오히려 불필요한 코드가 늘어나는 느낌이라 if를 사용했음을 기록해둔다.

defmodule ResistorColorTrio do
  @register_color %{
    black: 0,
    brown: 1,
    red: 2,
    orange: 3,
    yellow: 4,
    green: 5,
    blue: 6,
    violet: 7,
    grey: 8,
    white: 9
  }

  @doc """
  Calculate the resistance value in ohm or kiloohm from resistor colors
  """
  @spec label(colors :: [atom]) :: {number, :ohms | :kiloohms}
  def label([c1, c2, c3]) do
    main_value = value([c1, c2])
    exponent = @register_color[c3]
    format(main_value * Integer.pow(10, exponent))
  end

  # From Register Color Duo
  defp value([_, _] = colors) do
    colors
    |> Enum.map(&Map.get(@register_color, &1))
    |> Integer.undigits()
  end

  defp format(value) do
    kilo? = rem(value, 1_000) == 0
    unit = if kilo?, do: :kiloohms, else: :ohms
    divisor = if kilo?, do: 1_000, else: 1
    {div(value, divisor), unit}
  end
end