RosettaCodeData/Task/CUSIP/Racket/cusip.rkt

38 lines
1 KiB
Racket
Raw Permalink Normal View History

2023-07-01 11:58:00 -04:00
#lang racket
(require srfi/14)
(define 0-char (char->integer #\0))
(define A-char (char->integer #\A))
(define (cusip-value c)
(cond
[(char-set-contains? char-set:digit c)
(- (char->integer c) 0-char)]
[(char-set-contains? char-set:upper-case c)
(+ 10 (- (char->integer c) A-char))]
[(char=? c #\*) 36]
[(char=? c #\@) 37]
[(char=? c #\#) 38]))
(define (cusip-check-digit cusip)
(modulo
(- 10
(modulo
(for/sum
((i (sequence-map add1 (in-range 8))) (c (in-string cusip)))
(let* ((v (cusip-value c)) (v (if (even? i) (* v 2) v)))
(+ (quotient v 10) (modulo v 10)))) 10)) 10))
(define (CUSIP? s)
(char=? (string-ref s (sub1 (string-length s)))
(integer->char (+ 0-char (cusip-check-digit s)))))
(module+ test
(require rackunit)
(check-true (CUSIP? "037833100"))
(check-true (CUSIP? "17275R102"))
(check-true (CUSIP? "38259P508"))
(check-true (CUSIP? "594918104"))
(check-false (CUSIP? "68389X106"))
(check-true (CUSIP? "68389X105")))