]>
# apt-get install x-window-system-core
僕の使っているGeForce6100だとnvドライバが使えないので、とりあえずvesaでごまかす。マウスの設定はカーネル2.6の場合、/dev/input/miceでUSB、PS/2両方いける。
再設定するには
# dpkg-reconfigure xserver-xfree86
# startx
# apt-get install kterm # update-alternatives --config x-terminal-emulator
大学で使ってるktermをX端末にする。
ついでにフォントもインストール。僕のようにloopbackを削ったりしてなければつまずく所ではない。
# apt-get install gnome ttf-kochi-mincho ttf-kochi-gothic
KDEなんかも入れてる場合は、下のコマンドでデフォルトを設定。
# update-alternatives --config x-session-manager
は使わないことにする。
# 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
# 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のサイトにあるドライバを入れ直してみよう...。
# 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
そのままだと2.4がインストールされるので、CD挿入後のboot画面で:linux26
僕の使っているGbE-PCI2は自動認識してくれなかった。
# /sbin/modprobe via-velocity
DHCPを使ってる場合は
iface lo inet loopback auto lo iface eth0 inet dhcp auto eth0
loopbackを削ると、名前解決ができないためかgnomeが起動中のスプラッシュスクリーンのまま止まる(バカ)
/etc/init.d/networking restart
# ifconfig -a
# wget http://www.debian.or.jp/debian-ftp-mirrors-jp
# apt-get install netselect # netselect debian-ftp-mirrors-jpミラーによってパッケージの品揃えに差がある。僕はftp1.debian.or.jpを選んだ。
# 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でチェックしてみる。
![]()
ふー……。
![]()
ふー。
次は1.1に直さないとな。
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 )
となる。
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ビット左シフト
できた!
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もほぼ一緒みたいなので略。
#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;
}
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 してやればよいのか。それにしてもこういうところでしゃれた文字列を思いつけないのが悲しいところだ。
#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がどうとかいう以前の問題なのでちょっと考えよう。
#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;
}
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, Fourth Editionを読んでいる。
今日印象に残ったフレーズ。・スタティックメソッドを使ってインスタンスをいじるのは、ゴールデンゲートパークでジョギングしてるやつがぶらさげてるウォークマンのシリアルを変えてくれとウォークマンの工場に言うようなもんだ。
この三つ目、フィールドの初期化にコストがかかって、しかもそれがごくまれにしか参照されないときは、その値が必要になってはじめて計算するほうがコストが安い。これを遅延初期化(lazy initialization)と言う、なんてさらっと書いてる。まー当たり前といえば当たり前のことなんだけど。僕がはじめて遅延という概念に出会ったときは結構衝撃を受けた。
やはりいろいろ得るものがありそうだ。
文字列のスライシングについて、ちょっと考えて納得した。
![]()
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 ]のとき、開始地点 > 終端地点であるので、スライシングは行われない。
![]()
s[ 0 : 10 : 3 ] も同じように考えられる。
![]()
三つ目のインデックスが負のときは終了判定が逆になる。
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 ] を求める。