본문 바로가기
알고리즘 구상

[알고리즘] 겹치지 않는 16자리 상품권 코드 만들기

by 코딩히어로 2020. 8. 12.
728x90

이번에는 회사에서 진행한 상품권 발행 관련 알고리즘에 대한 이야기를 해보려 합니다.

 

시중에서 많이 접해본 문화 상품권, 백화점 상품권 이러한 상품권을 보면 대게는 16자리로 구성이 되어 있는데

16자리 숫자는 어떻게 겹치지 않고 발행이 가능한것일까 라는 생각에서 알고리즘을 생각해보았습니다.

 

일단 겹치지 않고 발행이라는 전제보다 먼저 생각해볼 문제는 사람들이 임의로 숫자를 넣어서

16자리의 숫자를 모두 맞힐 확률이 얼마나 될까..?? 에대한 고민이 전제가 되어야 합니다.

 

 

 

1) 임의로 숫자를 맞출 확률


상품권의 코드는 16자리로 아래와 같이 나타납니다.

 

1234-5678-1234-ABCD

 

자그럼 여기에서 한자리의 숫자는 0~9까지 추가로 A~F까지라고 가정하면

 

0 1 2 3 4 5 6 7 8 9 A B C D E F

 

한자리당 총 16경우의 수가 생기고

 

16x16x16x16  16x16x16x16  16x16x16x16  16x16x16x16

 

임의로 숫자를 넣어서 하나의 상품권을 맞출 확률은

 

18446744073709551616 분의 1이라는 확률이 나오게 됩니다

 

즉 간단히 말해서 이 상품권 한장을 맞추기는 거의 불가능하다고 보면 됩니다.

 

 

 

1) 랜덤 숫자 발권에대한 고찰


자 이제는 숫자를 겹치지않고 발권하기 위한 알고리즘에 대해 이야기해보겠습니다.

 

처음 숫자를 만들어내기 위한 기준값이 필요한데 저는 아래와같이 설정하겠습니다.

 

1234-9ABC-5678-DEF0

 

무작위로 제가 설정한 값으로 다른값으로 변경하셔도 상관 없습니다.

 

숫자가 겹치면 안되므로 발권시 겹치지않는 숫자값으로 활용할게 무엇이 있을까를 생각하다가

 

정말 간단하게 우리는 현재를 살아가고있고 지나간 과거시간은 돌아오지 않는다는점을 활용하여

 

지금 발권하는 시간대를 알고리즘에 녹이기로 했습니다.

 

그러나 여기에서 문제점은 시간을 녹이면 한번 발권당 다른시간대의 숫자는 겹치지 않지만

예를들어 16개이상을 발권하는 경우에는

제가 고안해낸 알고리즘으로는 16개만 다른숫자로 무한 반복된다는점이였습니다.

 

무슨의미인지는 아래와 같습니다.

 

1234-1234-1234-1234

2345-2345-2345-2345

.

.

.

ABCD-ABCD-ABCD-ABCD

1234-1234-1234-1234

(다시 16개 반복)

.

.

ABCD-ABCD-ABCD-ABCD

 

왜냐하면 생각해본 알고리즘에는 자리수를 쉬프트하고 시간값을 넣는데

발권하는 시간대가 그 순간이기 때문에 알고리즘이 16번 반복한뒤

같은 시간대를 가지고 계속 반복되기 때문입니다.

 

말이좀 어려운데 다음주제에 알고리즘을 보시면 이해가 쉬울거예요.

 

그래서 여기에 마지막으로 발권번호라는 것을 추가해 줍니다.

 

즉 발권을 20개 한다면 각 상품권마다 발권번호값을 녹이기 때문에

결국에는 다른 상품권 코드가 나오게 되는 것입니다.

 

 

 

3) 발권 알고리즘의 순서 


1. 첫번째로 발권번호 기본값을 정해줍니다.

 

1234-9ABC-5678-DEF0

 

 

2. 발권번호만큼 오른쪽으로 Shift 해줍니다.

 

발권번호 1번 >> 0123-49AB-C567-8DEF

발권번호 2번 >> F012-349A-BC56-78DE

 

이런식으로 발권번호만큼 오른쪽으로 한칸식 이동해주면 됩니다.

 

여기에서 위에서말한 16개이후에 반복된다는 문제점이 나오는데

발권번호 17은 결국 1번 오른쪽으로 Shift 한것과 같기 때문입니다.

 

 

3. 년도만큼 자리값을 증가시켜 줍니다.

 

현재 2020년이기 때문에

 

1234-9ABC-5678-DEF0

2020-2020-2020-2020

3254-BADC-7698-FE10

 

자리수마다 해당 년도값을 증가해주되 F를 초과시에 0부터 다시 증가시킵니다

0 1 2 3 4 5 6 7 8 9 A B C D E F

즉 A=10이고 F=15로 계산하면 됩니다.

 

 

4. 월일만큼 자리값을 차감시켜 줍니다.

 

현재기준 8월12일이기 때문에

 

3254-BADC-7698-FE10

0812-0812-0812-0812

3ACE-B2CA-7E86-F60E

 

자리수마다 해당 월일값을 차감해주되 자리값이 0이하일때에는 F부터 다시 차감합니다.

 

5. 시분만큼 증감차감 해줍니다.

 

현재기준 5:49분

0549에서 0증가5차감4증가9차감

 

3ACE-B2CA-7E86-F60E

0549-0549-0549-0549

3505-BD01-79CD-F145

 

6. 마지막으로 발권번호만큼 자리수에 대입

 

오른쪽부터 1의자리 10의자리...증가

예를들어서 아래와 같이

 

발권번호 1번

3505-BD01-79CD-F145

3505-BD01-79CD-F146

 

발권번호 2번

3505-BD01-79CD-F145

3505-BD01-79CD-F147

 

발권번호 11번

3505-BD01-79CD-F145

3505-BD01-79CD-F156

 

이런식으로 자리수에 해당하는 숫자를 녹여준다.

 


여기까지 알고리즘을 만들어 프로그램을 통해 발권을 확인해본 결과 겹치지 않는 번호생성이 가능했다.

처음 만들어본 알고리즘이지만 만족스러운 결과를 보여주고있고 잘 사용중입니다.

 

728x90
반응형

댓글