実みつるのPreプログラミング

プログラミングの学習を考えている方へ

4-2 途中で別の事をする

第四章 繰り返し

(2)途中で別の事をする

中距離走競技では有り得ないと思いますが、繰り返しの折り返し地点、例えば10周走る競走なら5周走り終わった時に、水分補給するというルールが有ったとします。走る事以外の行為ですが、走者は周回表示器の数字を見て「5」だったら水分補給を行うのではないでしょうか。

 

コンピューターが行う繰り返し作業でもこの様な事が可能です。前項ではコンピューターにカウンターを持たせましたが、このカウンターが「5」を示した時には別の処理を行う様にします。この場合、先ほど登場した「10」と固定表示されている表示器とは別に、「5」と表示された何かが必要になります。例えば「カウンターが5になったら○○して」といった内容が記載された看板の様な物です。

 

ところで、上で述べたような表示器や看板はどこに置かれるべきでしょうか。持っているカウンターと見比べるタイミングを考えると、スタートライン(ゴールラインと一緒)に置く必要があります。こうすれば、コンピューターはスタートラインに到達するたびに二つの表示と自分のカウンターを比較し、繰り返しを継続するのか、また何か特別な事は無いかと毎周回判断できます。

 

さて、これまで述べてきた中距離競走の内容を前章で見てきた「条件分岐」を使って図で表してみます。

 

 

この条件分岐に従えば、スタートして5周走ったら水分補給、10周走ったらゴールということが実現できます。しかし先ほど述べた通りコンピューターの場合は、持たされたカウンターの値と掲示板の値を比較します。そこでもう少しコンピューターの目線に近い図を作ってみます。COUNTERという変数(要するにカウンターです)を用意し、「5」や「10」といった数値と比較する様子を確認して下さい。

 

 

まずスタート時にCOUNTERを0にします。次に、条件分岐を2つ(値の比較)を通過し、トラックを1周します。その次の内容はわかりますか?第一章で見た「変数の中身を増やす」事をやっています。元々COUNTERには0が入っていましたが、これに1を足した値(すなわち1なのですが)を再びCOUNTERに入れています。結果としてCOUNTERの内容を1増やす事ができました。

 

ここから矢印に従い初めに戻り、順調に行けばCOUNTERの値が1ずつ増えていきます。COUNTERが5の時に水分補給、10になったらゴールして終了となります。

 

ところでCOUNTERの値を1増やした後、「COUNTER←0」という箇所よりも下に戻るようにしています。仮にSTARTの直後、すなわち「COUNTER←0」より上に戻すようにしたらどうなるでしょうか?再びCOUNTERに0が入ってしまいます。すると、また条件分岐を2つ通り、一度はCOUNTERが1になるも、また0に戻され…もうお分かりでしょうか。このままではCOUNTERが10になることは永遠に無く、ゴールする事ができません。そしてただひたすら周り続けます。

 

つまり繰り返しの制御に失敗したのです。この様に永遠に周り続けるプログラムを「無限ループ」と言います。最近ではコンピューターに限らず、様々な場面でも使われる様になった言葉ですね。

 

さて、ここで少しひねった例を考えてみます。もし水分補給のタイミングを半周した地点、つまり5周半した時点で行いたい場合はどうしたら良いでしょうか。イメージとしてはトラックのスタートラインのちょうど反対側という感じです。

 

実際の競走で実現する方法を考えます。スタートライン通過時に周回表示器の「5」を確認した選手が、その後半周走った後に水分補給すれば良いのですが、スタートラインで確認した数字を忘れてしまうという可能性は有ります。ですから半周する場所に予めテーブルを設置し、6周目を走っている選手のボトルだけ置くといった対策が必要になるかもしれません。一方、コンピューターではどうしたら良いでしょうか。

 

これは「カウンターが5になったら水分補給して」という看板を半周した地点に置けば実現できます。イメージとしては、スタートラインから半周したらカウンターが「5」なのかを確認、そこから半周して再びスタートラインに戻ってきたらカウンターが「10」なのかを確認します。以下の条件分岐を見て下さい。

 

 

「1周走る」というのが無くなり、「半周走る」が2個になりました。この様に1周走るプロセスを半分にする事で、半周した際に条件を判断する事が可能となります。当然ですが、トラックを1周走る事を10回繰り返すのと、半周を20回繰り返す結果は同じです。

 

