주민등록번호와 바코드

== 개요 ==

체크섬 계산을 통해 주어진 주민번호나 바코드가 옳은지 확인한다.

== 주민번호 ==
주민번호는 총 13자리인데, 앞의 12자리를 떼내어서 첫 숫자부터 각각 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5를 곱한다. 그 수들을 모두 합한다음, 11로 나누어 그 나머지를 다시 11에서 뺀 수가 마지막 자릿수(13번째)와 일치하면 주민등록번호가 정상이라 본다. 하지만 마지막 수식 결과가 10이면 0을 취하고 11이면 1을 취한다.

== 바코드 ==

바코드는 전체 13자리인데 처음 세 개 숫자는 국가로 880은 한국을 가리킨다. 다음 네개가 제조업자이고 다음 다섯개는 어떤 상품인지를 말한다. 마지막 하나의 숫자가 체크섬이 된다.

앞 부분의 12자리 중 홀수자리는 그대로 더하고, 짝수자리는 더한 후 곱하기 3. 이 두 값의 함에 체크 숫자를 더하면 10으로 나누어 떨어져야 한다.

예시 바코드: 8809010665009

== 주어진 것 ==

열 세 자리 숫자 (주민번호 혹은 바코드 번호)

자신이 처리하기 쉬운 형태로 입력이 들어온다고 가정하면 된다. (예를 들어 크기가 13인 정수 어레이나 리스트)

== 얻을 것 ==

valid인지 invalid인지

댓글 보기 옵션

원하시는 댓글 전시 방법을 선택한 다음 "설정 저장"을 누르셔서 적용하십시오.

주민등록번호와

주민등록번호와 관련된 글은 법적인 제재를 받을 수도 있습니다.

주민등록법

http://www.klaw.go.kr/CNT2/Easy/MCNT2EasyLawService.jsp?s_lawmst=73411

"허위의 주민등록번호를 생성하는 프로그램을 다른 사람에게 전달하거나 유포한 자"가 처벌 대상이라는 표현은 있으나, 주민등록번호의 진위 여부를 확인할 수 있는 코드에 대한 언급은 없는 것 같습니다. 문제가 될까요?

주민번호 검사 - Haskell 버전

module Test where

import Data.List

-- 숫자를 수열 리스트로 변환
asList n
	| n < 10 	= [n]
	| otherwise = asList (n `div` 10) ++ [n `mod` 10]

-- 두 리스트의 각 원소끼리 서로 곱한 값으로 새로운 리스트를 만든다	
list_multiply (x1:y1s) (x2:y2s)
	| y1s == [] = [x1 * x2]
	| otherwise = (x1 * x2) : (list_multiply y1s y2s)

-- 숫자 n의 마지막 자리 수를 구한다	
lastNumber n = numList !! (length numList - 1)
	where numList = asList n

-- 주민번호의 체크섬 검사
checkKoreanID num
	| length numList == 13 = numList !! 12 == lastNumber checkSum
	| otherwise = False
	where 
		numList = asList num
		checkSum = 11 - (sum $ list_multiply numList ([2..9] ++ [2..5] ++ [0])) `mod` 11

하스켈에 기본

하스켈에 기본 함수로 주어진 것들을 사용하면 좀 더 간단히 할 수 있습니다. 아래는 짧게 줄인 코드입니다.

idCheck str
    | length str == 13 && all isDigit str = checksum == last num
    | otherwise = False
        where 
            num = map digitToInt str
            result = 11 - sum (zipWith (*) ([2..9]++[2..5]) num) `mod` 11
            checksum = result - if result > 9 then 10 else 0