夏休み、100校1万人プログラミングにチューター参加してきた。

7月29日に、"みんなのコード"が主催する下のイベントでチューターをしてきた。

code.or.jp

今、流行りの子供向けプログラミングの1つだが、小学校で必修化するにあたってどうしよう、を少しでも解決しようというイベントである。

申し込みページを見ると、開催地にScratch Dayが開催された古賀市があって、toRuby宇都宮のラズパイ勉強会の高井さんのホームグラウンドだから、彼は必ず参加するに決まっていると思って申し込んだみた。結局、送迎から何から、高井さんにはすっかりお世話になってしまった。感謝!!

みんなのコードから開催1週間前に資料が送られてきたが、自分が何をすればいいのか明確ではなく、不安のまま学校に向かったのだけど、幸いにもみんなのコードから一人、チューターとしてきてくださったので、私の役はHour of code版のマインクラフトの使い方説明プレゼンと子供達の質問に答えたり話しかけること、で済んでしまった。

生徒達は普段、学校でマインクラフトをやっているようで、説明の時の反応は良かったが、Hour of code版は初めての子が多かった。でも操作はいたって簡単なので、みんなすぐに課題にとりかかり、始めて間もなく1段階クリアした時の効果音が教室に響き始めた。早い子はほんとに早く、30分くらいで全部の課題を終わらせた子もいたので、その子達は同じHour of codeのスターウォーズアナと雪の女王をやってもらった。

一方あまり上手に進められない子を見てみると、ループを使うあたりで引っかかっている子が多かった。この課題、キャラクターを決まった位置まで動かすことが目的になっていて、最初は直進するだけなので、”前にすすむ”ブロックを必要な歩数分くっつけると完成する。次に向く方を変えながら、でもシーケンシャルにブロックをつなげる課題があり、そしてループや条件分岐のブロックが登場する。動きも複雑になり、動く以外の振る舞いも導入されてくる。すると子供達の進み具合に幾つかのパターンが現れる。最適なコードを書く子、冗長な部分もあるがループを導入できてる子、ループブロックは置いてあるが中身は空(!!)で、シーケンシャルにたくさんのブロックを置いて実現できている子、たくさんブロックはあるけどゴールにたどり着けない子、そしてループブロックが頭に重くのしかっているのか、手が止まっちゃう子だ。シーケンシャルに実現できている子にはループブロックの使い方や、ループの切り出しをアドバイスするとできるようになる。たどり着けない子も、きっと時間をかければできるんだと思う。そして手が動かない子はちょっとかわいそうだったけど、こちらもなす術が無かった。

授業の後半はややゲームをしている感じになったので終わりにし、最後に生徒に感想を話してもらい授業は終了した。教室をでる時に先生から一人一人にHour of codeの Certificationを手渡されて帰って行った。

 

正味90分だったけど、なんだかあっという間だった。

もっと子供達のコードを見たかったし、お話ししたかったし、もっと気づかせてあげたかったな。語り好きの私にはちょっと不完全燃焼だったな。

 

校長先生から、この小学校では来年度からプログラミングを授業に取り入れると伺った。ハードはiPad40台、近々さらに10台増やすとのこと。やや箱物重視な感じもしたけど、主担当の先生、古河市ではエバンジェリストと呼ばれるそうなのだが、その先生ならきっと大丈夫でしょう。それでも1年間という長いスパンで、何をどこまで教えていくのだろうか。また実習時にチューター役の先生は付くのだろうか。そして、今回のように募集に応えた生徒ばかりではない状態で授業が成り立つのだろうか。いずれ解消できるとは思っていても心配になってしまう。

 しかし、Certificationを手にした時の、子供達の達成感と満足感のあの笑顔を見たら、あまり細かいことは考えず、子供が楽しめればいいのだと強く感じた。そして先生も、その笑顔もモチベーションに一緒に楽しんじゃえばいいんじゃないかな。

 

追加

