Introduction

ブログ内検索

  • このサイトの記事を検索 by Google

おすすめの一冊!

無料ブログはココログ

« 「なぜふぉろ」リリース | トップページ | topcoder はとおい »

2009-12-20

10分でコーディング

日曜の朝早く(5時くらい)に目が覚めてしまって
ネットをふらふらしていると、ちょっと面白そうな話が。

先日トラックバックをいただいた FloralCompany.log で
「10分間コーディング」というネタがとりあげられていました。

  ⇒ お題(元ネタ)はこちら


せっかくなので xyzzy (Common Lisp) で書いてみることに。

(defun card-distribute (members cards) (labels ((rec (c len) (if (>= len members) (mapcar #'(lambda (lst) (push (pop c) lst)) (rec (nthcdr members c) (- len members))) (map1-n #'(lambda (x) nil) members)))) (mapcar #'(lambda (x) (coerce x 'string)) (rec (coerce cards 'list) (length cards)))))
時間は計り忘れましたが、たぶん10分以内だったハズ(きっと pop してるあたりがちょっと微妙な気もしますが、 とりあえずちゃんと動きます。
(card-distribute 3 "123123123") ("111" "222" "333") (card-distribute 4 "123123123") ("12" "23" "31" "12") (card-distribute 6 "012345012345012345") ("000" "111" "222" "333" "444" "555") (card-distribute 4 "111122223333") ("123" "123" "123" "123") (card-distribute 1 "012345012345012345") ("012345012345012345") (card-distribute 6 "01234") ("" "" "" "" "" "") (card-distribute 2 "") ("" "")
ここで、ふと、mapcar を使ったほうが簡単じゃないかと思いつく。 各巡のカード(ちょうど人数分)のリストを並べて 各リストから1枚ずつ抜き出せば一人分ができる、という考え。 しかし、リストのリストに対して mapcar する方法が分からず、 しばし悩む・・・ 結局、なにも考えずに apply すればよいことが判明。
(defun mapcarapply (fn lsts) (if (null lsts) nil (apply #'mapcar fn lsts)))
というわけで、書き直したコードが↓
(defun card-distribute (members cards) (if (< (length cards) members) (map1-n #'(lambda (x) (coerce nil 'string)) members) (labels ((rec (lst len) (if (< len (* 2 members)) (cons (subseq lst 0 members) nil) (cons lst (rec (nthcdr members lst) (- len members)))))) (apply #'mapcar #'(lambda (&rest args) (coerce args 'string)) (rec (coerce cards 'list) (length cards))))))
お題では、「カードを配らない」ときにあっさり nil とか 返しちゃいけないので、ちょっと余計なコードが必要だったり。 なんか最初のより悪くなってる気もしないでもないです。 2通り書いてみましたが、どっちもどっちかもしれない。 で、思いつく順番がおかしいですが、たぶん一番素直な書き方は このコードじゃないかと思われます。
(defun card-distribute (members cards) (let ((num (floor (/ (length cards) members)))) (map0-n #'(lambda (i) (coerce (map0-n #'(lambda (j) (char cards (+ i (* members j)))) (1- num)) 'string)) (1- members))))
ちなみに、各コードで使ってる map0-n や map1-n という関数は Paul Graham 氏の "On Lisp" の中で紹介されている ユーティリティ関数です。
(defun map0-n (fn n) (mapa-b fn 0 n)) (defun map1-n (fn n) (mapa-b fn 1 n)) (defun mapa-b (fn a b &optional (step 1)) (do ((i a (+ i step)) (result nil)) ((> i b) (nreverse result)) (push (funcall fn i) result)))
日曜の朝からいい運動になりました♪

« 「なぜふぉろ」リリース | トップページ | topcoder はとおい »