第29回 Excel Interpreter(ExcelによるExcelのための変態的プログラム)'99/4/10-99/4/25

今回紹介するのは、Excel用のインタプリタである。はっきり言って、冗談のようなプログラムである。しかし、結構有用なんではないかなーとか思わなくもない。構想2年。製作時間3時間という、謎なプログラムである。

Excelというのは、ワークシート上の関数で制御構造を持つことが出来ない。早い話、forやwhileと言ったものが無いのである。そこで、繰り返して何かをしようと思うと、必ずモジュール(いわゆるマクロのことである。Excelでは、マクロはユーザーの行なった動作をVBA形式で記録したもののことを言うようだ)を組まなくてはならない。

それが故に、ちょっとしたモジュールを小遣い稼ぎに組まなくてはならなくなったりする。みなさん、周知の(?)事実である。

モジュールと言っても、そんな深いプログラムが必要なのではなくて、ループ制御とごく特定の関数だけあれば十分であることが多い。どちらかと言えば、Accessのマクロのように、実行する関数を順番に指定するだけのようなもので良いのである。そういった機能がないもんだから、ちょっとしたことでもモジュールに頼らなくてはならなくなる。プログラマにとってはどうということはない日常的な光景なのだが、パンピーにとってはモジュールというのは恐ろしく敷居の高いものなのだ。

そこで。Excelのワークシートでループ制御等を記述できるような機能を持たせることは出来ないか?というのである。これは、Excel97なら出来なくはない。(ここで説明はしない) ここでは、Excel95でも動くように、ワークシートにプログラムを書く機能をつける方向で進める。

ワークシートにプログラム?

Excelのプログラミングに熟練した人ですら、この発想は理解しにくいはずだ。やねうらおの知人であるベテランExcelプログラマにこのプログラムを見せたとき、

「あ、ああああ、アホやーーーー!!お前、絶対、ぜーーーったい、アホや!!!!なんちゅーことすんねん。凄いわ、自分!」

と賛辞(?)の声をいただいた。要は、ワークシートに記述した文字をプログラムであるとしてインタプリトしていくモジュールを組むのである。


'
' Excel上のデータ系列を一連のプログラムとみなして”実行”するためのインタプリタ
'
' Excel Interpreter by yaneurao '99/4/9
' Excel Interpreting technology was developed by yaneurao '97
'
'
Option Explicit

Sub interpret()

Dim index As String
Dim scanline As Integer ' 実行行

Dim stacks(50) As Integer 'スタックフレーム
Dim stackp As Integer

Dim foundcell As Range

Dim sx, sx2, sl As Integer

scanline = 2 ' 実行開始行
stackp = 0 ' スタックポインタ

While (True)
index = Cells(scanline, 2)
If index = "end" Then GoTo finish_interpret
' ここには内部命令が来る
' If index = "circle" Then
'
' GoTo iloop
' End If
If index = "return" Then
sl = scanline

stackp = stackp - 1
If stackp < 0 Then
MsgBox scanline & "行のreturnは不正です"
GoTo finish_interpret
End If

scanline = stacks(stackp)
sx2 = 3
While (Not IsEmpty(Cells(scanline, sx2)))
sx2 = sx2 + 1
Wend
sx2 = sx2 + 1

' returnが返し値を持つ!
sx = 3
While (Not IsEmpty(Cells(sl, sx)))
Cells(scanline, sx2) = Cells(sl, sx)
sx = sx + 1
sx2 = sx2 + 1
Wend

GoTo iloop
End If
If index = "set" Then
' 変数のコピー
index = Cells(scanline, 3)

Set foundcell = Columns("A").Find(index)
If foundcell Is Nothing Then
MsgBox scanline & "行の変数は未定義です"
GoTo finish_interpret
End If

Cells(foundcell.Row, foundcell.Column + 1) = Cells(scanline, 4)

GoTo iloop
End If
If index = "get" Then
' 変数のコピー
index = Cells(scanline, 3)