これから数年間はどちらかというと先生の立ち上げ期間になるだろう。先生にこそプログラミングの楽しさや技法を学んで欲しい。そのためには実務としてプログラムを作ったことのある人間たちが率先して協力すべきだと思う。ボランティアで自分達の培ってきた技法や哲学を先生方に教えるのは、自分達のいるソフトウエア開発の世界への強い投資になるはず。そのためには、今は性善説ベースな仕組みにしかなっていないので、ボランティアをよりシステマチックにサポートする体制も必要だろう。やるべきことはたくさんたくさんあるね。

 

那須ラボ7月

これまで、その時々でやりたいことをやっていたけれど、OSMOに会って、ようやく継続してやれることがみつかってきたようだ。以前もOSMO Tangramをやらせてもらって楽しめた時もあったけど、ちょっとその場限りな感じだった。しかし前々回から始めたCodingは面をクリアしていく楽しさもあるようだが、クリアした面を敢えて違うCodingで達成できる、という楽しさも知ったようだ。最初は1ブロックづつだったのが、昨日は一気に進められるよう、ブロック4段5段+ループ制御と複雑度があがっていた。ゲームチックにゴールが存在するようなので、とりあえずは飽きるまで進めばいいかな。

那須ラボ4月

マイクラでほぼ90分間、羊の毛刈りだけをしたり、ジェイソンに刺激されてScratchをやったりと、相変わらず的が定まっていない活動(?)をしているけど、それが楽しいと言ってくれているので親としても続けたいと考えている。

羊の毛刈りは本人もやり続けてはどうかと思っていたらしく、感想を聞いても照れ笑いをしていた。もう少し話を聞くと、本来は海や山のあるワールドを作りたかったらしい。イメージはあるようなので、フラットなワールドを用意してもらった後は、あまり口出しをせずに好きにやらせたいと考えている。

 

Project Euler 57を書いて思ったこと

またもやProject Eulerネタ。

Problem57にトライ。 

def root2_series
  (1..1000).inject( [3/2r] ) do |result, i|
    result << 1 + 1 / (result.last + 1)
  end
end

def bigger_numerators
  root2_series.select do |term|
    term.numerator.to_s.size > term.denominator.to_s.size
  end
end

p bigger_numerators.size

 3/2rはRationalのリテラルで、2.1から使えるようになったとのことだ。ちなみに複素数リテラルもできたみたいで、そういえば昔、3+2iって試して、できなかったことがあったのを思い出した。

それと今回は√2の級数を求めるのにinjectを使った。私はinjectは「前の値を使って1つの値を求める」しか頭になかった。しかしある人のコードで、「前の値」に配列を入れることで、まるでmapのように配列を作った例があったので、そのアイデアを使わせてもらった。injectを使うことで漸化式の各要素の入った配列を作ることができるなんて、自分だけではなかなか気づけないと思う。

そうなるとコードはシンプルになる。初項の3/2rが入った配列を初期値にしてやると、前イテレーションの計算結果がresult.lastで取り出せるので、最終的に1000個の項が入った配列になってくれる。

級数配列が完成すれば、Rationalの分母分子の桁数(.to_s.size)で比較すれば終わり、となる。

Rationalすごい?!

このコードをtoRubyで見せたところ、@you_ssk から、この級数の不思議な特徴を教えてもらった。ProjrctEulerにあるように、この級数は以下のように算出できる。

1 + 1/2 = 3/2 = 1.5
1 + 1/(2 + 1/2) = 7/5 = 1.4
1 + 1/(2 + 1/(2 + 1/2)) = 17/12 = 1.41666...
1 + 1/(2 + 1/(2 + 1/(2 + 1/2))) = 41/29 = 1.41379...

この各項を見てみると以下のような規則があるというのだ。


3/2
7/5 = (3+2*2)/(3+2)
17/12 = (7+2*5)/(7+5)
41/29 = (17+2*12)/(17+12)

つまり、
an/bn = (an-1 + 2 * bn-1)/(an-1 + bn-1)
なのである。これはすごいと、早速コードを書き直した。

def root2_series
  (1..1000).inject( [ [3,2] ] ) do |result, n|
    result << [result.last[0] + 2 * result.last[1], result.last[0] + result.last[1]]
  end
end

def bigger_numerators
  root2_series.select do |term|
    term[0].to_s.size > term[1].to_s.size
  end
end

