11 KiB
11 KiB
title | author | date | url | wordtwit_post_info | categories | |||
---|---|---|---|---|---|---|---|---|
isbn13→isbn10を求めるlispスクリプト | kazu634 | 2008-11-08 | /2008/11/08/_1141/ |
|
|
これで完結編だよ。
ソース
;; 引数が13桁の数字かどうかを判断する。 ;; 13桁の場合はisbn10を求める (define (isbn arg) ;; もし13桁の数字であれば (if (rxmatch #/\d\d\d\d\d\d\d\d\d\d\d\d\d/ (number->string arg)) (begin ;; split-listの返り値のリストを表示する。 ;; そのリストから最後の1桁を求め、最後に表示する。 (for-each (lambda (x) (display x)) (split-list (number->list arg))) (display (chkdigit arg))) ;; 13桁の数字でなければ (print "Not match"))) ;; 数字からリストにする。後ろにShiroさんの別解あり (define (number->list number) (define (loop lis) (cond [(null? lis) '()] [else (cons (digit->integer (car lis)) (loop (cdr lis)))])) (let ((num_list (string->list (number->string number)))) (loop num_list))) ;; isbn13から必要な部分だけを抜き出してリストにする。 ;; これで10桁のうち9桁の数字が決まる。 (define (split-list list) (drop-right (take-right list 10) 1)) ;; チェックディジットを求める関数。残りの1桁がこれで判明する。 (define (chkdigit num) (define (proc list) (cond [(null? list) ] [else (+ (* (car list) (+ 1 (length list))) (proc (cdr list)))])) (let ((result (- 11 (modulo (proc (split-list (number->list num))) 11)))) (if (= result 10) 'X result))) ;; number->list別解 - (1) (define (number->list n) (map digit->integer (string->list (number->string n)))) ;; number->list別解 - (2) (define (number->list n) (let loop ((n n) (r '())) (if (< n 10) (cons n r) (loop (quotient n 10) (cons (modulo n 10) r)))))
これだけだとなにをやっているかわからないと思うので、Perl版が「2008-07-02 – 武蔵の日記」にあります。アルゴリズムはそっちをごらんください。
実行結果
『プログラミングGauche』で試してみます。isbn13は9784873113487なので
gosh> (isbn 9784873113487) 4873113482#<undef>
という結果でした。確かめてみましょう。
asinはisbn10のことなので、asin記法のところを見ます。あってますね。というわけで、できました。