2010-01-01から1年間の記事一覧

cxr, cxxr, cxxxr, cxxxxr の読み方

ずっと謎だった caar、 cadr、あるいはそれ以上に長いやつの発音が、この本の48ページ目(まえがきを入れると60ページ目)に書いてあった。 cadr はずっとカダーと読んでいたけど、正しくはキャットみたいにキャダーと読むべきなのか。まあ英語だとそうなる…

カリー化するマクロ

Paul Graham が開発したことで有名な Lisp 方言の Arc では、複合データを関数のように扱うことができるらしい。たとえば変数 s に文字列が入っていれば、(s 1) で1文字目を返す、とか。意味論的にどうなのかはともかく、いちいち (char s 1) と書きたくな…

let it B

CL-USER> (let ((it 'b 'e)) it) B なんてこった。

イテレータ生成メソッドと複合イテレータ

イテレータ・クラスのオブジェクトを作る、というのもやってみたけど、どうも無駄に仕様が大きくなっていくだけな気がしてすっきりしない。結局、Gauche が採用しているように関数オブジェクトで返すのが一番自由を感じられて良いのかな、と。それらを格納す…

代入マクロを書くマクロ

Common Lisp では、代入先の「変数」がシンボルであるとは限らないため、一般の代入マクロを書くには get-setf-expansion を使って情報を展開する必要がある。これを毎回やるのは面倒なので、マクロに肩代わりさせよう。 _f は『On Lisp』にあったものに少し…

継続による非決定計算の実装

SICP を読んでいる今日この頃だが、Ruby でも継続が使えると知って、実際にやってみた。処理系は Windows の ActiveScriptRuby 1.8.7。最後に触ったの、いつだっけ……。そもそも今回のプログラムを書くために Ruby の文法を1日かけて復習しなければならなか…

制約関数

