چند وقت پیش داشتم یک وبسایتی رو اسنیف میکردم که متوجه شدم یک بخشی داره که وقتی کد ملی وارد میکنی، به نحوه خیلی عجیبی میگه که آیا این کد ملی معتبره یا نه!
اولش فکر کردم احتمالا به سیستم ثبت احوالی یا جایی وصله ولی اینکه مشخصات فرد رو نمیگفت و بلافاصله نتیجه رو اعلام میکرد باعث شد شک کنم و یکمی راجبش سرچ کنم.
در نهایت متوجه شدم یک الگوریتمی وجود داره که بهتون اعلام میکنه کد ملی ای که بهش دادید معتبره یا نه!
هنوز هم خیلی دوست دارم بدونم چطوری این الگوریتمو کشف کردن.
امروز توی این پست قراره کد پایتون این الگوریتم و خود الگوریتمو توضیح بدم و در نهایت قراره دوتا باگی که این الگوریتم داره رو مطرح کنم.
این مطلب حاصل بازنگری سایت های مختلف هست که در این مورد مطلب نوشته بودند.
عکس بالا بیانگر همه چیز هست.
ما به هر رقم در کد ملی یک ارزش مکانی میدهیم که در ردیف سوم نوشته شده.
هر کد ملی از 10 رقم تشکیل شده که ما از رقم سمت راست برای بررسی صحت باقی ارقام استفاده میکنیم.
ابتدا یک کد ملی دلخواه رو در ردیف "کد ملی نمونه" مینویسیم. برای مثال ما اینجا از یک کد ملی کاملا شانسی استفاده کردیم : 0218674719
حالا بیاید ببینم معتبره یا نه.
بعد ازینه کد ملی رو توی جدول نوشتیم، میایم و ضربدر ارزش مکانیش که پایینش نوشته شده میکنیم و جواب رو در ردیف آخر مینویسیم. لازم نیست حاصل ضرب رقم کنترل رو بنویسید چون اولا ضربدر 1 میشه دوما ما از این رقم برای بررسی سایر ارقام استفاده میکنیم. چطور؟
بعد از اینکه حاصل ضرب هارو نوشتید، بیاید و اعداد داخل باکس خاکستری رو باهم جمع کنید. یعنی 0+18+8+56+36+35+16+21+2
که حاصل هرچی شد برابر Y قرار میدیم. در اینجا Y شده 192.
حالا میایم و یک تقسیم انجام میدیم. توی این تقسیم ما با خارج قسمت کار داریم که اونو X مینامیم.
بعد ازینکه X بدست اومد دوتا حالت داره، یا کمتر از 2 هست یا بیشتر از 2. اگه کمتر از 2 بود، اونوقت رقم کنترل باید برابر X باشه در غیر این صورت رقم کنترل باید برابر یازده - X باشه.
اگه اینطوری نبود یعنی کد ملی نا معتبره.
پس نتیجه میگیرم این کد ملی معتبر است
def check_id(id): def devide(x,y): a = 0 for i in range(x): if y*i <= x: a = i else: return a,x-(a*y) break lst = [] for i in range(9): lst.append(int(id[i]) * int(10-i)) if (devide(sum(lst),11)[1]) < 2: if int(id[-1]) ==devide(sum(lst),11)[1]: return True else: return False else: if int(id[-1]) ==(11-(devide(sum(lst),11)[1])): return True else: return False print(check_id("0218676719"))
این الگوریتم برای محاسبه معتبر بودن کد ملی هست نه اینکه اطلاعات فرد رو بهتون بده!
با استفاده از این الگوریتم ممکنه کد ملی یکی که هنوز به دنیا نیومده رو پیدا کنید و ممکنه اینجوری کد ملی نامعتبر دریافت کنید.
سه رقم سمت چپ کد ملی بیانگر محل تولد هست که ممکنه دارای 0 باشه و کاربر اونارو وارد نکنه که نیازه به همون تعداد، 0 به سمت چپ اضافه بشه.
ممکنه 3 رقم سمت چپ، اصلا مربوط به هیچ جایی نباشه.
و در نهایت کد پایتون من میتونه کلی بهینه بشه. مثلا من بجای استفاده از %، یک تابع نوشتم!