]> Panopticon :: 2006年12月 Archive

・読みたい本

  • "The Java Programming Language, Fourth Edition"
  • "Concepts, Techniques, and Models of Computer Programming"
  • "Programming Python"
  • "Python Cookbook"
  • "Mastering Regular Expressions"
  • "UNIX Programming Environment"
  • "Hacker's Delight"
  • 『時間割』 ビュトール
  • 『特性のない男』 ムージル
  • 『石蹴り遊び』 コルタサル

・やりたいこと

  • サイトをいじる(MT, Flash, XML)
  • 情報処理技術者試験テクニカルエンジニアDB, NWを取得
  • フリークライミングに挑戦

いろいろあるけれども、一歩ずつ確実にやっていこう。

進学するのか就職するのか、そろそろ結論を出さなくてはならない。

python1_22_2.jpg

>>> s = "0123456789"
>>> s[ : ]
'0123456789'
>>> s[ 0 : 0 ]
''
>>> s[ 0 : 1 ]
'0'
>>> s[ -10 : -9 ]
'0'
>>> s[ -10 : 1 ]
'0'
>>> s[ -10 : 2 ]
'01'
>>> s[ 0 : len(s) ]
'0123456789'
>>> s[ 0 : len(s) - 1 ]
'012345678'
>>> s[ -len(s) : len(s) ]
'0123456789'

>>> s[ -len(s) : len(s) - 1 ]
'012345678'
>>> s[ len(s) : 0 : -1 ]
'987654321'
>>> s[ : : -1 ]
'9876543210'
>>> s[ len(s) - 1 : len(s) - 2 : -1 ]
'9'
>>> s[ len(s) - 1 : 0 : -1 ]
'987654321'

三つ目のインデックスを負にしたときの挙動がよくわからない。『最初からn文字を逆順で取り出す』といった操作を行うには、『n文字取り出す→逆順にする』とスライシングが二回必要なんだろうか。

>>> s[ 3 : : -1 ]
'3210'

これでいけた。逆順の時はインデックスがひとつずれるのかな。

>>> s[ 0 : : -1 ]
'0'

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

問題の意味がわからない。『入力のn文字目までにある最後の非ブランク文字の後で"折りたたむ"』というのはどいういこっちゃ。

python1_22.jpg
こんな感じになればいいんだろうか?

1.22 in C

#include <stdio.h>
#define BUF_SIZE 1024
#define TURN_SIZE 10

int main(void){
	char s[BUF_SIZE];
	int i, j, len;
	int last, space;

	while (fgets(s,BUF_SIZE,stdin)){
		last = space = 0;
		for (i=0;i < strlen(s);i++){
			if (s[i] == ' ') space++;
			else {
				if (last + space >= TURN_SIZE) {
					putchar('\n');
					last=0;
				} else {
					for (j = 0;j < space;j++){
						putchar(' ');
					}
					last+=space;
				}
				space=0;
				putchar(s[i]);
				last++;
			}
		}
	}
	return 0;
}

1.22 in Python?

def eraceSpace(line):
    i=0
    while line[i] == ' ' and i < len(line)-1: 
        i += 1
    line = line[i:]
    i = len(line)-1
    while line[i] == ' ' and i >= 0:
        i -= 1
    line = line[:i]
    return line

TURNSIZE=10
s=raw_input()
last = 0
space = 0
i = 0
for i in range(0,len(s),TURNSIZE):
    line = s[i:i+TURNSIZE]
    line = eraceSpace(line)
    print line

