マイナンバーと法律と円周率 第9夜
お久しぶり、たくんまです
Twitterをやっていたらこんなツイートを見つけました
https://x.com/Archangel_HT/status/1860160577211171012
このツイートによると、マイナンバーが含まれている文字列をインターネットに上げるのは違法、根拠はこれ
というわけで、今回はインターネットにあるであろう円周率に、どの程度マイナンバーが含まれているか見ていきます
そもそも、マイナンバーはどのような法則でできているのでしょうか?
これはここで公開されていて、その内容はこのとうり
マイナンバーは12桁である
最初の11桁はランダムである
最後の12桁目は、このようにして計算される↓
$ 11-\left(\sum_{n=1}^{11}Pn\cdot Qnを11で除した余り\right)
ただし、
$ Pn=最初の11桁の最下位の桁を1桁目としたときのn桁目の数字
$ Qn=\left\{1\le n\le6:n+1,7\le n\le11:n-5\right\}
それに加え、
$ (\sum_{n=1}^{11}Pn\cdot Qnを11で除した余り)\le1
の場合は0である
これに伴ってとりあえず11桁の整数から12桁目を計算するPythonスクリプトを作成します
まずは関数定義から
n桁目を取り出す計算があるため、ゼロ埋めとか考えるのめんどいので、11桁の整数は文字列として扱うことにしました
code:hoge.py
def P(num: str,N: int) -> int:
return int(numlen(num)- N)
def Q(N: int) -> int:
if 1 <= N <= 6:
return N + 1
if 7 <= N <= 11:
return N - 5
次
本体のスクリプトを書くわよ
code:hoge.py
def check(kensa: str) -> int:
if len(kensa) != 11:
raise ValueError("11桁にして、どうぞ")
sum = 0
for N in range(1,12,1): # N=1のため、わざわざこういう書き方をする、原作には忠実にね
sum += (P(kensa, N) * Q(N))
amari = sum % 11
check = None
if amari <= 1:
check = 0
else:
check = 11 - amari
return check
はい、これで11桁から12桁目を錬成できるようになりました!!!!!
使用例↓
code:hoge.py
print(check("00721180682")) # 0
円周率はy-cruncherというソフトで計算しました、こいつが一番早いらしいです(小並感)
うちのPCで250,000,000桁が8.136秒かかりました、早すぎ
で、このファイルをもとにマイナンバーを検出します
具体的な方法としては、
code:mermaid
flowchart LR
11桁読む --> 1桁読む --> 古い11桁から12桁目を生成 --> 最後に読んだ1桁と12桁目は一致してる?
最後に読んだ1桁と12桁目は一致してる? -- してる --> ヒット!
ヒット! --> 1桁読む
最後に読んだ1桁と12桁目は一致してる? -- してない --> 1桁読む
まずい、カスのフローチャートになった
やはり自然言語は滅びるべき
カキカキ
code:hoge.py
with open("./PI.txt") as file:
temp = file.read(2)
if temp != "3.": # y-cruncherが吐き出す円周率には"3."が含まれている
print("これは円周率のファイルではないよ!")
else:
file2 = open('output.txt', 'w', encoding='utf-8')
keta = 1
hitnum = 0
max = 250000000
temp = "." + file.read(11) #file.read(N)でN文字読み込める、open()した時点ではファイル全部がメモリに飛ぶわけじゃないっぽい、エコ
temp2 = file.read(1)
start = time.time()
while len(temp2) == 1:
temp = temp1:12 + temp2 #12桁のうち新しい方の11桁を保持し、新しく取得した1桁を追加
if check(temp0:11) == int(temp2):
pass
file2.write(f"{keta:8d}:{temp}\n")
hitnum += 1
#print("hit!")
if keta % 100000 == 0:
finish = time.time()
print(f"済み:小数点{keta:9d}桁以下 ヒット数:{hitnum:8d} 時間:{finish - start:.4f} 進捗:{(keta / max) * 100:.2f}% のこり:{(max - keta) / 100000 * (finish - start):.2f}s")
start = time.time()
temp2 = file.read(1)
keta += 1
実行、、、とても遅い、10分ぐらいかかる見込み、、、
ChatGPTにマルチコアになるようにしてもらおう
非同期のコードなんて目を通したくもないからエラー出たらそんまま言うか、、、。
code:hoge.py
import time
from concurrent.futures import ProcessPoolExecutor
def P(num: str, N: int) -> int:
return int(numlen(num) - N)
def Q(N: int) -> int:
if 1 <= N <= 6:
return N + 1
if 7 <= N <= 11:
return N - 5
def check(kensa: str) -> int:
kensa = str(kensa).zfill(11)
if len(kensa) != 11:
raise ValueError("ゼロありの11桁の文字列にして、どうぞ")
sum = 0
for N in range(1, 12, 1):
sum += P(kensa, N) * Q(N)
amari = sum % 11
return 0 if amari <= 1 else 11 - amari
def process_chunk(chunk_start: int, chunk_size: int, pi_data: str, max_keta: int):
results = []
keta = chunk_start
hitnum = 0
temp = "." + pi_dataketa - 1:keta + 10
start = time.time()
for i in range(chunk_size):
if keta + 10 >= len(pi_data):
break
temp2 = pi_dataketa + 10
temp = temp1: + temp2
if check(temp0:11) == int(temp2):
results.append(f"{keta:8d}:{temp}\n")
hitnum += 1
if keta % 100000 == 0:
finish = time.time()
print(f"済み:小数点{keta:9d}桁以下 ヒット数:{hitnum:8d} 時間:{finish - start:.4f} 進捗:{(keta / max_keta) * 100:.2f}%")
start = time.time()
keta += 1
return results
def main():
max_keta = 250000000
num_processes = 16
chunk_size = max_keta // num_processes
with open("./PI.txt") as file:
temp = file.read(2)
if temp != "3.":
print("これは円周率のファイルではないよ!")
return
pi_data = file.read(max_keta + 11) # 必要な範囲を一度に読み込む
with ProcessPoolExecutor(max_workers=num_processes) as executor:
futures = []
for i in range(num_processes):
chunk_start = i * chunk_size + 1
futures.append(executor.submit(
process_chunk, chunk_start, chunk_size, pi_data, max_keta
))
with open("output.txt", "w", encoding="utf-8") as out_file:
for future in futures:
results = future.result()
out_file.writelines(results)
if __name__ == "__main__":
main()
1発で動いた!!!すごい
40秒ぐらいですみました、すごい
結果!!!!!!!
円周率
250,000,000桁には
025,001,817個のマイナンバーが含まれているようです!!!!!!!
まあ検証用の桁が1桁で最後に%11されるからだいたい1/10で引っかかるよな、笑
厳密な確率はめんどいので計算しません
ちなみに一番最初に出てくるマイナンバーは3.141592"653589793238"
おまけ
総務省の資料によると10月末時点で102,926,981人にマイナンバーが交付されているようです
これを元に確率的に実際に載っている人数を計算することができます!
$ (102926981/(10^{11}))\cdot25001817
≒25733人
というわけで、円周率250,000,000桁には約25733人の個人情報が書かれています、完
小数点以下N桁目とマイナンバーの値の対応表を配布します
https://scrapbox.io/files/67434c53712c4f6cf39be55f.png
量を見誤ったせいでインデントが足りなくなって途中でズレてます、なんてこった
500MBぐらいあるのであらかじめ .7z したものも配布しています、えらい!
130MBとかになってますそっちだけで良かったんじゃね
どちらにせよ、メモ帳とかで開くとバカ重いので気をつけてくださいね
https://drive.google.com/drive/folders/1udTnXc20u821872c3L2zi5vgwEnpJQp6?usp=sharing
それじゃまたね
次回記事:Pythonを改造しよう 第10夜
#ゆめにっき