% % issn.erl % Routines for ISSN numbers. % % Written by Yegor Samusev . % % This source code is in the public domain. % -module(issn). -export([is/1, calculate_check_digit/1, get_check_digit/1, is_valid/1]). % % > issn:is("0131-1417"). % true % is(ISSN) -> case length(ISSN) of 9 -> check(ISSN, 1); _ -> false end. check([], _) -> true; check([Separator|S], 5) -> case Separator of $- -> check(S, 6); _ -> false end; check([Char|_], 9) -> if Char == $X -> true; Char >= $0, Char =< $9 -> true; true -> false end; check([Digit|S], N) -> if Digit >= $0, Digit =< $9 -> check(S, N + 1); true -> false end. % % > issn:calculate_check_digit("0131-1417"). % 55 % calculate_check_digit(ISSN) -> Chars = lists:sublist(ISSN, 4) ++ lists:sublist(lists:nthtail(5, ISSN), 3), Digits = lists:map(fun(X) -> X - 48 end, Chars), calculate_check_digit(Digits, 8, []). calculate_check_digit([], 1, Calculated) -> Remainder = lists:sum(Calculated) rem 11, case Remainder of 0 -> $0; _ -> Digit = 11 - Remainder, case Digit of 10 -> $X; _ -> Digit + 48 end end; calculate_check_digit([Digit|Digits], I, Calculated) -> calculate_check_digit(Digits, I - 1, Calculated ++ [Digit * I]). % % > issn:get_check_digit("0131-1417"). % 55 % get_check_digit(ISSN) -> lists:nth(9, ISSN). % % > issn:is_valid("0131-1417"). % true % is_valid(ISSN) -> IsISSN = is(ISSN), [CheckDigit, Valid] = [get_check_digit(ISSN), calculate_check_digit(ISSN)], if IsISSN, CheckDigit == Valid -> true; true -> false end.