最初からn文字ずつに区切っちゃえばいいんじゃね?と思ったけどぜんぜん違ったヽ(`Д´)ノ行の頭にくるたびに文字を数えなおさなきゃいけないんだなー。

1.22 in Python

def eraceSpace(line):
    i = len(line)-1
    while i >= 0 and line[i] == ' ':
        i -= 1
    line = line[:i+1]
    return line

TURNSIZE = 10
s = raw_input()
start = 0
last = TURNSIZE
end = len(s)
while start < end:
    line = s[start:last]
    print eraceSpace(line)
    start = last
    while start < end and s[start] == ' ':
        start +=1
    last = start + TURNSIZE

こんな感じ?

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

1.21 in C

#include <stdio.h>
#define BUF_SIZE 1024
#define TAB_SIZE 5

int main(void){
	char s[BUF_SIZE];
	int i, j, len;
	int space=0;

	while (fgets(s,BUF_SIZE,stdin)){
		for (i=0;i < strlen(s);i++){
			if (s[i] == ' '){
				space++;
				if (space == TAB_SIZE){
					putchar('\t');
					space=0;
				}
			}else{
				for(j=0;j<space;j++) putchar(' ');
				space=0;
				putchar(s[i]);
			}
		}

	}
	return 0;
}

1.21 in Python

TABSIZE = 5
s = raw_input()
s = s.replace(' ' * TABSIZE, '\t')
print s

1.20とreplaceの引数を逆にしただけ。

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

K&Rに載ってる問題をPythonでやってみようと思う。PyJUGでやっているのがソフトウェア作法だったのでインスパイヤしました。復習もかねてCでも書いてみる。

1.20 in C

#include <stdio.h>
#define BUF_SIZE 1024
#define TAB_SIZE 5

int main(void){
	char s[BUF_SIZE];
	int i, j, len;

	while (fgets(s, BUF_SIZE,stdin)){
		for (i=0;i < strlen(s);i++){
			if (s[i] == '\t'){
				for(j = 0;j < TAB_SIZE;j++){
					putchar(' ');
				}
			}else{
				putchar(s[i]);
			}
		}
	}
	return 0;
}

getstringはEOFまでの改行を含む文字列の入力を受け取り、その長さを返す。cygwinだと挙動がなんかおかしいぞ、と思って海外のサイトを見ると、EOFを入力するにはCtrl-Dを二回か空白行の頭でCtrl-Dを押せと書いてあった。これは仕様なんだろうか。

1.20 in Python

TABSIZE = 5
s = raw_input()
s = string.replace('\t', ' ' * TABSIZE)
print s

raw_inputを使っているので一行の入力しか受け取れないが、改行が含まれててもreplaceでいけるはず。

ゲーデル、エッシャー、バッハ―あるいは不思議の環 20周年記念版

に行ってきた。

エッシャーの父は5年ほど日本にいたことがあるようで、そのためかエッシャーの作品にはどこか日本的な要素が感じられる。パターンの繰り返しや画面の分割といった手法から、まず思いつくのは俵屋宗達であろう。

今回『夜のローマ』という作品群のなかに、それは表題どおり夜のローマの風景を描いた連作群なのだけれども、真っ黒い樹木が後方からの光で浮かび上がっているという作品があった。これは版画であるから、エッシャーが彫ったのは樹木本体ではなく、背後からの光である。この作品のことは今回展覧会で目にするまで知らなかったが、かなり迫力のある作品だった。俵屋宗達の作品に『雲竜図』というものがある。黒雲のなかを飛ぶ竜を描いた水墨画である。水墨画で白い竜を描くにはどうすればよいか?宗達もまた、雲を描くことで竜を浮かび上がらせようとしたのであった。

僕がエッシャーに魅かれるのは、到達不可能なものに漸近しようとする姿勢である。それは無限であったり、ペンローズの三角であったりする。エッシャーは混沌とした世界の中に秩序を見出さんとして数々の作品を作り上げたが、それらの作品は秩序に到達することの不可能性をもまた示さんとしているように思えてならない。

数々の半現実的、半神話的世界、不思議の環にみちみちた世界、見る者を誘い入れようとしているその世界、それを思いついただけでなく実際に描いたところが、エッシャーの天才である。
――『ゲーデル,エッシャー,バッハ あるいは不思議の環』

image061224.jpg

Score Descriptor Tableによると

・長い聴解文において、情報が繰り返され、解答に必要な情報が話の最初か最後に提示されるときは、話の詳細が理解できる。

ホントおっしゃるとおりです。

モジュールとオブジェクト指向について。
後でまた読もう。

もっと式を入力してみましょう。
『3 + 5』 →( + 3 5 )

scheme1_51.jpg

『4 x 3』 → ( * 4 3 )

scheme1_52.jpg

『4 / 2』 → (/ 4 2)

scheme1_53.jpg

『2 / 4』の場合は(/ 2 4)となります。
足し算の手続き『+』の場合は、( + 2 4 )も( + 4 2 )と順番を変えても一緒ですが、
『/』手続きがとる引数はその順序が決められています。

『√9』 → ( sqrt 9)
『sqrt』はもとから定義されている、引数のルートを計算してくれる手続きです。

scheme1_54.jpg

『 | -3 | 』 → (abs -3)
『abs』は引数の絶対値を返します。

scheme1_55.jpg

ここまででわかるとおり、手続きにはひとつの共通点があります。
それは必ずカッコのなかで先頭にくるということです。
処理系はカッコのなかで先頭に来た要素を手続きとして判断します。
さきほどの入力、( abs 3 )の順序を逆にしてみましょう。

scheme1_56.jpg

『3』という手続きを、『abs』という引数に対して適用しようとしています。
これは、手続きとして『3』をもらったのに、『3』なんて手続き見つからないんですけど……というエラーです。
とりあえずここでは
『カッコの中で最初に来るのは手続き!そのあとに続くのは全部引数!』
と考えてください。
この手続きが先頭にきて、その後に引数を続ける記述方法を前置記法といいます。

初めてのPython 第2版

・ステートメントを式に書き直す

>>> (((True and [0]) or (True and [1])) or [2]) [0]
0
>>> (((False and [0]) or (True and [1])) or [2]) [0]
1
>>> (((False and [0]) or (False and [1])) or [2]) [0]
2

つまりこんな書き方もできると。

def teststate(x,y):
	return ((x and ((y and ['11']) or ['10'])) or ((y and ['01']) or ['00'])) [0]
>>> print teststate(True, True)
11
>>> print teststate(True, False)
10
>>> print teststate(False, True)
01
>>> print teststate(False, False)
00
def exor(x, y):
	return (((x==y) and [False]) or [True]) [0]
>>> print exor(True, True)
False
>>> print exor(True, False)
True
>>> print exor(False, True)
True
>>> print exor(False, False)
False

まあ

def exor(x, y):
	return x!=y

これでいいんだけどね……。

・ディクショナリの更新

for i in D.keys():
×	CD={i : D[i]}
〇	CD[i]=D[i]

ディクショナリに存在しないインデックスを指定すると値が代入される、と。

・リスト内包表記

>>> [x * x for x in range(10)]
[0, 1, 4, 9, 25, 36, 49, 64, 81]

初めてのPython 第2版

defのネストと関数オブジェクトへの代入ってありなんだ。

x = 1
if x == 1:
	def func():
		print 1
else:
	def func():
		print 2
other = func
other()

初めてのPython 第2版

(第二版)を読みながら勉強している。さすがオライリー、という感じで入門書にもかかわらず700Pもある。いまそのうちの200Pちょっとを読んだところで、3部も終わりにさしかかりちょっと楽しくなってきた。冬期休暇中に読み終えられるかな。

今日覚えたこと

>>> range(7)
[0, 1, 2, 3, 4, 5, 6]
>>> 3 in [2, 3, 4]
True
>>> zip(range(3),range(7))
[(0, 0), (1, 1), (2, 2)]

を観てきた。金曜に。主催の岡田利規さんは非常に頭のいい方なのだろうな、と思った。

脚本自体はそれほど深いわけではないのだけれども、それが過剰気味な若者言葉で語られ、異常な身体表現とあわさったとき独特の空間が形成される。筋としては新宿の漫画喫茶で働くフリーターとその周辺の人々の会話という形で進んでいき、そこに非正規就労者の問題なんかが絡められる。フリーターはもちろん、学生や社会人でも、将来に漠とした不安を抱く人には何かしら共感できる内容を含んでいるのではないかと思う。

今回は式を入力してみましょう。
『3 + 5』を計算するには
(+ 3 5)
と入力してエンターします。

scheme1_31.jpg

Schemeの式には基本的に二つのルールがあります。
1. 式は括弧でくくられる。
2. 式は前置記法で書く。

『3 + 5』とは、『3』と『5』を『足す』ことです。
このとき、『足す』を手続き、『3』と『5』を引数(ひきすう)といいます。
手続きを使うことを『適用する』といいます。
『3 + 5』とは、『3』と『5』に対して『足す』手続きを適用することです。
前置記法に関しては次回説明しますが、
ここではとりあえず手続きは引数より前に書かなきゃいけないんだと思ってください。
『3 + 5』の手続きは『+』です。
『+』を前に出して全体を括弧でくくると、
(+ 3 5)
となります。

『+』は2つ以上の引数をとることが出来るため、こんな書き方も出来ます。
これは『3+5+7』と一緒です。

scheme1_32.jpg

引数として変数も使えます。
(define a 2)
(+ a 3)
を評価すると5になります。
『a = 2』のとき、『a + 3』は5だから当たり前ですね。

scheme1_33.jpg

手続きにも名前をつけることが出来ます。
(define b +)
と入力しエンターすると、変数b の矢印は手続き『+』に向きます。

scheme1_34.jpg

手続き『b』は手続き『+』と同じように使えます。

scheme1_35.jpg

さっき定義した変数 aを使うと、

scheme1_36.jpg

手続きはそれ単体では評価することが出来ません。
『b』自体を評価すると、これ手続きですよ~と表示されます。

scheme1_37.jpg

わたしは英語で使ってますが、中身は一緒です。
ウィンドウが二段にわかれているのがわかります。
とりあえず下の段の 『>』 のところをクリックして、キャレット(文字入力カーソル)をもっていきます。

scheme1_21.jpg

まず 『3』 と入力して、エンターキーを押してみましょう。
『3』と二回表示されています。
緑色が入力した文字、青色がDrSchemeが返した文字です。
DrSchemeに 『3』 を渡すと、 『3』 を返してくれるのがわかります。

scheme1_22.jpg

次に『"a"』と入力して、エンターキーを押してみましょう。
『"a"』と二回表示されています。
さきほどと同様に、緑色が入力した文字、青色がDrSchemeが返した文字です。
DrSchemeに 『"a"』 を渡すと、 『"a"』 を返してくれるのがわかります。

scheme1_23.jpg

上で"a"は文字列を意味します。
DrSchemeはダブルクォーテーション"で囲まれたものを文字列として認識します。
では、ダブルクォーテーションを使わず、単に 『a』 と入力するとどうなるでしょう。

scheme1_24.jpg

天道虫と赤い文字が出てきました。エラーです。
『a』 って言われてもわかんないんです><
と言っています。

上の三種類の入力に対して、処理系のなかでいったい何が行われているのでしょう?

Schemeでは、 『3と入力してエンター』 する動作を、 『3』 を 『評価する』 といいます。
同様に、 『"a"と入力してエンター』 する動作を、 『"a"』 を『評価する』といいます。

上の例では 『3』 を評価した結果、青文字で 『3』 と表示されました。
これは、『3を評価した結果は3である』ということです。

また、 『"a"』 を評価すると青文字で 『"a"』 と表示されるのですから、
『"a"を評価した結果は"a"である』ということです。

『評価する』とはいったいどういうことなのか?
上の例では与えられた数字や文字列を鸚鵡返ししただけです。
数字や文字列を『評価する』と、その数字や文字列になります。

上の最後の例はエラーとなってしまいました。
これは『aを評価した結果がエラーである』、
つまり、aを評価しようと思ったけど出来なかったということです。

Schemeでは単に a と入力された場合、aは変数として扱われます。
ここでは 変数 a はなんか標識みたいなものだと思ってください。
標識には意味があります。
たとえば、『↑東京』という標識にそって進んでいけば、まず間違いなく東京に着きます。
同じように、a は矢印をもっています。その矢印の方向へずっと歩いていくと、『2』 という数字がありました。
これは、a は 『2』 を指し示す標識であるということ、つまり、変数 aの値が 『2』 であることを意味します。

エラーが起きた例では、変数 a という矢印はあるけれども、それは何にも指していない、
つまりa が意味のない標識だということです。
単に矢印だけの標識 『↑』 は、それがどこに通じているのかがわからなければ、
標識としては全く意味がありません。
標識に意味を持たせるためには、その矢印がどこを指しているのかしっかり定義してやる必要があります。

変数 aの矢印を数字の『2』に向けるには
(define a 2)
と入力してエンターします。

同じように、変数 bの矢印を文字列の『"a"』に向けるには
(define b "a")
と入力してエンターします。
define a 2
なんてやるとエラーになります。括弧でくくってあげてください。

scheme1_25.jpg

『a』 と 『b』 を評価してみましょう。
処理系は変数 a と b の矢印をたどり、『2』 、『"a"』という数字、文字列をそれぞれ見つけます。

scheme1_26.jpg

情報処理推進機構が行っている、ソフトウェア開発技術者試験の結果が発表されました。春に基本情報技術者を取得してそのまま挑戦。合格率は17.6%と比較的高かったようです。

わたしとしては午後Ⅱがアルゴリズムで助かりました。内部設計は問題文読み違えるとたいへん悲惨なことになるので。

午前は六問ほど間違えているはずですが、IRTのためかスコアにすると満点でした。問題番号で言うと48 49 52 66 76 80。この六問は配点が0なのか、それともスコア800以上はみな800点扱いなのか?どちらにしろ合格ラインは600点なので、午前のための勉強というのはそれほど必要ではなくて、午後で問われる頻度の高い内容をしっかり理解しておくことが重要なんでしょうね。

image061211.jpg

午前用。

平成18年度[秋期] ソフトウェア開発技術者 合格教本 [CD-ROM付き]

午前・午後用。

ソフトウェア開発技術者予想問題集〈2006秋〉

午後用。

合格への総まとめ ソフトウェア開発技術者めざせスコア+100〈2006‐2007〉

アイテックさまさまです。

スタートメニューから起動。インストール時に設定したフォルダに入ってます。

scheme1_10.jpg

少し待ちます。

scheme1_11.jpg

こんな画面になりました。再インストール時には表示されませんでしたが、
初回起動時には初期設定があったかもしれません。以下の内容を読み替えてください。

DrSchemeは、方言も含めて何種類かの言語を扱うことが出来ます。
下のメッセージは、『その言語が指定されてないのでこのままだと動かないですよ~』という意味です。
まず日本語化し、それから言語を設定しましょう。

scheme1_12.jpg

メニューバーのヘルプボタンを押し、『DrSchemeを日本語で使う』

scheme1_13.jpg

何かウィンドウが出てくるので『承認』してください。
いったんDrSchemeが終了します。手動で再起動しましょう。
メッセージが日本語化されています。文字間隔がやたら詰まってて見にくいですが、
さっきのような画面になったら、『言語』ボタン( 『language』ボタン )をクリックし、『言語を選択』してください。

scheme1_14.jpg

PLTの脇の三角をクリックし、Graphicalを選択。
理由はわたしが最初に使ったのがこれだからです。

最上段の『Standard ( R5RS ) 』がSchemeの標準規格です。

scheme1_15.jpg

右上の『実行』ボタンを押してください。下のような画面になりましたか?

scheme1_16.jpg

Schemeで組んだプログラムを動かすためには処理系が必要です。
処理系ってのは人間とPCとの橋渡しをするソフトとでも思ってください。
人間が書いたプログラムをPCに理解できる形に直し、
PCが計算した結果を人間がわかるように表示する役割を持ちます。

ここでは教育機関で広く使われているDrSchemeを使ってみます。

DrSchemeへ移動し、ダウンロードをクリック。

scheme1_1.jpg

OSの種類を選んでダウンロードボタンを押す。

わたしはWindowsXPを使っているのでWindowsで!

256Mのメモリと60MBの容量が必要だと書いてあります。

scheme1_2.jpg

ダウンロード先を選ぶ。MIT(マサチューセッツ工科大学)にはMITSchemeという処理系もあります。こちらのほうが比較的高速なようです。

scheme1_3.gif

こんなファイルが出来ているはずなので実行

scheme1_4.jpg

インストール画面。

scheme1_5.jpg

インストール先を選んで

scheme1_6.jpg

スタートメニューに登録するフォルダ名を決めたらインストール。

scheme1_7.jpg

しばし待つ。

scheme1_8.jpg

続けてDrSchemeを起動しない場合はチェックをはずして下さい。

scheme1_9.jpg

Schemeというのはプログラミング言語の一種なんだけれども、はっきり言ってかなーりマイナーなので仕事でプログラム組んでる人にも知られてなかったりする……。そんなSchemeのすごさをひっそり広めてみる試み。

SchemeはもともとLispから派生したもので、関数型言語のひとつ。関数型言語の仲間のうちでは、LispとHaskellあたりが有名……っていってもたかが知れてるますね。構文が非常に単純なことと、徹底的に抽象化されていることが特徴です。こうした理由から大学の授業なんかでよく使われます。C→Javaとやってきて、オブジェクト指向とかデザインパターンがどーもわかんないんですよって人がたまにいますが、間に関数型言語が挟まればまずそんなことは起きません、たぶん。関数型言語を学ぶと、プログラムの構造に眼を向ける癖がつくからです。

(define (sqrt x)
  (define (improve guess)   
    ((lambda (a b) (/ (+ a b) 2)) guess (/ x guess)))
  (define (sqrt-iter guess guess-p)
    (define (good-enough?) 
      (< (abs (- guess guess-p)) (* guess 0.001)))
    (if (good-enough?)
        guess
        (sqrt-iter (improve guess)
                   guess)))
  (sqrt-iter (improve 1.0) 1.0))

Schemeのプログラムはたとえばこんな感じになります。はじめての人にはどう読んでいいのかすらわからないと思いますが、これはある数の平方根を求めるプログラムです(念のために言っておくと、Schemeには平方根を求める関数は最初から入ってます)。しかしこういう小さい例から初めてだんだん複雑な構造を考えていきましょう、というのがSchemerのバイブル『計算機プログラムの構造と解釈』の教えなので、とっくに誰かが作ってるものであってもどんどん再実装しながら勉強していくのがよいと思います。

上に述べたようにSchemeの実装はコンパクトですが、かなり強力なライブラリ群を持っているため、ちょっとなんか書いてみようかなというレベルならまず不自由なく書けます。そして何より書いてて楽しい!大量の括弧をみて難しそうだなと思う方がよくいるようですが、括弧の対応は機械がとってくれるので、プログラマがやるのは構造をしっかり考えることだけです。

僕の予想では、2008年くらいには関数型言語のブームきちゃうんじゃないのかな?という感じなので、ちょっと触ってみてもいいんじゃないでしょうか。