]> Panopticon :: 2007年1月 Archive

http://www.debian.or.jp/

Xのインストール

# apt-get install x-window-system-core

Xの設定

僕の使っているGeForce6100だとnvドライバが使えないので、とりあえずvesaでごまかす。マウスの設定はカーネル2.6の場合、/dev/input/miceでUSB、PS/2両方いける。

再設定するには

# dpkg-reconfigure xserver-xfree86

Xの起動

# startx

ktermもインストール

# apt-get install kterm
# update-alternatives --config x-terminal-emulator

大学で使ってるktermをX端末にする。

GNOMEのインストール

ついでにフォントもインストール。僕のようにloopbackを削ったりしてなければつまずく所ではない。

# apt-get install gnome ttf-kochi-mincho ttf-kochi-gothic

KDEなんかも入れてる場合は、下のコマンドでデフォルトを設定。

# update-alternatives --config x-session-manager

ディスプレイマネージャ

は使わないことにする。

nvidiaドライバのインストール(1)

# apt-get install nvidia-kernel-source nvidia-kernel-common

カーネルのバージョンを調べる。

# uname -r

カーネルに対応したヘッダをインストール。

# apt-get install kernel-headers-2.6.8-2-386

カーネルソースを解凍。

# /usr/src/
# tar xvfz nvidia-kernel-source.tar.gz

環境変数の設定。

# export KSRC=/usr/src/kernel-headers-2.6.8-2-386
# export KVERS=2.6.8-2-386

コンパイル。

# cd modules
# /nvidia-kernel/debian/rules binary_modules

/usr/src/modules/になんか長い名前のファイルができてるはずなので、それをインストール。

# dpkg -i nvidia-kernel-2.6.8-2-386_1.0.7174-3_i386.deb

GLXを入れる

# apt-get install nvidia-glx

/etc/X11/XF86Config-4を編集。下二行をコメントアウトし、ドライバをnvidiaに変える。

# Load "GLCore"
# Load "dri"

そしてstartx...するとディスプレイが見つからないとエラー。とりあえずvesaに戻す。GLXの確認は、X端末上で。

# glxinfo
...
Segmentation Fault

アレ!?あー、GLXがnvidiaでドライバがvesaだからダメなのかな。当り前か。

nvidiaドライバのインストール(2)

とりあえずnvidiaのサイトにあるドライバを入れ直してみよう...。

# wget http://us.download.nvidia.com/XFree86/Linux-x86/1.0-9746/NVIDIA-Linux-x86-1.0-9746-pkg1.run
# sh NVIDIA-Linux-x86-1.0-9746-pkg1.run

設定画面になったので適当に答えてstartx。なんかnvidiaのでっかいロゴが表示された!

# glxinfo
name of display: :0.0
display: :0  screen: 0
direct rendering: Yes
server glx vendor string: NVIDIA Corporation
server glx version string: 1.4
server glx extensions:
...

キタ!

# glxgears
6686 frames in 5.0 seconds = 1337.200 FPS
7247 frames in 5.0 seconds = 1449.400 FPS
7250 frames in 5.0 seconds = 1450.000 FPS
7208 frames in 5.0 seconds = 1441.600 FPS
7250 frames in 5.0 seconds = 1450.000 FPS

http://www.debian.or.jp/

Kernel2.6をインストール

そのままだと2.4がインストールされるので、CD挿入後のboot画面で:linux26

NICの認識

僕の使っているGbE-PCI2は自動認識してくれなかった。

# /sbin/modprobe via-velocity

/etc/network/interfacesを書き換える

DHCPを使ってる場合は

iface lo inet loopback
auto lo

iface eth0 inet dhcp
auto eth0

loopbackを削ると、名前解決ができないためかgnomeが起動中のスプラッシュスクリーンのまま止まる(バカ)

ネットワーク設定の再起動

/etc/init.d/networking restart

ネットワークの確認

# ifconfig -a

国内FTPサイト一覧を取得

# wget http://www.debian.or.jp/debian-ftp-mirrors-jp

一番近いミラーを探す

