プログラミング所感 - 前へ 目次 次へ


05/01/05(水)

新年である。今年の目標は子供にSqueakでプログラムを作ってもらうように教えることにしようか。

パターン認識で、K-Dツリーみたいに超空間を超立方体に区切って判定するのはどうだろうか。 誰か考えてそうだが。SVMの前処理で、領域を狭めるために使うとか。


05/01/07(金)

日経コンピュータより。 三井銀行の第1次オンラインは、アセンブリで20万ステップ、しかも稼動に成功。 すごいね。

05/01/14(金)

待ち行列の統計の問題。
無限の長さの待ち行列があり、サービス終了者は出口で、券を置いていくものとする。 一定時間毎に券の枚数を記録することにより、その間のサービス終了者数がわかるものとする。 そのとき、サービスの分布に関して何がわかるか?指数分布だとしたときのパラメータの推定は?

05/01/15(土)

演算子+=は、C++では メソッドだが、C#では、代入の簡略表記にすぎない。構造体ならばよいが、クラスでは代入であることを意識すべきだ。 a=...;//(1) a+=...;(2)で、(1)と(2)で、aは指しているものが異なる。基本的にクラスでは+=は使わずにAddのように メソッドに使うべきだろう。例外はdelegateか。

05/01/17(月)

デリゲートのハッシュコードは メソッドで決まるようだ。オブジェクトは関係ない。別々にnewしても同じハッシュコードになるのは気持ち悪い。

05/01/20(木)

ここ半年近く、高速化を 含むプロジェクトをしていたが、行き詰っていた。アルゴリズムは、大ループがあり、その中は ステップ1、ステップ2に分かれている。ステップ1とステップ2の両方に成功すると、そこで大ループは終了して成功。
ステップ2の計算時間は、ステップ1のおよそ数十分の一、当然、高速化の検討は、ステップ1が主体となるが、 うまくいかなかった。ステップ2でも問題があり、ステップ2自体を修正を行った。 この修正により、ステップ2の1回当りの計算時間は数倍となった。しかし、トータルの計算時間は、数分の一になった。 理由は、ステップ2の成功する確率が高まったためである。早く気づけばよかったのだが、とりあえず、納期前に できたのでよしとする。

05/01/24(月)

歯医者行ったら、 親知らず抜けと言われた。はぁ。

05/02/03(木)

高速化に関する ドットネットマガジンの記事は参考になる。
  • %WINDIR%\Microsoft.NET\Framework\v1.1.4322\ngen.exe によるプリコンパイル。
    JIT実行をしないので起動が早くなる。
    参考:MSDNの「チュートリアル:カスタム動作を使用して、インストール中にアセンブリをプリコンパイルする」
  • リソースの集約。exeにリソースを埋め込む。
  • コントロールの追加。AddではなくAddRangeを使う。BeginUpdate, EndUpdateを使って描画の一時停止。
  • SuspendLayoutとResumeLayoutによるコントロール追加時の高速化。また、リサイズ時の高速化にも使える。
    Resizeイベントで、SuspendとIdleイベントの登録。IdleイベントでResumeと登録解除。この方法は秀逸。他にも応用可能だろう。
  • GDI+の高速化。DrawImage時には、サイズ指定すると3倍くらい早くなっている。
    ラインの描画をFileeRectangleに変えると、倍くらい早くなる。
    Graphics.SmoothingModeやTextRenderingHintを変えると、数倍早くなる。
    コントロールのダブルバッファリング。 SetStyle(ControlStyles.UserPaint | ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint,true); この方法は前にも書いた
  • マルチスレッドによる応答性の改善。p64のあたりは一読の価値あり。
  • GCの影響。文字列の連結にStringBuilderを使うことは、常識とすべきだろう。但し、1,2個なら+でつなげる方が早い。 数個なら、string.Formatという手もある。また、int i,j;に対し、「,」でつなげた文字列は、i+","+jで作れるが、 i.ToString()+","+j.ToString()の方が早い。とは言っても、通常は簡潔に書くべきで、どうしても速度が気になる部分だけ直すべきだろう。
  • WeakRefernceによるキャッシュ。大量の生成と廃棄時などに有効。
  • 例外処理。これは、VB.NETのOnErrorの話。

どうせ、だれかが作るか標準で入るんだけど複素数クラス
/// <summary>複素数</summary>
public struct Complex
{
	private double			_Re;
	/// <summary>実部</summary>
	public double Re {get {return _Re;} set {_Re = value;}}
	private double			_Im;
	/// <summary>虚部</summary>
	public double Im {get {return _Im;} set {_Im = value;}}
	/// <summary>絶対値</summary>
	public double Abs
	{
		get {return Math.Sqrt(Re*Re+Im*Im);}
		set
		{
			double d = Abs;
			// Abs==0ならば、そのまま
			if (d == 0) return;
			d = value / d;
			_Re *= d;
			_Im *= d;
		}
	}
	/// <summary>角度(ラジアン)</summary>
	public double Angle
	{
		get {return Math.Atan2(_Im,_Re);}
		set
		{
			double d = Abs;
			_Re = d*Math.Cos(value);
			_Im = d*Math.Sin(value);
		}
	}
	#region コンストラクタと演算子
	/// <summary>コンストラクタ</summary>
	public Complex(double r) {_Re = r; _Im = 0;}
	/// <summary>コンストラクタ</summary>
	public Complex(double r,double i) {_Re = r; _Im = i;}
	/// <summary>コンストラクタ</summary>
	public static explicit operator Complex(double r) {return new Complex(r);}
	/// <summary>生成</summary>
	public static Complex FromPolar(double a,double t)
	{
		return new Complex(a*Math.Cos(t),a*Math.Sin(t));
	}
	/// <summary>単項演算子+</summary>
	public static Complex operator+(Complex c) {return c;}
	/// <summary>単項演算子-</summary>
	public static Complex operator-(Complex c) {return new Complex(-c.Re,-c.Im);}
	/// <summary>単項演算子~(共役)</summary>
	public static Complex operator~(Complex c) {return new Complex(c.Re,-c.Im);}
	/// <summary>2項演算子+</summary>
	public static Complex operator+(Complex c1,Complex c2)
	{
		return new Complex(c1.Re + c2.Re, c1.Im + c2.Im);
	}
	/// <summary>2項演算子+</summary>
	public static Complex operator+(double d,Complex c2)
	{
		return new Complex(d + c2.Re, c2.Im);
	}
	/// <summary>2項演算子+</summary>
	public static Complex operator+(Complex c1,double d)
	{
		return new Complex(c1.Re + d, c1.Im);
	}
	/// <summary>2項演算子-</summary>
	public static Complex operator-(Complex c1,Complex c2)
	{
		return new Complex(c1.Re - c2.Re, c1.Im - c2.Im);
	}
	/// <summary>2項演算子-</summary>
	public static Complex operator-(double d,Complex c2)
	{
		return new Complex(d - c2.Re, -c2.Im);
	}
	/// <summary>2項演算子-</summary>
	public static Complex operator-(Complex c1,double d)
	{
		return new Complex(c1.Re - d, c1.Im);
	}
	/// <summary>2項演算子*</summary>
	public static Complex operator*(Complex c1,Complex c2)
	{
		return new Complex(c1.Re*c2.Re - c1.Im*c2.Im, c1.Re*c2.Im + c1.Im*c2.Re);
	}
	/// <summary>2項演算子*</summary>
	public static Complex operator*(double d,Complex c2)
	{
		return new Complex(d*c2.Re, d*c2.Im);
	}
	/// <summary>2項演算子*</summary>
	public static Complex operator*(Complex c1,double d)
	{
		return new Complex(d*c1.Re, d*c1.Im);
	}
	/// <summary>2項演算子/</summary>
	public static Complex operator/(Complex c1,Complex c2)
	{
		double v = c2.Re*c2.Re+c2.Im*c2.Im;
		// v == 0 ならば +∞となる
		return new Complex((c1.Re*c2.Re + c1.Im*c2.Im)/v,
			(-c1.Re*c2.Im + c1.Im*c2.Re)/v);
	}
	/// <summary>2項演算子/</summary>
	public static Complex operator/(double d,Complex c2)
	{
		double v = c2.Re*c2.Re+c2.Im*c2.Im;
		return new Complex(d*c2.Re/v, -d*c2.Im/v);
	}
	/// <summary>2項演算子/</summary>
	public static Complex operator/(Complex c1,double d)
	{
		return new Complex(c1.Re/d, c1.Im/d);
	}
	/// <summary>比較</summary>
	public static bool operator==(Complex c1,Complex c2)
	{
		return c1.Re == c2.Re && c1.Im == c2.Im;
	}
	/// <summary>比較</summary>
	public static bool operator!=(Complex c1,Complex c2)
	{
		return c1.Re != c2.Re || c1.Im != c2.Im;
	}
	/// <summary>比較</summary>
	public override bool Equals(object o)
	{
		if (!(o is Complex)) return false;
		return this == (Complex)o;
	}
	#endregion
	/// <summary>ハッシュコード</summary>
	public override int GetHashCode()
	{
		return Re.GetHashCode() ^ Im.GetHashCode();
	}
	/// <summary>文字列</summary>
	public override string ToString()
	{
		return Im == 0 ? Re.ToString() : (Re == 0 ? Im.ToString()+"i" :
			(Im > 0 ? string.Format("{0}+{1}i",Re,Im) : string.Format("{0}-{1}i",Re,-Im)));
	}
	/// <summary>実数かどうか</summary>
	public bool IsReal()
	{
		return Im == 0;
	}
	/// <summary>iをかける</summary>
	public Complex MulI()
	{
		return new Complex(-_Im,Re);
	}
	/// <summary>iで割る</summary>
	public Complex DivI()
	{
		return new Complex(_Im,-Re);
	}
}
/// <summary>複素数演算</summary>
public struct ComplexMath
{
	/// <summary>Abs</summary>
	public static double Abs(Complex c)
	{
		return c.Abs;
	}
	/// <summary>Conj</summary>
	public static Complex Conj(Complex c)
	{
		return ~c;
	}
	/// <summary>Exp</summary>
	public static Complex Exp(Complex c)
	{
		double d = Math.Exp(c.Re);
		return new Complex(d*Math.Cos(c.Im), d*Math.Sin(c.Im));
	}
	/// <summary>Log</summary>
	public static Complex Log(Complex c)
	{
		return new Complex(Math.Log(c.Abs),c.Angle);
	}
	/// <summary>Log10</summary>
	public static Complex Log10(Complex c)
	{
		return Log(c) / Math.Log(10);
	}
	/// <summary>Pow</summary>
	public static Complex Pow(Complex c1,Complex c2)
	{
		return Exp(c2*Log(c1));
	}
	/// <summary>Pow</summary>
	public static Complex Pow(double d,Complex c2)
	{
		return Exp(c2*Math.Log(d));
	}
	/// <summary>Pow</summary>
	public static Complex Pow(Complex c1,double d)
	{
		return Exp(d*Log(c1));
	}
	/// <summary>Sin</summary>
	public static Complex Sin(Complex c)
	{
		Complex d = c.MulI();
		return ((Exp(d)-Exp(-d))/2).DivI();
	}
	/// <summary>Cos</summary>
	public static Complex Cos(Complex c)
	{
		Complex d = c.MulI();
		return (Exp(d)+Exp(-d))/2;
	}
	/// <summary>Tan</summary>
	public static Complex Tan(Complex c)
	{
		return Sin(c)/Cos(c);
	}
	/// <summary>Asin</summary>
	public static Complex Asin(Complex c)
	{
		return Log(c.MulI() + Sqrt(1-c*c)).DivI();
	}
	/// <summary>Acos</summary>
	public static Complex Acos(Complex c)
	{
		return Log(c + Sqrt(1-c*c).MulI()).DivI();
	}
	/// <summary>Atan</summary>
	public static Complex Atan(Complex c)
	{
		Complex i = new Complex(0,1);
		return Log((i+c)/(i-c)).MulI()/2;
	}
	/// <summary>Sinh</summary>
	public static Complex Sinh(Complex c)
	{
		return (Exp(c)-Exp(-c))/2;
		//return Sin(c.MulI()).DivI();
	}
	/// <summary>Cosh</summary>
	public static Complex Cosh(Complex c)
	{
		return (Exp(c)+Exp(-c))/2;
		//return Cos(c.MulI());
	}
	/// <summary>Tanh</summary>
	public static Complex Tanh(Complex c)
	{
		Complex d1 = Exp(c), d2 = Exp(-c);
		return (d1-d2)/(d1+d2);
		//return Tan(c.MulI()).DivI();
	}
	/// <summary>Sqrt</summary>
	public static Complex Sqrt(Complex c)
	{
		if (c.Im == 0)
		{
			double d = Math.Sqrt(Math.Abs(c.Re));
			return c.Re >= 0 ? new Complex(d) : new Complex(0,d);
		}
		return Complex.FromPolar(Math.Sqrt(c.Abs),c.Angle/2);
	}
	/// <summary>Sign</summary>
	public static Complex Sign(Complex c)
	{
		return c / c.Abs;
	}
	/// <summary>Test用</summary>
	public static void Test()
	{
		Complex c1 = new Complex(0.3,0.2);
		Console.WriteLine(c1 == new Complex(c1.Re,c1.Im));
		Console.WriteLine(c1 == Complex.FromPolar(c1.Abs,c1.Angle));
		Console.WriteLine(c1 == c1.Abs * Exp(((Complex)c1.Angle).MulI()));
	}
}


