Best of show

最優秀賞

受賞者:Jari Arkko, Ora Lassila and Esko Nuutila

引用元:https://www.ioccc.org/1989/jar.2.c

審査員・作者による説明:https://github.com/ioccc-src/winner/blob/main/1989/jar.2.hint

動作

Lispインタプリタ。

$ gcc -o jar.2 jar.2.c

$ echo "(+ 1 1") | ./jar.2

$ cat fib.lisp
(defun fib (n)
   (if (< n 2)
       1
       (+ (fib (- n 2)) (fib (- n 1)))))
(fib 10)

$ cat fib.lisp | ./jar.2
89.000000

解説

初の言語処理系作品。1465バイトに次の機能が盛り込まれているとのこと。

	+	-	*	<	()
	car	cdr	cons	defun	equal
	function if	lambda	quote	t

jar.2.hintにかんたんなサンプルコードがいくつか掲載されている。 エラーチェックは非常に甘く、たとえば最初のカッコの前にスペースがあったら動かないとのこと。

形状の意味は特に解説されておらず不明だが、カッコを表現しているだろうか(下のほうがよくわからないが)。 上下に挟まれた行のアルファベットだけ拾い読みするとO B F U S C A T E D L i s pになっている。

,O;}B(F)U S(C(A(T(E)?D:_)));}L(i,s)p

作者のコメントによると、「Lispはコンスセルを基本データとするが、このプログラムはchar*を基本とする」と書かれている。 つまり単なるベタメモリということで、基本的にはただのジョークだと思うけれど、実際、組み込み関数のテーブルは{関数名,関数ポインタをchar*にキャストしたもの}の列となっている(構造体を宣言する必要がなくなるのでコードが小さくなる効果はあると思う)。

オリジナルのソースコードは、グローバル変数の配列が連続領域に確保されていることを前提としている。 p r[4][2]={...};p not[99][2]={...};とう定義に対してr[13]not[9]をアクセスする。 このようにした理由はわからない(特に小さくなるわけでも、レイアウトしやすくなるわけでもないと思うし、notは直接アクセスされていない)。 単に難読化のためだろうか。 このせいで現代のコンパイラで最適化オプション付きでビルドするとsegfaultになって動かないので、ひとつの定義とするように修正をおこなった。

[[1989/jar.1]]と合わせ、同じ年に同じ作者の作品が複数入賞した初の事例。

パッチ

パッチをダウンロード