# apt-get install netselect
# netselect debian-ftp-mirrors-jp
ミラーによってパッケージの品揃えに差がある。僕はftp1.debian.or.jpを選んだ。

sources.listを取得

# wget http://www.debian.or.jp/apt/sources.list.ftp.ftp1.debian.or.jp

/etc/apt/sources.listへコピー

パッケージリストの更新

# apt-get update
# apt-get upgrade

updateでパッケージリストの更新、upgradeでパッケージ自体のアップグレードが行われるようだ。

先日の作業でXHTML1.0の仕様は満たすことができた。W3CとしてはXHTMLで論理的な構造を、CSSで見た目をデザインしろというスタンスのようで、aタグやimgタグにborder, alignといった属性が含まれているとXHTML1.1でチェックにかけたとき警告が出る。とりあえずborderやalignはフィルタして外してしまおう。alignを取り除いたのはいいが、画像の配置でちょっと迷う。あーCSSでfloat : right とすれば右に寄るのか。bタグなんかもhやstrongタグあたりで置き換えたほうがいいのかな。このへんは地味~に作業して直す。

外見はあれだけどもXHTMLでもCSSでもチェックエラーはでなくなった。Web標準への第一歩を踏み出せたわけだ。今の時点ではblog以外に手をつけていないからまー楽だったが、規模が大きくなるとこれは結構大変だなあ。

Blogのテンプレートをいじってみる。せっかくなのでちゃんと書いたほうがいいのかな?と思って調べてみると、どうやら最近はXHTMLなるものが標準らしい。いままでメモ帳でつくったテキストにプログラムでタグをつけてUpしていたわけですが、それはXHTMLなんて調べもせずにてきとーに作ったしろものだったため、出力されてくるHTML?は本当にただタグがついているだけというもうひどいありさまで、どうせならまだエントリーの少ないうちに全て直してしまったほうがいいだろう、と考えたわけです。

とりあえず間違ってるタグを全部置換するプログラムを10行くらいで書いて、エントリーを通していく。これで大文字で打ってたタグなんかを直して、あとは図書館で借りた本をもとにテンプレートもいじる。とりあえず形がととのってきた!

W3Cでチェックしてみる。

Failed validation, 172 errors

ふー……。

Passed validation

ふー。

次は1.1に直さないとな。

プログラミング言語C ANSI規格準拠

2.6 in C 位置pからはじまるnビットを右端にセット。他はそのまま。

unsigned setbits(unsigned x, int p, int n){
	//return (x & (~0 << n)) | (x >> (p+1-n)) & ~(~0 << n);
	return x^((x^(x >> (p+1-n))) & ~(~0 << n));
}

最下位ビットを0番目とする。

戻り値の論理式は
X & MASK | Y & ~MASK = Y ^ ( (Y ^ X) & MASK )
から。

これは、各ビットに対して
MASK == 1 のとき、Y ^ ( Y ^ X ) = X
MASK == 0 のとき、Y ^ 0 = Y
なので成り立つ。同様にMASKをひっくり返すと

X & ~~MASK | Y & ~MASK = X ^ ( (X ^ Y) & ~MASK )
となる。

2.7 in C 位置pからはじまるnビットを反転。他はそのまま。

unsigned invert(unsigned x, int p, int n){
	return x ^(~(~0 << n ) << p-n+1);
}

反転させたいビットを1にしたマスクを作って、XORをとってやればよい。
たとえば4ビット目から数えて3ビット分のマスクを作る場合、
11111111 全て1のビット列を用意し
11111000 3ビット左シフト
00000111 反転
00011100 4-3+1ビット左シフト
できた!

2.8 in C nビット右へ回転シフト

unsigned rightrot(unsigned x, int n){
	int i = 0;
	unsigned mask = ~(~0U >> 1);
	for (; i<n;i++){
		if(x & 1 == 1){
			x = (x >> 1) | mask;
		} else {
			x = x >> 1;
		}
	}
	return x;
}

