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/^(?\d{9})(?[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