-
Star
(171)
You must be signed in to star a gist -
Fork
(24)
You must be signed in to fork a gist
-
-
Save ebraminio/5292017 to your computer and use it in GitHub Desktop.
// Check Iranian National Code Validity - Clojure, C#, F#, Ruby, JavaScript, Dart, Python, Scala, Java 8, PHP, C, Go, Swift, Kotlin, Groovy, Rust, Haskell, Erlang, Elixir, Power Query M Language, VBA, R, Lua, Fortran, Pascal/Delphi, Excel, Stored Procedure / MySQL | |
// بررسی صحت کد ملی ایران - کلوژر، سیشارپ، افشارپ، روبی، جاوااسکریپت، دارت، پایتون، اسکالا، جاوا ۸، پیاچپی، سی، گو، سوئیفت، کاتلین، گرووی، راست، هسکل، ارلنگ، الکسیر، پاورکوئری ام، ویبی ای، آر، لوآ، فرترن، پاسکال/دلفی، اکسل، مایاسکیوال | |
// در نسخههای قبل یکسان بودن اعداد نا معتبر تشخیص داده میشد ولی | |
// اعداد یکسان نامعتبر نیست https://web.archive.org/web/20170706081048/http://www.fardanews.com/fa/news/127747/رندترین-شماره-ملی-بلای-جان-صاحبش-شد | |
// بعضی از پیادهسازیها سریع نیستند، میتوانید نسخهٔ خود را بر پایهٔ | |
// نسخهٔ سی یا گو ایجاد کنید که بهترین سرعت را داشته باشد | |
/** | |
* @author Ebrahim Byagowi (2013-) | |
* @license: Public Domain | |
*/ | |
// Clojure | |
(defn valid-iran-code? [input] | |
(if (re-matches #"^\d{10}$" input) | |
(let | |
[check (Integer/parseInt (subs input 9 10)) | |
sum (mod (reduce + (map (fn [x] (* (Integer/parseInt | |
(subs | |
input x (+ x 1))) | |
(- 10 x))) | |
(range 9))) 11)] | |
(if (< sum 2) (== check sum) (== (+ check sum) 11)) | |
false)) | |
// Ruby | |
def is_valid_iran_code(input) | |
return false if /^\d{10}$/ !~ input | |
check = Integer(input[9]) | |
s = (0..8).sum {|x| Integer(input[x]) * (10 - x)} % 11 | |
s < 2 ? check == s : check + s == 11 | |
end | |
// C# | |
using System.Text.RegularExpressions; | |
public static bool IsValidIranianNationalCode(string input) | |
{ | |
if (!Regex.IsMatch(input, @"^\d{10}$")) | |
return false; | |
var check = Convert.ToInt32(input.Substring(9, 1)); | |
var sum = Enumerable.Range(0, 9) | |
.Select(x => Convert.ToInt32(input.Substring(x, 1)) * (10 - x)) | |
.Sum() % 11; | |
return sum < 2 ? check == sum : check + sum == 11; | |
} | |
// F# | |
open System.Text.RegularExpressions | |
let isValidIranianNationalCode input = | |
if Regex.IsMatch(input, @"^\d{10}$") then | |
let check = Convert.ToInt32(input.Substring(9, 1)) | |
let sum = (seq { 0 .. 8 } | |
|> Seq.map (fun x -> Convert.ToInt32(input.Substring(x, 1)) * (10 - x)) | |
|> Seq.sum) % 11 | |
if sum < 2 then check = sum else check + sum = 11 | |
else | |
false | |
// JavaScript | |
function isValidIranianNationalCode(input) { | |
if (!/^\d{10}$/.test(input)) return false; | |
const check = +input[9]; | |
const sum = input.split('').slice(0, 9).reduce((acc, x, i) => acc + +x * (10 - i), 0) % 11; | |
return sum < 2 ? check === sum : check + sum === 11; | |
} | |
// Dart | |
bool isValidIranianNationalCode(String input) { | |
if (!RegExp("^\\d{10}").hasMatch(input)) return false; | |
final check = int.parse(input[9]); | |
final sum = Iterable<int>.generate(9).map((x) => int.parse(input[x]) * (10 - x)).reduce((x, y) => x + y) % 11; | |
return sum < 2 ? check == sum : check + sum == 11; | |
} | |
// C | |
bool isValidIranianNationalCode(const char *input) { | |
for (unsigned i = 0; i < 10; ++i) if (input[i] < '0' || input[i] > '9') return false; | |
if (input[10]) return false; | |
unsigned check = input[9] - '0'; | |
unsigned sum = 0; | |
for (unsigned i = 0; i < 9; ++i) sum += (int)(input[i] - '0') * (10 - i); | |
sum %= 11; | |
return sum < 2 ? check == sum : check + sum == 11; | |
} | |
// Go | |
func isValidIranianNationalCode(input string) bool { | |
for i := 0; i < 10; i++ { | |
if input[i] < '0' || input[i] > '9' { | |
return false | |
} | |
} | |
check := int(input[9] - '0') | |
sum := 0 | |
for i := 0; i < 9; i++ { | |
sum += int(input[i]-'0') * (10 - i) | |
} | |
sum %= 11 | |
return (sum < 2 && check == sum) || (sum >= 2 && check+sum == 11) | |
} | |
// Python | |
import re | |
def is_valid_iran_code(input: str) -> bool: | |
if not re.search(r'^\d{10}$', input): return False | |
check = int(input[9]) | |
s = sum(int(input[x]) * (10 - x) for x in range(9)) % 11 | |
return check == s if s < 2 else check + s == 11 | |
// Scala | |
def isValidIranianNationalCode(input: String) = { | |
val pattern = """^(\d{10})$""".r | |
input match { | |
case pattern(_) => | |
val check = input.substring(9, 10).toInt | |
val sum = (0 to 8) | |
.map(x => input.substring(x, x + 1).toInt * (10 - x)) | |
.sum % 11 | |
if (sum < 2) check == sum else check + sum == 11 | |
case _ => false | |
} | |
} | |
// Java 8 | |
import java.util.stream.Streams; | |
import java.util.function.IntUnaryOperator; | |
public static boolean isValidIranianNationalCode(String input) { | |
if (!input.matches("^\\d{10}$")) | |
return false; | |
int check = Integer.parseInt(input.substring(9, 10)); | |
int sum = IntStream.range(0, 9) | |
.map(x -> Integer.parseInt(input.substring(x, x + 1)) * (10 - x)) | |
.sum() % 11; | |
return sum < 2 ? check == sum : check + sum == 11; | |
} | |
// PHP | |
function isValidIranianNationalCode(string $input): boolean { | |
if (!preg_match("/^\d{10}$/", $input)) { | |
return false; | |
} | |
$check = (int) $input[9]; | |
$sum = array_sum(array_map(function ($x) use ($input) { | |
return ((int) $input[$x]) * (10 - $x); | |
}, range(0, 8))) % 11; | |
return $sum < 2 ? $check == $sum : $check + $sum == 11; | |
} | |
// Swift, based on @farzadshbfn work but modified a little, tested with Swift 5.3.1 | |
func isValidIranianNationalCode(input: String) -> Bool { | |
let digits = input.compactMap { Int(String($0)) } | |
guard digits.count == 10 && digits.count == input.count else { | |
return false | |
} | |
let check = digits[9] | |
let sum = digits[0 ..< 9].enumerated().reduce(0) { $0 + $1.element * (10 - $1.offset) } % 11 | |
return sum < 2 ? check == sum : check + sum == 11 | |
} | |
// Kotlin | |
fun isValidIranianNationalCode(input: String): Boolean { | |
if (input.length != 10) return false | |
val digits = input.mapNotNull(Char::digitToIntOrNull).takeIf { it.size == 10 } ?: return false | |
val check = digits[9] | |
val sum = digits.slice(0..8).asSequence().mapIndexed { i, x -> x * (10 - i) }.sum() % 11 | |
return if (sum < 2) check == sum else check + sum == 11 | |
} | |
// Groovy, based on @mehrali work | |
boolean isValidIranianNationalCode(String input) { | |
if (!input?.matches('^\\d{10}$')) | |
return false | |
int check = input[9].toInteger() | |
int sum = (0..8).sum({ input[it].toInteger() * (10 - it) }) % 11 | |
return sum < 2 ? check == sum : check + sum == 11 | |
} | |
// Rust | |
fn is_valid_iranian_national_code(s: &str) -> bool { | |
let digits: Vec<u32> = s.chars().filter_map(|x| x.to_digit(10)).collect(); | |
if s.len() != 10 || digits.len() != 10 { | |
return false; | |
} | |
let check = digits[9]; | |
let sum = (0..9).map(|x| digits[x] * (10 - x) as u32).sum::<u32>() % 11; | |
if sum < 2 { | |
check == sum | |
} else { | |
check + sum == 11 | |
} | |
} | |
// Haskell, contributed by @hzamani | |
import Data.Char | |
isValidNationalCode code = | |
length code == 10 && all isDigit code && if s < 2 then check == s else check + s == 11 | |
where | |
digits = map digitToInt code | |
check = last digits | |
s = sum (map (\(d, i) -> d * (10 - i)) $ digits `zip` [0..8]) `mod` 11 | |
// Erlang, contributed by @hzamani | |
is_valid_national_code(Code) -> | |
length(Code) == 10 | |
andalso lists:all(fun(D) -> $0 =< D andalso D =< $9 end, Code) | |
andalso begin | |
ToDigit = fun(Char) -> Char - $0 end, | |
S = lists:sum(lists:map(fun({I, D}) -> D * (10 - I) end, lists:zip(lists:seq(0, 8), lists:droplast(lists:map(ToDigit, Code))))) rem 11, | |
Check = ToDigit(lists:last(Code)), | |
if | |
S < 2 -> Check == S; | |
true -> Check + S == 11 | |
end | |
end. | |
// Elixir, contributed by @hzamani | |
fn input -> | |
if input =~ ~r/^\d{10}$/ do | |
[check | digits] = | |
input | |
|> String.split("", trim: true) | |
|> Enum.map(&String.to_integer/1) | |
|> Enum.reverse | |
s = | |
digits | |
|> Enum.with_index(2) | |
|> Enum.map(fn {digit, i} -> digit * i end) | |
|> Enum.sum | |
|> rem(11) | |
if s < 2 do check == s else check + s == 11 end | |
else | |
false | |
end | |
end | |
// PowerQuery M Language, in a collaboration with Calak | |
(input as text) as logical => | |
let | |
check = Number.From(Text.End(input, 1)), | |
s = Number.Mod(List.Sum(List.Transform({0..8}, each (10 - _) * Number.From(Text.At(input, _)))), 11) | |
in Text.Length(input) = 10 and | |
Text.Select(input, {"0".."9"}) = input and | |
(if s < 2 then check = s else check + s = 11) | |
// VBA, in a collaboration with Calak | |
Public Function IsValidIranianNationalCode(code As String) As Boolean | |
If Not code Like String(10, "#") Then Exit Function | |
Dim check As Byte, i As Byte, s As Integer | |
check = Mid(code, 10) | |
For i = 1 To 9 | |
s = s + (11 - i) * Mid(code, i, 1) | |
Next i | |
s = s Mod 11 | |
IsValidIranianNationalCode = IIf(s < 2, check = s, check + s = 11) | |
End Function | |
// R, by Calak | |
is_valid_iran_code <- function(input) { | |
if (!grepl('^[0-9]{10}$', input)) return (FALSE) | |
check <- as.integer(substr(input, 10, 10)) | |
s <- t(10:2) %*% as.integer(unlist(strsplit(input, "")))[-10] %% 11 | |
return (if (s < 2) check == s else check + s == 11) | |
} | |
// Lua | |
function is_valid_iranian_national_code(input) | |
if input:match(string.rep("%d", 10)) ~= input then return false end | |
local check = tonumber(input:sub(10, 10)) | |
local sum = 0 | |
for i = 1, 9 do | |
sum = sum + (11 - i) * tonumber(input:sub(index, index)) | |
end | |
sum = sum % 11 | |
return (sum < 2) and (check == sum) or (check + sum == 11) | |
end | |
// Fortran, by Calak | |
logical pure function is_valid_iranian_national_code(input) | |
character(10), intent(in) :: input; integer :: check, i, s | |
integer, parameter :: zero = ichar("0") | |
is_valid_iranian_national_code = .false. | |
if (verify(input, "0123456789") /= 0) return | |
check = ichar(input(10:)) - zero | |
s = mod(sum((/ ((11 - i) * (ichar(input(i:i)) - zero), i = 1, 9) /)), 11) | |
is_valid_iranian_national_code = merge(check == s, check + s == 11, s < 2) | |
end function is_valid_iranian_national_code | |
// Pascal/Delphi, by Calak | |
function isValidIranianNationalCode(input: string): boolean; | |
const s: integer = 0; | |
var check, i: byte; | |
begin | |
isValidIranianNationalCode := false; | |
if ord(input[0]) <> 10 then exit; | |
for i := 1 to 10 do if not (input[i] in ['0'..'9']) then exit; | |
val(input[10], check); | |
for i := 1 to 9 do inc(s, (11 - i) * (ord(input[i]) - ord('0'))); | |
s := s mod 11; | |
isValidIranianNationalCode := ((s < 2) and (check = s) or (s >= 2) and (check + s = 11)); | |
end; | |
// Excel 365, by Calak | |
= LAMBDA(input, | |
IF( | |
AND(LEN(input) = 10, ISNUMBER(--MID(input, SEQUENCE(10), 1))), | |
LET( | |
check, --RIGHT(input), | |
s, MOD(SUMPRODUCT(SEQUENCE(9, 1, 10, -1), --MID(input, SEQUENCE(9), 1)), 11), | |
IF(s < 2, check = s, check + s = 11) | |
) | |
) | |
) | |
// Stored Procedure, MySQL | |
DELIMITER $$ | |
CREATE FUNCTION is_valid_iranian_national_code(input TEXT) RETURNS BOOLEAN DETERMINISTIC BEGIN | |
IF input NOT REGEXP '^[0-9]{10}$' THEN RETURN false; END IF; | |
SET @i = 1, @s = 0; | |
WHILE @i < 10 DO SET @s = @s + (11 - @i) * SUBSTR(input, @i, 1), @i = @i + 1; END WHILE; | |
SET @s = @s % 11, @check = +SUBSTR(input, -1); | |
RETURN IF(@s < 2, @check = @s, @check + @s = 11); | |
END $$ | |
DELIMITER ; |
Excellent! thanks a lot.
Thank You! it's very helpful
سپاسگزار از زحمات شما، عالی بود
بعد از سالها این اسکریپت دوباره به کارم آمد و نسخهٔ کاتلینش را اضافه کردم :)
In ES6, the fill
method needs has 1-3 arguments. you need to change Array(9).fill()
to Array(9).fill(undefined)
.
Or I prefer to use this code instead:
Array.from(new Array(9), (_, i) => +input[i] * (10 - i)).reduce((x, y) => x + y) % 11
@dehghani-mehdi @iMojtaba @aghasoroush توضیح بالای کد را یک بررسی مجدد کنید، ممنونم
ورژن جاوااسکریپت کار نمیکنه! هر چی میدی غلط تشخیص میده حتی ۱۱۱۱۱۱۱۱۱۱
لطفاً از نوع رشته ارسال کنید چون بعضی از شماره ملیها دارای صفر در اول هستند و اعداد به نظر ورودی درستی نباشن برای همچین کاری، ممنون
ممنونم
توی کنسول حل شد اما توی پروژم به طرز عجیبی همچنان نمیشه
مشکل هم از همون تعداد اوله با اینکه دقیقا تعداد ارقامش ۱۰ تاست ولی بازم فالس میده
مشکلم حل شد
مشکل از اونجا بود که وقتی از
template engine
استفاده میکنی مرورگر بک اسلش ها رو اسکیپ میکنه
باید با همچین حالتی بنویسی تا اوکی بشه
/^\\d{10}$/
if (!/^\d{10}$/.test(input))
===> if (!/^\\d{10}$/.test(input))
این کد اصلی این صفحه نیست، شرط اعداد برابر نادرست است (و این بدترین شیوهٔ بررسی آن است، میتوان آن را در همان عبارت باقاعدهٔ اصلی چا کرد) و در بالای صفحهٔ توضیح داده شده که چرا، اگر کاربرتان نمیخواهد اعداد واقعی دهد چه این شرط را بگذارید چه نه به شما اعداد واقعی نخواهد داد و آخر راهی برای دادن اعداد اشتباه پیدا خواهد کرد
Hi Ebrahim.
Thanks for share this code with us.But it has one problem for java code.
I run my test and i found this problem.
For nationalCode = ''0000000000", "1111111111" this code return True But should return false.
Why it should, it was doing but removed after http://www.fardanews.com/fa/news/127747 years ago
سلام گرامی خواستید دو کد جاوااسکریپت موجود در همین صفحه که همین کار را با تعداد کمتری دستور و
http://www.fardanews.com/fa/news/127747
این خبر را هم نگاهی بیاندازید، عملکرد پد
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
هم مدت خوبی است به مرورگرها اضافه شده خواستید میتوانید از آن استفاده کنید، ممنونم
ممنون
درسته
خودم از همین استفاده می کنیم
برای تایپ اسکریپتش زدم
Thx
ممنون .
اسکریپتی هست که بشه احتمالشو بررسی کرد ؟
ینی مثلا یه عددی بین صفر تا یک بده بگه که چقدر این میتونه شبیه به کدملی باشه .
این الگوریتم ها به یک طریق دیگه ای هم گول میخورن مثل :
1666666661
3337777333
9999229999
یعنی اعداد اول و آخر مثل هم باشن و اعداد بین هم مثل هم
در هر صورت کاربر یه راهی پیدا میکنه برای دور زدن!
بله
را حتماً بررسی کردهاید
یک الگوریتم صحتسنجی اولیه ببیشتر جنبهٔ کمک به کاربر در وارد کردن دارد و اگر کاربر قصد وارد کردن اطلاعات نادرست داشته باشد چارهاش بررسی با پایگاه دادههای ملی است تا ایدههای مثل بررسی عدم تکرار ده رقم
بله، راه حل اصلی همون بررسی با دیتابیس ملی است
برای نمونه سایتی مثل دیجی کالا هم برای بررسی از همین الگوریتم ها استفاده میکند و حتی عدم تکرار ده رقم کد ملی را هم بررسی می کند اما با روشی که بالاتر گفتم گول میخورد!
اون بنده خدا تو دیجی کالا هم نمیتونه کد ملیش رو ثبت کنه!
سلام و ممنون
خدا خیرت بده
سلام و ممنون
لطفا به زبان SQL-Server هم کد را ترجمه کنید...
در پایگاه داده یک کوئری می خواهیم که کدهای ملی نامعتبر را فیلتر کند.
به sql server دسترسی ندارم ولی برای mysql را قرار دادم، احتمالاً بتوانید آن را در sql server با کمی تغییر استفاده کنید 😊
دمت گرم، عالی بود😊
خیلی ممنون
دوستان من قصد استفاده از بخش php برای woocommerce را دارم، لطفا بفرمایید که کد زیر چه مشکلی دارد؟
`function isValidIranianNationalCode($input) {
if (!preg_match("/^\d{10}$/", $input)) {
return false;
}
$check = (int) $input[9];
$sum = array_sum(array_map(function ($x) use ($input) {
return ((int) $input[$x]) * (10 - $x);
}, range(0, 8))) % 11;
return $sum < 2 ? $check == $sum : $check + $sum == 11;
}
add_filter( 'flexible_checkout_fields_custom_validation', 'wpdesk_fcf_custom_validation_CodeMelli' );
/**
- Add custom URL validation
*/
function wpdesk_fcf_custom_validation_CodeMelli( $custom_validation ) {
$custom_validation['_billing_code_melli'] = array(
'label' => 'Code Melli',
'callback' => 'isValidIranianNationalCode'
);
return $custom_validation;
}
`
سلام @mbgame اعداد تکراری نامعتبر نیست https://web.archive.org/web/20170706081048/http://www.fardanews.com/fa/news/127747/رندترین-شماره-ملی-بلای-جان-صاحبش-شد قبلاً همین regular expression را داشتیم که حذف کردم و بالای این صفحه هم این موضوع رو نوشتهام، اگر کاربر قصد دور زدن ورود عدد را داشته باشد به هر حال راهی برای دور زدن آن پیدا میکند و راهحل، اضافه کردن قانونی ناموجود نیست
thanks!
این الگوریتم ها به یک طریق دیگه ای هم گول میخورن مثل : 1666666661 3337777333 9999229999 یعنی اعداد اول و آخر مثل هم باشن و اعداد بین هم مثل هم در هر صورت کاربر یه راهی پیدا میکنه برای دور زدن!
این کد را من تست کردم و هیچ خطایی نداره
// JavaScript
function isValidIranianNationalCode(input) {
if (!/^\d{10}$/.test(input))
return false;
var check = parseInt(input[9]);
var sum = 0;
var i;
for (i = 0; i < 9; ++i) {
sum += parseInt(input[i]) * (10 - i);
}
sum %= 11;
return (sum < 2 && check == sum) || (sum >= 2 && check + sum == 11);
}
You are hero !!!