HamidOsouli
4/2/2013 - 12:59 PM

Check Iranian National Code Validity - بررسی صحت کد ملی ایرانی - Clojure, C#, Ruby, JavaScript, Python, Scala, Java 8, PHP, C, Go, Swift, Ko

Check Iranian National Code Validity - بررسی صحت کد ملی ایرانی - Clojure, C#, Ruby, JavaScript, Python, Scala, Java 8, PHP, C, Go, Swift, Kotlin

// Check Iranian National Code Validity - Clojure, C#, Ruby, JavaScript, Python, Scala, Java 8, PHP, C, Go, Swift, Kotlin
// بررسی صحت کد ملی ایران - کلوژر، سی‌شارپ، روبی، جاوااسکریپت، پایتون، اسکالا، جاوا ۸، پی‌اچ‌پی، سی، گو، سوئیفت، کاتلین

// در نسخه‌های قبل یکسان بودن اعداد نا معتبر تشخیص داده می‌شد ولی
// اعداد یکسان نامعتبر نیست http://www.fardanews.com/fa/news/127747

// بعضی از پیاده‌سازی‌ها سریع نیستند، می‌توانید نسخهٔ خود را بر پایهٔ
// نسخهٔ سی یا گو ایجاد کنید که بهترین سرعت را داشته باشد

/**
 * @author Ebrahim Byagowi (2013-)
 * @lincense: 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)]
      (or (and (< sum 2) (== check sum))
          (and (>= sum 2) (== (+ check sum) 11))))
    false))

// Ruby
def is_valid_iran_code(input)
  return false if /^\d{10}$/ !~ input

  check = Integer(input[9])

  s = (0..8).map{|x| Integer(input[x]) * (10 - x)}.inject(:+) % 11
  (s < 2 && check == s) || (s >= 2 && 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) || (sum >= 2 && check + sum == 11);
}

// 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);
}

// ES2015
function isValidIranianNationalCode(input) {
    if (!/^\d{10}$/.test(input))
        return false;
 
    var check = +input[9];
    var sum = Array(9).fill().map((_, i) => +input[i] * (10 - i)).reduce((x, y) => x + y) % 11;
    return (sum < 2 && check == sum) || (sum >= 2 && check + sum == 11);
}

// C
bool isValidIranianNationalCode(const char *input) {
    for (int i = 0; i < 10; ++i) if (input[i] < '0' || input[i] > '9') return false;
    int check = input[9] - '0';
    int sum = 0;
    for (int i = 0; i < 9; ++i) sum += (int)(input[i] - '0') * (10 - i);
    sum %= 11;
    return (sum < 2 && check == sum) || (sum >= 2 && 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):
    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 (s < 2 and check == s) or (s >= 2 and 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

      (sum < 2 && check == sum) || (sum >= 2 && 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 = Streams.intRange(0, 9)
            .map((IntUnaryOperator) x ->
                    Integer.parseInt(input.substring(x, x + 1)) * (10 - x))
            .sum() % 11;

    return (sum < 2 && check == sum) || (sum >= 2 && check + sum == 11);
}

// PHP
function isValidIranianNationalCode($input) {
    # check if input has 10 digits that all of them are not equal
    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) || ($sum >= 2 && $check + $sum == 11);
}

// Swift 3, based on @farzadshbfn work but modified a little
func isValidIranianNationalCode(input: String) -> Bool {
    var digits = input.characters.flatMap { 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, Android
fun isValidIranianNationalCode(input: String): Boolean {
  if (!"^\\d{10}$".toRegex().matches(input))
    return false

  input.toCharArray().map(Character::getNumericValue).let {
    val check = it[9]
    val sum = (0..8).map { i -> it[i] * (10 - i) }.sum() % 11
    return sum < 2 && check == sum || sum >= 2 && check + sum == 11
  }
}