AtCoder Beginner Contest 062

テストケース実行マクロを導入して、テストも書きやすくなったのはよかった。
でも、A問題の提出のときに、なんども関数呼出をしないコードを提出してしまい、時間をロスしてしまった。
結局、C問題は解けなかったので、過去問を解いてなれていくしかないかな。

テストケース実行マクロについて

いちいち標準入力に入力するのはもったいないので、 動作確認用のユーティリティを定義した。前の defsolver とあわせて使う。

(defsolver solution-a (n)
  (dotimes (i n)
    (format t "~a~%" (1+ (read)))))

(run-testcases
 solution-a
 ((3 1 2 3) . (2 3 4))
 ((2 4 5) . (5 6)))

問題ページから例をコピペして、リストに整形してあげればよくなったので、楽になったと思う。

(defun %run-test (solver input)
  (with-output-to-string (*standard-output*)
    (with-input-from-string (*standard-input* input)
      (funcall solver))))

(defun run-test (solver input expected)
  (let* ((actual (%run-test solver input))
    (samep (equal actual expected)))
    (format t "~:[FAILS~;pass~]~%" samep)
    samep))

(defmacro run-testcases (solver &rest cases)
  `(progn
     ,@(mapcar
    #'(lambda (c)
        `(run-test
          #',solver
          ,(format nil "~{~a~%~}" (car c))
          ,(format nil "~{~a~%~}" (cdr c))))
    cases)))

意識はしていなかったけれど、つくり終えてみれば、 実践Common Lisp のテストフレームワークのような出来になった。 http://www.gigamonkeys.com/book/practical-building-a-unit-test-framework.html

記事をかいてておもったことは、testng の data provider みたいに

(bind-testcases solultion-a
  ...)

(run-testcases solution-a)

とできると、かっこいいかも。