この様に、コンピューターでは繰り返しの途中に何かを行う場合、行いを分割するというちょっとした工夫が必要になります。さて次回は途中で繰り返しを止めてしまうということを考えてみます。

4-1 同じことを繰り返す

第四章 繰り返し

何かを繰り返し行うというのは大変なことだと思います。特に飽きっぽい性格の人は、途中でやめたくなるでしょう。しかしコンピューターは、愚直に何回でも繰り返す事が非常に得意なのです。100回でも1,000回でも10,000回でも繰り返します。

この特性を利用する為には、プログラムで正確に指示する必要が有ります。そこでこの章では「繰り返し」という作業を考えていきたいと思います。

 

(1)同じことを繰り返す

陸上の中距離走競技は、同じ所を何回も周ります。例えば、5,000メートル走は一周400メートルのトラックなら12周半周ります。言い換えると、「トラック1周走ることを12.5回繰り返す」です。

 

ところで、繰り返し作業を行うときに考えなくてはならない重要な要素が有ります。それは「何回繰り返すのか」という事です。今、仮に4,000メートル走という競技が存在したとします。これを一周400メートルのトラックで行うとすれば、選手は10周する事になります。さて出場した選手達は、どうやって「10周する」ことを認識しているのでしょうか。

 

私は実際にこの競技に参加したことが無いので判らないのですが、恐らく選手はスタート地点(ゴール地点にもなります)付近に掲示されている周回表示器を見る、あるいは最後の周回時に鳴らされる鐘の音などを参考にしているのではないでしょうか。選手によっては、頭の中で正確にカウントする人もいるでしょう。

 

もし、これが判らない状況で走っていたら大変なことになります。レースで有れば選手間の駆け引きもあるでしょうし、何より自分のペース配分に影響します。「あと何周でゴール」、すなわち「あと何回繰り返せば良い」という情報は重要です。

 

先ほど、コンピューターは繰り返す事が得意と述べましたが、あまりにも得意すぎるので制御しなくてはならないのです。もし制御に失敗すると暴走してしまい、永遠に繰り返してしまうのです。陸上競技の選手ならいつか疲れ果てて立ち止まるでしょうが、コンピューターは永遠に疲れないので、電気が供給される限り動いてしまいます。

 

そこでコンピューターにも陸上競技で利用している周回数を掲示した板の様な物を用意してあげれば良いのですが、ここでもう少し人間の話を続けます。陸上競技の走者は、仮に周回表示器を使う場合、この表示器が「5」を示していたら、ゴールラインを通過する時に「あと5周走るんだ」と認識します。「1」であれば「あと1周、つまりラストだ」とわかります。

 

コンピューターもこの仕組みを使って繰り返す数を制御できます。但し、人間と違うのは1」という数字を「あと1回」という意味に捉えられないのです。

 

言っている事が良く分からないかもしれません。要するにコンピューターに対しては「あと1回」とか「5回繰り返して」というダイレクトな指示ができないのです。1や5はあくまでも数字の一つで、回数であるという認識をしてくれません。これではせっかくコンピューターが得意としている「繰り返し」を上手くコントロールできません。

 

これを解消する為に、繰り返しを行う場合はコンピューターに「カウンター」を持たせます。よく通行量調査などで利用されるカウンターをイメージして下さい。もし10回繰り返したいと思ったら、まずこのカウンターを0にします。次に1回終わったらカウンターを1回押します。カウンターは1を示します。

 

ここで、先ほどの陸上競技で利用した表示器が出てくるのですが、コンピューターの場合、この表示器の値は固定されています。10回繰り返すのであれば「10」と表示されているだけです。とうてい周回表示器とは言えないのですが、イメージをつかむ為に、あえて周回表示器を利用します。

 

コンピューターはカウンターを1回押す度に、カウンターの値と表示器の値を比較します。もしカウンターの値の方が小さかったら繰り返しを続けます。2回、3回と繰り返す内に、カウンターの値が10になったとします。つまり10回繰り返しが行われた事になります。ここでカウンターの値と表示器の値を比べると、等しくなります。もし繰り返しの条件として、「カウンターの値が表示器の値より小さい間は繰り返す」と設定すれば、10回繰り返したあと無事に止まります。

 

