43 lines
1.1 KiB
Racket
43 lines
1.1 KiB
Racket
#lang racket/base
|
|
(require racket/match)
|
|
|
|
(define operation-table
|
|
#(#(0 3 1 7 5 9 8 6 4 2)
|
|
#(7 0 9 2 1 5 4 8 6 3)
|
|
#(4 2 0 6 8 7 1 3 5 9)
|
|
#(1 7 5 0 9 8 3 4 2 6)
|
|
#(6 1 2 3 0 4 5 9 7 8)
|
|
#(3 6 7 4 2 0 9 5 8 1)
|
|
#(5 8 6 9 7 2 0 1 3 4)
|
|
#(8 9 4 5 3 6 2 0 1 7)
|
|
#(9 4 3 8 6 1 7 2 0 5)
|
|
#(2 5 8 1 4 3 6 7 9 0)))
|
|
|
|
(define (integer->digit-list n)
|
|
(let loop ((n n) (a null))
|
|
(if (zero? n) a (let-values (([q r] (quotient/remainder n 10))) (loop q (cons r a))))))
|
|
|
|
(define/match (check-digit n)
|
|
[((list ds ...))
|
|
(foldl
|
|
(λ (d interim)
|
|
(vector-ref (vector-ref operation-table interim) d))
|
|
0 ds)]
|
|
[((? integer? i))
|
|
(check-digit (integer->digit-list i))])
|
|
|
|
(define/match (valid-number? n)
|
|
[((? integer? i))
|
|
(valid-number? (integer->digit-list i))]
|
|
[((list ds ...))
|
|
(zero? (check-digit ds))])
|
|
|
|
(module+ test
|
|
(require rackunit)
|
|
(check-equal? (integer->digit-list 572) '(5 7 2))
|
|
(check-equal? (check-digit 572) 4)
|
|
(check-equal? (check-digit '(5 7 2)) 4)
|
|
(check-true (valid-number? 5724))
|
|
(check-false (valid-number? 5274))
|
|
(check-true (valid-number? 112946)))
|