ブログトップ 記事一覧 ログイン 無料ブログ開設

Game Scripting Memo このページをアンテナに追加 RSSフィード

2007-08-04

LL魂

Lightweight Language のイベント「LL魂」に行ってまいりました。毎年名前が違うという変なイベントです。前から興味はあったのですが、ようやく今年、初めて参加できました。

会場は神保町の日本教育会館一ツ橋ホールでした。プログラミング言語の有料イベント(3500円)で、900人近く入る会場がそれなりに埋まるというのがびっくりですね。LLのユーザ層の意識の高さというか、ハッカー気質への共感度が伺えます。

内容は、思っていたよりは普通でした(去年の映像のインパクトが強すぎたという話があり)が、充分に楽しむことができました。自分向けのメモを順不同に:

  • 基調講演は和田先生でしたが、相変わらず味のあるお話でした。hacker とは自ら名乗るよりも他人からそう呼ばれるほうがよい、という hacker 辞典の言葉にはなるほどと感心。円盤と円盤で積分ができるというのにも驚きました。それにしても、楕円を書くコンパスの PostScript ファイルのソースが見てみたかったですね。(和田先生は PostScript をプログラミング言語として使いこなす hacker として有名です)
  • Lua は少しアピールに失敗したかもしれませんね。Lua の唯一にして最大の特長はコンパクトである、ということなのですが、それがいかに重要か、というのが客席に伝わらなかったのではないかと思います。アプリにスクリプトエンジンを組み込む場合、メモリが非常に貴重な環境では、Python や Ruby は使用メモリ量が大きすぎて選択肢に入りません。それに比べて、Lua はスクリプトとしてサポートして欲しい機能を適切に備えつつも、コードもメモリ使用量もコンパクトで、移植性も高い(ANSI C で書かれ、トリッキーなコードも含まれていない)という、組み込みアプリに組み込み可能なオンリーワンのスクリプト言語なのです。Squirrel というライバルも出てきてはいますが、実績などを考えるとまだまだ Lua が強いですね。
  • Io は面白い言語ですけれども、言語仕様の安定性や、そもそも利用者の学習コストを考えると、やはり製品に組み込むという用途では難しいですよね……。
  • Xtal はゲーム組み込みが最初からターゲットになっているスクリプト言語です。GC で止まらないように設計され、Lua5.1 と同等の速さがあり、Luabind と同等のC/C++とのバインディング機能を有し、例外や名前付き引数など Lua よりモダンな言語機能も持っている素晴らしい言語です。しかし、C++ で書いているためかメモリ使用量が多めなのが玉に瑕。メモリ使用量削減は今後のテーマに。とりあえずは今年中に出るという1.0のリリースを楽しみに。
  • プログラミング言語を作る: 独自のスクリプト言語を実際に作りながら方法を解説するページがあると始めて知りました。
  • Coq が市民権を得つつあるかもしれない?という状況に戦慄。……hatena の自動トラバ機能でトラバが飛んでいってしまったようです。失礼しました orz
  • 最近話題の http://ja.doukaku.org/ は素敵なサイトだと思います。

難読 FizzBuzz: N進カウンタ篇

LL魂にて、にしおくんの顔を見ていたら、無性に難読 FizzBuzzを超えてみたくなってしまったので、以前ベッドの中でちらっと思いついたアイデアを休み時間中に実装してみました。

FizzBuzz とは何か、については→ どうしてプログラマに・・・プログラムが書けないのか?

#!/bin/env perl

my $bits = 0;

for ( my $i = 1; $i < 100; $i++ )
{
    my $tmp = $bits & 0x1b;
    $tmp |= $tmp >> 1;
    $tmp |= $tmp >> 1;

    $bits <<= 1;
    $bits &= 0x1b;
    $bits |= (~$tmp) & 0x05;

    if    ($bits == 0)          { print "FizzBuzz\n"; }
    elsif (($bits & 0x03) == 0) { print "Fizz\n"; }
    elsif (($bits & 0x1c) == 0) { print "Buzz\n"; }
    else                        { print "$i\n"; }
}

ソースコードから意味を追うのはかなりたいへんだと思いますが、原理は簡単です。

1周期+αの $bits の値を2進で出力すると:

00101
01110
11000
10001
00010
00100
01101
11010
10000
00001
00110
01100
11001
10010
00000
00101

これを見ると、最下位2bitが 00->01->10->00 を、その上3bitが 000->001->011->110->100->000 を繰り返していることが分かります。Q.E.D.

発想元は、フリップフロップの組み合わせで3進カウンタと5進カウンタを作る、というただそれだけです。実際、TTL で組む場合は、FFが5個と、NOR2個で構成でき、Fizz信号とBuzz信号を取り出すのにそれぞれNOR2個で済むかと思います。

論理回路はけっこう綺麗になりましたので、本当はプログラムのほうも論理演算をあと1〜2個は減らせると思っていたのですが、1時間仕事としては僕にはこのくらいが限界でした……。挑戦すればもう少し綺麗にかけるかもしれません。

Cで書けば、論理演算や代入の合間にシフトがおまけでできる ARM みたいな CPU では、それなりに少ないステップで実行できるはず。

某学科のCPU演習はこんなところでも役立つ、ということで(笑)

ちょっとだけ補足

いくらなんでも説明をはしょりすぎな気もしますので、ポイントだけ補足を。最下位ビットを b0 と呼ぶことにします。

1ステップで $bits に対して以下の操作を並行に行いたい。

b0 = b0 nor b1
b1 = b0
b2 = b3 nor b4
b3 = b2
b4 = b3

nor を計算している部分の肝が以下:

    my $tmp = $bits & 0x1b;
    $tmp |= $tmp >> 1;
    $tmp |= $tmp >> 1;

下の2行により、$tmp は、b0 = b0 | b1 | b2 に、b2 = b2 | b3 | b4 にそれぞれなります。が、b2 はその前にマスクされており 0 であることが保障されていますので、結局 b0 = b0 | b1 に、b2 = b3 | b4 になります。この演算結果の b0 と b2 だけをマスクして、あとで $bits の同じ位置にセットしてます。

ちなみに、Fizz = b0 nor b1, Buzz = b2 nor b4 で得られます。