05/02/17(木)

例えば、平均を求める プログラムを書かせたとしよう。計算自体は問題ない。しかし、データ数をチェックして ゼロ割しないように心がける人が少ない。このような基本的なことができないとプロとはいえない。 まして、何度も指摘しても直らないようであれば、プログラマ失格といってよい。
なになに、「以前描いた複素数クラスではチェックしてない」って。 それは、C#において、doubleのゼロ割は 正当な演算だからである。(整数のゼロ割はエラーである。)
これは、C#において、doubleのとりうる値に、NaNと±∞があるからである。 (IEEEにもNaNはあるが。)数値演算の定義域がきちんと定まっているので、 (NaNなどを考慮していれば)NaNなどを使うことは間違いではない。 例えば、1/0は、∞になるし、0/0はNaNになる。NaNとの演算はまたNaNである。 ∞との演算も∞になる。あるいは、割れば0になる。これらは、学校で習う数学に にているが異なっている。このコンピュータ数学もコンピュータに従事する可能性のある学生は 学校で習うべきだろう。(つまり、「整数のゼロ割をしない」ようにするのと同じく常識であるべきだ。)

05/02/18(金)

数値計算において、行列は避けて通れない だろう。それで、C#で行列クラスをちゃちゃっと作り、行列を用いてアルゴリズムを書くのだが、 効率の悪いプログラムができあがる。それを直すこともできるが、そうするとプログラムの見通しは悪くなる。
行列に限らず、このようなことはあるだろう。
「実現したいこと」は、なるべくシンプルに記述するべきである。 それをどう実現するかよりも記述のシンプルさに重点を置くことも必要である。
例えば、「min cTx; s.t. Ax<=b; を内点法で解く」。この日本語の要求をコンピュータで直接実行はできない。 そこで、プログラミング言語で記述し、コンパイラがマシン語に翻訳して実行することになる。 翻訳という作業は知的であるが機械的である。将来的には、この翻訳作業がシームレスかつ高度に なっていくであろう。例えば、効率の悪い行列のプログラムは、自動的に効率のよいものに翻訳されるだろう。 行列演算で書かれた内点法のプログラムは、自動的に疎行列でもfill-inが少ないアルゴリズムに翻訳されるだろう。 実現したいことを意図している人は、シンプルな表現の方の意図を保持しメンテナンスすべきである。
とはいえ現状では、高度に知的な自動翻訳はないので、プログラマが代行しなければいけない。
ドットネットだけで、実現できるわけではないが、ドットネットはこの方向に向かっているように思う。 Javaも同じ方向を向いているだろう。私には、Javaは理想と現実のバランスが悪い。C#の方がバランスよく感じられる。

double.NaNは、IsNaNでチェックすること。下記は、2番目はfalseである。その他はtrue。
double d = double.NaN;
Console.WriteLine(double.IsNaN(d));
Console.WriteLine(d == double.NaN);
d = double.PositiveInfinity;
Console.WriteLine(double.IsPositiveInfinity(d));
Console.WriteLine(d == double.PositiveInfinity);


05/02/22(火)

RealProxyの話。
/// <summary>ペア</summary>
public class Pair : ICloneable
{
	private object			_First;
	/// <summary></summary>
	public object First {get {return _First;} set {_First = value;}}
	private object			_Second;
	/// <summary></summary>
	public object Second {get {return _Second;} set {_Second = value;}}
	/// <summary>コンストラクタ</summary>
	public Pair(object o1,object o2) {_First = o1; _Second = o2;}
	/// <summary></summary>
	public sealed override bool Equals(object obj)
	{
		Pair p = (Pair)obj;
		return p != null && _First.Equals(p._First) && _Second.Equals(p._Second);
	}
	/// <summary></summary>
	public override int GetHashCode()
	{
		return _First.GetHashCode() ^ _Second.GetHashCode();
	}
	/// <summary></summary>
	public override string ToString()
	{
		return _First.ToString() + " " + _Second.ToString();
	}
	public object Clone()
	{
		return new Pair(_First,_Second);
	}
}
/// <summary></summary>
public interface IHashtable2
{
	/// <summary>インデクサ</summary>
	object this[object o1,object o2] {get; set;}
}
/// <summary>キーが2つのHashtable</summary>
public class Hashtable2 : Hashtable, IHashtable2
{
	/// <summary>インデクサ</summary>
	public object this[object o1,object o2]
	{
		get {return this[new Pair(o1,o2)];}
		set {this[new Pair(o1,o2)] = value;}
	}
}
例えば、キーは2つのインデクサを持つHashtable2型の h があったとしよう。これにネットワークの2地点間の距離が 入っているとする。最初の設計では、ネットワークは無向グラフだったとしよう。 地点i1と地点i2の距離がh[i1,i2]で取り出せるとしよう。無向なので、i2からi1の距離は、h[i1,i2]と同じである。 メモリの節約からh[i2,i1]には、何も入っていないとする。
あるとき仕様が変わって、ネットワークを有向グラフにしなければいけなくなったとする。
h「i2,i1]=h[i1,i2];をhの構築時にすればいいように思われる。おっと、もう1つの要件で、オリジナルの h(すなわち片方向のデータ)も別途必要というのがあった。では、hを複製しよう。なになに、 複製のタイミングが多すぎて、速度とメモリが問題だと。こんなときは、プロクシを使うことができる。
/// <summary></summary>
public class DualHashTable2 : RealProxy
{
	private IHashtable2		org;
	/// <summary></summary>
	public DualHashTable2(IHashtable2 h) : base(typeof(IHashtable2)) {org = h;}
	/// <summary></summary>
	public override IMessage Invoke(IMessage msg)
	{
		IMethodCallMessage mm = msg as IMethodCallMessage;
		MethodInfo mi = org.GetType().GetMethod(mm.MethodName,(Type[])mm.MethodSignature);
		object res = mi.Invoke(org,mm.Args);
		if (res == null && mm.InArgCount == 3 && mm.MethodName == "set_Item")
			res = mi.Invoke(org,new object[]{mm.Args[1],mm.Args[0],mm.Args[2]});
		return new ReturnMessage(res,null,0,mm.LogicalCallContext,mm);
	}
}
	IHashtable2 h = new DualHashTable2(original).GetTransparentProxy() as IHashtable2;
例えば、こんな感じに。対象がインターフェースかMarshalByRefObjectでないといけないのがネックだが。

VG.netいいなぁ。私は、デザインセンスないんだけどね。


05/02/23(水)

ソフトウェア開発など の本を読んでいる。
isbn:4822282155:detail
isbn:475611623X:detail
isbn:4254275161:detail
コンストラックス社は理想郷のようだ。

05/02/24(木)

続き。
isbn:4872834151:detail
これはお勧め。部内の標準にしたい。内容的には、ほぼ納得できる。 とはいえ、私はこのルールの1/3は意図して破っている。こんど、日を改めてまた書くとしよう。

日経ソフトウェアは、C/C++特集だ。C/C++は、一番長く付き合った言語だが、私は、 子供にはC#を教えるだろう。(今は、Squeakでお絵かきさせている)
C++は、プログラミング学習に向いているとは思えない。 「プログラミング言語C++第3版」はいい本だが、初心者には向かない。実際、プログラミング演習で しばらく使ったことがあるが、無理だとあきらめた。
私が、C#を選ぶ理由は、前にも書いたが生産性の高さだ。 とはいえ、プログラマとしては、常識として、アセンブラ、C/C++である程度のレベルの プログラムを書けるべきだという気もする。

5x5の先手25目勝ちが証明されたそうだ。すごいね。生きているうちに9x9は無理かな。

VG.netの勉強会を考えている。


05/02/26(土)

改行コードメモ。 。&#13;&#10;。

05/03/01(火)

WikiにC#のコーディングルールを 入れた。1項目1ページでおそらく300ページ近くになった。
WebRequest req = HttpWebRequest.Create("http://.../wiki.cgi?");
req.Method = "POST";
StreamWriter sw = new StreamWriter(req.GetRequestStream(),
	Encoding.GetEncoding("EUC-jp")); // Linuxサーバのため
sw.Write("save=1&");
sw.Write("action=EDIT&");
sw.Write("content=...");
sw.Write("page=...&");
sw.Write("lastmodified={0}",(int)(DateTime.Now
	- new DateTime(1970,1,1,9,0,0)).TotalSeconds);
sw.Close();
req.GetResponse().Close();
途中からプログラムでWikiに書き込むようにした。
次はコメントを入れていこう。

05/03/02(水)

パラメータの設定。 実数パラメータを指定するとき、「-1」なら無限大を表すというような仕様をよく見かける。 これからは、無限大の表現は「+∞」にしよう。double.Parseでも使える。

05/03/03(木)

ブログで、 求人情報や案件情報を出しているところがある。 関西圏のみだが。東京とかないかな。

05/03/08(火)

C#の案件が増えつつある。 誘導しているんだけど。
C#開発者をどのように増やすかを考える必要がある。