何でそんな面倒な事をするのだと思いますか。しかしこの様にしないとコンピューターは繰り返しを制御できないのです。

 

思えば、陸上競技の選手も「1」という数字を見て「あと1周」と解釈しますが、それには次の様な思考が無意識になされているはずです。

 

(1)周回表示器に1と出ている。

(2)次に1周してくれば、この表示器は0と出すだろう。

(3)0ということは、それ以上走らなくて良いということだ。

(4)つまり、あと1周でゴールということだ。

 

人間の認識にある「0」つまりゴールという状況と、次の周回後に見られると思われる「0」が表示される状況を比べて、あと1周、あと1回繰り返せば良いと考えているのです(もちろん実際にはここまで細かく分析して走ってはいません)。

 

人間は「1」という数字を「1」「1個」「1回」と、場面に応じて色々意味を変えられます。しかしコンピューターにとっては「1」は「1」です。繰り返す回数と、持たせたカウンターにそれぞれ値を設定し、その両者を比較する事で、この数字が「回数」なのだと初めて認識されるのです。

 

最後は少し難しい事を書いてしまいましたが、何となくでも分かってもらえましたでしょうか。次回は繰り返しの途中で、別の事をするということを考えてみます。

3-3 漏れは無いか?

第三章 条件分岐

(3)漏れは無いか?

これまで見てきた条件分岐を使えば、条件に応じ結果を分ける事ができます。ところでこの仕組みを利用すれば、現象の判断に応用する事もできます。例えば「勝ち」「負け」といった勝負事の結果も表せます。

 

では身近な勝負事、「じゃんけん」の結果を判断する条件分岐を考えてみます。じゃんけんで自分の出したもの(グーやパー)が勝ったのか、或いは負けたのかを判断するには、相手の出したものと自分のものを比較します。当たり前ですが、以下にまとめます。

 

自分:グー/相手:チョキ      → 勝ち

自分:グー/相手:パー      → 負け

自分:チョキ/相手:パー     → 勝ち

自分:チョキ/相手:グー      → 負け

自分:パー/相手:グー        → 勝ち

自分:パー/相手:チョキ     → 負け

 

勝敗は以上の6パターンしか有りません。これを図で表すと以下の様になります。

 

 

今までよりも多くのひし形が出てきましたが、これで自分の勝敗を判断する事ができます。

 

さて、プログラミングで条件分岐を考える際に一点重要な事が有ります。それは、「起こり得る現象の想定に漏れが無い様にする」という事です。

 

コンピューターは速度の性能が優れているとはいえ、実は不測の事態には弱いのです。人間の様に臨機応変に対応できれば良いのですが、コンピューターの場合は予期せぬ現象にぶつかると、そこで止まってしまうのです。

 

例えば、もう一度じゃんけんを考えてみます。先ほど図で表した条件分岐には「あいこ(引き分け)」の現象が入っていません。「その場合はもう一回じゃんけんすれば良い」と考えられるのは人間だけで、コンピューターは「どうしたら良いのか?」と迷ってしまうのです。

 

そこで、もし「あいこの場合は引き分けとする」と決めるのであれば、条件分岐は以下の様になります。

 

 

先ほどの図に対し、「引き分け」という結果が加わりました。

 

ここで一つ注目する点が有ります。図の中では「あいこかどうか」の判定を行っていません。じゃんけんの場合、勝ちでも負けでもなければ、残る可能性はあいこしか有りません。ですから、自分の出したものが判断できた後は、相手の出したものが何か、という判断は2回で済みます。

 

例えば、自分の出したものがグーであれば、相手の出したものがチョキか、もしくはパーかを判断するだけで結論が出ます。なぜなら、じゃんけんで出せるものは3種類しかないからです。2種類の判断ができれば、残りは1種類しか有り得ないからです(相手が何も出さなかったという状況はここでは考えません)。

 

ではもう一つ考えてみます。あいこの場合は再度じゃんけんをする(「あいこでしょ」です)と決めた場合です。この場合、これまで見てきた条件分岐をもう一度行うようにします。以下の様になります。

 

 

ポイントは、もう一度じゃんけんをした後「条件分岐のスタート地点に戻る」という仕組みを入れた点です。こうすると、決着がつくまでじゃんけんが繰り返される様になります。

 