語調と独立な実装を考えると、1ビットずつシフトさせる方法しか思いつかなかった。
1ビット回転右シフトするときには、最も右端のビットがぐるっとまわって左端に入る。
つまり最下位ビットが0の場合は普通にシフトすればよく、1となっているときは左端に1をいれてやる。
そのためには最上位ビットのみを1にしたビット列とORをとってやればよい。

ビット演算子はPythonもほぼ一緒みたいなので略。

プログラミング言語C ANSI規格準拠

2.4 in C

#include <stdio.h>

void squeeze(char s1[], char s2[]){
	int i, j, k = 0;
	for ( i = 0; s1[i] != '\0'; i++){
		for (j = 0; s2[j] != '\0'; j++){
			if (s1[i] == s2[j]) break;
		}
		if (s2[j] == '\0') s1[k++] = s1[i];
	}
	s1[k] = '\0';
}
			
int main(void){
	char x[]="fjdfskalfjda";
	char y[]="bcde";
	squeeze(x,y);
	printf("%s",x);
	
	return 0;
}

2.4 in Python

def squeeze(s1,s2):
    return ''.join([((c in s2 and [''])or [c])[0] for c in s1])

x = "abfjdksahfjdas"
y = "abcde"
print squeeze(x,y)

リストを文字のシーケンスに戻すには空列に join してやればよいのか。それにしてもこういうところでしゃれた文字列を思いつけないのが悲しいところだ。

プログラミング言語C ANSI規格準拠

1.24 in C

#include <stdio.h>
#define BUF_SIZE 1024
#define SIZE 128

int sp = 0;
char *stack = NULL;
int ssize = 0;

int is_empty(){
	if (sp == 0){
		return 1;
	} else {
		return 0;
	}
}

void push(char c){
	if ( sp >= ssize){
		stack = realloc(stack,sizeof(char) * (ssize += SIZE));
	}
	stack[sp++] = c;
}

char pop(void){
	if (sp == 0){
		fprintf(stderr,"STACK IS EMPTY");
		exit(0);
	} else {
		return stack[--sp];
	}
}

void spit_stack(){
	int i;
	fprintf(stderr,"%d\n",sp);
	while(!is_empty()){
		fprintf(stderr,"unpaired %c was found\n",pop());
	}
	free(stack);
}

int find_pair(char c){

	char c1,c2;
	if (c == ')') c1 = '(';
	else if (c == '}') c1 = '{';
	else if (c == ']') c1 = '[';

	if (is_empty()) {
		fprintf(stderr,"unpaired %c was found\n",c);
		exit(0);
	} else if ((c2 = pop()) == c1){
		return 1;
	} else {
		fprintf(stderr,"mismatch between %c and %c\n",c2,c);
		exit(0);
	}
}
	
int main(void){
	char s[BUF_SIZE];
	int i, j, len;
	int comment1, comment2, quoted1, quoted2;
	comment1 = comment2 = quoted1 = quoted2 = 0;
	while (fgets(s,BUF_SIZE,stdin)){

		for (i=0;i < strlen(s);i++){
			if (quoted1){
				if (s[i] == '\\') {
					putchar(s[i]);
					putchar(s[++i]);
				} else if (s[i] == '\"'){
					quoted1 = 0;
				}
				putchar(s[i]);
			} else if (quoted2){
				if (s[i] == '\\') {
					putchar(s[i]);
					putchar(s[++i]);
				} else if (s[i] == '\''){
					quoted2 = 0;
				}
				putchar(s[i]);
			} else if(comment1) {
				if (s[i] == '*' && s[i+1] == '/') {
					comment1 = 0;
					i++;
					putchar('\n');
				}
			} else if(comment2) {
				if (s[i] == '\n') {
					comment2 = 0;
					putchar('\n');
				}
			} else {
				if (s[i] == '\"'){
					quoted1 = 1;
					putchar(s[i]);
				} else if (s[i] == '\''){
					quoted2 = 1;
					putchar(s[i]);
				} else if (s[i] == '/') {
					if(s[i+1] == '*') {
						comment1 = 1;
						i++;
					} else if (s[i+1] == '/') {
						comment2 = 1;
						i++;
					} else {
						putchar(s[i]);
					}
				} else if (s[i] == '(' || s[i] == '{' || s[i] == '['){
					push(s[i]);
					putchar(s[i]);
				} else if (s[i] == ')' || s[i] == '}' || s[i] == ']'){
					find_pair(s[i]);
					putchar(s[i]);
				} else {
					putchar(s[i]);
				}
			}
		}
	}
	if (is_empty() == 0){
		spit_stack();
	}
	return 0;
}

