🐣

中学生にAtCoderでプログラミングを教える記録 5回目 〜 ABC081A - Placing Marbles

2022/08/13に公開

この記事の内容

ソフトウェアエンジニアが中学生の子にプログラミングを教えていく様子を記録する。この記事は5回目。前回は自分の手でコードを書いて、初めての提出までの流れをこなした。今回は別の問題で同じように提出までやってみる。

【前回の記事】 過去問 (ABC086A - Product) を1題解き、初めて提出した回。

今回の達成目標

今回のタスクはABC081A - Placing Marbles。このタスクを題材に、前回と同じ流れをもう一度おさらいする。
https://atcoder.jp/contests/abc081/tasks/abc081_a

  • 書く、動かす、確認する、を積み重ねてコードを書くということに慣れる
  • 提出までの手順に慣れる

問題概要

3つのマスにビー玉が置かれている。その様子を次のように数字で表す。0はビー玉なし、1はビー玉あり。

入力例
010

これが1行入力されるので、マスにビー玉が何個置かれているかを出力する。

出力例
1

解く様子

1. 入力取得を確かめる

私「入力を取得するところから書くか」
子「また入力取ってきて無視するの?」
私「お好きにどうぞ。前回書いた分は動くのもう確かめたじゃん? 持って来てもいいよ」
子「じゃあやまびこからやる」

solve_abc081_a.py
a = input()
print(a)
結果
010

私「いいね、これはもう自分のものになったね」
子「うん。これを…どうしよう。空白で区切れないな」

2. 解き筋を考える

本来はここで本人が解き筋を考えるシーンだが、この人はあまりにも道具を持っていない。しばらくはこちらで解き筋を考えて、必要な道具を渡し、それを使ってもらうことにする。

前回、空白で区切って、数に変換して、計算した経験があるので、今回もそれに似た方法にする。

  1. 入力を取得する。
  2. それを1文字ずつ分けて配列にする
  3. それを数に直す。
  4. 足す。
  5. そうするとビー玉の数になるので、出力する。

1文字ずつに分けて配列にする」という道具を渡すことにした。

3. もらった道具を動かしてみる

私「じゃあ、役に立ちそうな道具をひとつ渡しましょう。list(文字列)これね。」
子「何これ?」
私「何だと思う?」
子「道具あっても使い方わからんかったら使えないじゃん! どうせ『やってみ』って言うんでしょ。わかったよ」
私「ピンポン!」
子「とってきた入力は文字列だから、これを入れてみる」

solve_abc081_a.py
a = input()
print(a)
l = list(a)
print(l)
結果
010
['0', '1', '0']

子「どゆこと?」
私「文字列を1文字ずつバラバラにして、1文字の文字列の配列にする道具ってことです」
子「なるほどそうきたか。じゃあこれを、あのmapで数に直して、全部足し算すればいいんじゃ?」

4. 道具の成果を使って結果を出力する

子「前と同じだから、3つ変数作って代入すればいいんだよね」

solve_abc081_a.py
a = input()
print(a)
l = list(a)
print(l)
x, y, z = map(int, l)
print(x, y, z)
print(x+y+z)
結果
010
['0', '1', '0']
0 1 0
1

私「スムーズに行き過ぎ! 間が持たないだろ!」
子「えっ、おこられた! 草」

5. 初めてのリファクタリング

私「草も木もないんだよ。じゃあ次はテスト通してくださいよ」

oj test の結果
[FAILURE] test failed: 0 AC / 3 cases

子「なんだよ、ダメって言われたじゃん」
私「かかったな! フハハハ」
子「陥れるようなことをしないでほしいんですけど! デバッグ出力のせいじゃん」
私「チッ、気がついたか。」

solve_abc081_a.py
a = input()
l = list(a)
x, y, z = map(int, l)
print(x+y+z)
結果
1

子「こうね。テスト通していい?」
私「テスト通す前に、これもっと行数減らせると思わない? いい方法があるんだけど、興味ある?」
子「詐欺師みたいな言い方するじゃん」
私「バラバラにして配列にした後、変数lに入れてるけど、これ変数に入れないで、そのままmapの引数のところに書いてもいいんだよ」
子「詐欺師のくせに役に立ちそうなこと言ってくるの笑うからやめて」

solve_abc081_a.py
a = input()
x, y, z = map(int, list(a))
print(x+y+z)

子「おお、なるほど。変数も減るし分かりやすい」
私「え、ほんまに動くかわからんで? 信じてええの?」
子「そうやっていちいちハメようとしてくるみたいなん何w 動かしてみろって言えばいいじゃんw」
私「我が子が悪い人に騙されない人になってほしいっていう親心なんだよ」

結果
1

子「ちゃんと動いた。よかった。最初からこうすればよかったな」
私「何でもこうすればいいわけじゃないよ。さっきいったん変数に入れたのは、動作確認のデバッグ出力に必要だった。確認できたから、こうやって書いても大丈夫になった」
子「なるほど、最初からこう書くのは『一気に書いて動かなかったら困る』ってやつになっちゃうのか」
私「そういうこと。プロの人も、まず書いて動作確認してから、同じ動作のまま、読みやすいようにコードを整えていく、っていうことをするよ。『リファクタリング』っていう名前がついてる」
子「リファクタリング!かっこいい」
私「今のは初めてのリファクタリングだったね、実績解除だな🏆」
子「初めてだらけだわw」

6. コードの読みやすさ

子「これ、この行にinput()も入れちゃっていいの?」
私「いいよ。やってみ」

solve_abc081_a.py
x, y, z = map(int, list(input()))
print(x+y+z)

子「みじかなった」

結果
1

子「動いた」
私「2行で動くんだねえ。すごい。よし、短くなったコード、もっかい見てくれる? 行数は少なくなったよね。けど、こうやって入れ子が多くなると、ちょっと読みづらくなるのわかる?」
子「ああ、確かに…突然これ見せられても読めないかも…」
私「このくらいなら大丈夫だけど、コードって他の人も読むし、未来の自分も読むから、読みやすさを考えて書くといいよ。何もかもいちいち変数に入れるのも読みづらいし、全部1行で書かれても読みづらい」
子「えー、でも何が読みやすいかわからん」
私「せやねw いまは競プロだからとりあえず動けばオッケー! じゃあこのへんでテスト通そう」

oj test の結果
[SUCCESS] test success: 3 cases

子「通った!」
私「素晴らしいね、さすが! じゃ提出してみようか」

子「やった!」

今回やったこと まとめ

  • 動作確認しながらのコーディング
  • 提出までの手順のおさらい
  • 新しい道具list(文字列)を使ってみた
  • 関数呼び出しの引数に、関数呼び出しを書けることがわかった
  • 初めてリファクタリングをした
  • コードには読みやすいものとそうでないものがあると知った

【次の記事】 次は ABC081B - Shift Only に進むとあるが、ちょい難しめを感じたので、準備として配列(リスト)やfor文を使って今までの問題の別解を作ってみる。

Discussion