純粋関数型雑記帳から。
同じ大きさのいくつかの円の面積を求める。63個までしか計算できないし、指数オーダになっている。
public class Calc
{
	static void Test()
	{
		ArrayList a = new ArrayList();
		Random r = new Random(1);
		for (int i=0;i<10;++i)
			a.Add(new double[]{r.NextDouble()*5,r.NextDouble()*5});
		Console.WriteLine("{0:F3}",GetCircleArea(a,1));
		Console.WriteLine("{0:F3}",GetCircleArea2(a,1));
	}
	public static double GetCircleArea(ArrayList center, double rad)
	{
		ArrayList cnt = (ArrayList)center.Clone();
		for (int i=0;i<cnt.Count-1;++i)
		{
			double[] d1 = (double[])cnt[i];
			int j = i+1;
			while (j < cnt.Count)
			{
				double[] d2 = (double[])cnt[j];
				if (d1[0] == d2[0] && d1[1] == d2[1])
					cnt.RemoveAt(j);
				else ++j;
			}
		}
		if (cnt.Count > 63) throw new ApplicationException("サイズが大きすぎます");
		ulong ui, umx = 1UL << cnt.Count;
		double[,][][] pos = new double[cnt.Count,cnt.Count][][];
		for (int i=0;i<cnt.Count-1;++i)
		{
			double[] d1 = (double[])cnt[i];
			for (int j=i+1;j<cnt.Count;++j)
			{
				double[] d2 = (double[])cnt[j];
				double x = d2[0]-d1[0], y = d2[1] - d1[1];
				double a = rad*rad/(x*x+y*y)-0.25;
				if (a <= 0) continue;
				a = Math.Sqrt(a);
				double xx = (d1[0]+d2[0])/2, yy = (d1[1]+d2[1])/2;
				pos[i,j] = pos[j,i] = new double[][]{
					new double[]{xx+a*y, yy-a*x, i, j}, new double[]{xx-a*y, yy+a*x, i , j}};
			}
		}
		ArrayList lst = new ArrayList();
		double res = 0;
		for (ui=1UL;ui<umx;++ui)
		{
			int n = 0;
			lst.Clear();
			for (int i=0;i<cnt.Count;++i)
			{
				if ((ui & (1UL<<i)) == 0) continue;
				++n;
				for (int j=i+1;j<cnt.Count;++j)
				{
					if ((ui & (1UL<<j)) == 0) continue;
					if (pos[i,j] == null) goto last;
					for (int k=0;k<2;++k)
					{
						int	l;
						for (l=0;l<cnt.Count;++l)
						{
							if (l == i || l == j) continue;
							if ((ui & (1UL<<l)) == 0) continue;
							if (pos[i,l] == null || pos[j,l] == null) goto not_found;
							double[] d3 = (double[])cnt[l];
							double x = d3[0] - pos[i,j][k][0], y = d3[1] - pos[i,j][k][1];
							if (x*x+y*y > rad*rad) goto not_found;
						}
						lst.Add(pos[i,j][k]);
					not_found:;
					}
				}
			}
			if (lst.Count == 0)
			{
				if (n == 1) res += Math.PI*rad*rad;
				continue;
			}
			double v1 = ((double[])lst[0])[2];
			double v2 = ((double[])lst[0])[3];
			for (int i=1;i<lst.Count;++i)
			{
				int j;
				for (j=i;j<lst.Count;++j)
				{
					double vv1 = ((double[])lst[j])[2];
					double vv2 = ((double[])lst[j])[3];
					if (v1 == vv1) {v1 = vv2; break;}
					if (v1 == vv2) {v1 = vv1; break;}
				}
				if (j == lst.Count) throw new ApplicationException("Not found");
				object tmp = lst[i]; lst[i] = lst[j]; lst[j] = tmp;
			}
			if (v1 != v2) throw new ApplicationException("Not match");
			double	s,a,b,c, d = 0;
			if (lst.Count > 2)
			{
				c = GetLength((double[])lst[0], (double[])lst[1]);
				for (int i=2;i<lst.Count;++i) 
				{
					a = c;
					b = GetLength((double[])lst[i], (double[])lst[i-1]);
					c = GetLength((double[])lst[i], (double[])lst[0]);
					s = (a+b+c)/2;
					d += Math.Sqrt(s*(s-a)*(s-b)*(s-c));
				}
			}
			for (int i=0;i<lst.Count;++i)
			{
				double x = GetLength((double[])lst[i], (double[])lst[(i+1)%lst.Count]);
				d += Math.Asin(x/rad/2)*rad*rad - x/2*Math.Sqrt(rad*rad-x*x/4);
			}
			res += n%2 == 1 ? d : -d;
		last:;
		}
		return res;
	}
	public static double GetLength(double[] d1, double[] d2)
	{
		double x = d1[0]-d2[0];
		double y = d1[1]-d2[1];
		return Math.Sqrt(x*x+y*y);
	}
	public static double GetCircleArea2(ArrayList center, double rad)
	{
		double	res = 0, d = 1e-2, l, t, r, b;
		l = b = double.MaxValue;
		t = r = double.MinValue;
		foreach (double[] dd in center)
		{
			if (dd[0] < l) l = dd[0];
			if (dd[0] > r) r = dd[0];
			if (dd[1] < b) b = dd[1];
			if (dd[1] > t) t = dd[1];
		}
		l -= rad;
		b -= rad;
		t += rad;
		r += rad;
		for (double x=l;x<=r;x+=d)
		{
			for (double y=b;y<=t;y+=d)
			{
				foreach (double[] dd in center)
				{
					double xx = x-dd[0];
					double yy = y-dd[1];
					if (xx*xx+yy*yy < rad*rad)
					{
						res += d*d;
						break;
					}
				}
			}
		}
		return res;
	}
}


05/03/09(水)

再び、純粋関数型雑記帳 id:tanakh:20050308の記事から。
昨日のプログラムは、2次元座標をdouble[2]で表していた。他にもSystem.Drawing.PointFを使うこともある。 PointFはfloatなんで、使い勝手はイマイチである。某筋では、C++で2次元座標は、complexを使うのが常識だそうだ。 確かに便利である。dot Net Frameworkにも複素数入れてくれ。

05/03/10(木)

10代の男子の人気職業1位は、 プログラマだそうだ。最近の新入社員の様子を見ていると信じられない。

「PropertyGridに複数のオブジェクトを設定できて、複数のプロパティを同時に更新できるようにする クラス」をRealProxyかなんかでできないかと考えたが、できない。ふと、やってみると、元々、 複数オブジェクトに対応している。こりゃ便利だ。何も作る必要なし。やるなPropertyGrid。

株式会社に社会責任はあるのか?
世間一般の認識では、もちろん「ある」だろう。私も、ドラッカーに感化されているので 「ある」と思っていた。しかし、奥村宏は「ない」と看破する。言われてみるとその通りなんだが、しっくりこない。 株式会社が社会責任上、どうあるべきなのかがわからない。


05/03/11(金)

スラドより。
「合否確認のためのシステム侵入で不合格に」。 不合格になったことに関しては、学校の判断なので、ここでは置いておく。
問題は、 不正アクセス行為の禁止等に関する法律 によると、以下の作業が日本で違法になるかもしれないとのことだ。
  • ブラウザで、あるページを開く。(ここまでは合法であると仮定する)
  • ソースからある文字列を取り出す。
  • ブラウザのアドレスの一部を上記文字列に変えてアクセス。
  • あるいは、アドレスの一部を容易に推測可能な文字列に変更してアクセス。 (例えば、01を02に変えるとか、自分のIDを入れるとか)
こんなことが違法になるのはおかしいと思うが、実際の所どうなのかはっきりして欲しい。

queuingのスペルミスでqueueingが多い。本のタイトルで間違っているのは恥ずかしい。
queueingで引っかかるページも恥ずかしいが、 "queuing queueing"で検索に引っかかるページはもっと恥ずかしい。
"Queuing theory"より"Queueing theory"の方が、googleの検索結果数が多いのは納得いかないし、 goo辞書には、後者しか載っていないのはさらに理解不能だ。 ここまでくると、実は両方正しいのかとさえ思われる。どうなんですか>○○先生。

構造化プログラミングに反する関数を書けるか? から。
言葉を替えると、関数の入口や出口を1つ以上できるか?ということである。
以下のプログラム(シミュレーションクラスSimSystemを用いた待ち行列の例)を見て欲しい。
public class Test
{
	public class 待ち行列
	{
		public static Queue 行列 = new Queue();
		public static void サービス開始(通行人 x)
		{
			行列.Enqueue(x);
			if (行列.Count == 1) while (行列.Count > 0)
			{
				通行人 y = (通行人)行列.Peek();
				Console.WriteLine("{0} {1} サービス開始", SimSystem.Now, y.名前);
				SimSystem.Wait(3);
				Console.WriteLine("{0} {1} サービス終了", SimSystem.Now, y.名前);
				行列.Dequeue();
			}
		}
	}
	public class 通行人
	{
		public string 名前;
		public 通行人(string s) {名前 = s;}
		public void 到着()
		{
			Console.WriteLine("{0} {1} 到着", SimSystem.Now,名前);
			待ち行列.サービス開始(this);
		}
	}
	static void Main(string[] args)
	{
		SimSystem.ScheduleAt(2,new SimEvent(new 通行人("その1").到着));
		SimSystem.ScheduleAt(4,new SimEvent(new 通行人("その2").到着));
		SimSystem.Start(100);
	}
}
このプログラムは、そのまま動き、出力は次のようになる。
2 その1 到着
2 その1 サービス開始
4 その2 到着
5 その1 サービス終了
5 その2 サービス開始
8 その2 サービス終了
さて、SimSystem.Waitは、シミュレーション時間上で、指定時間だけ待つ関数である。
結果を見ると、 「サービス開始」のSimSystem.Waitで別関数の「到着」に飛び、終わったらSimSystem.Waitの次の行から続いている。 これらの関数の入口と出口は1つだろうか?


05/03/13(日)

大学で、ヒューマン・インターフェースを 教えるので、参考にヒューメイン・インターフェース isbn:4894714205 を読んでいる。

05/03/14(月)

学研で、ECircを紹介してもらった。 非常によくできている。
http://kids.gakken.co.jp/kagaku/softland/0503/index.html
時間があれば、C#で作り直したい。表示は、回路図モードと写真モードがいいなぁ。 問題作成とWebサーバへの解答や、豆電球とか色電球とか、あると面白いかな。 端点の表示は2重丸の方がいいかな。

錯視のページから。 http://www.ritsumei.ac.jp/~akitaoka/index-j.html
見た瞬間、gifアニメかと思い、下を読むと、「勝手に回転して見える」との文字が。で、よく見ると、動いていない。 おぉ。しかし、動いて見える。すごいな。

Excel使っていて、えらい目にあった。発端は、最初のシート以外を印刷したかったので、 最初のシート以外を選択して、印刷。そのまま保存して終了。その後、再び開いて、セルの修正して保存。 さらにしばらくして開いてみると、最初のシート以外の全シートに同じ修正が反映されている。

前にも同じことを書いたかもしれない。アプリケーションで上書き保存する場合、 backupフォルダを作成し、上書き前のファイルを退避させるといいのではないだろうか。


05/03/15(火)

UMLのテストをやってみた。 http://hp.vector.co.jp/authors/VA034778/ NOVICEの方を満点になるまで4回くらいやりました。そういえば、ブロンズも満点になるまでやりました。 RUPはやる気なし。

このブログを読んでいる人がごのくらいいるのか知りませんが、ここでアンケート。 コメントかTBでよろしくお願いします。
   IT業界で働いている人で、1年間の納期の数はおおよそいくつですか?
私は、6から10かな。今年度は、私がPLのは、9ヶ月で7つかな。(うちは6月が年度末)
J、N、N、S、M、B、R。後3ヶ月で、T、D、Hがある。全て、業種もやっていることも違う。


05/03/16(水)

個人情報保護法の オンラインテストを受けた。条文を張っておく。 http://www5.cao.go.jp/seikatsu/kojin/houritsu/index.html
日常使う言葉に翻訳して欲しいな。

05/03/17(木)

昨日と今日はOR学会。 今年は発表せず。懐かしい人に会った。
たまには学会に出るなどで、頭の違う部分を使うのも必要なんだろう。 昔は、講演の内容を吟味したが、最近は概要程度しか気にしない。あるいは、その技術のビジネスの方向性とか。

05/03/18(金)

本の記録。
急に忙しくなったんだけど、本を買ってしまう。ううむ。
SEは今夜も眠れない。 isbn:4896917014。
知識ゼロから学ぶソフトウェアテスト。isbn:4798107093
仕事の効率を上げるワザ100選。isbn:479809490

05/03/19(土)

よくあるテストケースの問題。
  3つのdoubleを引数に取り、正三角形か二等辺三角形かその他の三角形かを返す関数を作成せよ。
  三角形の要件を満たさない場合は非三角形とせよ。
