「Ruby力向上のための基礎トレーニング」をCommon Lispで解いてみた を見て、Gauche で書いてみようと思った。
で、試してみたけど、リスト操作でやるのがイマイチイメージできなかったのと、 むしろ良くあるインデックスアクセスの方が簡単じゃないか、と思ったので、 そっち方面から攻めてみた。
以下の様になった
#!/usr/bin/env gosh ;; -*- coding: utf-8 -*- (use gauche.array) (define INPUT '((9 85 92 20) (68 25 80 55) (43 96 71 73) (43 19 20 87) (95 66 73 62))) (define INPUTA #,(<array> (0 5 0 4) 9 85 92 20 68 25 80 55 43 96 71 73 43 19 20 87 95 66 73 62) ) (define OUTPUTA (make-array (shape 0 6 0 5) 0) ) (define (main args) (let ((x (array-length INPUTA 0)) (y (array-length INPUTA 1))) (array-for-each-index INPUTA (lambda (i j) (array-set! OUTPUTA i j (array-ref INPUTA i j)) (array-set! OUTPUTA x j (+ (array-ref OUTPUTA x j) (array-ref INPUTA i j))) (array-set! OUTPUTA i y (+ (array-ref OUTPUTA i y) (array-ref INPUTA i j))) (array-set! OUTPUTA x y (+ (array-ref OUTPUTA x y) (array-ref INPUTA i j))) )) ) (print "result: " OUTPUTA) 0)
for-each なループがあったので 2 重ループにしなくて済んだ。 それでもアクセスは 2 次元として実行している。 結果、見やすくなったと思う。
元ページのやり方を良く見てみた
ポイントは「行を列に変換する」事。
1 行を扱うのは通常のリスト処理と同じ。で、縦方向の処理は配列全体を 裏返して横方向で処理できる様にする。
あとは裏返しをもう一度実行して元に戻す。
発想の飛躍具合はスゴいと思う。けど、効率とか。うーんってなる。
sxml みたいな階層構造を持つデータ形式だと親和性が高いと思う。 頂点を取り換えながら再帰するとか、自然に書けるし。