Set foundcell = Columns("A").Find(index)
If foundcell Is Nothing Then
MsgBox scanline & "行の変数は未定義です"
GoTo finish_interpret
End If

Cells(scanline, 4) = Cells(foundcell.Row, foundcell.Column + 1)

GoTo iloop
End If
If index = "if" Then
' 変数のコピー
If Cells(scanline, 3) Then

index = Cells(scanline, 4)
Set foundcell = Columns("A").Find(index)
If foundcell Is Nothing Then
MsgBox scanline & "行のジャンプ先ラベルは未定義です"
GoTo finish_interpret
End If

scanline = foundcell.Row - 1
End If

GoTo iloop
End If


If index = "" Then GoTo iloop

sl = scanline

If stackp = 50 Then
MsgBox scanline & "行の関数呼び出しでスタックがあふれました"
GoTo finish_interpret
End If

' どのコマンドにも該当しないということは、これはcall文
stacks(stackp) = scanline ' 帰り先の行-1
stackp = stackp + 1
' jmp (scanline = ...)

Set foundcell = Columns("A").Find(index)
If foundcell Is Nothing Then
MsgBox scanline & "行の命令が未定義です"
GoTo finish_interpret
End If
scanline = foundcell.Row ' これでジャンプ!
'call時の引数のコピー!!

sx = 3
While (Not IsEmpty(Cells(sl, sx)))
Cells(scanline, sx) = Cells(sl, sx)
sx = sx + 1
Wend

iloop:
scanline = scanline + 1 ' 実行行の加算
Wend

finish_interpret:
Exit Sub

End Sub


非常に単純なプログラムだが、必要な言語機能は一通り完備している。

プログラムは行方向に記述して行く。ラベルをサポートしているので、ジャンプ等はすべてラベル参照で行なう。よって行番号という概念はない。

A列には行ラベルを書く。B列にはコマンドを書く。内部で定義されているコマンドは、以下のもの。

get,set,if,return,end

たったこれだけしかないが、あとはお客様の仕様に合わせてモジュール内に自由に追加していけば良い。コマンド名をすべて日本語にして、「ぴゅう太」(誰も知らん?)のような日本語プログラミング環境を構築することも可能である。

コマンドは、5つしかないが、これだけでいいの?とか思われるかも知れない。まずは、変数について考えよう。

変数は、どこかの行の行ラベル(A列ね)に変数名を記述することで変数名と認識される。この行のB列が、変数格納エリアである。Excelのすることなので、文字列であろうが、数字であろうがそんなことはお構いなしである。

A列    B列   C列   D列

      set    j     200
      end

とすれば、変数jに200が代入され

j     200

となる。逆に、変数の値を得たいときは、

A列    B列   C列   D列

      get    j
      end
j     123

のようにすれば、

      get    j   123

と、getの記述した行のD列に、その変数値が代入される。非常にシンプルである。

gotoは、さらに単純で、

A列    B列   C列   D列

      if    true  あっち

あっち  end

のようにすれば、「あっち」にジャンプしてから終了する。ifの行のC列の部分がtrueであれば、D列に記述されているラベルにジャンプするのである。

いま説明した、set/get/ifだけでループ制御が出来る。

   for i=1 to 5  ... next i

と同等のプログラムを書いてみよう。

A列      B列     C列                 D列

        set      I                  1
loop
        get      I
        set      I                =上のセル+1
        if     =右上のセル<=5        loop 
        end

おわかりいただけるだろうか?getすれば、その行のD列に変数値が代入される。モジュール実行中であれ、Excelのワークシートはセルに数値代入を行なうと、それに伴いそれを参照しているセルをすべて更新するので、その下のsetと書いてある行のD列は、I+1の値になるのである。それをsetするわけだから、実質、I=I+1が達成されるのである。同様の原理で、ifと書いてある行のC列では、ワークシート関数ifを用いて、5を超えているかを判定させ、5以下ならtrueを返すことでloopへジャンプさせることに成功している。