この項では、「条件分岐を考える際、その結果に漏れが無いか」という事を考えてみました。「こうなったらどうなるの?」「この場合はどう対応したら良いの?」などと「条件と結果」を想像する事は、プログラミングに於いて重要な要素になります。機会が有れば身の回りにある「条件分岐」を図式化してみて、「漏れ」が無いか考えてみて下さい。

 

条件分岐の章は今回で終わります。次回は「繰り返し」について考えていきたいと思います。

3-2 ひし形の記号

第三章 条件分岐

(2)ひし形の記号

まずは以下の図形をご覧下さい。

 

 

いわゆる「ひし形」です。ところで皆さんは、「フローチャート」あるいは「流れ図」といった言葉を聞いたことが有りますか。実際にプログラミングを行う前に作成される概略図、もしくは設計図の様な物なのですが、その中でこの図形は使われます。最近ではプログラミングとは関係無く、「あなたはどのタイプ」といった診断で見たことがあるかもしれません。

 

このひし形を使うと、これまで述べてきた「条件分岐」を図で表す事ができます。例えば、運動会の「雨天順延」は以下の様に表現されます。

 

 

ひし形の上の頂点から上に線が出ています。これはこの条件分岐よりも前に何かが行われていた事を表しています。「上から落ちてきた」「ひし形に入ってきた」という様な感覚で捉えて下さい。

 

次にひし形の左右からも線が出ています。これはひし形の中にある条件の結果によって進む道を示しています。この線は先ほどの線とは逆で、「ひし形から出ていく」という感覚になります。

 

左の線の上には「いいえ」、右の線の上には「はい」と書かれています。これは判断の結果で、「いいえ」なら左に、「はい」なら右に進めという事です。前項(1)で述べた通り、雨天順延とは「運動会は雨が降らなかったら実施。雨が降ったら後日実施。」という意味ですので、この図はその内容を表している事になります。

 

フローチャートは上から下に進むのが一般的ですので、矢印は記載されないのですが分かりやすくする為に矢印を記載した図も掲載します。

 

 

ここまでひし形を使って条件分岐を表現してきましたが、二者択一はこれで表現できそうです。しかし下の頂点を「出口」として使ったとしても最大で三者択一(いわゆる三択です)までしか表現できないのではと思いませんか。例えば前項(1)で例に挙げられていた干支は12も選択肢が有ります。ひし形でこれを表す事ができるのでしょうか…

 

答えは「できる」です。12の選択肢が有るのでしたら、最大12回質問をすれば結論が出るはずです。下の図を見て下さい。ただしここでは便宜上、誕生年から干支を推測するのではなく、「あなたの干支は○○ですか?」と尋ねることとします。

 

 

実際の会話では、

 

A:「あなたはネズミ年?」

B:「いいえ」

A:「じゃぁ、ウシ年?」

B:「そうそう」

 

という感じなのですが、ひし形を使った図で表すと上の様になります。ひし形をいくつも組み合わせる事で、選択肢が無数に増えても表現できるのです。

 

それでは最後に、前項(1)で見てきたランチのカレーについて考えてみます。簡単に振り返ると、「昼食に馴染みのカレー屋へ行き、営業していたらそこでライスかナンを選び、休業していたら別の店へ行く」というお話でした。これを図にすると下の様になります。

 

 

如何でしょうか。これを見れば、カレー屋が営業していなければライスかナンを選ぶことはない、という状況を簡単に捉える事ができます。

 

今回は条件分岐というものを、図を使ってイメージすることを試みましたが、もう一点確認すべき点が有ります。それは「二者択一を組み合わせる事で、複雑な条件分岐も実現できる」という事です。

 

プログラミングの条件分岐は、大半が「Yes or No」の二者択一で表されます。多くの結果に応じ、それぞれ処理を分ける事もできますが、基本は二者択一です。プログラミングを学び始めた頃は、できるだけ「二者択一を組み合わせる」練習をして欲しいと思いますので、これまで見てきた内容を是非覚えておいて下さい。

 

次回は条件に対する結果について考えていきたいと思います。

3-1 日常にあふれる「もしも」

第三章 条件分岐

突然、「条件分岐」と言われてもピンとこない方が多いと思います。条件分岐とは、「条件」に応じてその後の行動が分かれるという事です。これから具体例をあげながら分かりやすく説明してみます。

 

