ワールドカップの観客数は2,705,197人。 日本で売り切れたチケットに対して、空席が93,000席あった。 とメモしておこう。
TVを全部デジタル化するというのだが、 2008年頃にBSアナログ放送を停止するってマジ?
どこかにも書いたけど、 TVは現状のままでオッケーで、 インターネットを使ったデジタル有線放送に移行するのがいいんじゃないか、 とか思うのだが。
他でそんなの見たことないな。 もしかして、私だけか、インターネットTVに期待しているのは。
§
アメリカでアーミッシュの馬車に車が追突して子供が2人死んだ、 というニュースが出ていたが、 アーミッシュって何だろ? キリスト教系らしいのだが、 夜間追突防止用の反射板を宗教上の理由で拒否しているというのだが、 そこが分からない。 そんな制限ってキリスト教にあったっけ?
松下電器が「福祉年金制度」の利率を下げると発表したために、 元社員が怒っているというニュースがあった。 社員側の主張。 高利(7.5%)の運用だからというので早期退職に賛成したのに、 退社したら利率を下げるというのはだまし討ちだ。 会社の主張。 利下げの可能性は規定に書いてある。 何も問題ない。
問題は利下げの可能性を説明したかどうか、ですか。 説明がなかったとすれば、 クーリングオフ…じゃないな、何だろ?
いずれにしても、正直言って「ふーん、大企業なんだな」って感じ。
ワン切りの経験者が20〜40代の携帯電話でインターネット契約している人の92%だというレポートがあったのだが、 ワン切りの未経験者がいるというのは驚きだな。 週2回以上というのが7割だそうです。 私の場合、週2〜3回か。
そういえば、掛け直したことがないですが。
§
カブールで日本の外務省職員が宿泊しているゲストハウスにロケット弾が撃ち込まれたそうですが、報道では「怪我人はない」とか。
じゃなくて、 抗議するとか、自衛隊派遣するとか、そーいう話じゃないのか? 日本の「のほほん性」も悟りの境地に入ったというか。
韓国勝ったのか〜。 というか、イタリア負けるか?
外しまくるヴィエリとか、 アピールして退場になるトッティとか、 まあセリエA見ているのと同じというか、皆さん絶好調ではあったようだ。 最後のヴィエリの大外しが入っていれば勝っているわけで。
「ファイナルファンタジー」のDVDを借りた。 観ました。 いやぁ、絵が綺麗なものですね。 流石、全編CGですね。
凄かったです。 絵が。
えーと、他に思いつかないな。 とりあえず、これで利益が出ると思ったスタッフというのが信じられないというか、 いくら何でも製作した人達は分かっていると思いますが。 各所の掲示板でストーリーというかシナリオが酷評されていたようだが、 それ以前の問題でしょう。
個人的に気になったのは、CGの出来ですな。 なんだ、あんな程度か、という感じ。 リアルだというからどんなにリアルなのかと思ったら、 異様に動きは不自然だし、 風景もいかにもCGという割に細かい所はとことん細かい。 どこが一番リアルじゃないかというと、空気が感じられないんですよね。 真空中で演技しているというか、 確かに「風」をCGで表現するのは難しいかもしれないけど、 髪の毛1本1本にこだわったと言われている割にはガチッとセットされたような髪型だし、 大暴れしても服は綺麗で汗もかかない、って感じか。 ヘンな喩えかもしれないが、サンダーバードの精密版を見てるとかいう。
それに、皆、顔色悪すぎ。 もう一言いっちゃうと、ヒロインのアキだっけ、いまいち好みじゃない。 特に表情が。
あ、そうそう、特典でFFの歴代紹介があった。 あれが一番よかったかも。
§
3名の姓名をローマ字で入力し、それらをアルファベット順(辞書式順序、大文字小文字は区別しない)で出力する。 という問題。
質問のメールではよく分からないと書いてあったが、 多分、全然分かっていないと思う。
大雑把に考えれば、必要になるのは、 「3名の姓名をローマ字で入力する」 と 「それらをアルファベット順(辞書式順序)で出力する」 の2つの処理だから、これをまず分けて考える。 と、ちょっと待てよ、関数の定義の仕方って習っているのだろうか?
main() { get_names(); print_names(); return 0; }
これだと名前を入力してどこに入れたらいいのか分からない。 C++ だったら vector とか使えばいいのだが、
先にいろいろ考えておくと、アルファベット順に出力するということは、 文字列の順序関係を決める処理が必要になる。 実はこれは標準ライブラリに既にある、というか、 strcmp という関数はまさにそれをやってくれる。 値がプラスなら…どっちだっけ、とかいう感じになってしまうが、 やってみれば分かるか。
問題は、strcmp は大文字と小文字を区別してしまうということで、 つまり、大文字と小文字を区別せずに比較するような処理を作らないといけない。 stricmp って、標準であったっけ? VC++ にはあるようだが。 なければ作るまで。
int stricmp(char *string1, char *string2);
みたいな。 先頭から1文字ずつ見ていって、大文字なら小文字に変換してから比較、 みたいな感じでどうでしょうか。
比較できたとして、次なる問題は、それをどう使うかということである。 要するにこれは一般化すれば「結果をソートして表示しろ」という問題だ。 この種の問題では、大雑把に言って、2通りの策がある。 入力した時点で並べかえておいて、表示は順番に行う、というのと、 入力は入力順でとりあえず入れておき、表示する時に比較する、というのだ。
珍しく休日出勤。
新宿とか、大画面TVがあちこちにあるが、 ワールドカップは中継しないそうだ。 人が集まって大変なことになるのだとか。 秋葉原の店頭TVも自粛しているというが。
ショップ側は、折角お客を集められる機会なのに、複雑だとか。
§
原爆のプラグの競売をアメリカ司法省が差し止め請求していた件、 裁判所は無効だということで競売が成立するそうだ。
国家機密に関わるというのが差し止めの理由なのだが、 裁判所は「既に公開された」という判断。 競売で買った人は物理学者で、 「これが国家機密だなんて科学をよく理解していない人の言うこと」とコメントしたそうだが、 国家機密ってそうじゃないと思うけど。 ほら、ロシアのジョークで、 某氏をバカだと言ったら侮辱罪と国家機密漏洩罪で逮捕されたというのがあるじゃん。
あれ、誰だっけ?
インテルのCEOのグレイグ氏が、 日本の半導体大手は長期的に2、3社しか残らないという談話。
うーむ、2、3社も残るのかな。 というか、インテル大丈夫か? 5年もたったらCPUは全部中国製、なんて世界もアリだと思うが。
§
W杯で、 バイロム社がホテルを何十万室も予約キャンセルしたために、 ホテルが大打撃だとか。 具体的には、韓国の場合、 最初80万室を仮予約(って何?)していたのが、 2001年10月に18万室、12月に11万室、 2002年4月に28万室がキャンセルされたという。 トータルで57万室。 日本の場合、 全室のうち20%とか25%が4月末までにキャンセルとか、そういう報道が出ていたが。
何かナメてんじゃないですか、ホテルの経営者って。
続きはCマガジンで。
Q
ポインタが分からないのて教えてください。
という凄い問題が来てしまったが、こういうのはどうすればいいだろう? ちなみに「初級C言語Q&A」では、
それを詳しく説明すると他のQ&Aを書く頁がなくなってしまいます。:-)
C言語に関する入門書の殆どが、 ポインタとは何かというテーマで解説した章を含んでいるはずなので、 それらを読んでください。 簡単なイメージとしては、実体そのものではなく、 実体がどこかにあるという情報を間接的に持つと理解することができます。
とか書いた。全然簡単ではないか。
古今東西、ポインタというと各種ありとあらゆる比喩で説明されてきたと思うが、 こういう概念を比喩で説明するからややこしくなるのでは、 という考え方もあるかと思って直接説明してみるというのはどうだろうか。
int i;
これは変数iを宣言している、または定義しているのだが、 その変数って一体何かというと、 コンピュータの実装されているメモリのどこかに値を入れるのである。 つまり、対応したメモリがどこかにある。 これが変数で、そのメモリに書かれている値が変数の値。
i = 10;
とかやると、メモリ上には10という値が書き込まれる。 このメモリから値を読めば10という値を得ることができる、というのがメモリ。
ところで、メモリのどこか、ってのは何かというと、 最近のpcだと256MBとか、メモリが結構大量にあるようだが、 256MBというのは、268435456バイト。 8切って147待ちか…って理牌してどうするってのは冗談だが、 つまり1バイトの情報を記憶する素子が268435456個ある。 この中のどこにiを対応させるか、というのは、やはり数値で表現して、 何番目のメモリに値を入れろ、という感じになる。 この「何番目」というのをアドレスと呼ぶ。
例えば100,000番目のメモリにiを対応させるというのであれば、 iに対応するアドレスは100,000、というような感じ。 整数値は1バイトでは表現できなから、 実際は100,001番目や100,002〜100,003番目も使うことになるかもしれないが。 とりあえず、 i に対応するメモリの位置を表現する「アドレス」という概念があるということが重要。
これが分かれば、次はiという変数に対してアドレスをgetすることができるか。 という問題。 ポインタの話題を持ってくるレベルの人なら本で見たりしていると思うが、 そのためにアドレス演算子というものがあって「&」のように書く。 変数 i に対して、&i と書けば、iのアドレスをgetできる。 iに対応するアドレスが100,000なら、&i の値は100,000になる、と思えばいい。
ここまで来たら、 ではアドレスが100,000というメモリに対応した変数の値を知るにはどうするか、 という問題。 変数 i の値が10なら、 100,000番目のメモリには10という値が書かれているはずだが (実際はエンディアンの問題とかあってややこしいけど、気にしない)、 そのアドレスから変数の値をgetするような演算子があるか、というと、 それがポインタなわけです。 記号としては「*」と書く。
ここまで説明した話で想像してもらえば、 つまり、100,000番目のメモリに入っている値をgetするには、 *(100,000) という式を使えばいいことになるが、 これはこれで間違いではないのだが、 普通はこういう書き方はあまりしない。 というのは、変数がメモリのどこに対応することになるかというと、 実際、これは結構ややこしい話なのだ。 実行するまで分からない場合も多い。
ということで、実際によくある使い方は、次のような感じになる。
int i; /* 変数 i */ int *p; /* int へのポインタ p */ i = 10; /* 変数 i に 10 という値を代入 */ p = &i; /* 変数 p に、変数 i のアドレスを代入 */ int j; j = *p; /* 変数 j に、pに入っているアドレスに対応したメモリの内容を代入 */
変数 i に対するアドレスが100,000だと、pの値は100,000となるのだが、 ここでは100,000という値はあまり重要ではなく、 肝心なのは、その値がiという変数に対応したアドレスだということである。 つまり、pに「iに対応するアドレス」が入っていれば、 *p という式は、アドレスの指している所の内容、つまり、iの値を持っているということ。
これだけなら j = i; とかやればいいのでは、という話になってしまうのだが、 実用上のポインタの特徴は何かといえば、 一つは、代入の左辺に来た場合の振る舞いである。
p = &i; *p = 20;
上のような処理を考える。 p にはiに対応するアドレスが入ってとして、 *p というのは i が指している先を意味する。 これはメモリ的にはiそのものなのだ。 なぜかというと、そのアドレスの内容を書き換えるというのは、 i の値を変更することに等しいから。 というわけで、この処理を実行したら、i の値が 20 になるのである。
ここまで書いたら疲れたので、とりあえず保留。
§
ちょっと前の報道で、 通勤電車の中が強い電磁波にさらされているというショッキングな記事があった。 要するに携帯の電磁波なのだが、 電車の中で反射して国際的な安全基準値を大幅に超え うる という曖昧な話だ。 というか、「うる」って何。 論文にはちゃんと数値が出ているのだと思うが、 報道も割とアバウトだよな。
日本物理学会の論文誌で発表したのは、 東北大理学研究科の本堂毅助手だということで、 車内で同時に携帯電話を使った場合の平均電力密度を調べたというのだが、 報道では「計算式を導き出した」というのである。
まさか、測定してないのだろうか? なわけないよな、理論と実験、って物理学の基本だし(除・トンデモ系)。
アサヒコムには冗談のような話が出ていました。 50人が0.4Wの電波を持つ携帯…という仮定ね。 ふむ、携帯って待ち受け時に0.4Wの電波を継続的に出すのか。 その割にバッテリー凄く持つよな。 バッテリー技術って進歩しているみたいだな。
で、結局、 車内の電力密度はWHOの協力機関(って何?) の定めた国際基準値の数倍に達し得るという。 なるほど、それは凄い。 で、この人の結論だと思うけど、 「閉鎖空間での電磁波の影響を考慮し、予防原則を考えなさい」 だそうです。
というわけで、私の結論。 人体は、電磁波に対してこれまで予想されている以上に強い ってことですね。 だって皆平気だし。電車に乗ってる人。
そろそろ「携帯電話はガンに効く」みたいなソレ系の本が出てくるのではないかと、 密かに期待しているのだが…。 脳細胞活性化するとか。 いやー、個人的に、脳は危ないような気もしますけど。携帯。 というか、携帯使い始めてから物忘れがよくなったような気がするのは、 気のせいか。
一つだけ疑問。 どうして電車内でガンガン電波が反射するのに、 外部と通話できるのだろ?
RIMNETの本家ページのCQAに来ていた質問の回答。 CQAの方、ちゃんとデータベースから表示するようにシステム改装中なので、 暫定でこちらに書いておく。
Q
次の (1) と (2) は何が違うのか?
char a; int b; a = (char) b; /* (1) */ a = *((char *) &b); /* (2) */
A
まず簡単な方から、
(1) は b に対してキャスト演算子を使った結果を a に代入するという処理です。
b の型は int なので、char の表現範囲に含まれる値であれば、
そのまま a の値となりますが、そうでない場合には値を保つことができませんから、
要注意です。
(2) は、変数 b に対するアドレス &b を char へのポインタとみなして、 そこにある値を a に突っ込むという処理です。 具体的には、 int を格納するつもりで確保されているメモリを先頭の 1 バイトだけ読む、 ということになります。
特に (1) と (2) の差が出てくるのは、 ビッグエンディアンのシステムで処理する場合です。 ビッグエンディアンの場合、 整数値は上位バイトから順に低いアドレスに格納されますから、 例えば b が 1 という値である場合、メモリ上には、次のようにデータが入ります。
0 0 0 1
これに対して、(2) を実行した結果の a の値は、先頭の値の 0 となります。 ちなみに、リトルエンディアンの処理系の場合は、
1 0 0 0
の順にメモリ上のデータが並びますから、(2) を実行した結果は 1 となるでしょう。
§
チューリング機械のシミュレータを作るという質問。 C++ で書きたいような気もするのだが、 C言語を使うという条件。 質問はこんな感じの内容。
シミュレータ結果を次のように表現する。 「CS=」に続いてその時点の状態を表示。 その後、テープの状態を表示する。 ヘッドの位置は()で表示する。 CS=a *(0)01100* CS=a *0(0)1100* CS=a *01(1)100* CS=a *010(1)00* CS=a *0100(0)0* CS=a *01001(0)* CS=a *010011(*) CS=b *01001(1)* CS=b *0100(1)0* CS=b *010(0)00* CS=b *01(0)100* CS=b *0(1)1100* CS=b *(0)01100* CS=b (*)101100* 動作: ヘッドが右に移動しながら、テープ上の文字が1ならば0、0ならば1に置き換える。 右端の「*」に到達すると移動方向を変えて、左に移動する状態になる。 左端の「*」に到達すると右移動状態に戻る。 という動作の繰り返し。
この仕様では、初期条件と状態定義が欠けているのでプログラムが作れないが、 そこは都合のいいように解釈することにする。 状態がa、bというのが定義されていないが、 aが右移動状態、bが左移動状態だと解釈した。 ちなみに、その通りなら「R」と「L」にした方がいいが。
これをC言語で書くという条件なのだが、 とりあえず C++ で書いてみて、 そこから C にしてみることにした。 最近、C++ の方がさっさと書けるようになったような気がする。 もっとも、Javaの方がいいかもしれませんけど。
#include <iostream> using namespace std; #define MAXSIZE 80 class TM { public: TM(); void PrintCurrentStatus(); void NextStatus(); void SetStatus(char* InitialTape, int pos, int direction); void UpdateStatus(); void Reverse(); private: int HeadPos; // Headの位置 bool reverse; // char tape[MAXSIZE]; }; TM::TM() { } void TM::SetStatus(char* InitialTape, int pos, int direction) { strcpy(tape, InitialTape); HeadPos = pos; reverse = direction; } void TM::NextStatus() { UpdateStatus(); if (reverse) { HeadPos--; } else { HeadPos++; } } void TM::UpdateStatus() { if (tape[HeadPos] == '*') { Reverse(); return; } if (tape[HeadPos] == '0') { tape[HeadPos] = '1'; return; } if (tape[HeadPos] == '1') { tape[HeadPos] = '0'; return; } } void TM::Reverse() { reverse = !reverse; } void TM::PrintCurrentStatus() { cout << "CS="; cout << reverse ? "b" : "a"; cout << " "; for (int i = 0; tape[i] != '\0'; i++) { if (i == HeadPos) { cout << "("; cout << tape[i]; cout << ")"; } else { cout << tape[i]; } } cout << "\n"; } int main() { TM tm; int i = 0; tm.SetStatus("*001100*", 1, 0); while (i++ < 100) { tm.PrintCurrentStatus(); tm.NextStatus(); } }
あえて説明略。 結構簡単な問題のように見えるでしょ、これがバグっている。 というか、実行開始から途中までの結果はこうなる。
CS=0 *(0)01100* CS=0 *1(0)1100* CS=0 *11(1)100* CS=0 *110(1)00* CS=0 *1100(0)0* CS=0 *11001(0)* CS=0 *110011(*) CS=1 *11001(1)* CS=1 *1100(1)0* CS=1 *110(0)00* CS=1 *11(0)100* CS=1 *1(1)1100* CS=1 *(1)01100* CS=1 (*)001100* CS=0 *(0)01100*
問題の結果の例とは、2行目が違っている。 つまり、このチューリングマシンは、 [結果を表示]→[状態変化]→[ヘッドを移動] という手順で処理しなければ、問題文のような結果にならない。 UpdateStatus() の位置が甘かったか。 てなわけで、UpdateStatus()を NextStatus() の外に出して、 main() で指定するようにした。 というか、UpdateStetus と NextStatus の違いというか、 このような名前のメソッドだと混乱してしまうので、 NextStatus は MoveHead に改名して、これで少しすっきりするのだが。
(略) void TM::MoveHead() { if (reverse) { HeadPos--; } else { HeadPos++; } } (略) int main() { TM tm; int i = 0; tm.SetStatus("*001100*", 1, 0); while (i++ < 100) { tm.PrintCurrentStatus(); tm.MoveHead(); tm.UpdateStatus(); } }
しかし、これもダメ。
CS=0 *(0)01100* CS=0 *0(1)1100* CS=0 *01(0)100*
要求仕様は次のような表示結果である。
CS=a *(0)01100* CS=a *0(0)1100* CS=a *01(1)100*
よく考えてみると、 1行目から2行目への遷移だけ、現在のヘッド位置の値を変えずに次の状態になっていて、 他は現在のヘッド位置の値を変えているのだ。 つまり、初回は状態変化なし、 2回目以降のステップは、まず表示してから状態を変化させて移動、というのが正しいか。 ってことは、こうですか。
tm.SetStatus("*001100*", 1, 0); tm.PrintCurrentStatus(); while (i++ < 100) { tm.MoveHead(); tm.PrintCurrentStatus(); tm.UpdateStatus(); }
あと、状態表示の所で、優先順位の処理を間違えているので、括弧でくくる。
cout << (reverse ? "b" : "a");
これでfinal release なのだが、今更何だが、 どちらかというと問題の設定がおかしいのでは。 それは気にしないで、ここからが本題。 C言語にコンバートするのである。
#include <stdio.h> #define MAXSIZE 80 void PrintCurrentStatus(); void MoveHead(); void SetStatus(char* InitialTape, int pos, int direction); void UpdateStatus(); void Reverse(); int HeadPos; /* Headの位置 */ int reverse; char tape[MAXSIZE]; void SetStatus(char* InitialTape, int pos, int direction) { strcpy(tape, InitialTape); HeadPos = pos; reverse = direction; } void MoveHead() { if (reverse) { HeadPos--; } else { HeadPos++; } } void UpdateStatus() { if (tape[HeadPos] == '*') { Reverse(); return; } if (tape[HeadPos] == '0') { tape[HeadPos] = '1'; return; } if (tape[HeadPos] == '1') { tape[HeadPos] = '0'; return; } } void Reverse() { reverse = !reverse; } void PrintCurrentStatus() { int i; printf("CS=%s ", reverse ? "b" : "a"); for (i = 0; tape[i] != '\0'; i++) { if (i == HeadPos) { printf("(%c)", tape[i]); } else { printf("%c", tape[i]); } } printf("\n"); } int main() { int i = 0; SetStatus("*001100*", 1, 0); PrintCurrentStatus(); while (i++ < 100) { MoveHead(); PrintCurrentStatus(); UpdateStatus(); } return 0; }
しかしこれでは回答になっていない。 質問は、多分、どうやってプログラム作るかというノウハウを教えて欲しいということで、 コードを作ってくれという話じゃないのだ。 ではポイントはどこにあるのか。 まず、 データ構造 を決める。 ここでは、charの配列をテープに対応させたが、そういう所。 問題を解決するためには、 あるモデルを表現するためにどのような変数が必要なのか、 という所に注目するのがいい。 今回はチューリングマシンだから、 テープの内容、ヘッドの位置、移動方向、という3つの要素を変数にしようと考えた。 これが正解かどうかはともかく、 発想のとっかかりとしては基本だと思う。 このような最初の発想がややこしい場合は、プログラムもややこしくなって破綻する。 単純なモデルを考えるというのがコツか。
そして、ロジックは単純なものを組み合わせて作る。 ある程度の組み合わせた結果がブラックボックスになる、というのが理想か。 例えばメインループの中身が、
MoveHead(); PrintCurrentStatus(); UpdateStatus();
となっているが、ここだけ見れば大雑把にやっていることが分かるはず。 細部は分からないが、大筋が分かる。 こういう書き方だと後が楽である。 ご覧のように、最初は UpdateStatus() は別の関数内の処理だったが、 このレベルに持ってくることでプログラマーが読みやすい構成になったのではないか。
富山県で昨年、 集団リンチで死んだ高校生がいたのだが、 それが1999年にも同じ集団に暴行を受けていたのに、 警察が「寛大な措置を」ということで家庭裁判所に送致しなかったそうだ。 つまり、寛大な措置の結果、また同じメンバーに暴行されて殺された、という話だ。 1度目の暴行は1週間の怪我だとか。
で、報道では、どういう理由で寛大な措置を要求したかというと、 「少年たちは深く反省している」 「少年と保護者を指導した」 「中学校が二度と起きないように注意を払うと約束した」 ということで、 被害届を取り下げるように説得したという。
ちなみに、警察の「説得」というのがどういう感じなのか、 …いやその、やめ。
で、誰がどう責任取るかという話だが、 基本的に、こういうのは加害者と警察がグルというか、 何かコネがあるとか(親が警察官とか政治家とか)、 それ系が多いと思っていたのだが、 今回はそうでもないのか。 中学校の校長は既に退職しているし、 確か中学卒業後の事件なので、 そういう意味では中学校では二度と事件は起きていない。
これはその後の事件を期待…というか、興味深く見てみたいと思う。 反省しても人を殺せるという性格である訳だから、 加害者は社会復帰してから多分再犯するだろうし、 それより恐いのは被害者の親の報復攻撃かもしれない。
§
個人情報の流出ニュースが流行中ですが、 なんでそう簡単に情報が出るかな。 servlet でデータ突っ込む方向だけ開けておけば、 基本的に外から情報は見えないと思うのだが。
まさか、CGIで public_html にデータファイル作ってます?
そりゃ「らんだむCGりんく」とか、データファイルが誰でも見える所にあるわけで、 情報だだ漏れ状態ですけど。 もちろん、見たけりゃミロってファイルだからそこに置いてあるのだが。 servlet 版はデータファイルは見えないだろ。
(C) 2002 Phinloda, all rights reserved