11ケース考えればいいそうだが、以下では適当に359ケースも作ってみた。
public class Test
{
    public enum Triangle {非三角形, その他の三角形, 二等辺三角形, 正三角形};
    /// <summary>
    /// 正三角形か二等辺三角形かその他の三角形かを求める
    /// 三角形の要件を満たさない場合は非三角形となる
    /// </summary>
    public static Triangle CheckTriangle(double d1, double d2, double d3)
    {
        double[] length = {d1,d2,d3};
        foreach (double d in length)
            if (double.IsNaN(d) || double.IsInfinity(d) || d <= 0) return Triangle.非三角形;
        Array.Sort(length);
        if (length[0] == length[1]) return length[1] == length[2] ? Triangle.正三角形 :
            (length[0] + length[1] > length[2] ? Triangle.二等辺三角形 : Triangle.非三角形);
        return length[1] == length[2] ? Triangle.二等辺三角形 :
            (length[0] + length[1] > length[2] ? Triangle.その他の三角形 : Triangle.非三角形);
    }
    /// <summary>359ケースのテスト</summary>
    public static bool CheckTriangleTest()
    {
        double[] dd = {-1,0,double.Epsilon,2,double.MaxValue,
                        double.PositiveInfinity,double.NaN};
        int[] ii = {3,0,0, 0,2,0, 0,0,2, 0,2,0, 2,3,0, 0,0,2, 0,0,2, 0,0,2, 2,2,3};
        int    i = 0;
        foreach (double d1 in dd)
        {
            bool b1 = double.IsNaN(d1) || double.IsInfinity(d1) || d1 <= 0;
            foreach (double d2 in dd)
            {
                bool b2 = double.IsNaN(d2) || double.IsInfinity(d2) || d2 <= 0;
                foreach (double d3 in dd)
                {
                    bool b3 = double.IsNaN(d3) || double.IsInfinity(d3) || d3 <= 0;
                    Triangle res = b1 || b2 || b3 ? Triangle.非三角形 : (Triangle)ii[i++];
                    if (CheckTriangle(d1,d2,d3) != res)
                        return false;
                }
            }
        }
        double e = double.Epsilon, m4 = double.MaxValue*0.4,
            m6 = double.MaxValue*0.6, m = double.MaxValue;
        double[,] ddd = {{2,3,e}, {m,e,m6}, {2,2,3}, {4,2,2}, {2,3,2}, {2,3,3}, {2,4,3},
            {2,4,2}, {3,m,2}, {m4,2,m}, {m4,m4,m6}, {m4,m4,m}, {m4,m6,m6}, {m4,m6,m}, {m4,m,m}};
        int[] iii = {0,0,2,0,2,2,1,0,0,0,2,0,2,0,2};
        for (int k=0;k<ddd.GetLength(0);++k)
            if (CheckTriangle(ddd[k,0],ddd[k,1],ddd[k,2]) != (Triangle)iii[k])
                return false;
        return true;
    }
    static void Main(string[] args)
    {
        Console.WriteLine(CheckTriangleTest());
    }
}
よく考えてCheckTriangleを作らないと、全ケース通らないと思う。

05/03/21(月)

一昨日の三角形の判定を簡単にできるように、 VS.NET 2003用のプロジェクトにした。 http://plaza.harmonix.ne.jp/~fakira/turedure/TriangleCheckTest.zip 素直にエラーをつぶしていけばできるはずだが、はまるとできないかも。三項演算子は使わないこと。

05/03/24(木)

C#がJISになって、 電通大で教えるそうだ。 私は、去年から大学でC#を教えているが、結構、早い方なのかもしれない。 2005 Expressが無料だとよかったのに。
β版は、6月末まで延長されたようだが、もうちょっと伸ばして欲しいなぁ。 授業が7月なので。

05/03/29(火)

今週は、 納品3つ。完了報告と実行計画ばかり書いていて、何がなにやら。

05/04/01(金)

子供が小学校1年生。

スラドより。人はマルチタスクか?
意識はシングルタスクだが、無意識はマルチタスクだ。
時分割では、多少マルチの方が効率がよいと思う。
私は、本を読むとき、1冊読み終わらなくても、平行して何冊か読んだりする。 ひどいときは、上下の本を下から読んだりする。1冊の本でも短編集などは 読むページの順番もばらばらだ。

今月は納品なし、だよね。

WindowsサービスとRemotingを調査。やっぱ、dot NETは楽だね。

読書録。 isbn:4840110328、 isbn:4087733270、 isbn:4087733467、 isbn:4150307210、 isbn:4150307261、 isbn:415030730x。


05/04/02(土)

サービスする人に求めるもの。 正しいことをよく考え、迅速に、謙虚に行うこと。新聞のコラムより。

05/04/07(木)

どうも花粉症のようだ。 しかも、下手すると30年以上そうかもしれない。アレルゲンはいろいろありそうだ。

05/04/08(金)

日経コンピュータで、高校のIT教育 に関しての問題が取り上げられている。 私の考える解決方法は、2つある。1つは、知的好奇心を大きく起こさせることをさせる。 もう1つは、よくできる生徒に教師役を任せる。その生徒はOBでもよい。

05/04/13(水)

中国に観光に行きたいと、常々 思っていたのだが、こんな様子ではあきらめざるを得ない。 中国への観光者数は激減するだろう。中国政府は浅薄である。

05/04/14(木)

またたて込んできた。 今月、新規の引き合いが4件。体が持たないかも。

05/04/21(木)

今週は、 プロジェクト5種類で、打合せが、定例除いて7件。しかも、開発、ケーススタディ、バイトの対応もある。働きすぎだよね。
バイトが身内なので、気が楽だし、仕事の内容も知ってもらえるのがいい。

05/05/09(月)

GWは、妻の実家に帰省。 ヒカルの碁を立ち読みで23巻読了。子供に碁を教えるが、難しくてわからないと言われる。

05/05/10(火)

「ACな人」の法則は、13歳までに 感電の経験があるかどうかだそうだ。 私も洗濯機で洗濯していて漏電していて、感電したことがあるが、13歳以前かどうかは覚えていない。
他にも、(1)ガラスのコップに水を入れて、交流電源で直接、電気分解したところ、銅が溶けて緑青が発生し、 熱でコップを割ったりとか、(2)塩酸を作ろうとして、10個ぐらいの乾電池を直列にして、塩水を電気分解したところ、 塩素が発生し、それを吸って寝込んだりとか、(3)硫酸を作ろうとして湯のもとを燃やしたりとか、 (4)乾燥剤を集めて、水をかけて、爆発させたりとか、 (5)爆竹をばらして炭と混ぜて燃やしたりとか、(6)竹筒で鉄砲作ったりとか、我ながらとんでもないことしているなぁ。

05/05/11(水)

バグった。 コピーコンストラクタで、オブジェクトを普通に代入して、共有してしまった。Cloneして代入しなければいけなかった。 こんな単純なやつは、自動的にチェックしてほしいな。

05/05/18(水)

コンパイル時のエラー検出。 ladybugさんの記事は参考になるなぁ。 http://d.hatena.ne.jp/ladybug/20050512
オーバロードして、[Obsolete("...", true)] [EditorBrowsable(EditorBrowsableState.Never)]をつける。

05/05/26(木)

コーディングルールで、 「catchする例外クラスは、なるべく具象にし、Exceptionを使わない」というものがある。 理由は、catchで対応しようとしている例外以外が発生したら、わかるようにするためのもので、当然そうすべきであろう。 しかし、実際にはcatch (Exception e)ばかり書いている。面倒なだけだが、今後あらためようか。 1つ嫌なのは、複数の例外クラスを一箇所でキャッチできないことだろうか。gotoで飛ばすか。

05/05/27(金)

トレンドマイクロのバグ騒動は、 日本全国大変だったようだ。うちの会社では、トレンドマイクロ使っていないので、全く関係なかったが。
この事件は興味深い。おそらく、この種の事件は、今後も(事故でも、テロでも)続くだろう。 ユーザ側は、(1)1社のソフトではなく、複数のソフトまたは複数のOSを使う、(2)同時に更新するのではなく、時間をずらす、 (3)バックアップシステムを併用する、(4)完全に閉鎖ネットワークとする、などの対策をとらざるを得ないだろう。
トレンドマイクロの事件は、いくつかの企業等では業務に致命的だった。これを教訓とすべきである。

05/05/31(火)

来年度から、 年間営業日の日数を固定化するらしい。で、6日ほど土日出勤増えたようなんだが。
今年度は、残り半分休まないと、有給捨てられてしまうので、有給の申請をする。 それでも10日ほど捨てられてしまう。入社以来、毎年捨てているけど。
自宅をリフォーム中。結構、大変。私は家にいないけど。

05/06/01(水)

nintendogsの すれ違い通信中に家にかえらずに、電源を切るとプレゼントが消失することに気づいた。

05/06/03(金)

交通費を 毎月清算するようにとおしかりのメールをもらう。 システムが、もっと、使いやすければいいんだけどね。

05/06/06(月)

図形を選んでIQを 計るサイトで、IQ above 171を出してみる。これ以上いくのだろうか。

動的計画法によるTSPのプログラムをC#に移植。(そのまんまだ)
http://blog.livedoor.jp/logopt/archives/2005-06.html#20050604
public static double TSP(double[,] dis)
{
	int	n = dis.GetLength(0);
	System.Diagnostics.Debug.Assert(n < 32);
	int	smax = 1<<n;
	double[,] f = new double[n, smax];
	for (int s=1;s<smax;++s) for (int i=0;i<n;++i) f[i,s] = double.PositiveInfinity;
	for (int i=0;i<n-1;++i) f[i, 1<<i] = dis[n-1, i];
	for (int s=1;s<smax;++s)
	{
		for (int i=0;i<n;++i)
		{
			if (((1<<i)&s) == 0) continue;
			for (int j=0;j<n;++j)
			{
				int	k = s | (1<<j);
				if (k == s) continue;
				double tmp = f[i,s] + dis[i,j];
				if (tmp < f[j,k]) f[j,k] = tmp;
			}
		}
	}
	return f[n-1,smax-1];
}
static void Main(string[] args)
{
	double[,] dis = {{0,2,4,5}, {2,0,4,2}, {4,4,0,3}, {5,2,3,0}};
	Console.WriteLine(TSP(dis));
}
有向グラフに対応しているが、無向ならばもっと早くなるかもしれない。 ルートも出せる方がいいだろう。実用的ではないが、考え方を学ぶのにいいだろう。 (いまいち理解していないが)

C#2.0の機能とサンプルをメモ代わりに貼る
/// C#2.0の新機能
/// (1) Generics
/// (2) 型制限
/// (3) Nullable Type
/// (4) Anonymous Method
/// (5) delegateの簡略表記
/// (6) Partial Type
/// (7) yield reurn, yield break

using System;
using System.Collections;
using System.Collections.Generic;

public interface ITest { }
public class Test : ITest
{
    // 以下を定義するためには、デフォルトコンストラクタも必要
    // public Test(int i) { }
}

public partial class Templ<T> : ITest where T : ITest, new()
{
    // これは、書けない。制限はシグネイチャではない
    // public void Func<U>(U u) where U : struct
    public void Func<U>(U u) where U : class
    {
        Console.WriteLine("Simple {0} {1}", typeof(T), typeof(U));
    }
}

public partial class Templ<T> : ITest where T : ITest, new()
{
    // whereからnew()などを取ることはできない
    public void Func<U>(Templ<U> u) where U : ITest, new()
    {
        Console.WriteLine("1 step {0} {1}", typeof(T), typeof(U));
    }
    public void Func<U>(Templ<Templ<U>> u) where U : ITest, new()
    {
        Console.WriteLine("2 step {0} {1}", typeof(T), typeof(U));
    }
}

public class MyList : IEnumerable
{
    private int[] ii;
    public MyList(int[] ii0) { ii = ii0; }
    public IEnumerator GetEnumerator()
    {
        foreach (int i in ii) yield return i;
    }
}
class CS20Test
{
    static void Main(string[] args)
    {
        Templ<Test> t = new Templ<Test>();
        Templ<Templ<Test>> s = new Templ<Templ<Test>>();
        t.Func("");  // Simple Test System.Int32
        t.Func(t);  // 1 step Test Test
        t.Func(s);  // 2 step Test Test

        int? ni = null;
        Console.WriteLine("Null [{0}]", ni+1);
        ni = 1;
        Console.WriteLine("Null [{0}]", ni+1);

        int k = 0;
        Action<int> a = delegate { Console.WriteLine("OK {0}", k); };
        int[] ii = {2,4,8};
        MyList ml = new MyList(ii);
        foreach (int i in ml) a(k = i);
    }
}


05/06/07(火)

OR学会誌の特集は、XMLデータベースだ 。理論的な説明も多い。RDBをベースにXMLDBを制御しようと、大手RDBベンダを中心にやっているようだが、 私には無駄な努力に思われる。XMLが適しているのは、データ交換である。データのシリアライズにXMLを 使うのも(いろいろ気をつければ)OKである。しかし、検索には向かない。

最近、外部データは基本的にXMLにしている。利用法は2パターンある。

  • DataSetをベースとする。スキーマからDataTable、DataRowを基底にしたクラスを自動生成して使う。 DataGridにそのまま指定できるので、同期を気にする必要がない。自由なデータ構造を作れないのが欠点。 「最適生産計画」は、このパターンを用いている。
  • 任意データ構造で持つ。DataGridとの同期用に汎用クラスライブラリを用いる。関連のあるメンバの設定は、 文字列をIDにして、ポインタで格納する。データの取得は、ポインタなので早い。 「パケットシミュレーション」は、このパターンを用いている。
どちらもXMLでのシリアライズは、簡単に行える。

