Last active
October 29, 2015 06:23
-
-
Save trsqxyz/11f90b64b9e517645d31 to your computer and use it in GitHub Desktop.
This file contains 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
# -*- coding: utf-8 -*- | |
from __future__ import absolute_import, unicode_literals, print_function | |
from collections import defaultdict | |
from contextlib import contextmanager | |
import random | |
_MIN_BASE = 10000000000 | |
_MAX_BASE = 99999999999 | |
class MyNumber(object): | |
def __iter__(self): | |
""" | |
return My Number Duplicate Yes | |
:rtype :int | |
""" | |
cls = MyNumber | |
while True: | |
seed = random.randint(_MIN_BASE, _MAX_BASE) | |
yield seed * 10 + cls.get_check_sum(int(str(seed)[::-1])) | |
@classmethod | |
def gets(cls, count): | |
""" | |
return My Number Duplicate No | |
:param count: | |
:return: | |
""" | |
limit = 10000000 | |
if count > limit: | |
raise ValueError | |
# generate My Number by Duplicate No | |
result = defaultdict(int) | |
depth = 0 | |
for number in cls(): | |
result[number] += 1 | |
if len(result) >= count: | |
return result | |
if depth > limit * 100: | |
raise ValueError | |
else: | |
depth += 1 | |
@classmethod | |
def validate(cls, number): | |
""" | |
validate number | |
# My Number System Laws #5 | |
http://www.soumu.go.jp/main_content/000327387.pdf | |
:param number: int | |
:rtype : bool | |
""" | |
try: | |
with cls._check(number) as (inspection, check_sum): | |
return cls.get_check_sum(inspection) == check_sum | |
except (TypeError, ValueError): | |
print("number must be 12-digit:{}".format(str(number))) | |
@classmethod | |
def get_check_sum(cls, inspection): | |
""" | |
calc check sum from inspection | |
:param inspection: int | |
:rtype : int | |
""" | |
def q(_n): | |
if 1 <= _n <= 6: | |
return _n + 1 | |
if 7 <= _n <= 11: | |
return _n - 5 | |
n = 12 - len(str(inspection)) | |
_result = 0 | |
for p in str(inspection): | |
_result += int(p) * q(n) | |
n += 1 | |
surplus = _result % 11 | |
if surplus <= 1: | |
return 0 | |
return 11 - surplus | |
@classmethod | |
def divide(cls, number): | |
""" | |
Divide My Number to inspection and check sum | |
:param number: int | |
:rtype : tuple(int, int) | |
""" | |
check_sum = int(str(number)[-1]) | |
inspection = int(str(number)[:11][::-1]) | |
return inspection, check_sum | |
@classmethod | |
@contextmanager | |
def _check(cls, number): | |
if not isinstance(number, int): | |
raise TypeError | |
if len(str(number)) != 12: | |
raise ValueError | |
yield cls.divide(number) |
This file contains 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
# -*- coding: utf-8 -*- | |
from __future__ import absolute_import, unicode_literals, print_function | |
from mynumber import MyNumber | |
def test_divide(): | |
num = 123456789018 | |
inspection, check_sum = MyNumber.divide(num) | |
assert inspection == 10987654321 | |
assert check_sum == 8 | |
def test_validate(): | |
num_group = [ | |
123456789018, | |
190852597007, | |
664559681879, | |
317115269465, | |
636234891610, | |
759492641118, | |
653148356959, | |
712502608231, | |
845344637296, | |
626150900081, | |
250059391352, | |
220009988475, | |
518472892796, | |
971973656959, | |
142943093120, | |
661945516417, | |
275391807883, | |
422468354448, | |
345381273668, | |
282612367782, | |
993274102186, | |
101951472043, | |
288204947884, | |
459810701741, | |
673630519726, | |
428367052872, | |
656861725106, | |
559958524339, | |
727514382775, | |
858986774968, | |
633284231620, | |
457474026230, | |
] | |
for num in num_group: | |
assert MyNumber.validate(num), MyNumber.validate(num) | |
def test_iter(): | |
ct = 1 | |
for m in MyNumber(): | |
ct += 1 | |
assert MyNumber.validate(m), m | |
if ct > 1000: | |
return | |
raise | |
def test_gets(): | |
count = 1000 | |
numbers = MyNumber.gets(count) | |
assert len(numbers) == count | |
for num in numbers: | |
print(num) | |
assert MyNumber.validate(num), num |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment