こんにちは。プロクラス の吉田です。
ヨシダミツヒロ(@milan40920)
Follow @milan40920
いきなりですが、上のプログラムはプロクラス キッズで子供達に教えているマインクラフトエデュケーションのビジュアル言語とpythonのプログラムで書いた同じアルゴリズムのプログラムです。
このプログラムの説明は後にして、
今回のブログは、とある東京の大学の進級試験に出ていた問題を解くための方法を、大学生に教える機会があったのですが、その中の1つが偶然にも、
プロクラス キッズで小学生に教えているマインクラフト塾のプログラミング言語「マイクラプログラミング塾の3級の課題」のと酷似していたので、その内容のご紹介をしたいと思います。
大学の問題はこちらです。
正整数 `n` を引数にとり、動作例に示すような高さ `n` のV字型をコンソールに表示する関数 `v(n)` を定義しなさい
動作例
v(3)
v(5)
言語や環境が違えども、「アルゴリズムは他の言語の書き写しができる」ということが理解していただければいいなと考えています。
「v」を作るための準備
この問題をクリアするためには、まずは「v」を構成する要素に分解する必要があります。
v(3)の場合、
「# #」
「 # # 」
「 ## 」
となればいいのです。
この「v」を構成する全体を眺めてみると、空白がわかりづらいので、
空白に数字を入れてみます。
「#1234#」
「1#12#1」
「12##12」
こうやってみると、少し法則性が見えてきますね。
・3行ある
・空白はどの行も「4つある」
・「#」はどの行も「2つある」
・はじめは両端の「#」の外側には空白がない
・2行目から左右の空白が1つずつ増えている
・全ての行の数は6個の文字で構成されている
・中央の空白は2つずつ減っている
と、こんな感じでしょうか。
「v(3)」だけだと他の数字が入った場合、例えば「v(5)」にした場合、
どう変化するのかもみておかないと、共通性が見えないので、こちらも確認してみると
「#12345678#」
「1#123456#1」
「12#1234#12」
「123#12#123」
「1234##1234」
となりますね。
さて、これをみて「v3」と「v5」の共通点、法則性をピックアップしてみましょう。
・3行ある
・空白はどの行も「4つある」
・「#」はどの行も「2つある」
・はじめは両端の「#」の外側には空白がない
・2行目から左右の空白が1つずつ増えている
・全ての行の数は「6個の文字」で構成されている
・中央の空白は2つずつ減っている
文字の濃くしてある条件は、3も5も同じですね。
ここで3と5の結果で変わるものは、
・3行ある
・空白はどの行も「4つある」
・全ての行の数は「6個の文字」で構成されている
となります。上は3の場合ですが、5の場合は、
・5行ある
・空白はどの行も「8つある」
・全ての行の数は「10個の文字」で構成されている
ですね。
「3行ある」「5行ある」これは当然引数の数ですよね。
それ以外のこの2つのケースで変化している法則性を考えてみると
「3のとき、全ての行は6個の文字」
「5のとき、全ての行は10個の文字」
という辺りに注目です。
共通性は、「引数となる数字の2倍が1行の空白の数」になっているということが分かってきましたね。
さらに、「中央の空白はどの行も引数となる数字の2倍−2」になっていると言えますね。
(ちなみにこの「-2」は1行にある#の数分を除外しているためです)
これをまとめてみると、
1)「引数となる数字の2倍が1行の空白の数」
2)中央の空白は2つずつ減っている
3)はじめは両端の「#」の外側には空白がない
4)2行目から左右の空白が1つずつ増えている
5)「#」はどの行も「2つある」
がこの「v」を引数で変化させることができるための条件となります。
まずは、このように共通する条件に分解することがとても重要ですし、これがないとプログラミングするための準備は整いませんので、しっかり分解し定量的な法則を書き出しておきましょう。慣れてくると頭の中でこの条件を保持することができるようになってきます。
pythonで考えるアルゴリズムとプログラミング
pythonで上の条件を満たすようにプログラミングしてみます。
def v(n): for i in range(n): s = ' ' * i + '#' + ' ' * (n - i - 1) * 2 + '#' + ' ' * i print(s)
たったこれだけです(笑)
pythonってシンプルですね。
s = ‘ ‘ * i + ‘#’ + ‘ ‘ * (n – i – 1) * 2 + ‘#’ + ‘ ‘ * i
この問題の結果は、この1行に凝縮されています。
先ほどの条件とpythonのプログラミングとの関連を紐解いてみましょう。
解説すると、
1)「引数となる数字の2倍が1行の空白(中央)の数」
では、ここでの引数が「n」なので、
「s = ‘ ‘ * i + ‘#’ + ‘ ‘ * (n – i – 1) * 2 + ‘#’ + ‘ ‘ * i」
が該当します。「’ ‘」が「空白」という意味です。
抜き出してみると「‘ ‘ * n * 2 」(空白×引数×2)ですね。
引数が3の場合、’ ‘ ×3×2=6 となり、6個の空白が表示され、
引数が5の場合、’ ‘ ×5×2=10 となり、10個の空白が表示されればOKですからこれで問題なさそうです。
2)中央の空白は2つずつ減っている
次に、この条件を満たすように考えてみましょう。
3の引数の場合、vの中央の空白「# #」。この#と#の間の空白が、2行目以降、2ずつ減っていっているのですが、
プログラムの中で、どのように処理しているかというと、
「s = ‘ ‘ * i + ‘#’ + ‘ ‘ * (n – i – 1) * 2 + ‘#’ + ‘ ‘ * i」
この「i」がいい味を出しています(笑)
pythonでは、iはforによって繰り返され、0、1、2(指定した数字の1つ小さい数3の場合は2ですね)、とカウントアップされていくわけなのですが、これを利用しています。
それと、「-1」の役割は、どの行でも「#が2つ」あるわけですから、その数分の2つを引くために、引数から-1することで3の場合は2になり、5の場合は4になるため、必要になるというわけです。
わかりますか?
1回目の処理では、
「‘ ‘ * (3 – 0 – 1) * 2 」 ” 空白×(引数-1回目のiは0 – 1)×2 “ なので3から0を引いても3は変わらず、v(3)のときは(3-0-1)×2で4個の空白が表示されます。
「#1234#」
「1#12#1」
「12##12」
いいですね。
v(5)のときは (5-0-1)×2で8個の空白なので、
「#12345678#」
「1#123456#1」
「12#1234#12」
「123#12#123」
「1234##1234」
これもOKですね。
2回目の処理では、
「‘ ‘ * (3 – 1 – 1) * 2 」 ” 空白×(引数-1回目のiは1 – 1)×2 “ なので3から1を引くと2。v(3)のときは(3-1-1)×2で2個の空白が表示されます。
「#1234#」
「1#12#1」
「12##12」
いいですね。
v(5)のときは (5-1-1)×2で6個の空白なので、
「#12345678#」
「1#123456#1」
「12#1234#12」
「123#12#123」
「1234##1234」
いい感じです。
あとは、どんどん2ずつ引かれていきますので、この条件は満たせますね。最後は空白は0個です。
3)はじめは両端の「#」の外側には空白がない
続いては、この処理です。
v(3)でもv(5)でも
「#1234#」「#12345678#」
と#の両サイド外は空白がなく、#から始まっています。例のプログラムのオレンジ部分が左の空白と#を示しています。(さっきの中央の空白に+で接続している処理です)
「s = ‘ ‘ * i + ‘#’ + ‘ ‘ * (n – i – 1) * 2 + ‘#’ + ‘ ‘ * i」
ここでも0から順番に増える「i」が活躍します。
‘ ‘(空白)は初めの1行には表示されないので、#だけを+で繋げばいいのですが、2行目以降は
4)2行目から左右の空白が1つずつ増えている
なので、「i」の特徴である、初めは「0」であることを利用し、
「’ ‘ × i」にすることで1行目は「’ ‘ × 0」となり、空白は0のため何も表示されません。
⇒「#1234#」
「1#12#1」
「12##12」
2行以降は「’ ‘ × 1」となり、左の空白が1つ。
「#1234#」
⇒「1#12#1」
「12##12」
3行以降は「’ ‘ × 2」となり、左の空白が2つ。
「#1234#」
「1#12#1」
⇒「12##12」
これは、引数が変わっても同じなので、引数は関係しません。
「v」の右側の空白も同じ考えでいけます。
#を加える場所が変わるだけですね。
「s = ‘ ‘ * i + ‘#’ + ‘ ‘ * (n – i – 1) * 2 + ‘#’ + ‘ ‘ * i」
左は、#よりも左に+で繋げて、右は、#の後に+で繋げると実現できます。
これで最後の、
5)「#」はどの行も「2つある」
もクリアですね。完了です。
pythonのプログラミング(アルゴリズム)をマインクラフトでプログラムしてみる
マインクラフトのプログラミングで同じアルゴリズムが実現してある「マイクラプログラミング塾の3級の課題」をみてみるとこのようなプログラミングです。
先ほどのpythonプログラムの内容を色分けし、マインクラフトのプログラミングと色を対応させてみました。
色が暗くグレーの部分はマインクラフト内でロボットを移動させないといけない部分とブロックの色を変えるための命令はpythonにはないので、暗くしてあります。
この結果が、こちらです。
nに5を入れると、こんな風に自動的にサイズを変えて作ってくれるようになります。
言語のルールで書き方は変わるのですが、色を対応させた通り、アルゴリズムに基づいて他の言語で組み立てることもできるため、プログラミングツールが子供用だと思っていても、しっかり大学の試験でも出てくるわけですし、将来のためにしっかり考えを学んでいるんだという1つの例を取り上げてみました。
今回は偶然にもマイクラプログラミングの問題と同じだったわけですが、これはScratchでもUnityでも同じことが言えますので、「アルゴリズムを考えて、プログラミングを組み立てる力を養うことは、将来の自分を支える」と言っても過言ではありません。
そんな考えをプロクラス キッズでは子供達に教えていますので、プログラミング教室に迷われた時は一度プロクラス キッズに体験に来てください。
プロクラス の吉田でした。
ヨシダミツヒロ(@milan40920)
Follow @milan40920