次に、関数呼び出しについて述べる。関数というよりは、実際のところgosub〜returnのようなサブルーチンに近いものだが、一応、引数渡しと返し値をサポートしている。関数の呼び出しは、B列に関数名を書くだけで良い。関数からのリターンは、returnで良い。また、引数は、関数呼び出し側が、C列以降に書いたものが、呼び出された瞬間に、呼び出し先のC列からにコピーされる。つまり、

A列      B列     C列       D列

       関数A     100     200
       end
関数A
       return

のようなプログラムがあれば、この100と200が引数として受け渡しされ、実行後は、

A列      B列     C列       D列

       関数A     100     200
       end
関数A            100     200
       return

となるのである。関数Aでは、例によってセル参照を用いてこの100,200にアクセスするわけである。なぜこのようにしているかというと、Excelでは行の挿入や削除を行なってもセル参照は保持されるが、行コピー等では、たいていうまくいかなくなるからである。そこで、関数単位でコピーや移動をしてもそのフレーム内でしかセル参照を使用していなければ、他のワークシートに切り張りすることが可能となるわけである。

ちなみに、関数が返し値を持つ場合、

A列      B列    C列    D列

       関数A   100    200
       end
関数A
       return   300    400

のように、returnのあとに任意の列まで書けます。すると...

A列      B列    C列     D列    E列    F列   G列

       関数A   100    200         300   400
       end
関数A          100    200
       return   300    400

のように、呼び出しもとの、emptyなセルの続きの列にそれが代入されてリターンする。返し値が複数持てるのは、なんだかLISPっぽくて個人的には気に入っている。

とりあえず、拡張はいろいろ考えられる。各種アセンブラのエミュレーションも出来なくはないだろう。何より、プログラミングの勉強にちょうどいいような教材であるような気がするのだが、そんなことを思うのは、私だけなんだろうか...?


第2A回 Excel Interpreter2(反響ちょっぴりあった:笑)99/4/13

前回のプログラム、あのあと、Excelの達人に手なおしてしてもらいました。コマンドは、すべて日本語じゃーとか言って、日本語にされてしまいました(笑) Excelのワークシートなので、全角でも全然オケッーですんで、全部日本語とかのほーが楽しいかも知れません。

あと、ジャンプと変数参照が遅いのは、findでA列全体に対して行なっているからで、一度使ったA列のラベルについては、ヒストリーを持つような構造に変えてくれました。(その間、約5分)

そのあと、「関数の返し値がマルチバリューを採用してんだから、変数も、マルチバリューでなきゃ言語の設計理念がおかしい」などと言われ、カチンと来たやねうらおは、速攻で修正。(その間、約5分)

そんなわけで、堂々たる日本語プログラミング環境が完成。ついでに、その分野専門の処理も内部コマンドの追加により可能だったりする。(もちろん、そっちが本命だけど)

そう言えば、私の大学時代の卒業研究の指導教官が、日本語プログラミング環境のどうのとか、エキスパートシステムがどうのとか言う研究をしていて(定年まぎわのおじいちゃんだ)、それを散々馬鹿にしていたのに、まさか自分がそんなもんを作るとは思わなかった。私が卒論で研究室に顔を出したのは、数回で、しかも卒論は4年のクリスマスぐらいからやり始めて、正月返上で書きあげたといういい加減なシロモノだったにもかかわらず、快く単位をくださったM脇教授。あんときは、大変、お世話になりました。これは、ほんのお礼です。どうかお納めください。


第2B回 インターネットを利用した選挙投票システムについて(もー、うざいんじゃ〜)99/4/13

今回は気分転換に、軽い話をする。

