C

2009年12月 8日 (火)

情報科学苦手の会に参加してきました

今年の情報科学若手の会には参加できなかったので、情報科学苦手の会の方に参加してきました。

幹事のみずしまさん、運営周りをいろいろサポートしていたsyuuさん(ハンドルネーム)、会場提供たけおかさん、その他発表者のみなさん、参加者のみなさん、ありがとうございました。

ボウズマンチョコ

自分はC++が苦手なので、templateでコンパイル時に素数を数え上げるプログラムを作成して自習勉強してみました。苦手な法律の話も勉強したのですが、ピザ到着の時間が近かったので今回は発表をパスさせていただきました。

■ C++テンプレートでコンパイル時に静的に素数を計算する

元ネタ:

  1. C++テンプレートでFizzBuzz - おびなたん☆
  2. Kazuho@Cybozu Labs: C++ テンプレートで(いまさら)FizzBuzz
  3. C++のテンプレートで素数計算 - 西尾泰和のはてなダイアリー

ちょっと古い話題ですが、enumを使うテクニックをherumiさんから教えてもらったので、書いてみました。

#include <stdio.h> 

template<int N, int n=N-1, int m=N%n> struct isPrime {
  enum { ok = isPrime<N, n-1>::ok };
};

template<int N, int n> struct isPrime<N, n, 0> {
  enum { ok = 0 };
};

template<int N> struct isPrime<N, 1, 0> {
  enum { ok = 1 };
};

template<int N> struct printPrime {
  printPrime() {
    printPrime<N-1>();
    isPrime<N>::ok && printf("%d\n", N);
  }
};

template<> struct printPrime<1> {};

int main()
{
  printPrime<MAX>();
}

コンパイルするときに -DMAX=100 のオプションをつけて #define MAX 100 してあげます。

■ 計測スクリプト

さきほどのC++のソースコードを prime.cpp に保存して #define MAX の値を変えて g++ のコンパイル時間を計測してみます。

#!/bin/bash
n="10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200"
for i in $n
do
  echo -n "$i, "
  /usr/bin/time -f "%U" g++ -DMAX=$i prime.cpp
done
■ 実行結果

以下の環境でベンチマークをとってみましたが、MAXの値が大きくなると結構な時間がかかるようです。

Athlon1640B 2.7GHz Memory8GB Ubuntu8.10(AMD64)
  gcc version 4.3.2 (Ubuntu 4.3.2-1ubuntu12)

10, 0.17
20, 0.19
30, 0.23
40, 0.30
50, 0.44
60, 0.60
70, 0.69
80, 0.73
90, 1.17
100, 1.87
110, 2.81
120, 4.00
130, 5.59
140, 7.54
150, 9.97
160, 12.52
170, 16.58
180, 20.55
190, 25.74
200, 32.17

グラフにするとこんな感じになりました。MAX=1000を予想すると絶望的です。

Cpptemplatecompiletime

結論:C++コンパイラは頑張り屋さん

ToDo:もっと早く計算させる方法を勉強する

enum じゃなくって typedef 使えば早くなるのかなぁ。。。

苦手なので誰か教えてください(><)

2007年9月13日 (木)

core dumpするコードの短さを競う「Core Golf」

まめめもさんの core golf のエントリー(6/27)より

さて、core dump するコードの短さで競う core golf はゲームとして成立するでしょうか。明らかに環境や処理系に依存するのでルールの決め方が難しいです。とりあえずうちでは core dump した C のコード (15B) 。もっと短くなる?

core dumpの定義はいろいろあると思いますが、とりあえず手元の環境 CentOS Linux x64_64 で segmentation fault が起きるコードで。

(1) C言語で core dump

