exercism/elixir/isbn-verifier/lib/isbn_verifier.ex

42 lines
977 B
Elixir

defmodule IsbnVerifier do
@doc """
Checks if a string is a valid ISBN-10 identifier
## Examples
iex> IsbnVerifier.isbn?("3-598-21507-X")
true
iex> IsbnVerifier.isbn?("3-598-2K507-0")
false
"""
@regex ~r/^(?<digits>\d{9})(?<check_digit>[0-9X])$/
@spec isbn?(String.t()) :: boolean
def isbn?(isbn) do
with isbn_without_dashes <- String.replace(isbn, "-", ""),
%{"digits" => digits, "check_digit" => check_digit} <-
Regex.named_captures(@regex, isbn_without_dashes) do
rem(check_sum(digits) + check_digit(check_digit), 11) == 0
else
_ -> false
end
end
defp check_sum(digits) do
{1, check_sum} =
digits
|> String.graphemes()
|> Enum.reduce({10, 0}, fn digit, {index, acc} ->
{index - 1, acc + String.to_integer(digit) * index}
end)
check_sum
end
defp check_digit("X"), do: 10
defp check_digit(string), do: String.to_integer(string)
end