Prolog みたいに逆算できる関数というのを作ってみた。 引数のうちクエスチョンマークが置かれた部分の値を求める。すべての引数が数値で与えられたときは真偽を返す述語となる。 コード: (defparameter ? (gensym)) (defun ?-test (exp) (if (consp exp) `…

Common Lisp で遅延評価(part 2/2)

Common Lisp で遅延評価をやってみようという話の続き。1度ミスで消してしまって心が折れかけたよ。 さて、『計算機プログラムの構造と解釈』(SICP)にある、遅延ストリームで冪(べき)級数を扱ったりそれを微積分したりするという問題を解く。以下のコー…

Common Lisp で遅延評価(part 1/2)

『計算機プログラムの構造と解釈』(SICP)を読んでいる。いま Scheme インタプリタ再構築の章。近いうち、Common Lisp の上に実装して遊びたい。 今日の記事は、遅延評価を Common Lisp でやってみた、という話。delay & force も、マクロにかかればイチコ…

簡単な文脈自由言語パーサ&コンバータ

文脈自由言語を解釈して Lisp の式に直す、簡単なパーサとコンバータを作ってみた。きっかけは以下の記事。 最高にキモい Lisp コードを書いてみよう with 100 行リーダーマクロ(LISPMEMO) 自分でもできるんじゃないかと思ってやってみたら一応できた、とい…

リード・マクロ遊び

まずは否定関数の生成。 (defun |#~-reader| (stream subchar numarg) (declare (ignore subchar numarg)) `(complement #',(read stream t nil t))) (set-dispatch-macro-character #\# #\~ #'|#~-reader|) CL-USER> #~oddp #<Closure (:INTERNAL COMPLEMENT 0) @ #x2085f112> CL-USER> (funcall #~oddp 2) </closure>…

重複のあるオブジェクトを抜き出す関数

「重複を取り除くとか。」(http://d.hatena.ne.jp/narumij/20100603/1275527119) 重複のあるオブジェクトをそれぞれ1つずつ抜き出す関数。 やってみた! コード: (defun overlap (list &optional (test #'eql)) (labels ((rec (ls acc) (if (cdr ls) (if…

cl-ppcre と Allegro CL で、正規表現ツリーの出力が違った

題名のとおり。文字列で表された正規表現パターンをパースしてツリーにする関数がどちらにもあるのだが、まったく同じ出力をするのかと思っていたらこんな違いが。 CL-USER> (parse-string "ab") ; cl-ppcre "ab" CL-USER> (parse-re "ab") ; Allegro CL (:S…

文字列の中で式を評価、展開するリーダ・マクロ

Gauche では、Perl や Ruby と同じように、文字列の中で式を展開することができるらしい。 →文字列の補間(Gauche ユーザリファレンス) そこで、似たようなものを Common Lisp でやってみた。 コード: (defun concat-chars (ls) (if (null ls) nil (let ((…

loop マクロの変数キャプチャもどき

つい昨日知った機能。loop マクロの if, when, while では、テスト部分の値を it で参照できる。 この it は変数ではなく、あくまでも collect などと同じキーワードであるため、剥き出しで使わないと効果はない。 CL-USER> (defun trues (fn ls) (loop for …

行列式を掃き出し法で計算する関数

そういえば行列計算は基本中の基本なのにやってなかったな、というわけで、行列式を計算する関数を作ってみた。 計算方法は、線型代数の入門で学ぶものをそのまま使っている。行列式の絶対値を変えない基本変形(ここでは行のみの変形、つまり基本行列を左か…

後置演算マクロを定義するマクロ

後置インクリメントのような演算をマクロとして手軽に定義できるようにする、メタ・マクロ。 使い方は、3つの引数(定義するマクロ名、使用する演算名、第2オペランドのデフォルト値)を渡すだけ。演算名は単に貼り付けられるだけなので、マクロやラムダ式…

宣教師と人食い人の川渡りパズル

宣教師と人食い人の集団が川を渡ろうとしている。定員の決まっている舟を一艘だけ使える。岸でも舟の上でも、人食い人の数が宣教師の数を上回ってはいけない。さて、どうするか。 (cross m c b) で、m 人の宣教師と c 人の人食い人が定員 b 人の舟で渡る場合…

文字列をラクダ記法に変える関数と、そのためのユーティリティ

正規表現を使わないで書いたので、楽をするため、区切り文字列の判定は1文字のみ対応。デフォルトで lowerCamelCase になるのは私の都合。 position-all で区切り文字の位置をすべて求め、sequence-parts で部分列に分け、nstring-capitalize でそれぞれの…

麻雀の手牌が入力として与えられたとき、「待ち」を出力するプログラム

あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定 ↑で出題されていた問題を Common Lisp で解いてみた。 最初の関数3つはユーティリティ。名前の通りで、条件を満たす要素すべての位置をリストにしたり、添字リストで nth して集めたり、…

16x16でお手軽ロゴ制作

はてラボの16x16というサービスでロゴを作ってみた。さっそくブログのアイコンに使っています。Pの存在感のなさといったらもう。LSIのページじゃないよ!

迷路を解くアルゴリズム(改)

前回の迷路を解くアルゴリズムがほとんどCみたいで気にくわなかったので、より Common Lisp らしくなるよう書き換えてみた。 前と違って迷路内の点をそのまま (i j) という座標リストで表している。ユーティリティの裏に隠してあるので、意識する必要はない…

迷路を解くアルゴリズム

Common Lisp で書いてみた。 人材獲得作戦・4 試験問題ほか(http://okajima.air-nifty.com/b/2010/01/post-abc6.html) でもメモリ確保が簡単にできるということ以外は、ほとんどCで書くのと同じに……。 まず file-to-matrix でファイルから文字を読み取り…

ヒープによる優先度付きキュー(priority queue)

ちょっと思うところあって、優先度付きキューをヒープで書いてみた。ただし実体はクロージャ。引数なしで呼ぶとデキュー、引数を受け取るとエンキューするという単純なもの。 キューを作るためには、初期要素となる配列(未整列で良い)と順序関数を与える。…

ビット単位の入出力マクロ

ファイルの圧縮や展開をするときなど、ビットごとの入出力をしたいことは多い。そのためのマクロ。 with-gensyms は超有名ユーティリティ。 do-bits は do-list などと同じ使い方をする。変数名と入力用ストリーム(byte 系)を受け取って、ビットを順に変数…

リストで挿入ソート

リストって挿入に強いよな、と思って挿入ソートを書いてみた。速度重視で破壊的(rplacd とか久々に使ったよ)なのに再帰を使っているという矛盾。一応、リストの長さが10ぐらいまでなら組み込み関数の sort に勝っていた。100でやったらもちろん余裕で負け…

JavaScript はじめました

昨日から JavaScript を勉強しはじめた。文法はひととおり学んだけれど、やはり HTML と組み合わせてこそだよな、という物足りない気分。あと、リスト・ユーティリティを充実させると Ruby っぽくなるな、とか。 とりあえず、知ってる知識だけでリストを書い…

ツリーのイテレータ(幅優先)

このまえ深さ優先のトラバースを書いたので、今回は幅優先で。キューを使うので一手間ある。 コード: (defun make-queue () (list nil)) (defun enque (q x) (if (car q) (setf (cdr q) (setf (cddr q) (list x))) (setf (car q) (setf (cdr q) (list x))))…

関数のように振る舞うシーケンスをマクロで

arc という Lisp の方言では、シーケンスが関数のように振る舞うらしい。つまり s にシーケンスが束縛されているとすると、(s n) が Common Lisp における (elt s n) のようになる。 というわけで、同じことを Common Lisp でやってみた。 with-sequence は…

更新されない定数リストの落とし穴

この前、マスターマインドのプログラムを書いたときに遭遇したこと。 以下の関数 random-digits は、与えられた引数を長さとする数字の順列をひとつ返す。ただしバグあり。 CL-USER> (defun random-digits (num) ; wrong (do ((digits '(0 1 2 3 4 5 6 7 8 9…