05/06/09(木)

「どうせ落ちるなら、とことんまで」 という話を聞くと、アイスバーンの谷川岳で目の前で滑落していった後輩を思い出して、「止まれるものなら一瞬でも早く」と思う。 実際に落ちていったのは、途中からはザックだけだったので、後輩は助かったが。そのザックは、半年後に見つかった。

05/06/14(火)

日経コンピュータが 新しくなった。見た目が日経っぽい。正直、これという記事はなかった。
「システム企画の勘所」では、いきなり「サプライチェーンの最適化」で始まっていて、おぉっと思ったものの、 最適化の話は、一切ない。サプライチェーンもほとんど関係ない。ただ、言いたかっただけのようだ。 ユーザよりの記事ばかりだ。

はてなで、「1000個の商品から、ちょうど10万になる組合せをExcelで求めるには」という質問があった。 Excelじゃないが、FindJustFileでできる。1000個の乱数でやってみたが、1分以内で厳密解が出る。 http://www.vector.co.jp/soft/winnt/util/se358350.html


05/06/15(水)

Virtual PCは、 *.vmcのethernet_card_addressタグでMACアドレスを指定できる。 適当に変えて、ipconfig -renewとしてみた。

部のサーバのHDが死んだようだ。 重要なのは、ローカルにしか入れていないつもりだったが、なくなるとやはり痛い。


05/06/20(月)

C#2.0では、GZipStreamが ある。ためしに使ってみたら、ちゃんとできた。PDF用のもほしいなぁ。

プログラマは、将来、どうやって稼ぐか考えた方がいいな。昔は、「なんとかなる」と 思って深く考えず、効率だけ追求していた気もするが。人脈も育てる努力も必要だな。

昔から絵を描くのがうまかった。うまいと言っても、写真のように正確に写実的に書いているだけであって、 芸術性がない。しかし、プログラミングは(密かに)芸術(アート)だと思っている。 なぜなら、誰でも作れるものではないものを作っていると思っているからだ。 毎度毎度、違うものを作っているし。


05/06/21(火)

とりあえず、 国でプログラマのコミュニティのインフラでも作って、公務員としてもプログラマの専門職を作って、高給でやとえば、多少よくなるんじゃないだろうか。

WordやPowerPointにSVGファイルをドラッグすると、絵が挿入される。Excelではされない。 いまいち、バグっているようだが。

先日、授業参観があった。ようやく学校にもなれたところか。算数は、まだ、1桁の足し算しかやっていない。 家に帰って Console.WriteLine(1+2); なんてものを娘に教えると、数字を変えて結果が予想と合うのを、よろこんでやっている。(まだ Hello Worldは教えていない。)
この武器(VS.NET)がいかに、強力かわかるのはいつだろうか。

ニンテンドッグスは、一度もすれ違いしないまま、16犬種そろってしまった。


05/06/27(月)

「検索条件をRSSで返す」 というのは、面白い。

日経ソフトウェアのコラムで「TVとインターネットが癒合するかどうか」の問いに「融合しない」 との意見があった。私は融合するかもと思う。
インターネットの普及に従い、TVの視聴時間が減少している。 調べたわけではないが、民放の収入は厳しくなりつつあると思う。ならば、 インターネットでも見られるようにし、広告収入を増やそうとするのではないか。
6年後にアナログ放送が停波し、チューナーをつけない旧来のTVでは視聴できない。 どこかでインターネットに地上波をTVで流し、デジタルTVを買わない人が見られるように なるのではないか。
という気がする。うまく説明できないが、2011年までには現在のTVの常識が変わっているような気がする。

巷にソースコードはあふれているが、ソースコード読む人はあまりいないんじゃないかと思う。 私はよく読んだ。ベーマガを打ち込んだり、junetで見つけたり。 rogueをhackのように「お店」が出てくるように直したりもした。(店主は作らなかったが)


05/06/28(火)

だいぶ前に落としたSolaris10を VirtualPC5.3に入れてみる。既に2回失敗していて、今回も起動すると横長に真っ黒になってダメだと思ったものの、 真っ黒になる前にコンソールでログインできることに気づく。調べてみても中々解決方法が見つからなかったが、 いろいろやっているうちに、kdmconfigでキーボードを日本語キーボードに指定し、テストで画面の設定をしたら ちゃんと起動するようになった。ユーザを作成して、(何年もUNIX使ってないし)シェルはCシェルにする。 コンパイラが入っていない。ここにあるようだ。入れてみるか。 http://www.sunfreeware.com/indexintel10.html Solarisはネットワークの設定をしないつもりなので、面倒だがファイルは、ISOに焼いてCDとしてマウントさせた。 こんな感じ。
gzip -cd /cdrom/cdrom0/*.gz > tmp; pkgadd -d tmp
/usr/local/lib/gcc-lib/i386-pc-solaris2.10/3.3.2/install-tools/mkheaders
もっといいやり方はあると思うが。
LD_LIBRARY_PATHを設定して、とりあえず、コンパイルできるようになった。

05/06/29(水)

Ajaxは、エイジャックス と発音するらしい。
正露丸は、神経毒が成分になっていて危険だそうだ。

@ITの記事から
http://jibun.atmarkit.co.jp/ljibun01/special/senpai/senpai01.html
http://jibun.atmarkit.co.jp/ljibun01/special/senpai/senpai02.html
以下、全部、自分のこと。

  • 手ぶらで質問をする。
    あぁデフォルトでそうだ。ジャブみたいなもんだからかな。
  • 教わってないからできない。
    言うこともあるな。プロジェクトの多くは、そうだな。教えてくれる人もほとんどいないけど。
  • 開発案件がどうやって利益を得ているか知らない。
    いや、ほんと、どうして、もうからないんだろうね。
  • ビジネスマナーがない。
    その通り。
  • メールの書き方を知らない。
    最近は、便利なので調べればある程度は。
  • スケジューリングしない。
    しないことはないな。守りたくないときもあるけど。
  • ホウレンソウは苦手。
    そのつもりはないな。
  • やりたいところしかやらない。
    気持ちはそうだが、やらざるをえないことはやる。
  • 納期の重みが分からない。
    自社の利益のためというか。契約不履行にならないようにじゃないのかな。 納期の重みもプロジェクトでいろいろあるし。
  • リセットしたがる。
    昔もそうだが、今でも半分以上そうだな。

05/07/01(金)

「デスマーチが起きる理由」より
『より多くの仕事が回ってくるようになっても、それに比例するほどには評価は上がらない』
http://www.hyuki.com/yukiwiki/wiki.cgi?%A5%C7%A5%B9%A5%DE%A1%BC%A5%C1%A4%AC%B5%AF%A4%AD%A4%EB%CD%FD%CD%B3
以下はグチだ。
6月末が年度末で、このまえ評価が終わったばかりだが、私の評価は「平均」である。 私も「魔法のように」仕事を片付け、忙しそうに見えないだろうが、売上から直接費と 間接費を引いた売上利益は、私の年収の5倍近い。しかも、営業の技術サポート、部内の教育、社内の事業開発、他部のサポートもしている。 グチは妻に聞いてもらったので書くのはやめた。

今年の新人は優秀だ。


05/07/04(月)

子供に読んだ本を 登録するように言ったら、喜んでやるようになって、週末に30冊以上も登録していた。 私は、700冊ぐらいだから、すぐ抜かれそうだ。 ブログに読書感想文を書いて、リンクを張ったり、リンク先の内容を取得してまとめたりできるようになると面白いかも。 もう少したったら、専用PCを買ってブログでも書かせてみようか。

10倍づつ早くなる歯車を 10個並べたら、光速を超えるか?
http://www.hatena.ne.jp/1120410644
私も同様の疑問で長いこと気になっていたことがある。結局、光速以上で回ることはない。 なぜなら、物体に伝わる力も波であり、光速を超えない。 例えば、非常に軽くて丈夫な棒の端を引っ張ると、反対側の端が引っ張られるが、これも光速を超えることはない。 歯車Aを歯車Bが押しても、その力は光速を超えて伝わらない。無理にやろうとすれば、物体が破壊されるだけだろう。

C#2.0でC++STLのvectorに対応するものを探すが、見つからない。調べてみるとListであった。あれ、 じゃリストは?と思って調べるとLinkedListであった。HashtableはDictionaryだし、SortedListは、SortedDictionaryだ。
まとめてみよう。
C#1.XC#2.0
ArrayListList<T>
リストLinkedList<T>
HashtableDictionary<T,U>
SortedListSortedDictionary<T,U>

先生のところのをC#2.0に移植してみた。
http://blog.livedoor.jp/logopt/archives/2005-07.html#20050703
using System;
using System.Collections.Generic;

/// <summary>ビンパッキング</summary>
class BinSet
{
    private decimal capacity;
    /// <summary>1本のビンの容量</summary>
    public decimal Capacity { get { return capacity; } }
    /// <summary>残り容量</summary>
    private List<decimal> free;
    /// <summary>ビン数</summary>
    public int NumBins { get { return free.Count == 0 ? 0 : free.Count / 2 + 1; } }
    /// <summary>コンストラクタ</summary>
    public BinSet(decimal capa)
    {
        capacity = capa;
        Reset();
    }
    /// <summary>リセット</summary>
    public void Reset()
    {
        free = new List<decimal>(14);
    }
    /// <summary>追加</summary>
    public void Insert(decimal d)
    {
        if (d == 0) return;
        if (d < 0) throw new ArgumentException("Out of range");
        while (d > capacity)
        {
            Insert(capacity);
            d -= capacity;
        }
        int k = free.Count, kk = 0;
        if (k == 0 || (d > free[0] && (k == 1 || d > free[1])))
        {
            if (k > 1) free.Add(free[k / 2 - 1]);
            free.Add(capacity - d);
        }
        else
        {
            while (kk < free.Count)
            {
                if (d <= free[kk] || ++kk < free.Count)
                {
                    k = kk;
                    kk = k * 2 + 2;
                }
            }
            free[k] -= d;
        }
        while (k > 1)
        {
            k = k / 2 - 1;
            free[k] = Math.Max(free[k * 2 + 2], free[k * 2 + 3]);
        }
    }
    /// <summary>文字列</summary>
    public override string ToString()
    {
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        for (int i = free.Count - NumBins; i < free.Count; ++i) sb.Append(free[i] + " ");
        return sb.ToString();
    }
    /// <summary>テスト</summary>
    public static void Main()
    {
        BinSet bs = new BinSet(1);
        for (int i = 0; i < 20; ++i)
        {
            bs.Insert((i * 0.1M) % 0.5M + 0.1M);
            Console.WriteLine("{0} ({1})", bs.NumBins, bs);
        }
    }
}


05/07/05(火)

「風邪もひかずに元気に...」 というのは、違和感がある。というのは、たまに軽い風邪をひいている方が健康だと思っているからだ。 全く風邪をひかなければ、体内の抵抗が作られず、結局、重い風邪をひくことになってしまうと思う。

読書録
新卒無業。 isbn:4492260641
大学生は就職考える前に読むべき。 人生に奇跡を起こすノート術 isbn:4877710523
KJ法の方が役立ちそうな気がする。


05/07/09(土)

日本語決定戦から
http://www.tbs.co.jp/nihongo05/
東大レベルだった。間違えたもの。
梨のつぶて。高熱に浮かされる。博士。間髪。態と。怒り心頭に発する。さいさきが悪い。 確信犯。煮詰まる。物語のさわり。檄をとばす。憮然。姑息。潮時。爆笑。アボカド。ぞうっとした。 じっぷん。遺憾。利いたふう。丸坊主。活を入れる。枝もたわわに。雪辱を果たす。 絆が強まる。被害を受ける。上には上がある。采配をふる。おまちどおさま。
てんてこまいも間違えそうだ。

05/07/12(火)

デザインパターンって 例題が大事だと思うんだが、本などでいい例題が少ないと思う。 もともと複雑さを制御するためのものなのに、簡単な例題を扱おうとするから違和感がある。 簡単な例題なら、デザパタを使わずに素直に設計した方が、楽だしわかりやすいしメモリも少ないし実行も早い。 さらに、そういったこと(使ったときと使わないときの比較)を検証しているものも少ない。 で、実際のプロジェクトなんかでも、デザパタを使っているのは無理しているものが多いんじゃないだろうか。 使いたくなる気持ちはわかるんだが、よけいに苦労してもしょうがない。

05/07/13(水)

画像圧縮メモ。
Console.Write(new FileInfo(fnam).Length * 0.001 + " -> ");
Bitmap b = new Bitmap(fnam);
EncoderParameters ep = new EncoderParameters(1);
ep.Param[0] = new EncoderParameter(
	System.Drawing.Imaging.Encoder.Quality, /* 圧縮率 */ 40L);