この時期、選挙の街頭演説やらビラ配りやら何やらで非常に不愉快に感じたりしているのだが、問題は、選挙投票である。ちょうど、今日(4/11)、投票のためやねうらおはご近所の白鳩幼稚園(誰もわからんて!)に行かなくてはならないのだが、なんで、日本はこんな旧石器時代の投票システムにいつまでも頼ってるんかなーとか思わんでもない。それこそ、マンモスぱお〜ん!ゆうてて、石のでっかいお金をごろごろ転がして買い物をし、「ギャオー」と叫んだら、それが文字の固まりになって空中に現れていたいた時代(そんな時代ないって..)の産物ではないか。

つまりだ。インターネットで電子的なマネーが使用でき、個人認証システムが確立された現在、本人かどうかの確認がどうのってーのは、インターネットで選挙投票できるシステムを構築しない理由にはならんのではないか。それは、単なる怠惰ではないのか。選挙の投票率が落ちているのは、若者の政治への関心がどうのってのは、ちょっと眉唾だと思う。

実際やね、せっかくのオフに白鳩幼稚園(だから、誰もわからんて!)まで行って投票せにゃならん若者(?)の気持ちを察して欲しい。まだその上、うざったい選挙の街頭演説を誰が朝から晩まで順番に聞き、比較しろと言うのか。あるいは、通勤の最中に立ち止まって耳を傾けろというのか。ビラを受け取って、地下鉄の中で見ろというのか。冗談も休み休み言え!と言いたい。

そこでだ。まずは、インターネットによる選挙システムを導入する。まー、こんなの僕が言ったところで個人事業として出来るわけではないので、国家レベルでやってもらわねばならないのだが、まあ、導入していただくことにする。次に、出馬した者は、自分のホームページを作る。選挙演説も、そこに掲載する。できれば、読みやすくウィットに富み、軽いジョークなんかもあるほうが良い。もちろん、ホームページ作成業者に頼んだ場合は、選挙違反で逮捕するものとする。(笑) あと、投票ページから「候補者」をクリックすれば、それらのページに飛べるようにしておく。とりあえず、それでシステム完成。「だれそれ議員のページは、ダイナミックHTMLじゃないからなぁ」とか、技術上のツッコミもOK。(やな選挙...)

そうそう。あと、携帯電話からも投票できるようにしておく。これだけすれば、投票率は相当あがるはずだ。せっかくの休みに白鳩幼稚園(だから、知らんっちゅーに!)まで、やねうらおを呼びつけるような選挙システムとはもうバイバイキンだ。(文章、支離滅裂ぎみ。謝々)


第2C回 やねうらお的仕事(5つの言語を使う男)99/4/15

なんか恥ずかしい話だが、あれだけWindowsを馬鹿にしながらも、現在もなお、Windowsでプログラムしていたりする。ゲームなんかではなく、仕事の成り行きで某CADをカスタマイズして、自動設計プログラムみたいなものを作っているのだが、結構、膨大な量だったりする。一応、今月末ぐらいにシステムアップを終わらせるつもりだが、完成したところで、日の目は見ないこと確実な企業機密である。(ほんまかいな...)

ついでに言えば、そのCADは、時代遅れなことに、C言語(C++ではない)でカスタマイズしてDLL化せえ!と強要してくる。さらに、Excelと連動させなくてはならないから、Excelのモジュール(VBA)とワークシート関数も大活躍である。その上、第29回で解説したExcel Interpreterで日本語の命令を駆使して、設計手順の指示を行なう。その出力されたファイルをプリプロセッサを介してからCADの方に渡してやるのだが、そのプリプロセッサは速度面と記述性からC++で書いている。つまり、5つの言語(?)を使っているわけだ。ついでに言えばヘルプは英語だし、用語はコンピュータ用語だし、閉領域の内外判定やらスプラインと楕円の交差判定やら線形代数と解析学が大活躍の、考えるのもうざったいクラス設計をしているので、もう日本語を忘れそうになる。さらに、昼休みには、トランジスタ技術を読んで、会社帰りにゲーセンでDDRして、家では椎名林檎をピアノで練習していたりする。ここまで来れば、何もかもがごっちゃになってくる。

