小学生くらいの子供がいる人向けにプログラミングを語ってみる

今年からプログラミング教育が必修になるということで、夏休みの課題なんかにも自由プログラミング研究みたいなものが増えるのですかねー。
なんて思いながら書いてます。そうなってくると当然ちちはは達にもプログラミングについての質問なども飛び交う世の中にだんだんとなってくるわけですが、いまの親世代だとそんなに知らないのではないのかなと。
ということで、小学生くらいの子供がいる人向けにプログラミングを語ってみようというものをやってみようと思いました。

ワックスかける、ワックスとる

小生がはじめてプログラミングを習ったときは例題として電話をかけるというのがお題だったような違うような。
まあともかく、電話についての一部始終を考えるような感じ。
最近の子供って固定電話なんかは分かるのだろうか?まあいいか。

固定電話っていうのはこういうやつです。

んでひとつプログラミングで大切なことを書くと、プログラミングは書かれているとおりに動きます。
書いたとおりに動きます。

ロシアのおじさんが、相手がちょっと離れていたとしてもパイルドライバーがかけれるのも、7回続けて逃げるといつも攻撃が会心の一撃になったりするのも、そう書かれているからだし、なんらかの理由があったりします。

では、電話をかけるための命令を上げてみようのコーナー。

1.電話アプリをタップする。
2.アドレス帳を呼び出す。
3.かけたい人の名前をタップする。
4.電話マークをタップする。

と、いう流れが一般的かなと思うけどどうやろう。最初の方に固定電話を上げてたんだけど、並べてみたらすごい命令が少なすぎたので、急ですが電話アプリにしました。うふふ。

ここに、4つの命令があるわけですが、この4つの命令の中にもまた細かい命令や制御が別途あったりするというような感じを想像すると、あ、なんかプログラムっぽい!って感じるかも。たとえば誰がするかとか、どっちの手でやるのかとか、どんな強さで押すのかとか。

ここではシンプルに電話をかけるというプログラムで、たとえばこの4個の命令でも1個でも順番が違うと成立しなくなってしまいます。
電話アプリをタップしてアプリが起動しないとアドレス帳が押せる状態にはならないので、もし人間だったら押し忘れとか押し損じなんかだったりするともう1度電話アプリをタップできるけど、プログラミングはそう書かれていなければ2番のアドレス帳を呼び出そうとするのでそこで失敗ブーです。★1個です。

なので1番に失敗してたら2番はやらずにそのまま終了にする!とか、1番をもう1回やるとかの命令を入れてやれば良い感じですね。

だいたいこんな感じです。
では、說明が終わったので実践です。
たぶんだけどプログラミングの授業というものの、論理的な考えを養っていこっぜというのもカリキュラムの一貫だろうとは思うので実際にプログラミングを書いてしまってそれについての解説をしていこうと思います。
もしかしたらその方がわかりやすいかもしれんし。

じゃんけんについて考えてみるコーナー

さっそくやけども進めていきます。言語は今をときめくGo言語にしました。

言語はGo!でーす!とか言うと喜ぶ子供が居るかもしれないと思った。。。おらんかな。

あくまで一例ですので、書き方は山ほどあるというのは覚えておいてください。

意味はとくに考えないで、goを走らせるための最初のテンプレ的なやつです。
このgo言語という言語ですが、なんと無料でインターネット上で簡単に試すことができます。

GOチュートリアル

こちらはGo言語のチュートリアルです。
チュートリアルを進めていくこともできるし、自分で自由に書いても大丈夫です。
右端の黄色の中で動かせますのでぜひお試し。

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {

}

動かしたいプログラムは func main() { の中に書いていきましょう。

ここでたけちゃんとけんちゃんという二人にじゃんけんをしてもらうことにしまうす。

human := map[string]int{"take": 0, "ken": 0}

二人とも、おれはグーしかださねー!とかではなくて、純粋にじゃんけんをしてもらいます。

rand.Seed(time.Now().UnixNano())

何回やるかのカウント、初期値は0にします。あいこも0回。

count := 0
aiko := 0

ひとまず10万回勝負してもらうよ。

for count < 100000 { }

10万回の繰り返してもらうものは {} の中に書きます。

じゃんけんはグーとチーとパーの3つです。

takePon := rand.Intn(3)
kenPon := rand.Intn(3)

ではそれぞれの場合を書いていきます。if 〜もしも〜という命令を使います。
0がグー、1がチー、2がパーです。勝ったほうに1ポイント。
アイコの数も数えることにして、ノーカウントにします。

if takePon == 0 && kenPon == 1 {
	human["take"]++
} else if takePon == 0 && kenPon == 2 {
	human["ken"]++
} else if takePon == 1 && kenPon == 0 {
	human["ken"]++
} else if takePon == 1 && kenPon == 2 {
	human["take"]++
} else if takePon == 2 && kenPon == 0 {
	human["take"]++
} else if takePon == 2 && kenPon == 1 {
	human["ken"]++
} else {
	aiko++
	count--
}

で、次の勝負。これを10万回。

count++
画面に表示してもらうよ。

fmt.Printf("結果 たけの勝ち %d けんの勝ち %d あいこ %d \n", human["take"], human["ken"], aiko)
全部くっつけるとこんなふうになる〜。

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	human := map[string]int{"take": 0, "ken": 0}

	rand.Seed(time.Now().UnixNano())

	count := 0
	aiko := 0

	for count < 100000 {

		takePon := rand.Intn(3)
		kenPon := rand.Intn(3)

		if takePon == 0 && kenPon == 1 {
			human["take"]++
		} else if takePon == 0 && kenPon == 2 {
			human["ken"]++
		} else if takePon == 1 && kenPon == 0 {
			human["ken"]++
		} else if takePon == 1 && kenPon == 2 {
			human["take"]++
		} else if takePon == 2 && kenPon == 0 {
			human["take"]++
		} else if takePon == 2 && kenPon == 1 {
			human["ken"]++
		} else {
			aiko++
			count--
		}

		count++
	}

	fmt.Printf("結果 たけの勝ち %d けんの勝ち %d あいこ %d \n", human["take"], human["ken"], aiko)
}

では!
実行してみましょうか。どっちが勝つかな。どっちが勝つかな。

sample01.go
結果 たけの勝ち 50108 けんの勝ち 49892 あいこ 49499 
おおっと、だいたい半分くらいでだいたい互角のようだね。では数学的に解いているのをヤフー知恵袋で見つけたので引用してみます。

YahooJapan知恵袋 じゃんけんで勝つ確率は何パーセントですか?
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12153383137

n人でじゃんけんした場合、
1回目の勝負で勝つパターンを考えます。
全パターンは、グー, チョキ, パーの
3種類をn個並べる重複順列ですから、3^n通り。
そのうち、勝負が決まるパターンとは
すべての人が出した手が、
グー, チョキのみ
グー, パーのみ
チョキ, パーのみ
のいずれかです。これらはそれぞれ、
2種類をn個並べる重複順列2^n通りから、
すべて同じ手(グーのみ、とか)である
2通りを引いたものですので、
それぞれは(2^n-2)通りとなります。
3パターンあるので3(2^n-2)通りです。

勝つパターンに限定すると
3(2^n-2)/2=3(2^(n-1)-1)通りになり、
勝負が決まる確率は全体の3^nで割って
3(2^(n-1)-1)/3^n
=(2^(n-1)-1)/3^(n-1)となります。
ややこしくなるので、これをP(n)と置いておきます。
同様にして、負ける確率も同じだと分かります。
あいこになる確率は、
勝ちでも負けでもない確率なので
1から引いて、1-2P(n)となります。

以上で1回の勝負で決まる諸確率が得られました。
次に、最終的に勝つ確率を見てみます。
1回目で勝つ確率はP(n)ですが、
2回目で勝つ確率とは、1回目であいこになって
2回目で勝つ場合の確率ですので、
(1-2P(n))P(n)となります。
3回目はあいこ、あいこ、勝ち、なので、
(1-2P(n))^2 P(n)となり、
k回目では(1-2P(n))^(k-1) P(n)となります。
従って、最終的に勝つ確率はこれらを
無限に足した結果であり、
P(n)+(1-2P(n))P(n)+(1-2P(n))^2 P(n)+…+(1-2P(n))^(k-1) P(n)+…
となります。
これは初項P(n)、公比(1-2P(n))の
無限等比級数になっていますから、
=P(n)/(1-(1-2P(n))) となります。
計算を進めてみると、
=P(n)/(1-1+2P(n))
=P(n)/(2P(n))
=1/2
となり、P(n)が何であろうと約分して消えて、
最終的に勝つ確率は人数によらず
1/2であることが確認できます。

ということで、だいたい1/2です。

何度か試した結果を下に貼りました。
多少のばらつきはありますが、じゃんけんなのでそんなにバラつかないですね。
全部たけの負けになってますけど。

相手がメンタリストDaigoさんとかでなければだいたい1/2で勝利できるんだね。

結果 たけの勝ち 49934 けんの勝ち 50066 あいこ 50259 
結果 たけの勝ち 49832 けんの勝ち 50168 あいこ 50098 
結果 たけの勝ち 49987 けんの勝ち 50013 あいこ 50161 
プログラミングの仕方によっては、たけはグーを出しやすいとか、パーを出しやすいとかできるので考えてみると面白いかもしか。
じゃあ今日はこんな感じです。場合の数は中学で習うみたいなのでちょっと予習になっちゃった。

Related Posts


投稿者: Takeken

インターネット利用者のITリテラシーを向上したいという設定の2次元キャラです。 サーバー弄りからプログラミングまで手を付けた自称エッセイストなたけけんの物語。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です