多分表示されてる頃にはロード済みでしょうから…もう遅いですが, 本日の日記はとてつもなく重いです
登場人物(全員IS2003er)
- Sacred Fox(以下Sとすると下とかぶるので…F)
このというよりサイト日記の管理人
2-3木の課題は終わっているのにふらふらとJ21に出没する輩
- 新堂翼嬢(以下S)
このサイトで本当によくネタにしやすいので…もっともよく弄られているIS日記Writerの1人
最近のプログラミング能力のただし, 『聖狐の主観で』です成長は著しい
2-3木の課題を早期から手をつけていたので実質2週間の期間で既に完成させている
ここでの記録はFの視点に基づいているので彼女の日記を見ると全然違うように書かれているかもなぜかどちらかが日記に書いた出来事はもう片方の日記には全く書かれていない事が多い知れない
- K氏
他のIS日記の中にも時たま現れている人, ただしあだ名からすぐに実名へと直結しやすいのであえてイニシャル使用
2-3木の挑戦は本日で5日目らしい
何と本日はといっても閉館までしっかりと居た, でも来る方は上手く時間をやりくりして早めにしたらしいバイトの間を縫っての参戦らしい
- M嬢
こちらは他のIS日記にはそれほど現れていないと思われている
IS2003にとってあ, 新堂さんもそうだった(←joke)数少ない女性
2-3木は今日が2日目という恐ろしいお方
ただしこの他にもISerは本日のJ21二出現しているが, 1人確認, 記憶の奥底に名前の記憶があったが, 他に聖狐が気付いてもいない人がいると困るのであえてこうさせて頂く, 申し訳ないです名前がピンと出てこない人や, なんだかんだ言ってnvaca氏のことです, 本日2回出没簡単に2-3木など終えてしまう事が出来るような人だったりと, この物語の大筋には影響がないので省略♥させて頂きます
概要
一部日記(特にROPPY氏や新堂嬢のもの)では『兄さん木』とか『アニキ』とか言われていたり…2-3木のアルゴリズムとデータ構造演習, 期間は4週間, 内容は『2-3木を実装せよ』という至極単純明快なもの課題の火曜日のAM0:00ということでいいのだろうか…〆切を日曜日, 安息日などでは決してない模様本日終わらせてしまおうという意思の元に行われた修羅場劇
日誌本文
- F, 何故か12:05頃J21に流れ着く, Italkというシステム上で動作しているもの, サーバはとし氏の提供ISのChatにROPPY氏が居ることを発見, Chatしながら日記やポケモンやファルコムの家にnet環境(←『.net』ではなくインターネットそのもの)がないのでこれらは情報棟での作業となる, この日記のUPも同様ページを巡礼
今日はSchemeの第6回課題の成績評価範囲外の問題, インタプリタを2重に噛ませて体感速度差を測るというもの最後の問題をやろうかなと思って来る
しかしそれは家でも出来るものなので実際は暇つぶしに来ているというほうが正しい
しかもここに来るために多少問題かもしれないが, 適当に理由(とりあえず駒場に行かなければならない)をつけて正当化済み(爆)寮行事を多少サボっている
- M, 以降時間感覚がかなり麻痺しているので嘘があるかもしれない1:00頃到着, 早速2-3木を始める
FがChatでROPPY氏に報告すると『撃墜は任せた』との密命が下る, 当然了承
- S, その後しばらくして到着, 本日はScheme第6回課題の問2(新堂さんは何だかとてつもない読みをしておられたようだが気にしないでおこうλ-closureの表示処理)を終わらせるつもりだったらしい
『すぐに』の間違いかもしばらくするとSがMの撃墜を始める
さすがに2週間かけて2-3木をやった年季は違う, 陥りうるミスの全てに陥ってきた経験から適切に撃墜していっている
とりあえず教科書プログラムの実装の詳細にはそれほど詳しくないFは戦線離脱
- K, 到着, 早速2-3木を始める
FはMの撃墜をSに任せてKの撃墜作業を開始する
結局FもSも本日はSchemeをやる暇がなかった
- K(with F), 時系列(出来事の順番)以外は殆ど嘘4:30頃, 修羅指数を上昇させながらもDeleteの実装を何とか完了…したようだった
実はDeleteの動作不良は殆どここから来る, これが起こるとデバッグはかなりの修羅場と化すInsertの実装にバグがあったりとかなり振り回された
実装終了後は, もしかしたら30かも20個ぐらい在ったデバッグ用printfの除去作業に入る, FがSegmentation Fault対策で異常のあるTreeを検出した時にStderrにメッセージを送って停止するというものかなりややこしいデバッグコードを入れていたので除去に苦労した模様, お疲れ様です
この後, 聖狐は既に終わっているものだと勘違いしていたMemberの実装を始める, 再帰のやり方などの細かな表現ミスに振り回されるものの, 30分ほどで実装完了, 晴れて完成
- F, しばし休憩ののちにMの撃墜に参加, この時点でMのプログラムを主に編集していたのは実はSだったりする, 実はSに撃墜王の才覚ありかと思う
しかしそのSを横から『そこQuote忘れている』, 『そこSemicolonがない』といった単純なミスが連発, ご愁傷様次々に撃墜するF, どうやら互いに駄目出し出来る人間の集合撃墜の同値類は[M]←S←[F]といったところ, [ ]は同値類の記号, 新堂さんに今のところ同値な人はいない半順序関係のようだ
- F, Sに代わって色々とデバッグ手法を試してみる
途中経過はあまり良く理解していなかったが, こちらもInsertのバグの所為でDeleteに失敗する模様, 実はミスの半数はポインタ渡しと値渡しの混乱, 場合分けの不備Kと同等のものだったりしたので割と効率良くデバッグできる
こちらはMemberの実装が終わっているかどうかは分からないが, 時間切れになったのでここで終了, Deleteのバグも取れたのでたとえMemberが残っていたとしても明日までには提出できる模様, 安心
退館音楽が『初めて』と『始めて』の使い分け流れ始めて初めて気がついたのだが, ここで5時45分, 3時ごろかと思っていたFが居たりする
- F, このサイトのログを回収したりIS-Chatを切断したりとこの時間になってから色々と動き出す
- 4人揃って2-3木の(Core部分の)実装が完了したので退館と相成ったわけである
結局あまりあの場の修羅場感が伝わらない文章となってしまった
多分その辺はあくまでも彼女がこのことを書いていたらの話だが…新堂さんの日記を見れば分かると思うのでそっちを参照してください
こっちではその代わりに今回使った多数のデバッグ方法を書き記しておきます
コンパイルエラーについては今回は対象外ですデバッグの時の参考にどうぞ
- printf法
Segmentation Faultや操作者が不細工だと出るエラーというわけではないBus Errorなどの途中でのメモリ違反による強制終了がかかった時の対処方法
怪しいところにとことん『printf("Something\n");』といった文を挿入して何処まで実行されているかを調べる
表示文字列に改行が入っていないと実際に画面に反映(表示)されず出力Bufferがフラッシュされずにエラーによってバッファが失われることもあるので注意
今日知ったことだが出力BufferがOverflowしてもSegmentation Faultになるようです
この方法はさらにバグの原因個所の追及で分岐等の実行経路の確認や変数の推移の確認などいろいろな用途につかえる基本技です
- 乱数代入
色々な場合の分岐をくまなく調べたい時にある程度有効な方法
printf法と併用する場合には得られた乱数を実際に表示しておくと便利
2-3木など入れた構造と同じ物を削除する場合には乱数を配列に格納してから利用すればよい
実行毎に違う乱数を入れたい場合は『srand(time(NULL));』とすればよい(便利関数は大抵この中, mallocもこの中ですよ~<stdlib.h>とこの用途以外に使うのをあまり見かけない…<time.h>が必要)
- 出力保存
実行時に『./a.out > test』といったように画面出力をテキストとして保存すると長い表示結果がスクロールアウトで失われることなくEmacs上で全部見られるので便利
基本的には前述のprintf法による分岐, 変数表示と併用することになる
但しSegmentation Faultのような途中停止のエラーがあると上手くいかないこともある
その場合は次の方法も併用するとよい
if分岐の中に入れるときには{ }で囲って単文を複文にしてifの構造が壊れないように注意する必要がある
- stderr & exit(0)
出力保存する際に途中停止を起こしたくない時に利用, 但し途中停止が怒る前の『前触れ』をみて強制終了させる方法なので万能とはいえないのが玉に瑕
今回の場合は2-3木の節点が1つになっても処理されていなかった時にツリーの表示を行った場合に停止するように設計
基本的な方法は簡単で問題があるかどうかの条件分岐に引っかかった時に標準エラー出力, 『>』や『|』を使っていても常に画面に表示されるという特徴をもつ, コンパイルエラーの一覧もこれなので保存できない(涙)Stderrに何かを表示して(見かけ上)正常終了するコードを書けばよい
実際には『fprintf(stderr, "Something is wrong!!"); exit(0);』といったコードを問題個所に挿入すればよい
これでこのエラーメッセージだけが常に画面に表示されるようになった
この方法は異常検出時点から実際のエラーまでの間を実行しないのでこのために多少プログラムを書き換えたりするので後片付けが面倒に…異常検出ポイントをいかに後ろに持ってくるかも鍵となるだろう
因みにこれをやるにはprintfに必要なので最初からincludeしているかと<stdio.h>とmallocやrand, srandに必要だったはず<stdlib.h>が多分必要
この2つは何を作るにも画面出力やメモリ確保をしないプログラムはそうはないだろうから…取り敢えずincludeしておいたほうが良いかと思われる
- 実行メモ, 手実行によるシミュレーション
エラーを理解することも時には必要
エラーが起こったら取り敢えずprintf結果等からどのようなルートでプログラムが実行されたかを調べて実際に図を書いてみたり手で設計的, 『こう動いてほしいという幻想』アルゴリズム的実行と『そこに立ちはだかる現実』プログラム的実行を手でやってみたり追跡したりして比較するなど, 要根性の力強い方法
- srand操作
乱数代入法においてデバッグ後の入力データに再現性を持たせたいときに有効
擬似乱数はSeedが同じ時には同じ結果を返すという特徴があるのであえて時間とは関係のないsrandを実行することによってデータを用意する
但し, サンプルの変更は手動になるので注意
具体的には敢えてsrandしないとか『srand(サンプルを換えたい時にはここの数字をかえてコンパイルしなおす50);』といった文を『srand(time(NULL));』の代わりに入れておくとかである
呼び出すゲームのルーチン等条件によって乱数を呼んだり呼ばなかったり…乱数の数が動的に変わるときは1箇所修正するごとに変更箇所までは入力とかが一緒なら変化しない変更箇所以降のサンプルが変化してしまう可能性があるのでこれも注意, データ構造のテストなど乱数を限定用途でしか使わない場合に有効かも
こんな感じである
他にも有効な方法があったら何らかの方法で公開していただけるとIS2003er的には助かります
特に上で書いたことに対する間違いの指摘等のこと撃墜はJAROではなく聖狐本人に伝わる方法(メールとか)でお願いします