ImageCodecInfo ic = null;
ImageCodecInfo[] ics = ImageCodecInfo.GetImageEncoders();
foreach (ImageCodecInfo ici in ics)
	if ((ic =ici).MimeType == "image/jpeg") break;
fnam = fnam.Replace(".jpg", "_.jpg");
b.Save(fnam, ic, ep);
Console.WriteLine(new FileInfo(fnam).Length * 0.001);

05/07/22(金)

非常勤でC#2.0を教える。 去年より、ちゃんと聞いている人が多かった。 最初に生徒のレベルを把握するための課題なりアンケートなりをやればよかった。

05/07/25(月)

ASP.NETでファイルのダウンロード。
Response.ContentType = "application/vnd.ms-excel-csv";
Response.AddHeader("Content-Disposition", "attachment; filename=\"abc.csv\"");
Response.Write("abc\n");
Response.End();

05/07/26(火)

昭文社で、震災時帰宅支援マップ というのを売っている。
昔話。 高校のマラソン大会は、浦和-古河の40kmだった。 大学のワンゲルでは、忘年ワン(大月-笹子峠-柳沢峠)の70kmや、歩こう会(大岡山-鎌倉七里ヶ浜)の50kmを歩いたことがある。
自転車では、地図も持たずに、大宮市から世田谷区とか江戸川区から杉並区へ行ったことがある。 合宿だと、北アルプス縦走とか、南アルプス縦走とか、日高山脈縦走とかがある。 (知床に行けなかったのは残念だった。)また、方向感覚がいいので、 山の中でも地図があれば、だいたい居場所がわかる。

いくつかのハッシュコードから1つのハッシュコードを作るとき、uncheckedして足す方法や、 排他的論理和(XOR)を使う方法が考えられる。XORの方が素直かな。

赤は何故赤く見えるのか
http://www.hatena.ne.jp/1121527958
長いので全部読んでない。結局、「わからない」ようだ。
赤が赤く見えるのは、赤い色に反応する視神経につながった脳細胞が活性化すると、「赤く見えた」ように意識するからである。 おそらく、赤の視神経と青の視神経を交換したら、赤いものが青く見え、青いものが赤く見えるだろう。 例えば、あなたが「赤い」と感じる脳の部位と同じところを、生まれてから盲目の人の脳で活性化することができたら、 盲目の人が赤色を知らなくても「赤い」を感じるだろう。
関連する質問で、「私の赤い感じとあなたの赤い感じは同じか?」というものがあるが、 私は、同じと確信している。ただし、異なる人がいない、ということはできないし、いてもおかしくない。


05/07/27(水)

読書録
  • isbn:4022500360
  • isbn:4344002857
    まあまあ。
  • isbn:406211528X
    寝不足だ。
  • isbn:4062115298
    枕にできる。
  • isbn:4087478297
    まあまあ。
  • isbn:4093875596
  • isbn:4798108502
  • isbn:4254126174
  • isbn:4254126158

エイリアス セカンドシーズンを見終わる。 謎は謎のまま、サードシーズンのプロローグで終わった。

インターフェース考
インターフェースとは、切り口である。あるオブジェクトがあったとしよう。 それを刀でばっさり切る。その切り口がインターフェースだ。 切り口は面であり、判子のように決まった形をしており、他の面と重ねることができる。 オブジェクトは、いくつでも面すなわちインターフェースをもてる。 面だけ見ても、オブジェクト全体はわからない。

フレームワーク考
フレームワーク(枠組み)とは、空の箱である。物が入っていることもあるが、たいしたものは入っていない。 箱は、飾りがついたり穴が開いていたり便利にできているが、大きさを変えることはできない。 ふたをして、ラッピングすれば、きれいなプレゼントができる。


05/07/28(木)

「死刑か無罪」のクジを引く
http://www.hirax.net/diaryweb/2005/07/27.html#200507272
この話は、前にも書いたが、もう一度書いてみよう。
http://plaza.harmonix.ne.jp/~fakira/turedure/cprog_02.htm#020311
あなたが、クジを引いたとき、無罪の確率は1/3である。 別の人が、有罪のクジを引いたときも、あなたの引いたクジの無罪の確率は1/3。 従って、残りの1枚は無罪の確率は2/3であり、変えた方がいい。
では、別の人があなたに悪意を持ち、既に結果を知っているとしよう。彼はあなたが上記のように考えることも知っている。 彼は、あなたが有罪のクジを引いたならば何もせず、無罪のクジを引いたら有罪のクジを引くつもりだったとしよう。 この場合、彼が有罪のクジを引いたとき、あなたが変更すると無罪となる確率は0である。 しかし、問題文では、別の人はクジの結果を知らないと読み取れるので、このシナリオは成り立たない。

上級者は「マイドキュメント」を使わない
http://arena.nikkeibp.co.jp/col/20050722/112907/
確かに、マイドキュメント直下には、テンポラリの物だけで、バックアップ対象外だな。 バックアップもデータのみ(3GB)だ。 グラフで使用容量を見えるツールを作って、HDの整理をし、1GBぐらい消したが、こまめに消している方ではないな。


05/08/02(火)

.NET Expert #01 がよい。 isbn:4774124532
VS2005β2がついているが、いらんのにと思ったが、Team Suit版だった。 記事も、ほとんど知らないことばかりで参考になる。 Team Suitの製品版が欲しくなる。でも高いよね。

05/08/15(月)

子供の読書数は、 130冊を超えた。1.5cmの厚さの字ばかりの本を1日に10冊も読んでいたりする。 いやはや。私よりよく読む。

非常勤の課題がいくつか届いた。私のサンプルと全く同じものばかりだ。これでは、批評のしようがない。


05/08/16(火)

OR学会誌の恩師の記事を 読んでいたら、自分の名前が出てきて驚いた。 「私が修士の時に作成した内点法のプログラムを維持できなくて残念」とのことだ。 こんなことを書くと怒られそうだが、内点法のプログラムは、私も紛失してしまったが、 当時作ったいくつかのユーティリティやゲームは今も持っている。とはいえ、今見ると何のプログラムだかよくわからないのも多い。 わかるものは、
  • 囲碁の手筋確認ツール。藤沢秀行名誉棋聖の本のデータを入力。 オリジナルは、X11用だったが、Macintoshのハイパーカードに移植したり、.netに移植したり。
  • クロスワード風パズル。
  • yahtzee。全ての状態の全ての役の期待値を計算できる力作だが、デバッグは無茶苦茶大変だろう。
  • interplay。4×4×4の4目並べ。
  • WordBowl。ハングマンとボーリングを組合せた私のオリジナルゲーム。
  • 全域木を全列挙するプログラム。授業で聞いて面白かったので、プログラムを作って勝手にレポートを書いて提出したら、えらい感動された。 アルゴリズムは、全く覚えていないが、メモリー関連のバグで苦労したのは覚えている。

05/08/17(水)

クリックワンスの例として、 「何でも開きます」というのは、どうだろう。1年に1回ぐらいしか使わない拡張子を見るために、 何らかのソフトをインストールするより、こういったサービスを利用する方が気楽だ。 アプリやフォーマットだって日々バージョンアップするし。既にあるかもしれないが。

Windows Media Playerなどで、画面キャプチャがうまくいかないことがあるが、 dxdiagでアクセラレータを切るとキャプチャできるようになる。


05/08/18(木)

非常勤の課題が、 結構集まってきた。結構、工夫されてあるものもあり面白い。

以前、プログラミングは芸術だと書いたが、工芸の方がぴったりくる。


05/08/21(日)

全域木を全列挙するプログラムを 見直して、アルゴリズムを思い出したので、書いておく。
目的はグラフから全域木を全列挙すること。
そのためには、グラフの式表現を求め、式表現を展開する。
例えば、三角形のグラフで各辺をそれぞれa,b,cとすると、 式表現は[abc]となり、これを展開するとab/ac/bcとなる。
グラフの式表現は以下のように求められる。 まず、辺に式表現を持つようにする。辺の最初の式表現は、アルファベット1文字としよう。
グラフは、式表現を維持しながら辺または辺と点を削除できる。このようにして、 グラフが1点になったときに式表現が求められる。
グラフGの式表現(Expr(G))は、任意の1つの辺Eを選んで以下のように変形できる。
Eを取り除くと、非連結になる場合:Expr(G)=Expr(E)Expr(GからEを縮約)
非連結にならない場合:Expr(G)=([Expr(E)]Expr(GからEを削除)+Expr(E)Expr(GからEを縮約))
辺を縮約とはその辺を長さ0にして、両端の点を1つに変える操作である。 式表現には、以下の種類がある。
  • (A+B):展開するとAの展開リストにBの展開リストが追加される形となる。 尚、展開した結果が同一であれば片方を削除する。
  • AB:展開するとAの展開リストとBの展開リストを組合せて文字を並べたものとなる。
  • [AB]:ABの展開リストの要素ごとに、1文字づつ消去して展開をさらに行う。 例えば、[abc]は、abとacとbcの3つに展開される。
さて、最初のルールだけでもできるが、大変なので特殊ケース用のルールも書いてみよう。 (最初のルールと同義である)
  • 辺Eと辺Fが(同一の点どうしをつないでいる)多重辺の場合:Expr(E)←(Expr(E)+Expr(F))として、 辺Fを削除した後のグラフについて求める。
  • 辺Eが自己ループの場合:Expr(G)=[Expr(E)]Expr(GからEを削除)
  • 辺Eの片方の端点の次数(接続する辺の数)=1の場合:Expr(G)=Expr(E)Expr(GからEを縮約))
  • 上記のルールを適用すれば、残りのどの辺を削除しても非連結とならない。
  • 辺Eと辺Fが点Vで接続しており、点Vの次数=2の場合:Expr(E)←Expr(E)Expr(F)として、 辺Fを縮約した後のグラフについて求める。
例として4点の完全グラフの場合、式表現は(([afce]+d[af][ce])+b[(a+e)d(c+f)])、展開すると afc/afe/ace/fce/dac/dae/dfc/dfe/bad/bac/bdc/baf/bdf/bed/bec/befとなる。
Cのプログラムは500行で、C#では330行ほどであった。

05/08/22(月)

非常勤の課題は、結局、 2/3ぐらい集まった。残りの人は、単位いらないんだろうか? 後半は、工夫している人はほとんどいなかった。また、完成していない人も多かった。

05/08/23(火)

以前作ったWikiCSを Ajax対応にして、公開してくれている人がいる。 http://plaza.harmonix.ne.jp/~fakira/turedure/cprog_03.htm#030616
http://proceed.fam.cx/wikics/
Monoらしいが、さくさく動く。次は、ブログシステムとかですか?

読書録。isbn:4839911118, isbn:4839911126, isbn:488380478X。

2004年度のNTTデータの外注費比率は88%、NRIが77%、TISが74%、CSKが60%。 私は外注と仕事したことはあるが、使ったことはないな。


05/08/24(水)

矢印の描画は、 自作してた。CustomLineCapを使った方がスマートと思ったが、
ladybugさんよりAdjustableArrowCapの方がよいとのご指摘。

05/08/25(木)

物流モデルにおいて、 戦略レベル、戦術レベル、運用レベルで統一的に扱うデータとして、 全レベルの情報を全て持つ方法がある。これをオブジェクト指向風に、 各レベル毎にインターフェースを定義するのはどうだろうか。 実際には問題グループ毎にインターフェースを定義する。データの方は、 解きたい問題のインターフェースを継承して実装する。 例えば、ネットワーク問題と配送問題を解きたければ、両方のインターフェースを実装するなど。