(1)日常にあふれる「もしも」

思えば私たちの生活は、数多くの「もしも」に制約されています。例えば学校の運動会の実施要項には「雨天順延」などと書かれています。これは、「もし運動会当日雨が降った場合は、運動会は実施せず後日改めて行う」という意味です。裏を返せば「雨が降らなかったら実施する」という事です。

 

この例では、天気という「条件」に応じて、運動会を「実施する」、もしくは「実施しない」とその後の対応が分かれる、すなわち「分岐」している状況を確認できます。

 

条件分岐は二者択一だけではありません。場合によっては分岐する数が10を超える事も有ります。例えば干支(えと)です。日本では12個存在し、生まれた年によって決まります。「もしあなたが2015年生まれなら干支は未(ヒツジ)」という判断も、生まれた年が判断の「条件」になっており、干支の決定が「分岐」した結果と言えます。

 

また、二者択一だったとしても、その後更なる条件分岐があるかもしれません。例えば昼食にカレーを食べようとします。行きつけのカレー屋に行こうと思いますが、もし営業していなければ昼食はカレー以外にしようと思います。この時点で既に条件分岐が存在しています。「もし行きつけのカレー屋が営業していたらそこで昼食をとり、休みだったら別の料理を考える。」という二者択一です。

 

さて、行ってみたら営業していました。そこでカレーを注文したところ、主食にライスかナン(パン)を選ぶことができました。この場合、特に制約が無ければ「ライスを食べたければライスを、ナンを食べたければナンを注文する」という選択を行います。

 

当然ですがこのケースでは、カレー屋が営業していなかったら「ライスかナンの選択」はできません。つまりこの選択は「カレー屋が営業しているかどうか」という条件よりも下に有ります。条件に階層(レベル)が存在しているのです。

 

実は、コンピューターはこの条件分岐を多用して様々な処理を行っています。言い換えれば、コンピューターに何か処理をさせたい場合、処理の内容を人間が条件分岐に細分化し指示する必要があります。具体的にはこれから考えていきますが、その前に次回は、条件分岐を表現する記号について見ていきます。

2-3 順番に並べる

第二章 比較

(3)順番に並べる

比較について見てきた流れで、比較ではないのですが「順番に並べる」という事を見ていきたいと思います。

 

何かを順番に並べる時には、必ず比較するということは分かりますか。例えば、1、2、3を小さい順に並べなさいと言われたら、答えは

 

1 2 3

 

です。逆に大きい順に並べなさいと言われたら、

 

3 2 1

 

が答えになります。この時、頭の中でどう考えているか…恐らく、ぱっと見た瞬間に1が一番小さく、2が二番目、3が一番大きいと直感で判り、順番に並べると思います。

 

では数が増えたらどうでしょうか。例えば

 

5 3 32 9 15 37 19 6 21 8

 

と示されたら、直感的にすぐ小さい順、或いは大きい順に並べられないと思います。小さい順に並べる場合、恐らく以下の様に行うのではと想像します。

 

①ざっと全体を見て3が一番小さいと判るので、解答欄に3と記す。

②3を除く(示された数字の内3に×を付ける)。

③残った数字の内で、一番小さいのが5と判る。

④解答欄で5を3の右側に記し、元の数字から5も消す。

⑤③と④を繰り返し行い、最後の数字まで解答欄に記す。

 

この動作内の①や③に注目してみます。ざっと全体を見て3或いは5が一番小さいと判るのはなぜでしょうか。もちろん数字の集合を絵的に捉えて「これだ!」と判断している可能性は大いに有りますが、実は細かく見ていくと頭の中では以下の様な過程を踏んでいませんか。

 

①最初の数字は5だけど、次の数字は3だ。よって今の段階では3が一番小さい数だ。

②3の横は32だ。まだ3の方が小さいぞ。

③他の数字を見ても3より小さいものは無さそうだ。よって3が一番小さい!

 

次に小さい数の5を見つけ出すのも、3を除いた数字に対し同じことをやっているはずです。

 

何が言いたいのかというと、並べる作業を行うときは必ず比較が行われているという事です。もし実感がわかなければ、示された数字が100個、しかも全て3桁の数字だった場合を想像して下さい。

 

163 729 483 901 671 372 496 583 225 774

