Introduction

ブログ内検索

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

おすすめの一冊!

無料ブログはココログ

« 2009年11月 | トップページ | 2010年2月 »

2009年12月

2009-12-22

topcoder はとおい

先日やってみた「Topcoder の道」の別の問題にチャレンジ。

やっぱり xyzzy (Common Lisp) です。
主に文字列操作の練習になった感じです。


    -・-        -・-        -・-        -・-


■ その1

文字列を rorate してみなさい、という問題です。

 ⇒ 問題はこちら

書いてみたコードが↓

(let* ((table "ABCDEFGHIJKLMNOPQRSTUVWXYZ") (table-size (length table))) (labels ((rotate-left (c num) (let ((org (position c table))) (if (>= org num) (char table (- org num)) (char table (- table-size (mod (- num org) table-size))))))) (defun foo (str num) (coerce (mapcar #'(lambda (c) (rotate-left c num)) (coerce str 'list)) 'string))))
まぁ、なにもひねらずに書くとこんな感じじゃないかと思われます。 目標時間の10分はちょっとオーバーしてしまいましたが。 いちおう、動きます。
(foo "VQREQFGT" 2) "TOPCODER" (foo "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 10) "QRSTUVWXYZABCDEFGHIJKLMNOP" (foo "TOPCODER" 0) "TOPCODER" (foo "LIPPSASVPH" 4) "HELLOWORLD"
-・- -・- -・- -・- ■ その2 条件を満たす要素をリストから抽出するという問題。   ⇒ 問題はこちら 書いてみたコードが↓
(defun find-user (names perms reports) (let ((table (map0-n #'(lambda (index) (cons (elt names index) (split-string (elt perms index) #\ ))) (1- (length names))))) (labels ((is-allowed (name report) (find report (cdr (assoc name table)) :test #'equal)) (filter (reports candidate) (if (null reports) candidate (mapcan #'(lambda (name) (if (is-allowed name (car reports)) (list name) nil)) (filter (cdr reports) candidate))))) (filter reports names))))
labels でローカル変数を思いつくままに定義しちゃっているので、 あまりよろしくないコードな気がします。 時間も15分をオーバーしちゃいました。 でも、いちおう動きます。
(find-user '("joe" "nick" "ted") '("clients products" "products orders" "clients orders") '("clients" "products")) ("joe") (find-user '("kathy" "john" "dan" "steve" "cheryl" "tony") '("users data" "data orders" "users permissions" "system users controls" "default" "admin users") '("users")) ("kathy" "dan" "steve" "tony") (find-user '("jim" "scott" "barbara") '("users order products" "products shipping" "tracking products orders") '("admin")) nil
敗因は、組み込み関数の split-string を知らずに手書きし始めてしまったこと。 こんな基本的な操作は提供されてるのが当然ですよね・・・

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)))
日曜の朝からいい運動になりました♪

2009-12-05

「なぜふぉろ」リリース

Twitter をちょっと便利にするサービス「なぜふぉろ」をリリースしました。

  ⇒ 「なぜふぉろ」ホームページ  「なぜふぉろ」アイコン


どんなサービスかというと、ユーザごとのメモを書けるというモノです。

具体的には、Twitter にログインした状態で任意のユーザの
プロフィールページを開いたときに、そのユーザに関する
メモ(テキストのみ)を表示&編集できるようになります。

たとえば、フォロー先を追加するときになんでこの人をフォローしようと
思ったのか理由を書いておいたり、その人の属性(クラスター?)を
メモしておいたりすると、ちょっとだけ便利になるかと思います。

まぁ、Seaoak の記憶力が弱くって100人程度のフォロー先が
すでに把握できなくなりつつあるので作ったんですけどね・・・

もちろん、ローカルのテキストファイルや Excel で管理すれば十分な
気もしますが、Twitter の Web 上で直接メモにアクセスできると
けっこう便利なんじゃないかな、と(自画自賛で)思ってます~



技術的には、Firefox の GreaseMonkey (グリモン)と CGI (Perl) を
連携させて実現しています。グリモンだと Twitter の Web を開いたときに
別のドメインのサーバにもアクセスできるので、CGI との連携が可能になる
わけです。この仕組みはまだいろいろ遊ぶ余地がありそうですね♪



なにはともあれ、使ってみてくれるヒトを絶賛募集中です!
ぜひとも「なぜふぉろ」をお試しくださいませ。

ご要望や不具合報告などあったら、なんでも言ってください。
この記事へのコメントか、または Twitter で @seaoak2003 マデ。


どうぞよろしくおねがいします!

« 2009年11月 | トップページ | 2010年2月 »