-
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 ; |
خیلی ممنون
دوستان من قصد استفاده از بخش 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);
}
دمت گرم، عالی بود😊