elispでisbn13->ASIN記法
http://d.hatena.ne.jp/tomisima/20071223/1198339760
おもしろそうなのでやってみました><
追記:
- isbn-10にはBugがあります。
- isbn13-to-isbn10もxxx-xxxxxxxxx-yではなくxxx-xxxxxxxxxyのときにはうまく計算できていません。
(コメント欄でplusさんが教えてくれました)
コメント欄のコードが正規表現のところや",'などが全角になってしまっているため記事の中にコードを追加。
;;plusさんのコード(こちらの方が良いです><) (defun my-isbn13-to-isbn10 (isbn) (interactive "sEnter ISBN-13: ") (let ((isbn (replace-regexp-in-string "[- ]" "" isbn)) (i 9) (check 0)) (cond ((string-match "\\`[0-9]\\{13\\}\\'" isbn) (setq isbn (substring isbn 3 12)) (while (> i 0) (setq check (+ check (* (- (aref isbn (- 9 i)) ?0) (1+ i)))) (setq i (1- i))) (setq check (- 11 (% check 11))) (insert isbn (cond ((= check 10) "X") ((= check 11) "0") (t (number-to-string check))))) (t (message "Not ISBN-13")))))
以下は前に書いたもの。(bugがあります><)
(require 'cl) (defun string-to-numlist (numbers) (mapcar (lambda (str) (string-to-number str)) (filter (lambda (elem) (not (or (equal elem "") (equal elem "-")))) (split-string numbers "")))) (defun fold (fn init lst) (do* ((result init (funcall fn result (car lst))) (lst lst (cdr lst))) ((null lst) result))) (defun filter (p xs) (cond ((null xs) nil) ((funcall p (car xs)) (cons (car xs) (filter p (cdr xs)))) (t (filter p (cdr xs))))) (defun isbn-10 (isbn) ;;チェックデジットを調べる (let ((total (fold (lambda (aa bb) (+ aa bb)) 0 (mapcar* (lambda (x y) (* x y)) (string-to-numlist isbn) '(10 9 8 7 6 5 4 3 2 1))))) (- 11 (% total 11)))) (defun isbn-13 (isbn) ;;チェックデジットを調べる (let* ((total (fold (lambda (aa bb) (+ aa bb)) 0 (mapcar* (lambda (x y) (* x y)) (string-to-numlist isbn) '(1 3 1 3 1 3 1 3 1 3 1 3)))) (n (% total 10))) (if (= n 0) 0 (- 10 n)))) ;; 対話的に呼べない方 ;; (defun isbn-13-to-10 (isbn) ;; (let ((string9 (cadr (split-string ;; (car (split-string isbn "-.$")) ;; "^.*?-")))) ;; (concat (fold (lambda (x rest) (concat x rest)) "" ;; (split-string string9 "-")) ;; (number-to-string (isbn-10 string9))))) ;; (print (isbn-13-to-10 "978-4-8401-1984-9") (current-buffer)) ;; "4840119848" (defun isbn-13-to-10 (isbn) (interactive "s") (let ((string9 (cadr (split-string (car (split-string isbn "-.$")) "^.*?-")))) (print (concat (fold (lambda (x rest) (concat x rest)) "" (split-string string9 "-")) (number-to-string (isbn-10 string9))) (current-buffer)))) (provide 'calc-isbn)
.emacsで
(add-load-path "(上のコードを保存したディレクトリのパス) (require 'calc-isbn)
とすると
M-x isbn-13-to-10で呼ぶことができます。ミニバッファにisbn-13を渡してあげるとASSIN形式でバッファに書き込まれます。