public interface ITest1
{
  string Name {get;}
}
public interface ITest2
{
  string Name {get;}
}
public class Test1 : ITest1
{
  public string Name {get {return "Test1";}}
}
public class NewTest : Test1, ITest2
{
  public string Name {get {return "NewTest";}} // (1)
}
例えば、上記のようなクラスが合ったときに、下記はどのような出力になるか?
NewTest org = new NewTest();
Console.WriteLine(((ITest1)org).Name);
Console.WriteLine(((ITest2)org).Name);
最初の出力は、Test1である。クラスNewTestを修正して最初の出力をNewTestにするには どうすればよいだろうか?回答は、ちょっと気持ち悪い書き方になる。
尚、上記の(1)のpublicをとると、また違う結果が得られる。

家で、ADSLから 光ファイバになった。無線LANも使えるようになった。


05/08/30(火)

Acrobat Readerで読み上げ ができるそうだ。携帯かPDAで動くと便利そうだな。

人が書いたプログラムの計算式に「+10」されているかどうかの確認で、 10で検索すると6万5千行もヒットする。が、ヒット行を頭から眺めると該当箇所がすぐわかった。 たまたまだが。

CiNiiって便利だね。 本文読むには、登録が必要だけど。

gotoを使うべきか?
理想的には、言語にgotoがそもそも存在しなければよい。 で、(多段ループの脱出などの)使いたい状況では、 使わなくてすむような機能が備わっていればいい。
現実論では、シンプルになるなら使ってもよい。(ただし、よく考えること)
gotoのデメリットとしては、わかりにくさ、保守しにくさの他にも、 最適化されにくい(推測)、デバッガが挙動不審になる(Cで体験済み)などもある。
わかりやすさっていうのは、習慣に関係するので、水掛け論になりやすい。


05/08/31(水)

Array.Initialize で初期化しているつもりだったが、何もしてくれない。Array.Clearでできた。

05/09/01(木)

非常勤の授業の休憩時間に 家と電話を話していたら、マイクがONのままで、教室に筒抜けとなったしまった。
授業に出てきた学生は、9割ぐらい課題を提出したようだ。(課題未提出者は、授業にも出ていない人が多かった。) 思ったより多かった。もっと、いろいろ工夫が見られるとよかったのだが、難しいか。

子供が、夏休み中に読んだ本は100冊になったらしい。リストを印刷して学校に持っていったのだが、 先生には渡せなかったようだ。


05/09/04(日)

囲碁ツールを また作ってしまった。
http://plaza.harmonix.ne.jp/~fakira/turedure/IgoMaster.zip
著作権放棄の手筋集とかないだろうか。

05/09/05(月)

郵便もしくはメールで、 こんなサービスはどうだろうか。
お客は、店から商品を購入したいが、自分の住所は知らせたくない。 そこで、自分の住所を郵政公社の公開鍵で暗号化して、店に伝える。 店は、暗号化された住所のまま郵便局に持っていく。 郵便局では複合して配達する。

法律用語では、「及びと並びに」や「若しくはと又は」は厳密に使い分けられているらしい。


05/09/07(水)

CD-ROMでWindowsXPを起動できるBartPEを作った。 フリーである(Windowsのライセンスを除く)。 日本語は、Ver3.0.32じゃないとダメなようだ。 デスクトップは有線だがネットワークがつながらない。 ノートは、無線はダメだが、有線はなんとかつながる。 USBメモリは認識しない。 少なくとも、ノートは、OSが死んでHDが生きていれば、ネットワーク越しに コピーはできそうだ。KNOPIXでもできればいいんだけど。

05/09/09(金)

妻が翻訳した本が、 やっとアマゾンにのった。 isbn:4254270127
写真もなし。在庫もなしというのは、どういうこった。
売上貢献のために、これから、中身を紹介していこう。

05/09/14(水)

汎用的なグラフクラス。 グラフの要素には、ノードとアークがあるが、汎用的なデータ構造では、 さらに、接続(ノード識別子とアーク識別子の組)とリンクがあるべきだ。 リンクは、リソースであり、アークとリンクは、有向グラフでは1対1となり、 無向グラフでは2対1となる。
このようにすれば、同じ1つのクラスで、無向グラフとしても有向グラフとしても使える。
大抵のグラフクラスは、内部に隣接行列を持つが、汎用的なものでは、 隣接行列は、内部に持たずに動的に作成し、必要ならキャッシュすべきである。 理由は、denseとsparseに対応させるためだ。
また、これまでの経験から、ノードとアークはランダムアクセス可能であるべきだ。

05/09/15(木)

健康診断の結果が返ってきて がっくり。視力検査の結果は、その場で確認したのと違っいて明らかにおかしい。 再検査はバックレよう。

05/09/22(木)

満員電車の天井付近に クモが巣を張っていた。 獲物はかかってないようだが、結構ゴミがくっついている。 車内清浄に貢献しているようだ。今にも壊されてしまいそうだったが.
電車内にも空気清浄機とか加湿器とか置いた方がいいような気がする。特に冬は、風邪予防にならないだろうか。

05/09/29(木)

Solaris 10(x86,Sparc32、Sparc64)でMonoが 動くらしいが、やってみたが、ダメだった。
経緯を書く。
g++3.3.2を入れる。makeをいれる。普通は、configureしてmake、make installだが、 makeの作成にmakeは使えないので、sh build.shで行う。
次のを入れようとしたら、arがないと言われる。 arなんぞ、転がってないようなので、HD内を探すと、/usr/ccs/binにある。ここにmakeもある。 なんだ、最初からpath通っていればよかったのに。 2つもあると嫌なので、後から入れた/usr/localのmakeは消す。
ちなみに、/usr/local以下はa+wにしており、 通常ユーザでインストールしている。
さて、Monoを入れようとするとbisonを入れろと言われる。 bisonを入れようとすると、m4を入れろと言われる。m4は、/usr/ccs/binにあるのに、GNU m4でないとお気に召さないようだ。 で、m4を入れて、bisonを入れる。これで、Mono 1.1.9のconfigureは通る。
しかし、makeは通らない。ここであきらめて、1.1.8を試す。同じくダメ。1.1.7がダウンロードできないので、 1.1.6を試す。同じエラーだ。-tオプションがないと言われる。関係しそうなMakefileの-mtオプションを-mに変更する。 monoburgでlibgthreadだかなんだかがないと怒られる。monoburgをスキップする。次のは、コンパイルエラーだ。 引数の数が合わないようだ。ソースを直すが、通らない。あきらめる。

05/10/04(火)

Logi-Biz9月号は、 物流行政の新常識が特集となっていて面白い。また、東京海洋大学が理系で唯一のロジスティクス学科を 持っているという記事もある。東京海洋大学の歴史は岩崎弥太郎に始まるらしい。日本郵船と同じだ。 1990年から情報系の科目が追加されたという。(私も手伝っている)中々いい記事だ。

05/10/05(水)

あっけなく決着がついたかに 見える郵政民営化だが、(失敗したときの影響は半端ではなく、ツケは国民に回ってくるのだから)慎重な議論を重ねてほしい。
郵政公社は、ロジスティクスの高度な専門部隊を持ち、国内外を問わず、コンサルを提供できるぐらいになってほしい。

05/10/06(木)

過去はワークステーションのUNIX上の、 現在はPCのWindows上ののアプリケーション作成がメインだが、 将来は組込みに近い小型PCも増えるかもしれない。そのときのOSはLinuxの可能性も高い。 やはり言語はC#がよいので、MonoやGNU C#も商用で十分通用するようになってほしい。
現在、dot netはOS上のフレームワークだが、将来はOSの一部になるだろう。 また、さらに進めば、汎用のアプリケーションに特化したフレームワークのようなものが登場し、 多くのソフトがそのフレームワーク上で動くだろう。 フレームワークの提供する機能により、ソフト自体は人格があるように見える。 あるいは本当の人間(サポート)とシームレスに結びついていている。(SFのように聞こえるが)

05/10/14(金)

共同主催の3日間のセミナー が無事終わった。講師の方はお疲れ様。 懇親会の偉い人の熱弁や、若い人の本音が面白かった。

05/10/21(金)

DEAの重みは、 各DMUが任意に決められることになっているが、ここに制約を入れた制約付DEAを考えても面白いかもしれない。

喫茶店で、1杯500円のコーヒーの定期券を4000円で売ろうとしているとしよう。 客は、月に9回以上利用すれば、定期がお得だが、その見込みがないと定期を買わないかもしれない。 こういうのは、どうだろう。
8枚4000円でコーヒー券を売る。客は、帰るときに、チェッカーに券を入れる。 もし、その月の利用が9回目以降なら、チェッカーは1回券をそのまま戻す。 これだと、8枚で1ヶ月に飲み放題。しかも、券が余れば、翌月でも使える。


05/11/01(火)

LogiBiz11月号に、 ドイツポストが、世界最大の3PLのエクセルを買収して、ロジスティクス部門の強化に乗り出す記事があった。

仕事が切羽詰っている。


05/11/07(月)

XMLで、 XmlArrayとXmlArrayItemで配列のタグを指定できる。

05/11/09(水)

IDEでお気楽入力 していると、スペルミスを見逃す可能性が高い。 ついこの前も、XxxConnnectなんて変数名のスペルミスを数十ヶ所で使っているのに気づかなかった。 (検索しても出てこなくてはじめて気づいた)

05/11/16(水)

size_tについて。 STLで、for (int i=0;i<v.size();++i) などと書くと、 「signed と unsigned を比較している」と警告が出る。
これは、size_tがunsignedなためだ。これを消すために、iをunsignedにしていたら、バグった。
for (uint i=0;i<v.size()-1;++i)としたときに、size()が0だと、おかしくなる。 size_tがunsignedだと、添え字の範囲チェックで「i>=0 && i<size」が 単に「i<size()」で済む。しかし、このようなバグを考えると、size_tはsignedであるべきだ。 CLIではそうなっている。

05/11/17(木)

単方向リストのデータがおかしくなって、 ループしているときに、これを判定するにはどうすればよいか。
ループしていれば、先頭からたどっていけば、同じアドレスが出てくるので、 ハッシュにでも覚えていけばできる。しかし、情報を2つしか持たなくても以下のようにできる。
bool IsLoop(List p)
{
  List q = p;
  while (p != null && q != (p = p.next) && p != null)
  {
    p = p.next;
    q = q.next;
  }
  return p != null;
}
(@ITの会議室では、ちょっと間違えた。)
pはqの2倍の速さで進むので、ループしていると追いつく。

神社なんかで願い事をするとき、「世界平和」を願っている。(本当の話である) しかし、世界平和とは抽象的すぎる。よく考えると、人によって世界平和の意味は違うような気がする。抽象的な願い事をしても意味がないような気がするし、「XXXの紛争がなくなりますように」とかの方がいいのかもしれない。
全知ならば全能であるはずである。しかし、全能とは実現できないものかもしれない。 全知とは、そもそも自己矛盾なのかもしれない。

ソフトウェア開発をシンプルにする考え方のコツに、日付をチェックする機能を作れというのがある。私だったら、次のように書く。
/// <summary></summary>
public sealed class Date
{
	private int		year;
	private int		month;
	private int		day;
	/// <summary></summary>
	public Date() : this(0, 0, 0) {}
	/// <summary></summary>
	public Date(int y, int m, int d)
	{
		year = y;
		month = m;
		day = d;
	}
	/// <summary></summary>
	public bool IsValid()
	{
		try
		{
			DateTime dt = new DateTime(year, month, day);
		}
		catch (ArgumentException)
		{
			return false;
		}
		return true;
	}
}
要点は、

  • publicなものには、空でもコメントを書く。(中身はリリースまでになるべく埋める)
  • アクセス修飾子は、必ず書く。
  • デフォルトコンストラクタは書く。
  • このくらいの規模だと、sealedで封印する。
  • チェックは、コンストラクタでなく別のメソッドを設ける。
    結果をキャッシュしない限りプロパティにはしない。
  • チェックは、楽をできるなら楽をする。(速度が気になるなら自前でチェックするだろうが)
  • DateTimeはstructである。classとstructの境界は、私の場合、48ビットぐらいだ。
    よほどのことがない限りメンバにshortを使わないが、メンバがshortならこのクラスをstructにするだろう。
記事の内容は、トップダウン開発の勧めだが、ある程度、開発の規模が大きくなればボトムアップでもやる方が効率がいいだろう。

05/11/18(金)

