わはは
問題 2.1 の以前の回答を確認してみたら大ウソ。これは無いなぁ。
とりあえず試験をナニ。add-rat の続きから。そういえば gcd の試験とか numer だの denom だのな試験も書いておく必要あり。
以下を追加。
(test-section "gcd") (test* "(gcd 5 0)" 5 (gcd 5 0)) (test* "(gcd 2 3)" 1 (gcd 2 3)) (test* "(gcd 3 6)" 3 (gcd 3 6)) (test* "(gcd -3 6)" -3 (gcd -3 6)) (test-section "numer") (test* "(numer '(1 . 2))" 1 (numer '(1 . 2))) (test-section "denom") (test* "(denom '(1 . 2))" 2 (denom '(1 . 2)))
前にこのあたりをヤッた時には gaunit を使っていたんだな。gauche.test の存在を知らなかったという物凄いオチなんですが。
以下な Makefile を書いておけば
SHELL=/bin/sh TARGET=$(wildcard test-*.scm) test: @rm -f test.log @for X in $(TARGET) ; do gosh $$X >> test.log ; done clean: rm -rf *~ test.log
emacs 上で M-x compile で make が動いて試験な標準出力を emacs 上で確認できます。
add-rat の試験
以下なカンジで良いのだろうか。
(test-section "add-rat") (test* "(+ 1/2 1/3)" '(5 . 6) (add-rat (make-rat 1 2) (make-rat 1 3))) (test* "(+ -1/2 1/3)" '(-1 . 6) (add-rat (make-rat -1 2) (make-rat 1 3))) (test* "(+ 1/-2 1/3)" '(-1 . 6) (add-rat (make-rat 1 -2) (make-rat 1 3))) (test* "(+ 1/2 -1/3)" '(1 . 6) (add-rat (make-rat 1 2) (make-rat -1 3))) (test* "(+ 1/2 1/-3)" '(1 . 6) (add-rat (make-rat 1 2) (make-rat 1 -3)))
sub も mul も div も上記コピペベースで試験書いちゃって良いかなぁ。
(test-section "sub-rat") (test* "(- 1/2 1/3)" '(1 . 6) (sub-rat (make-rat 1 2) (make-rat 1 3))) (test* "(- -1/2 1/3)" '(-5 . 6) (sub-rat (make-rat -1 2) (make-rat 1 3))) (test* "(+ 1/-2 1/3)" '(-5 . 6) (sub-rat (make-rat 1 -2) (make-rat 1 3))) (test* "(- 1/2 -1/3)" '(5 . 6) (sub-rat (make-rat 1 2) (make-rat -1 3))) (test* "(- 1/2 1/-3)" '(5 . 6) (sub-rat (make-rat 1 2) (make-rat 1 -3))) (test-section "mul-rat") (test* "(* 1/2 1/3)" '(1 . 6) (mul-rat (make-rat 1 2) (make-rat 1 3))) (test* "(* -1/2 1/3)" '(-1 . 6) (mul-rat (make-rat -1 2) (make-rat 1 3))) (test* "(* 1/-2 1/3)" '(-1 . 6) (mul-rat (make-rat 1 -2) (make-rat 1 3))) (test* "(* 1/2 -1/3)" '(-1 . 6) (mul-rat (make-rat 1 2) (make-rat -1 3))) (test* "(* 1/2 1/-3)" '(-1 . 6) (mul-rat (make-rat 1 2) (make-rat 1 -3))) (test-section "div-rat") (test* "(/ 1/2 1/3)" '(3 . 2) (div-rat (make-rat 1 2) (make-rat 1 3))) (test* "(/ -1/2 1/3)" '(-3 . 2) (div-rat (make-rat -1 2) (make-rat 1 3))) (test* "(/ 1/-2 1/3)" '(-3 . 2) (div-rat (make-rat 1 -2) (make-rat 1 3))) (test* "(/ 1/2 -1/3)" '(-3 . 2) (div-rat (make-rat 1 2) (make-rat -1 3))) (test* "(/ 1/2 1/-3)" '(-3 . 2) (div-rat (make-rat 1 2) (make-rat 1 -3)))
一応試験パス。equal-rat? な試験は以下。
(test-section "equal-rat?") (test* "(= 1/2 1/3)" #f (equal-rat? (make-rat 1 2) (make-rat 1 3))) (test* "(= 1/2 1/2)" #t (equal-rat? (make-rat 1 2) (make-rat 1 2))) (test* "(= 1/2 2/4)" #t (equal-rat? (make-rat 1 2) (make-rat 2 4)))
一応、実装と試験を以下に全部ナニ。
2.1.scm
(define (gcd a b) (if (= b 0) a (gcd b (remainder a b)))) (define (make-rat n d) (let ((n (if (and (> 0 d) (< 0 n)) (* -1 n) n)) (d (abs d))) (let ((g (abs (gcd n d)))) (cons (/ n g) (/ d g))))) (define (numer x) (car x)) (define (denom x) (cdr x)) (define (add-rat x y) (make-rat (+ (* (numer x) (denom y)) (* (numer y) (denom x))) (* (denom x) (denom y)))) (define (sub-rat x y) (make-rat (- (* (numer x) (denom y)) (* (numer y) (denom x))) (* (denom x) (denom y)))) (define (mul-rat x y) (make-rat (* (numer x) (numer y)) (* (denom x) (denom y)))) (define (div-rat x y) (make-rat (* (numer x) (denom y)) (* (denom x) (numer y)))) (define (equal-rat? x y) (= (* (numer x) (denom y)) (* (numer y) (denom x))))
test-2.1.scm
(use gauche.test) (add-load-path ".") (load "2.1") (test-start "rational") (test-section "gcd") (test* "(gcd 5 0)" 5 (gcd 5 0)) (test* "(gcd 2 3)" 1 (gcd 2 3)) (test* "(gcd 3 6)" 3 (gcd 3 6)) (test* "(gcd -3 6)" -3 (gcd -3 6)) (test-section "make-rat") (test* "3/3" '(1 . 1) (make-rat 3 3)) (test* "-3/3" '(-1 . 1) (make-rat -3 3)) (test* "3/-3" '(-1 . 1) (make-rat 3 -3)) (test* "-3/-3" '(-1 . 1) (make-rat -3 -3)) (test-section "numer") (test* "(numer '(1 . 2))" 1 (numer '(1 . 2))) (test-section "denom") (test* "(denom '(1 . 2))" 2 (denom '(1 . 2))) (test-section "add-rat") (test* "(+ 1/2 1/3)" '(5 . 6) (add-rat (make-rat 1 2) (make-rat 1 3))) (test* "(+ -1/2 1/3)" '(-1 . 6) (add-rat (make-rat -1 2) (make-rat 1 3))) (test* "(+ 1/-2 1/3)" '(-1 . 6) (add-rat (make-rat 1 -2) (make-rat 1 3))) (test* "(+ 1/2 -1/3)" '(1 . 6) (add-rat (make-rat 1 2) (make-rat -1 3))) (test* "(+ 1/2 1/-3)" '(1 . 6) (add-rat (make-rat 1 2) (make-rat 1 -3))) (test-section "sub-rat") (test* "(- 1/2 1/3)" '(1 . 6) (sub-rat (make-rat 1 2) (make-rat 1 3))) (test* "(- -1/2 1/3)" '(-5 . 6) (sub-rat (make-rat -1 2) (make-rat 1 3))) (test* "(+ 1/-2 1/3)" '(-5 . 6) (sub-rat (make-rat 1 -2) (make-rat 1 3))) (test* "(- 1/2 -1/3)" '(5 . 6) (sub-rat (make-rat 1 2) (make-rat -1 3))) (test* "(- 1/2 1/-3)" '(5 . 6) (sub-rat (make-rat 1 2) (make-rat 1 -3))) (test-section "mul-rat") (test* "(* 1/2 1/3)" '(1 . 6) (mul-rat (make-rat 1 2) (make-rat 1 3))) (test* "(* -1/2 1/3)" '(-1 . 6) (mul-rat (make-rat -1 2) (make-rat 1 3))) (test* "(* 1/-2 1/3)" '(-1 . 6) (mul-rat (make-rat 1 -2) (make-rat 1 3))) (test* "(* 1/2 -1/3)" '(-1 . 6) (mul-rat (make-rat 1 2) (make-rat -1 3))) (test* "(* 1/2 1/-3)" '(-1 . 6) (mul-rat (make-rat 1 2) (make-rat 1 -3))) (test-section "div-rat") (test* "(/ 1/2 1/3)" '(3 . 2) (div-rat (make-rat 1 2) (make-rat 1 3))) (test* "(/ -1/2 1/3)" '(-3 . 2) (div-rat (make-rat -1 2) (make-rat 1 3))) (test* "(/ 1/-2 1/3)" '(-3 . 2) (div-rat (make-rat 1 -2) (make-rat 1 3))) (test* "(/ 1/2 -1/3)" '(-3 . 2) (div-rat (make-rat 1 2) (make-rat -1 3))) (test* "(/ 1/2 1/-3)" '(-3 . 2) (div-rat (make-rat 1 2) (make-rat 1 -3))) (test-section "equal-rat?") (test* "(= 1/2 1/3)" #f (equal-rat? (make-rat 1 2) (make-rat 1 3))) (test* "(= 1/2 1/2)" #t (equal-rat? (make-rat 1 2) (make-rat 1 2))) (test* "(= 1/2 2/4)" #t (equal-rat? (make-rat 1 2) (make-rat 2 4))) (test-end)
gauche.test モジュール良いですね。