Hatena::Groupcadr

kozima の日記

2010-12-06

nil じゃなかったら表示

| 23:23

format string の一部を表示したりしなかったりする。

(format t "~1{hoge~}" x) ; x が non-nil な atom だとエラー
(format t "~:[~;hoge~]" x)
(format t "~@[~*hoge~]" x)

2010-09-28

cmsg

| 23:39

from http://cadr.g.hatena.ne.jp/g000001/20100928/1285683856

format を使うのなら ~? 使えばいいんじゃないかなって思いましたが,どうなんでしょうか。

(defun cmsg (template &rest args)
  "Format output to console"
  (when *console-msgs*
    (format t "~&;; ~?~%" template args)))

g000001g0000012010/09/29 20:40確かにこれは簡潔ですね!

2010-01-05

リストの偶数番目だけ表示とか奇数番目だけ表示とか

| 21:13

format でわりと簡単に書けますね。

(setf x '(A B C D E F G H I J))

(format t"~{~A~*~}" x)
;-> ACEGI
;=> NIL

(format t"~{~*~A~}" x)
;-> BDFHJ
;=> NIL

2009-04-30

99 bottles of beer on the wall

| 23:43

99 bottles of beer on the wall を format で書いたものが発掘されたので貼り付けてみます。

(format t "~{~A on the wall, ~:*~A.~%~
~#[Go to the store and buy some more, ~@*~A~#*~:;~
Take one down and pass it around, ~A~:*~] on the wall.~%~%~}"
        (loop for i to 98 collect (format nil "~A bottle~:P of beer" (- 99 i))))

出力。

99 bottles of beer on the wall, 99 bottles of beer.
Take one down and pass it around, 98 bottles of beer on the wall.

98 bottles of beer on the wall, 98 bottles of beer.
Take one down and pass it around, 97 bottles of beer on the wall.

(中略)

2 bottles of beer on the wall, 2 bottles of beer.
Take one down and pass it around, 1 bottle of beer on the wall.

1 bottle of beer on the wall, 1 bottle of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.

中身は "n bottle(s) of beer" のリストを生成してループしてるだけ。n が 99 から一つずつ減っていくんですが、最後に 99 に戻らなければならないので、その部分の処理だけトリッキーです。

  • 最後 (引数がもうない) かどうかを ~#[...~] の分岐で判定
  • 引数が残っていなければ ~@*~A~#* で最初の引数を表示して終了
    • ~@* で最初に戻る
    • ~A で最初の引数を表示
    • ~#* で残りの引数を捨ててループを抜ける

2009-02-15

format でリストの末尾を表示したりしなかったり

| 22:57

ゴルフしてたら気付いたこと。

リストの最後の要素を表示

(format t "~{~*~#@*~A~}" '(first second third fourth last))
;-> LAST

簡単な説明をしておくと、こんな感じです。

  1. 最初の引数は [(first second third fourth last)] *1
  2. まず ~{ でリストを受け取る。引数は [first second third fourth last]
  3. ~* で一つ捨てる。これで引数は [second third fourth last]
  4. ~#@* の処理。残りの引数は四つなので、残る引数は [last]
  5. ~A で LAST が出力され、引数が空になる
  6. 引数がもうないので繰り返し終了

リストの最後以外の要素を表示

(format t "~{~A~#[~;~*~]~%~}" '(first second third))
;-> FIRST
;   SECOND

~#[~;~*~] で「残り引数が一つなら、その残っている最後の引数を捨てる」処理になります。

組み合わせると。

rotate lines reversely の解 (82 bytes) になります。

(format t"~{~*~#@*~A~}
~:*~{~A~#[~;~*~]
~}"(loop while(listen)collect(read-line)))

可読性は酷いですが、頭をひねればいろんなことができるものです。

*1:引数の表記法は適当