昨日のリストの問題。 こんなのは、どうだろう。
public class Test
{
	private class Brother
	{
		private bool        b; // 兄だけ進む
		private IEnumerator p; // 兄
		private IEnumerator q; // 弟
		public Brother(IEnumerator it1, IEnumerator it2) {b = true; p = it1; q = it2;}
		public bool IsSame() {return p.Current == q.Current;} // 手抜き
		public bool MoveNext() 
		{
			if (!p.MoveNext()) return false;
			if (b = !b) q.MoveNext();
			return true;
		}
	}
	public static bool IsLoop(IEnumerable en)
	{
		Brother br = new Brother(en.GetEnumerator(), en.GetEnumerator());
		while (br.MoveNext()) if (br.IsSame()) return true;
		return false;
	}
	static void Main()
	{
		List l = new List();
		l.Add();
		l.Add();
		l.Add();
		l.Add();
		l.top.next.next.next.next = l.top.next.next;
		Console.WriteLine(IsLoop(l));
	}
	private class List : IEnumerable
	{
		public class ListItem : IEnumerator
		{
			public ListItem next;
			public ListItem(ListItem p) {next = p;}
			public void Reset() {} // 手抜き
			public object Current {get {return next;}}
			public bool MoveNext()
			{
				if (next == null) return false;
				next = next.next;
				return true;
			}
		}
		public ListItem top = null;
		public IEnumerator GetEnumerator() {return new ListItem(top);}
		public void Add() {top = new ListItem(top);}
	}
}
ループの有無を兄弟が調べる。兄が2歩行く間に弟は1歩しか歩けない。 兄が弟に追いついたらループしている。

チャレンジ1年生の付録に 電卓みたいなものがあって、「スピード」というゲームがある。 1分に何問の加減算を解けるか競えるようになっている。妻がはまっているので、試しにやってみる。 2桁の加減算は、計算ではなくパターンマッチングだ。結果は、今のところ妻とタイである。


05/11/24(木)

OK/NGなどの 結果をboolで返すことも多いだろう。しかし、後から、OK/NG/Not definedのように 拡張したくなることもあるかもしれない。そのときのために、bool?を使うこともできるかもしれない。
とはいえ、最初に必要ないのなら最初からbool?にはすべきではないだろう。 ただし、ときどき、「もしbool?に変更したら」と考えるのは、よいことだろう。
最初から、bool?にすることは、再利用性を高くしている。bool?に変更されることを考慮しつつも、 bool?を使わないのは、保守性を高くしている。まずは、再利用性を高くするのではなく、保守性を高くすべきである。なぜなら、「こうなったら、」という予想は外れることも多いからだ。

dot NET2.0の新機能。string.IsNullOrEmpty, File.ReadAllLines, StringSplitOptions.RemoveEmptyEntries, Stopwatchなど。

前にも書いたかもしれないが、運用システムをつくるときに、操作のログを収集するといいかもしれない。ネットワーク前提のソフトなら、サーバ上にログを残す手もありかな。


05/11/25(金)

IT専門職大学院の候補に 筑波や東工大があがっているそうだ。両方ともいいんじゃないだろうか。 他にも、北大、東北大、東大、名大、京大などいろいろあるだろうけど。 講師にベンダからも受け入れるみたいな話もある。

05/11/30(水)

子供に年間12冊、 本を読ませようと思っていたが、500冊まで行きそうな調子だ。 本を薦める理由はイメージ創造の演習ができるからだ。映画、漫画、TVではできない。

05/12/01(木)

2^n個の数字を列挙 する場合、(1<<n)回ループすればよい。このとき、なるべくビットの変更が最小になるようにしたいとしよう。
実は、簡単な法則で、変更は常に1ビットすむ。言葉を替えると、n次元単体の辺を周る一筆書きが存在する。 16個でやってみると、列挙は、0,1,3,2,6,7,5,4,12,13,15,14,10,11,9,8であり、このとき、 変更されるビットは、1,2,1,4,1,2,1,8,1,2,1,4,1,2,1である。2回おきに1が、4回おきに2が、8回おきに4が、16回おきに8が、以降も同様に現れる。

ここで、問題
i 番目に対して、変更されるビットを返す関数を作成せよ。


できただろうか。ヒント:関数内は20文字でできる。


答えは、return(i|~(~i-1))-i;である。(もっと、短くなるかもしれない。)


05/12/02(金)

いつものことだが、 思いつきのメモなので、的外れかもしれない。
ClickOnceのアプリケーションでユーザの認証をすることを考える。認証用のデータは当然サーバにおくべきだろう。 すると、クライアントから、サーバに認証の確認の要求をする必要がある。
webサービスを使うことにしよう。サーバにIISが必要になる。(まぁ、よしとしよう) webサービスの実装はASP.NETなので、認証機能が使える。継続的にサーバとやり取りするなら、セッション管理も利用できる。
さて、HTTPだとパケット見られたら、多分、ばれてしまうだろう。かといって、HTTPSにすると証明書が面倒だ。 自前で、暗号化することにしよう。パスワードを生(raw)にせず、クライアントでハッシュにしよう。 単なるハッシュだと、ばれたら一緒だ。クライアント固有の情報とパスワードを合わせてハッシュを作ろう。 クライアント固有の情報も偽装されないようにするのは、大変だ。サーバで作ってやろう。結局、こうだ。
  • サーバで、IDとパスワードを管理する。
  • クライアントからサーバに、Webサービスでワンタイム情報を要求する。
  • サーバでワンタイム情報(S)を作成し、(ID,S)をリストに追加し返す。
  • クライアントで、パスワード(P1)とSから、ハッシュ値(H1)を作り、H1をパスワードとして認証要求する。
  • 認証要求されたサーバは、IDからパスワードP2とリストからSを求め、ハッシュ値(H2)を作る。リストから、キーIDは削除する。
  • H1とH2が同じならば、認証OKとする。
この方法のデメリットは、2回呼ぶ必要があることと、2回の間で割込まれたら、不正に認証されてしまうことだ。
(ワンタイム情報は、パスポートの申請でつかわれる確認はがきのようなものかな。) サーバのパスワードもハッシュで持っておくべき。

株式会社に罪はない。法人が刑務所に入ることはできない。もしあるとすれば、誰が罪を負うのか。株式会社の所有者である株主か。 株主の責任範囲は明確に決まっており、出資リスクだけだ。株式会社の販売した商品に欠陥がある場合、購入者は、売買契約に則ったことしか要求できない。 (もちろん契約にないからといって突っぱねて社会的イメージを損なうことを推奨しているわけではない) 社会的影響範囲が大きいと認められる場合、経営者は早急に手を打たなければならない。基本は、真摯に対応することである。

顧客からソフトの無償バグ対応の期間に対し、疑問を投げかけられた。ハードでも保証は無期限ではないが、一般にソフトの方が短い。 1年、半年などである。
ソフトは目に見えないため、不具合が分かりづらい。従って、保障期間後にバグが見つかることもままあるだろう。 (別途保守契約を結ぶことにより、対応することも多い。)
無償保障期間を長くすると、その分、金額に跳ね返り、販売機会を逃しやすい。また、リスクのぶれも大きい。 これらの原因の1つは、ソフトの複雑さである。ソフトの複雑さを扱う方法が必要だ。


05/12/07(水)

計算書偽装に関して。
1つは、職業倫理は、プロとしての必要条件であるため、プロが職業倫理を保てるような体制が必要だろうと思う。
プログラミングで重要なのは、設計である。プロのソフト設計者としての建築士のような公的な資格があるといいと思う。
もう1つは、「検査の精度を上げるためにかけるコスト」を適正になるように考えるべきと思う。 例えば、今回ほどの偽装であれば、1棟あたり1日チェックすれば、ワーニングは出せるのではないか。

05/12/08(木)

最適化のORセミナーは、 100人ほどの参加者で盛況だった。 今野会長の話が面白く、最適化(ビジネス)の未来は明るいという印象を受けた。

PowerPointと連携して、話している内容をリアルタイムで字幕みたいに出すソフトがあると面白いんじゃないか。SpeechSDKとかでできるかな。


05/12/12(月)

memryというサイトで、 神経衰弱ができる。
http://www.pimpampum.net/memry/enter.php
16枚で神経衰弱をするとき、組合せは、202万7025通り、完全な記憶力を持っていれば、 平均 24.7859695859696 回でできる。

05/12/13(火)

日経コンピュータの プロジェクト実践塾で、プロジェクトマネージメントの分類をしている。 Pは目標達成機能を表し、Mは集団維持機能を表している。 私は、理論派のPm型であろう。理想は万能のPM型で、pM型は気配り派、pm型はリーダに向いていない。
Pm型で注意すべき点は、ダメ出ししても、相手のよい点を言及することだそうだ。気をつけよう。

05/12/20(火)

foreach でindexが 欲しいときなど。
/// <summary>ペア</summary>
public struct Pair<T, U>
{
	/// <summary>要素1</summary>
	public T First;
	/// <summary>要素2</summary>
	public U Second;
	/// <summary>コンストラクタ</summary>
	public Pair(T t) { First = t; Second = default(U); }
	/// <summary>コンストラクタ</summary>
	public Pair(T t, U u) { First = t; Second = u; }
	/// <summary>等値演算</summary>
	public override bool Equals(object obj)
	{
		Pair<T, U> pr = (Pair<T, U>)obj;
		return First.Equals(pr.First) && Second.Equals(pr.Second);
	}
	/// <summary>ハッシュコード</summary>
	public override int GetHashCode()
	{
		return First.GetHashCode() ^ Second.GetHashCode();
	}
	/// <summary>文字列化</summary>
	public override string ToString()
	{
		return First.ToString() + ", " + Second.ToString();
	}
}
/// <summary>トリプレット</summary>
public struct Triplet<T, U, V>
{
	/// <summary>要素1</summary>
	public T First;
	/// <summary>要素2</summary>
	public U Second;
	/// <summary>要素3</summary>
	public V Third;
	/// <summary>コンストラクタ</summary>
	public Triplet(T t) { First = t; Second = default(U); Third = default(V); }
	/// <summary>コンストラクタ</summary>
	public Triplet(T t, U u) { First = t; Second = u; Third = default(V); }
	/// <summary>コンストラクタ</summary>
	public Triplet(T t, U u, V v) { First = t; Second = u; Third = v; }
	/// <summary>等値演算</summary>
	public override bool Equals(object obj)
	{
		Triplet<T, U, V> pr = (Triplet<T, U, V>)obj;
		return First.Equals(pr.First) && Second.Equals(pr.Second) && Third.Equals(pr.Third);
	}
	/// <summary>ハッシュコード</summary>
	public override int GetHashCode()
	{
		return First.GetHashCode() ^ Second.GetHashCode() ^ Third.GetHashCode();
	}
	/// <summary>文字列化</summary>
	public override string ToString()
	{
		return First.ToString() + ", " + Second.ToString() + ", " + Third.ToString();
	}
}
public class PairList<T> : IEnumerable
{
	private IEnumerable		lst;
	public PairList(IEnumerable lst0) {lst = lst0;}
	public IEnumerator GetEnumerator()
	{
		int i = -1;
		foreach (T t in lst) yield return new Pair<int, T>(++i, t);
	}
}
class Program
{
    static void Main(string[] args)
    {
		List<string> l = new List<string>(new string[]{"a", "b", "c" });
		foreach (Pair<int, string> pr in new PairList<string>(l))
			Console.WriteLine("{0} {1}", pr.first, pr.second);
    }
}
1.0からSystem.Web.UI.Pairがあるとは知らなかった。2.0でgenerics版を入れなかったのはなぜだろう。

05/12/21(水)

C++で言うところの 参照のように、nullを代入できない参照。
/// <summary>nullを代入できない参照</summary>
public sealed class NonNullPointer<T>
{
	private T org;
	private NonNullPointer() { }
	public NonNullPointer(T o) { Value = o; }
	public T Value
	{
		get { return org; }
		set
		{
			if (value == null) throw new ApplicationException("Null pointer");
			org = value;
		}
	}
}
pmokyさんの話題から。
http://d.hatena.ne.jp/pmoky/20051217
未テスト。便利かどうかは不明。

05/12/26(月)

冬休みなのに 自宅で一日仕事。休まらなかった。メール受信20通、送信十数通、電話でのやりとり。会社にいるのと変わらない。

プログラミング所感 - 前へ 目次 次へ