Created
May 7, 2016 16:48
-
-
Save Cifer-Y/d3e34e2ee53ca0a5f4cf6e143fc4f879 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule CardValidation do | |
def output_result(cards) do | |
cards | |
|> Enum.map(fn(card) -> | |
"#{card_type(card)}: #{card |> strip_card}" | |
|> String.ljust(30) | |
|> Kernel.<>("(#{luhn(card)})") | |
end) | |
|> Enum.join("\n") | |
|> IO.puts | |
end | |
def card_type(card), do: amex?(card) || discover?(card) || master_card?(card) || visa?(card) || "Unknown" | |
def amex?(card), do: card_head(:amex, card) && card_length(:amex, card) && "AMEX" | |
def discover?(card), do: card_head(:discover, card) && card_length(:discover, card) && "Discover" | |
def master_card?(card), do: card_head(:master_card, card) && card_length(:master_card, card) && "MasterCard" | |
def visa?(card), do: card_head(:visa, card) && card_length(:visa, card) && "VISA" | |
def card_head(:amex, "34" <> _), do: true | |
def card_head(:amex, "37" <> _), do: true | |
def card_head(:amex, _), do: false | |
def card_head(:discover, "6011" <> _), do: true | |
def card_head(:discover, _), do: false | |
def card_head(:master_card, "51" <> _), do: true | |
def card_head(:master_card, "52" <> _), do: true | |
def card_head(:master_card, "53" <> _), do: true | |
def card_head(:master_card, "54" <> _), do: true | |
def card_head(:master_card, "55" <> _), do: true | |
def card_head(:master_card, _), do: false | |
def card_head(:visa, "4" <> _), do: true | |
def card_head(:visa, _), do: false | |
def card_length(:amex, card), do: card_length(card) == 15 | |
def card_length(:discover, card), do: card_length(card) == 16 | |
def card_length(:master_card, card), do: card_length(card) == 16 | |
def card_length(:visa, card), do: card_length(card) == 16 || card_length(card) == 13 | |
def card_length(card), do: card |> strip_card |> String.length | |
def luhn(card) do | |
card | |
|> get_data | |
|> update_data | |
|> count_result | |
|> valid_format? | |
end | |
def get_data(card), do: card |> strip_card |> String.to_integer |> Integer.digits | |
def update_data(data) do | |
reversed = data |> Enum.reverse | |
doubled = reversed | |
|> Enum.drop(1) | |
|> Enum.take_every(2) | |
|> Enum.map(&(&1 * 2)) | |
|> Enum.flat_map(&Integer.digits/1) | |
reversed | |
|> Enum.take_every(2) | |
|> Enum.concat(doubled) | |
end | |
def count_result(data) do | |
data | |
|> Enum.sum | |
|> rem(10) | |
|> Kernel.==(0) | |
end | |
def valid_format?(true), do: "valid" |> color_text(:green) | |
def valid_format?(false), do: "invalid" |> color_text(:red) | |
def color_text(text, color), do: IO.ANSI.format([color, :bright, "#{text}"], true) | |
def strip_card(card), do: card |> String.replace(~r/\s+/, "") | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment