Island Life

< 2月末締切の仕事が2つ重なって、どうにか... | 申告の書類作りに会計士さんのところへ。扶... >

2006/03/14

AA折れ線グラフ

入力は'R','F','C'の3種類の文字からなる長さ1以上の文字列

  • 'R'は上昇を表し,折れ線グラフの要素としては '/' (スラッシュ)1文字に対応
  • 'F'は下降を表し,折れ線グラフの要素としては '\' (バックスラッシュ)1文字に対応
  • 'C'は変化なしを表し,折れ線グラフの要素としては'_'(アンダスコア)1文字に対応

わしの答え。

(use gauche.sequence)

(define (graph input)
  (define (input->plist input)
    (fold2 (lambda (cmd r y)
             (case cmd
               ((#\R) (values (acons y #\/ r) (+ y 1)))
               ((#\F) (values (acons (- y 1) #\\ r) (- y 1)))
               ((#\C) (values (acons y #\_ r) y))))
           () 0 input))
  (define (draw-row plist y)
    (fold (lambda (p r)
            (cond ((= (car p) y) (display (cdr p)) #t)
                  (else          (display #\space) r)))
          #f plist))
  (let ((plist (reverse (values-ref (input->plist input) 0))))
    (let loop ((y (apply max -1/0 (map car plist))))
      (and (draw-row plist y) (display #\newline) (loop (- y 1))))))

最後に空行が入るのは気にしないっと。

yの最大値はinput->plistの段階で計算するって手もある。

gosh> (graph "RCRFCRFFCCRFFRRCRRCCFRFRFF")
                  __      
                 /  \/\/\ 
 _/\_/\        _/        \
/      \__/\  /           
            \/            
                          #f

Tags: Programming, Gauche

Past comment(s)

cut-sea (2006/03/14 22:57:39):

うーむ。凄いな。デバッグプリント差し込んでようやく理解でけた。 draw-rowの中でrを#fや#tにする意味が最初分らなかったけど、mainのlet loopの終端に使ってたのですね。 しかも-1/0とかも不要じゃないかと思ったんだけど、""をケアしてたわけかぁ。

shiro :

draw-rowで終端判定もするのではなく、縦軸の最大値と最小値を 先に求めてdo-ecかなんかでループ回した方が素直かもしれません。