登場人物紹介
僕:数学が好きな高校生。
テトラちゃん:僕の後輩。 好奇心旺盛で根気強い《元気少女》。言葉が大好き。
双倉図書館の一般講座《リンクとストラクチャー》でアルゴリズムを学んできたテトラちゃんは、 自分の理解のため、学んだことを僕に向けて《講義》している。
最大の値を求めるMAX-VALUEを題材にしたり(第321回参照)、 線形リストのノードを先頭に移動するMOVE-TO-FIRSTを題材にしたり(第322回参照)、 リストヘッド付き線形リストを議論したり(第323回参照)と、 いろんな議論を重ねてきた。
いまは、双方向リストというデータ構造を議論しているところだったんだけど……
テトラ「……難しいですけれど、具体例を使って《ステップ・バイ・ステップ》の図を描いて考えれば、まちがいを減らせます。 《例示は理解の試金石》ですから」
僕「あっ!」
テトラ「えっ!」
さっきからテトラちゃんは《図を描け》《図を描け》《ステップ・バイ・ステップの図を描け》と繰り返して言ってるのに、僕はいまだに図を描こうとしていない!
僕は、もしかしたら馬鹿じゃないのか?
その通りだ。
ほんの少しの時間を惜しむ馬鹿者だ。
ほんのちょっと手を動かして図を描く手間を惜しむ、大馬鹿者だ!
僕「……」
テトラ「……先輩?」
僕「……いや、大丈夫。テトラちゃんは何も悪くないよ。 《例示は理解の試金石》は本当に正しい。 そして《図を描け》も正しいよ」
テトラ「はい……?」
僕「僕は……ユーリに教えるときに『具体例を作ろうよ』や『めんどうくさがらないで図を描こう』ってよく言うんだ」
テトラ「……」
僕「ユーリは『めんどくさーい』と言いながらも、図を描く。そしてたいていはよく理解できる」
テトラ「はい、わかります。実際に描いてみるといろんなことがはっきりしますよね」
僕「だよね。僕も、数学の問題で手がかりがつかめないときに、具体例を作ったり、図を描いたりする……でも、 今回はどうもそういう方向に頭が動いていかないみたいだ」
テトラ「慣れないと、おっくうになっちゃいますし……」
僕「だから、きっと、テトラちゃんにこうやって僕が苦手なことを《教えてもらう》というのはすごく大切なんだと思う」
テトラ「き、恐縮です」
僕「テトラ先生、引き続きよろしくお願いします(ふかぶか)」
テトラ「こ、こちらこそです(ふかぶか)」
僕「それで、テトラちゃんの《双方向リスト版のMOVE-TO-FIRST》はこれなんだね(第323回参照)」
List 14 解答4(双方向リスト版のMOVE-TO-FIRST)
テトラ「はい、そうです。双方向リストDとして実装された数列があったとして、MOVE-TO-FIRSTは『指定した値vが最初に見つかったノードを先頭に移動する』という手続きになります」
僕「うん。そしてこれが実行例だね」
MOVE-TO-FIRST(D, 59)の実行例(59という値を持つノードを先頭に移動する例)
テトラ「そうですね」
僕「さっきはおたおたしちゃったけど、 このMOVE-TO-FIRSTについては理解したと思うよ。 次の問題をお願いします、テトラ先生!」
テトラ「はいっ! それでは、せっかく双方向リストを使って実装してきたので、今度はこういう問題5はいかがでしょうか。MOVE-TO-LASTです」
問題5(双方向リスト版のMOVE-TO-LAST)
与えられた双方向リストDに含まれているノードのうち「valueフィールドの値が与えられたvに等しいノード」を末尾に移動する手続きMOVE-TO-LAST(D, v)を書いてください。
もしも、vに等しいvalueフィールドを持つノードが見つからない場合には何もしません。
もしも、vに等しいvalueフィールドを持つノードが複数あった場合にはもっとも末尾に近いものだけを移動します。
手続き
入力
出力
僕「なるほどねえ……MOVE-TO-FIRSTは先頭に移動したけれど、このMOVE-TO-LASTは逆に末尾に移動するということだね。ちょうど同じ難易度の問題の出題になってる」
テトラ「え、ええと……同じ難易度なんですけど、同じ難易度じゃありません」
僕「??? どういうこと?」
テトラ「……あたし、気付いたことがあります」
僕「?」
テトラ「答えを知っていると、《ヒント》や《答えへの道筋》をつい、すぐに話したくなってしまいますね! テトラ、沈黙します……」
テトラちゃんはそう言うと、両手でぎゅっと口を塞いだ。
僕は考える。
MOVE-TO-LASTは、MOVE-TO-FIRSTと同じ難易度じゃないんだろうか。
指定された値のノードを探すのも、リンクのつなぎ方を変えるのも、似たような動作になるはずだ。そういう意味では、難易度は少し低くなるか。テトラちゃんのList 14を参考にすればいいから……
ああ、もしかすると……?
テトラ「……えんあい、いああえうあ?」
僕「テトラちゃん、もう口から手を離してもいいよ」
テトラ「……先輩、いかがですか?」
僕「うん、MOVE-TO-LASTのプログラムはもうできたよ。 いまは図を描いて確かめているところ。こういう実行例になるはずだよね」
MOVE-TO-LAST(D, 59)の実行例(59という値を持つノードを末尾に移動する例)
テトラ「そうですねっ!」
僕「……ああ、ちゃんとうまくいく。 List 15が僕の解答なんだけど、これ、すごいよね」
List 15 解答5(双方向リスト版のMOVE-TO-LAST)
テトラ「すごいですよね……」
僕「うん。このList 15のMOVE-TO-LASTは、 List 14のMOVE-TO-FIRSTに対して《すべてのprevとnextを交換しただけで完成してしまう》んだ!」
MOVE-TO-FIRSTとMOVE-TO-LASTの比較
テトラ「はいはい、その通りです。先輩、さすがですね。 あたしが双倉図書館でこの問題を考えたときは、 気がつきませんでした……」
僕「MOVE-TO-FIRSTから機械的にMOVE-TO-LASTが作れる。考えてみれば当たり前なんだけど、実際に図を描いて確かめてみるとやっぱり驚いちゃうなあ」
テトラ「はい。双方向リストが持っている《対称性》が効いていますよね」
僕「確かに」
テトラ「これであたしが思ったのは、別世界の言葉についてでした」
僕「別世界の言葉?」
無料で「試し読み」できるのはここまでです。 この続きをお読みになるには「読み放題プラン」へのご参加が必要です。
ひと月500円で「読み放題プラン」へご参加いただきますと、 440本すべての記事が読み放題になりますので、 ぜひ、ご参加ください。
参加済みの方/すぐに参加したい方はこちら
結城浩のメンバーシップで参加 結城浩のpixivFANBOXで参加(2021年5月21日)