15 märts, 2008

Eesti isikukoodi valideerimine Lispis

Dukelupus kirjutas isikukoodi valideerimisest .NET'is.
Võrdluseks sama kood kirjutatuna Lispis:

(defun number-to-digits (number)
  (map 'list #'digit-char-p (princ-to-string number))
)


(defun digits-to-number (digits)
  (parse-integer (map 'string #'digit-char digits))
)


(defun valid-birth-date (ik-digits)
  "Kontrollib kas tegu on korrektse kuupäevaga"
  (let ((sajand
         (case (first ik-digits)
           ((1 2) 1800)
           ((3 4) 1900)
           ((5 6) 2000)
)
)
)

    (when sajand
      (integerp
       (ignore-errors
         (encode-universal-time
          0 0 0
          (digits-to-number (subseq ik-digits 5 7))
          (digits-to-number (subseq ik-digits 3 5))
          (+ sajand (digits-to-number (subseq ik-digits 1 3)))
          0
)
)
)
)
)
)


(defun checksum (ik-digits fn)
  (mod
   (loop for n from 1 to 10
         sum (* (1+ (mod (funcall fn n) 9))
                (nth (1- n) ik-digits)
)
)

   11
)
)


(defun valid-checksum (ik-digits)
  (= (first (last ik-digits))  ;; kontrollnumber
    (let ((result (checksum ik-digits '1-)))
       (if (= 10 result)
         (mod (checksum ik-digits '1+) 10)
         result
)
)
)
)


(defun valid-isikukood (isikukood)
  (let ((ik-digits (number-to-digits isikukood)))
    (and
     (= (length ik-digits) 11) ;; peab sisaldama 11 numbrit
     (valid-birth-date ik-digits)
     (valid-checksum ik-digits)
)
)
)

Tulemused:

CL-USER 57 > (time (valid-isikukood 21107190012))
Timing the evaluation of (VALID-ISIKUKOOD 21107190012)

User time = 0.000
System time = 0.000
Elapsed time = 0.000
Allocation = 300 bytes
0 Page faults
T

CL-USER 58 > (time (valid-isikukood "21107190012"))
Timing the evaluation of (VALID-ISIKUKOOD "21107190012")

User time = 0.000
System time = 0.000
Elapsed time = 0.000
Allocation = 288 bytes
0 Page faults
T

CL-USER 59 > (time (valid-isikukood 21107190013))
Timing the evaluation of (VALID-ISIKUKOOD 21107190013)

User time = 0.000
System time = 0.000
Elapsed time = 0.000
Allocation = 300 bytes
0 Page faults
NIL


Huvitav on see, et kui anda isikukood ette stringina siis võtab programm vähem mälu kui numbritega.

Seda koodi saab Lispworksis kasutada ka läbi graafilise liidese:

(capi:prompt-for-integer
 "Sisesta isikukood:"
 :ok-check 'valid-isikukood
)

Tulemusena avaneb selline aken:

Ok-nupp aktiveerub alles siis kui sisestatud on korrektne isikukood.

blog comments powered by Disqus

Sildid