지정된 규칙에 따라 신용카드 번호가 올바른지 아닌지를 검증하는 문제였다. 오른쪽부터 세서 짝수 번째 자리에 있는 숫자에 2를 곱한 뒤, 모든 자리수를 더했을 때 10의 배수가 되면 유효한 자리수로 판정한다.
일반적인 신용카드처럼 자리수가 16자리 고정이면 참 쉬웠을텐데, 입력되는 번호의 자리수의 홀짝이 제각각이어서 자리수에 따라 달리 처리해야 하는 부분이 조금 까다로웠다.
defmodule Luhn do
require Integer
@doc """
Checks if the given number is valid via the luhn formula
"""
@spec valid?(String.t()) :: boolean
def valid?(number) do
space_removed = String.replace(number, ~r/\s+/, "")
if String.length(space_removed) > 1 and String.match?(space_removed, ~r/^[0-9]+$/) do
space_removed
|> String.graphemes()
|> Enum.map(&String.to_integer/1)
|> Enum.with_index()
|> Enum.map(fn {v, i} ->
double_every_second(v, i, String.length(space_removed))
|> reduce_to_single_digit()
end)
|> Enum.sum()
|> Kernel.rem(10)
|> Kernel.==(0)
else
false
end
end
defp double_every_second(v, i, str_len) when Integer.is_even(str_len) do
if rem(i, 2) == 0, do: v * 2, else: v
end
defp double_every_second(v, i, str_len) when Integer.is_odd(str_len) do
if rem(i, 2) == 1, do: v * 2, else: v
end
defp reduce_to_single_digit(v) when v > 9, do: v - 9
defp reduce_to_single_digit(v), do: v
end
'호두나무 공방 > Exercism in Elixir' 카테고리의 다른 글
Lucas Numbers - Exercism in Elixir (0) | 2022.09.08 |
---|---|
Need For Speed - Exercism in Elixir (0) | 2022.09.07 |
Meetup - Exercism in Elixir (0) | 2022.09.05 |
Complex Numbers - Exercism in Elixir (0) | 2022.08.19 |
Square Root - Exercism in Elixir (0) | 2022.08.18 |