続・ISBNのチェックデジット
昨日の続き。Schemeで、ISBNのチェックデジットを求めるプログラムを最適化。
shiroさんからいただいたヒントを使い、無駄なlambdaを省いたり、同じ意味の数値を変数で名前付けしてしまうなどして、
(define (isbn-check-digit4 n) (let ((isbn-check-digit-base 11) (isbn-base-vector '(10 9 8 7 6 5 4 3 2))) (modulo (- isbn-check-digit-base (apply + (map * n isbn-base-vector))) isbn-check-digit-base)))
と、かなりよくなった。
さらに、nishioさんのコメントをふまえて計算式自体をもう少し解析してみると、
c = (11 - (10n1 + 9n2 + ... + 2n9)) mod 11
= (11 - 10n1 - 9n2 - ... - 2n9) mod 11
= (1n1 + 2n2 + ... + 9n9) mod 11
= (n1 n2 ... n9)・(1 2 ... 9) mod 11 //
ということで、(1 2 3 4 5 6 7 8 9) との内積値の mod 11 にまとまる。
(define (isbn-check-digit5 n) (let ((isbn-check-digit-base 11) (isbn-base-vector '(1 2 3 4 5 6 7 8 9))) (modulo (apply + (map * n isbn-base-vector)) isbn-check-digit-base)))
とても分かりやすい。本来こんなに分かりやすい計算なのに、なんであんな小難しい形に定義したんだろう・・・。