気分転換に、マクドナルドで休憩する。何も余計なことは考えない。余計なことを考えずゆっくりしよう...とか思っていると、カレーバーガーがいまだけ半額!で、バリューセットもお買い得!とか書いてあるのを見て、マルチバリューのことを思い出した。カレーバーガーを食べながらなので、自分でも何を言っているのかわからないまま、独り言を延々と言い始めた。

そもそも値を2つ返したいときは、Cでは、どうするんや。あれか、引数にポインタ渡すんか。しかし、自分、それダサイんちゃうん。引数になんで出力される変数名書かなあかんねん。それってillegalやわ。関数プログラミングとしては、屈辱的な行為とちゃうか?まあ、実際そうならざるを得ないとしても。しかし、それを参照の&つこて誤魔化してみたところで、入出力関係が余計に不透明なるやんか。必要悪みたいなもんなんかなぁ。3変数以上渡したいときはどうなんねん。あれか。そういう構造体作ってしもたらええんか?作ってしもたらええゆうても、変数返すのに、わざわざなんで構造体作らなあかんねん。アホちゃうか。そんなんしてたら、際限なくチリメンジャコみたいな構造体が出来てしまうやん。それも、全部一回しか使わへんねん。ぎゃはは。なんちゅーやっちゃ。そんなんあかんわ。全然あかん。そもそも、なんでPASCALみたく関数の中に関数書かれへんのや。あれめちゃ便利やのに。それとも、そんなん全部クラス化してまえゆうんか?だいたい、クラス化ゆうても、そのクラスの2つのメンバ関数間でしか使わへんようなんメンバ変数に持ってるのんて気持ち悪くないか?他のメンバ関数からも見えてしまうねんでー。んなもん、正常なカプセル化やとは到底思えんわー。だいたい気持ち悪いわ。なんぼ、private変数やゆうても、あんまりやわ。そもそも、関数は複数返し値持つことにしようや。んで、PASCALみたく、returnやめて関数名に代入したら、それが返るとかな。そうしといたほーが、分岐してreturnするような場合、返し値をそれぞれのreturnに記述せんで済むし。まあ、返し値初期化し忘れたら大変やけど、それくらい今のコンパイラ賢いからコンパイル時になんとかしてくれるやろ。たとえば、そやなぁ。

[int x,int y] funcA(void){ x=3; y=5; }