こんなのになった。括弧の数の対応だけはとっているが、『基本的な構文エラーのチェック』よりかなり前の段階にいるなあ。Pythonがどうとかいう以前の問題なのでちょっと考えよう。

プログラミング言語C ANSI規格準拠

1.23 in C

#include <stdio.h>
#define BUF_SIZE 1024

int main(void){
	char s[BUF_SIZE];
	int i, j, len;
	int comment1, comment2, quoted1, quoted2;
	comment1 = comment2 = quoted1 = quoted2 = 0;
	while (fgets(s,BUF_SIZE,stdin)){
		for (i = 0; i< strlen(s); i++){
			if (quoted1){
				if (s[i] == '\\') {
					putchar(s[i]);
					putchar(s[++i]);
				} else if (s[i] == '\"'){
					quoted1 = 0;
				}
				putchar(s[i]);
			} else if (quoted2){
				if (s[i] == '\\') {
					putchar(s[i]);
					putchar(s[++i]);
				} else if (s[i] == '\''){
					quoted2 = 0;
				}
				putchar(s[i]);
			} else if(comment1) {
				if (s[i] == '*' && s[i+1] == '/') {
					comment1 = 0;
					i++;
					putchar('\n');
				}
			} else if(comment2) {
				if (s[i] == '\n') {
					comment2 = 0;
					putchar('\n');
				}
			} else {
				if (s[i] == '\"'){
					quoted1 = 1;
					putchar(s[i]);
				} else if (s[i] == '\''){
					quoted2 = 1;
					putchar(s[i]);
				} else if (s[i] == '/') {
					if(s[i+1] == '*') {
						comment1 = 1;
						i++;
					} else if (s[i+1] == '/') {
						comment2 = 1;
						i++;
					} else {
						putchar(s[i]);
					}
				} else {
					putchar(s[i]);
				}
			}
		}

	}
	return 0;
}

1.23 in Python

def linefind(s,t):  #searching symbol "t" expected to be forward of a linefeed
    p = s.find(t)
    eol = s.find('\n')  #if '\n' isn't found, eol = -1
    if eol == -1 or p <= eol:
        return p
    else:
        return -1

def commentDeleter(p):
    quote3 = 0;
    s=''
    i=0
    while(i < len(p)):
        if p[i] == '"':
            t = linefind(p[i+1:],'"')
            if t == -1:         #can't find pairing '"'
                raise 'syntax error ---string must be closed with double quotation'
            else:
                s += p[i:i+t+2] #add "string..."
                i = i + t + 2   #2 means ""itself
        elif p[i] == "'":
            t = linefind(p[i+1:],"'")
            if t == -1:         #can't find pairing "'"
                raise 'syntax error ---string must be closed with quotation'
            else:
                s += p[i:i+t+2] #add 'string...'
                i = i + t + 2   #2 means ''itself
        elif i+2 < len(p) and p[i] == '"' and p[i+1] == '"' and p[i+2] == '"':
            t = p[i+3:].find('"""')
            if t == -1: 
                raise 'syntax error ---string must be closed with """'
            else:
                s += p[i:i+t+6] #add """string..."""
                i = i + t + 6   #6 means ""","""
        elif p[i] == '#':
            t = linefind(p[i+1:],'\n')
            s += '\n'
            i = i + t + 2       #2 means # and '\n'
        else:
            s += p[i]
            i += 1
    return s

Python版はPythonのコメントを削除する……ハズ。findは見つからなかったときNoneではなくて -1 を返すのか。正規表現とか使えばもっとスマートになるんだろうか。

The Java Programming Language (Java Series)

The Java Programming Language, Fourth Editionを読んでいる。

今日印象に残ったフレーズ。