p bigger_numerators.size

コード的にはほとんど変わらないのだけど、Rationalクラスを使わずに済んでいるのでなんとなく節約できた気になった。そこで処理時間を測ってみた。以下に結果を載せる。(100回動かした合計時間と100で割った平均時間)

                      user     system      total        real
Without Rational  3.323000   0.000000   3.323000 (  3.315948)
 Avg              0.033230   0.000000   0.033230 (  0.033159)

Rational     	  1.700000   0.000000   1.700000 (  1.697862)
 Avg          	  0.017000   0.000000   0.017000 (  0.016979)

 

Rational使った方が早い。。。これはどういうこと?

分数を使わずにできることをたまたま人から教わったからいいけど、自分で必死に思いついてたら、Rubyに「時間返せ」と言ってたかもしれない。かっこいいなぁ、Rational。

 

Project EulerをRubyで書いている

Project EulerRubyで解いているんだけど、Problem55で初めて自分としては良い出来のコードが書けたので自慢しようと思う。

 

class Integer
  def reverse
    self.to_s.reverse.to_i
  end

  def palindrome?
    self == self.reverse
  end

  def lychrel?
    myself = self

    (1..50).all? do |i|
      !(myself += myself.reverse).palindrome?
    end
  end
end

puts (1..9999).select { |i| i.lychrel? }.size

配列のall?やany?メソッドは、これまで書いていた方法と比べるとスキッと書けるから使っていて楽しい。人に「好きなメソッドは?」と聞かれたら、all?とany?と答えることにしよう!!
それとワンライナーではないけど、私はメソッドを数珠繋ぎにしがちだった。人のWebでのRubyコードが適切にメソッド分けしていたので真似したら、これまたスキッと書けたので驚いた。「returnが必要ない」の意味が少しつかめたかもしれない。

 

那須ラボ3/5

本音を言うと、子供のコンピュータのアプローチは時期尚早だったと感じ始めている。わかっていたけども、別にプログラミングでなくても学べることはあると通ってきていたが、マイクラでそれほど完成度を上げられないのはどうしたものかと考えていた。

この日、最後に先生から、「次回はViscuitをやってみましょう」となって、ありがたく思うと同時に、子供の楽しみの1つになってくれそうで、ちょっとほっとした。自宅に帰り、私は少し真面目にViscuitをいじってみた。おもしろい!! 子供も熱中してくれると嬉しいな。

この日はマイクラの黄昏ワールドをやり始めた。結構、集中していたのか1時間過ぎたあたりで疲れたようだった。お姉さん二人のワールドをみながら、色々と考えていたみたいだった。

実はあまり記憶になく、これは私のProblem。子供とふりかえりをやらなかったからだ。次回は簡単な予習というか、課題の設定と、終わってからのふりかえりをやりたい。

 

MinecraftPIのタイマー

少し前に作ってうまくいかなかったタイマーを手直しして、1.1分で0.2秒くらいのずれで実現できた。なにより描画がスムースになったのがよかった。悪かったのは気を利かせたつもりの描画スレッドだった。minecraft_pi_rubyを見てみるとTCPソケットでマイクラと交信していたので、余計なスレッドをなくしたらあっさり動いてくれた。

時間精度の方はLindaのRuby実装であるRindaをタイマースレッドで動かすようにしたことで安定した。お試し以外でRindaを使ったのは初めてだったけど、とっても簡単にできた。もしCPUが混んでもいいように、tapleには表示すべき時刻を秒単位で書くようにしたけど、tapleはdefaultの60秒は残るので、ダメダメ、タイムアウトを変えないと。

マイクラの画面は以下のコードでフラットにしちゃってる。

 mc.set_blocks(-100, 0,  -100, 100, 63, 100, Block::AIR)
 mc.set_blocks(-100, -1,  -100, 100, 1, 100, Block::GRASS)
 mc.set_blocks(-100, -63,  -100, 100, -2, 100, Block::STONE)

これだとあまりに殺風景なので、適当なワールドを作って、ブロックデータを取り出し、それを毎回適用するようにしようと考えている。またタイマーのフォントも気に入らないので、できるだけ綺麗にしたいな。