836 298 652 803 271 703 339 205 174 487

 : (以下続く)

 

恐らく殆どの方が、ぱっと見ただけで判断できないと思います。やるとすれば、一番小さいと予想した数字をどこかに記録しておき、これ以外の数字でこれより小さいものが有るかどうかを「比較」しながら探すと思います。

 

これまで述べてきた通り、コンピューターは電卓と違い「比較」ができます。そしてこの能力を生かして、沢山あるデーターを規則通りに綺麗に並べる事ができます。但し、コンピューターの場合は人間の様に「ぱっと見て判断する」という事はできないので、一つ一つ比較して検証します。先ほど述べた3や5が一番小さいと判断する為のステップを地道に行うのです。

 

そんなことしていたら時間がかかってしょうがないよ、と思われるかもしれません。確かに一番初めに示した1,2,3の例では、コンピューターはいちいち

 

①1は2と比べて小さいから、今の段階では1が一番小さい。

②1は3と比べると小さいから、この3個の中では1が一番小さい。

③2は3と比べると小さいから、この3個の中では2が二番目に小さい。

④残った3は一番大きい。

 

といった過程を踏みます。しかしコンピューターはこれを我々が想像できないほど高速で行ってしまうのです。恐らく先ほど例にあげた、100個の3桁の数も数秒で小さい順、或いは大きい順に並べてしまいます。そのくらい、個々の比較を短時間でこなしてしまうのです。

 

ちなみに小さい順に並べる場合は「昇順」、大きい順に並べる場合は「降順」と言います。「△」は上の方が小さく、下の方が大きいです。逆に「▽」は上の方が大きく、下の方が小さいです。「△」は昇るイメージが、「▽」は降りるイメージがあるので、この様に名付けられたのだと思います。

 

順番に並べるという作業はプログラムを作れば実現できますし、表計算ソフトのソート機能でも実感できるでしょう。この機能は裏でこれまで述べてきた様なプログラムが流れているとお考え下さい。

 

 

比較については今回で終わります。次回は「条件分岐」について考えていきたいと思います。

2-2 文字の大小

第二章 比較

(2)文字の大小

前回は数の比較について考えてみました。ご存じの通り数には大小が有りますので、簡単に比較できます。ちなみにコンピューターは、数の比較しかできません

 

一方、実生活では数だけではなく色々なもの、例えば文字を比較します。「A」は「A」と一緒で「B」とは違う、「あ」は「い」よりも前にある、といった感じです。

 

先ほど申し上げた通り、コンピューターは数の比較しかできないのですが、プログラミングにおいては文字を比較する事で様々なことを実現できています。ではどうやっているのでしょうか。

 

コンピューターでは一文字一文字に背番号を付けています。文字だけでなく、記号(例えば「:」とか「#」)にも背番号が付されています(文字コードなどと呼ばれています)。この背番号を比較する事で、同じか、或いは前後を判断できます。

 

「同じ」は分かるかと思いますが、では「前後」とはなんでしょうか。

 

一般的に「ABC順」とか「五十音(あいうえお)順」などと言いますが、これは我々の概念に「A→B→C」という順番が有ることが前提となります。五十音も同様で、「あ→い→う→え→お」という順番を基にします。学校のクラスの出席番号はよく名前の五十音順で付けられますね。

 

先ほどの背番号の話に戻りますが、コンピューターでは一般的に「後にくる文字の方が大きく」なるように背番号が付されています。例えば

 

A: 背番号は1

B: 背番号は2

 

といった具合です。ちなみにASCII(アスキー)コードと呼ばれる背番号では

 

A: コードは65

B: コードは66

 

となります。ひらがなも同様に、「あ」よりも「い」の方が大きい番号が付されています(興味の有る人は「文字コード」をインターネットで調べてみて下さい)。

 

これにより、本来文字を比較できないコンピューターでも、数字を使って比べる事ができるようになります。例えば、

 

○ < ◇

 

という場合、○には「あ」、◇には「う」が入っている事が考えられますし、

 

○ >= △

 

の場合、○が「え」なら、△は「え」や「い」といった文字が想定されます。

 

ここまで如何でしたでしょうか。コンピューターは文字に付いている背番号を利用して、文字の比較もできるという内容でした。次回は「順番に並べる」という事について考えていきたいと思います。