早速、core dumpした5byteのCのコード。 (via. λx.x K S K @ はてな - core golf

main;
実行結果
$ echo -n "main;" > a.c && cc a.c && ./a.out 
a.c:1: 警告: データ定義が型や記憶クラスを持っていません
a.c:1:6: 警告: no newline at end of file
zsh: segmentation fault  ./a.out

コンパイラの警告は出るけどちゃんと実行バイナリができて、それを実行するとsegmentation faultしてくれます。

(2) Perlでcore dump

正規表現でsegmentation faultを起こすのが簡単かな、と思ってトライ。Perlで22byte。
(via. [perl #33945] Segmentation fault with deep recursion in regex engine

$x=qr/(??{$x})/;""=~$x
実行結果
$ perl -e'$x=qr/(??{$x})/;""=~$x' 
zsh: segmentation fault  perl -e'$x=qr/(??{$x})/;""=~$x'

barewordを使ってもよければもう1byte節約することができますが、とりあえずここまで。

(3) Rubyでcore dump

ruby-devのMLには、最新のrubyをcore dumpさせるコードがたくさん投稿されているようです。以下、手元の環境で再現した5byteのコードです。
(via. [ruby-dev:31085] 0..:" dumps core

0..:"
実行結果
$ ruby -e '0..:"'
-e:1: unterminated string meets end of file
-e:1: empty symbol literal
-e:1: [BUG] Segmentation fault
ruby 1.8.5 (2006-08-25) [x86_64-linux]

アボートしました

最強言語 Ruby ?

あと、Ruby 1.8系では正常に(?)core dumpできませんが、Ruby 1.9 では 4byte で core dump 可能なコードもいくつか報告されているみたいでした。 もしかしたら最新のリリースビルドでは再現できないかもしれません。

$ ruby -e '$&;[]'
$ ruby -e '$`;0'
$ ruby -e '$1;0'
$ ruby -e '{*0}'

ということで、現在 Ruby 1.9 が 4 byte で Core Golf 最強になっていますが、3 byte 以下で core dumpできる処理系をご存知の方がいらっしゃいましたら教えてください。

2006年1月10日 (火)

C-0.02 バージョンアップ

Kazuho@Cybozu Labs: C-0.02

C-0.02 をリリースします。... このバージョンでは、以下のような機能が追加になりました。 -m オプション: デバッガのサポート: man の追加: #option ディレクティブ ...

ということで、RPMパッケージを更新しました。

Red Hat系Linuxならバージョンアップ一発です。

# rpm -Uvh http://takesako.31tools.com/redhat/RPMS/noarch/C-0.02-0.noarch.rpm

ちなみに、Plamo Linux/Slackware なら rpm2tgz した後に installpkg でインストール
Debian GNU/Linux なら alien で .deb パッケージに変換してインストールすることができるみたいです。

将来のバージョンではコンパイル結果のキャッシングとかができるようになると理想ですね。

■追記(C-0.03 バージョンアップしました)

それでは have fun !

2006年1月 6日 (金)

#!/usr/bin/C でワンライナーを書く

Kazuho@Cybozu Labs: C - a pseudo-interpreter of the C programming language

 Perl や Ruby では、ワンライナーで処理が書けて便利です。でも、なぜか C では書くことができません。仕事上の都合で、小さな処理を C 言語で書く必要があったので、ワンライナーも書くことのできる C 言語のインタプリタ(?)を作ってみました。

面白そうなので、早速RPMパッケージを作ってみました。

Red Hat系Linuxならインストールは以下のコマンド一発です。

# rpm -ivh http://takesako.31tools.com/redhat/RPMS/noarch/C-0.01-0.noarch.rpm

こんなことができるようになります。

[1] C言語でワンライナー:

C -e 'printf("hello world\n");'

[2] shebangでスクリプト実行:

#!/usr/bin/C
printf("hello world\n");

処理させる内容によってはPerlの約100倍早く動作することもあるようです。

半分ジョークプログラムみたいですが、いや、これ、実は結構便利かも。。。

続きを読む "#!/usr/bin/C でワンライナーを書く" »