funcB(void) {
    int sx,sy;
    [sx,sy]=funcA(); // マルチバリューを受け取るための拡張構文

[ ]をマルチバリュー用に使うんや。テンポラリ構造体とでも言おうか。[ ]を使ったら、配列はどうなんねん?ああ。配列は、VBライクに( )を使用しよか。関数呼び出しは?関数呼び出しには、( )はつけない。明示的に呼び出したいであれば、call func;のように書けばええやん。そんなことしたら、x =z;と書いてあった場合、関数の返し値を代入しているのか、変数を代入しているのかわからんのでは?うーん。それは、デメリットではなくメリットだと言いたい。Prologなんかでは、それが「事実」(定数)なのか、「述語」(関数)なのか表記上の区別がない。「事実」をあとで「述語」に拡張しても、他の部分を変更しないで済むという大きなメリットがあるのだから...。

店員「お客様。当店は、まもなく閉店になりますにゃ」

ふと見上げると、びっくるの人がそこに居た。


第2D回 Linuxを導入する(まずは、格安マシーンをゲットせよ)99/4/17

Linuxユーザーを羨ましく思いながらも、どうせ家ではメールソフトとCD−Rライターしか使うわないんで、まあいいやとか思っていたのだが、大阪日本橋に安い店を見つけた。Celeron300A+マザー/32MB/3.2GB/ケース/キーボード/マウス/RIVA128で、6万台。安い!安すぎる。あまりに安いんで、その店の仕入先を調べたら、どうも、HYPER CITYのようだ。HYPER CITYって、この業界では有名な、オーム絡みの卸問屋である。

まあ、6万台なら、いいかと、さっそく、弟子の岸田君(仮)に連絡。なんで、岸田君(仮)に連絡を入れるのか、わからない人は、びっくるネットの書き込みでもうちょっとびっくるスピリットを勉強した方がいい。(笑)

やね「なー、日本橋に安い店あんねんけど。いま7万あるか?」
岸田「いやー。バイトの給料前で。4万ちょっとしか」
やね「ほな、2万貸したるから、買えよ」
岸田「えー。ほんまですかー。でもそれじゃ5千円ぐらい足りんのですが...」
やね「自分のいま使ってるFM−V、俺が買いとるわ。5千円で」
岸田「えー!!5千円ですかー」
やね「そらそうやん。自分、あれと同じスペックのノート、新古品がソフマップで3万で売ってるがな。中古でしかも、デスクトップ、場所ばっか食う上に、CD ROMはSoundBlasterインターフェースでつながってんやろ?どうしようもないやん。もう売るしか!」
岸田「えー。そう言われても...」
やね「だいたい、自分、考え方、おかしいで。5千円でFM−Vを売るやない!俺が言いたいんは、君が、たった2万の翌月払いの借金で、Celeron300Aのマシンをゲットできるということや!!」
岸田「あー。そうですねー...」
やね「買うか買わへんのか、はっきりせえ!!限定10台や。早よしやななくなってまうで。なんやったら、俺が、金だけ払っといたるから、あとでこの店、取りにこいよ」
岸田「..んー。わかりました。お願いします」

そんなわけで、5千円でLinuxマシンを入手することになった、やねうらお。
一瞬、「儲かったにゃ」とびっくるの人になったことは言うまでもない。


第2E回 Linuxを導入する2(ついにインストールしたぜよ)99/4/17

そして、待望のLinuxをインストール。ディストリビューションは、Debian。日本語化されていない頃のものだが、Xが動けば遊べるだろう。とりあえず、雑誌の通りにインストール。システムは250MB。ユーザー100MB。スワップ50MB。んで、カーネル入れて...あとは、dselectでxserver選択。ウィンドウマネージャは、afterstepで決まりやな。あとは、XF86Setup。マウスはPS2ポートなんで、dev/psaux。画面まわりは、設定が面倒なんでSVGAで結構ざんす。キーボードも106はトラブルんで、101で良いざんす。んで、設定終了...設定を保存して、startx。

これで、めでたく、X11が動く環境が整ったわけである。(所要時間約2時間)

し、しかーし。ここから何をしていいのかわからん!!

そもそも、Xなんか、大学入りたてのときに実習室で2時間ほど触っただけである。それも、コンソールからではcurses(カーソルを動かすライブラリ)が、思ったように動作せず、Xウインドウ下ならいけんちゃうか?とか思って動かしたにすぎない。実際、この時期にSUNで動いていたUNIXは非常にバグまみれだったようだ。

curses is cursed.(curseは呪うという意味の動詞。直訳すると、cursesは呪われている)

などとわけのわからんギャグでバグ報告をして、大笑いされた経歴を持つ。余談ではあるが、そこで動いていたCコンパイラでは、sunと言う変数名も、コンパイルエラーになる。一瞬、なんのことかわからなかったが、sunという名前は予約されているらしい。うおー。日曜日はどう書いたらええねん!などということは、日常茶飯事であった。

そうだ。あんとき、先生は確か「コンピュータを使え!だけど、コンピュータに使われるな。そして、酒を飲め。しかし、酒に飲まれるな」などと訳のわからんことをおっしゃっていたのを思い出した。

そうだ。何も、小難しいツールについて覚える必要はないのだ。自分で好きなようにプログラムすれば良いのだ!などわかったようなわからんようなことを閃いたやねうらおは、dselectでxemacsと、X関係の開発ツールとOpenGLのツールキットを選択してインストール。これで、見事にエディタとコンパイル出来る環境だけは整ったわけである。

しかし、UNIXもロクに知らんまま、Linuxをインストールして2時間後にXのプログラム書き始める姿って、どうも異常のような気がする。ひょっとすると、世界的に見ても類まれなるアホなのかも知れない。そんなことゆーたかてー、自分には、それしか出来ひんねんもん!!ほっといてんか!!

自慢ではないが、Linuxからフロッピーにアクセスする方法も、CDROMからファイルを読み出す方法もわからない。こんなことでいいのだろうか。どこか順番を間違えているような気がしないでもない。


第2F回 大人は誰も教えてくれない連立方程式の解法(なんのこっちゃ)99/4/18

最近、ホームページの更新ペースが早いねーと言われる。3ヶ月近く更新をさぼっていたかと思ったら、今度は、毎日大量に更新である。やねうらおは、実は、頭のなかのメモリが不足しているため、ひとつのことしか考えられないのだ。何かをやり始めると、そのことばかりにつきっきりになってしまうのである。K2が僕のことを評して言わく。「あー、昔、ファミコン出た当時、そんなんでしたわ。ドンキーコングしかカセットもってへんかってね、もー、電源入れたらドンキーコングなんですよ。電源入れても、それしか出来ませ〜ん、みたいな。そうゆうのですね」 おい、コラ!誰がドンキーコングやねん!(そんなんゆうてへんて..?)

さて。今日は、連立方程式をアチョーと解く方法についてである。会社で、ちょっとした連立方程式を解かなければならないことがある。やねうらおは、職業上、構造力学についてマトリクスを解く必要が出てきたりするわけだが、行列の演算ってのは、意外と面倒である。実際のところ、Excelのワークシートにマトリクスを書いて、そいつの逆行列を吐出法か何かで求めれば良いのだが、毎回マトリクスの大きさが変わったり、非線形の式や微分形やらが入り込んでくると、結局のところ、その都度、計算するようなプログラムを書いていたのでは、効率も悪い。

そこで、考えたのは、Excelのソルバーを使う方法である。ソルバーというのは、ゴールシークの多変数版である。ゴールシーク自体を使ったことがないという方のために、簡単に説明する。

セルA  =セルB^2 + 5*セルB + 1

となっているとする。このとき、セルBの値を適当に変更して、セルAの値が0になるように頑張りなさい!というような作業を行なうことが出来るのである。この結果が、つまり、x^2+5x+1=0の解となることはわかるだろう。つまり、ゴールシークで1変数の方程式が解けるのである。(実際のところ、収束するかどうかは初期条件等により変わってくる。さらに興味のある人は、線形計画法や非線形最適化について勉強すること)

このゴールシークの「どこそこのセルを変化させて」の部分を、複数のセルに対して行なえるようにしたのがソルバーである。しかし、ソルバーをもってしても、目的のセルは1つしか選べない。よって、方程式は解けないように思われるかも知れない。(そんなん思うん俺だけかなぁ...) しかし、

f(x,y,z) = 0
g(x,y,z) = 0
h(x,y,z) = 0

のような3の方程式が与えられているならば、

f(x,y,z)^2 + g(x,y,z)^2 + h(x,y,z)^2

というような二乗和が0(あるいは最小値)となるようにソルバーを用いれば良い。この方法を使えばノンプログラミングで逆行列も求められたりする。ただ、多変数の場合、収束に関して安定度が問題となったりもするが、ここで深くは立ち入らない。

大戦略のようなゲームを作る場合、必ず局面のstaticな評価関数を作らなくてはならないのだが、その係数を調整するときなどに、この方法はとても便利である。さすれば、大戦略のような接待ゲームにはならないだろう。一度、お試しあれ。(どうでもいいけど、あの大戦略の作者、あれでほんまに強いと思ってんねんから、ちょっとは探索理論、まじめに勉強せえ!と言いたくなる)


戻る