・スタティックメソッドを使ってインスタンスをいじるのは、ゴールデンゲートパークでジョギングしてるやつがぶらさげてるウォークマンのシリアルを変えてくれとウォークマンの工場に言うようなもんだ。

  • どんなものにfinal修飾子をつけるべきか
    • ・値が不変である
    • ・値がオブジェクト(インスタンス)が作られるときに決定されている
    • ・オブジェクト(インスタンス)を生成する際に、その値を求めるのが現実的かつ適切である

この三つ目、フィールドの初期化にコストがかかって、しかもそれがごくまれにしか参照されないときは、その値が必要になってはじめて計算するほうがコストが安い。これを遅延初期化(lazy initialization)と言う、なんてさらっと書いてる。まー当たり前といえば当たり前のことなんだけど。僕がはじめて遅延という概念に出会ったときは結構衝撃を受けた。

やはりいろいろ得るものがありそうだ。

文字列のスライシングについて、ちょっと考えて納得した。

python1_22_3.jpg

s = ' 0123456789 'とすると、こんなデータ構造が作られる。データ構造の上下に振られた添え字はそれぞれスライシングの開始地点、終端地点である。

s[ 0 : 0 ]のとき、開始地点 = 終端地点であるので、スライシングは行われない。

s[ 0 : 3 ]のとき、上の添え字 0 から右下に矢印を伸ばし、データ『 0 』をとってくる。
一番目の添え字に 1 を足し、s[ 1 : 3 ]とする。
上の添え字 1 から右下に矢印を伸ばし、データ『 1 』をとってくる。
一番目の添え字に 1 を足し、s[ 2 : 3 ]とする。
上の添え字 0 から右下に矢印を伸ばし、データ『 2 』をとってくる。
一番目の添え字に 1 を足し、s[ 3 : 3 ]とする。
s[ 3 : 3 ]のとき、開始地点 = 終端地点であるので、スライシングは行われない。

s[ 4 : 7 : 2 ]のとき、上の添え字 4 から右下に矢印を伸ばし、データ『 4 』をとってくる。
一番目の添え字に 2 を足し、s[ 6 : 7 : 2 ]とする。
上の添え字 6 から右下に矢印を伸ばし、データ『 6 』をとってくる。
一番目の添え字に 2 を足し、s[ 8 : 7 : 2 ]とする。
s[ 8 : 7 : 2 ]のとき、開始地点 > 終端地点であるので、スライシングは行われない。

python1_22_4.jpg

s[ 0 : 10 : 3 ] も同じように考えられる。

python1_22_5.jpg

三つ目のインデックスが負のときは終了判定が逆になる。

s[ 1 : 0 : -1 ]のとき、上の添え字 1 から右下に矢印を伸ばし、データ『 1 』をとってくる。
一番目の添え字に -1 を足し、s[ 0 : 0 : -1 ]とする。
s[ 0 : 0 : -1 ]のとき、開始地点 = 終端地点であるので、スライシングは行われない。

s[ 9 : 3 : -2 ]のとき、上の添え字 9 から右下に矢印を伸ばし、データ『 9 』をとってくる。
一番目の添え字に -2 を足し、s[ 7 : 3 : -2 ]とする。
上の添え字 7 から右下に矢印を伸ばし、データ『 7 』をとってくる。
一番目の添え字に -2 を足し、s[ 5 : 3 : -2 ]とする。
上の添え字 5 から右下に矢印を伸ばし、データ『 5 』をとってくる。
一番目の添え字に -2 を足し、s[ 3 : 3 : -2 ]とする。
s[ 3 : 3 : -2 ]のとき、開始地点 = 終端地点であるので、スライシングは行われない。

つまり s[ a : b : c ] を求めるアルゴリズムとしては、
1. A = ' ' とする。
2. 配列の添え字 a , b が有効な範囲にあるか確かめ、範囲を超えていれば境界をその値として振りなおす。
3. c が正のとき、a <= b なら終了、c が負のとき、a => b ならば終了。A を出力する。
4. A += s[ a ]。
5. a += c として、A = A + s[ a : b : c ] を求める。