pythonの基本構文を学んだから、それらを組み合わせてプログラムでやってみようって課題です。
正直、どのプログラミング言語も特徴はあれど基本は同じです。
これらの課題は他のプログラミング言語の練習課題としても有効です。
よろしくー
▼事前に読んで欲しい記事▼
簡単な計算 | 時分秒の変換
数式をプログラムに落とし込むことと、検算などの確認することの萌芽を狙います。
秒数の計算
- 1日が何秒なのか計算して表示しなさい。
- 1年が何秒なのか計算して表示しなさい。
もし、うるう年まで勘定にいれるなら偉いです!
そういうところに気がつくって良いことですね。
出力結果です。
1日は86400です。
1年は31536000です。
1年は31557600.0です。
下記がコードです。
print(f"1日は{24*60*60}です。")
print(f"1年は{365*24*60*60}です。")
print(f"1年は{365.25*24*60*60}です。")
できたー?
秒と時分秒の変換
秒と時分秒の変換・逆変換をしてみましょう。
ヒントとして、割り算の余り計算「%」と整数への切り捨て「int()」が教えときますね。
print(3%2)
print(f"{3/2} {int(3/2)}")
1
1.5 1
int()による切り捨ては
よく使うねー
課題は下記です。
- 1時2分3秒を、秒に計算して表示しなさい
- 3723秒が、何時何分何秒か計算して表示しなさい
出力結果です。
1時2分3秒は、3723秒です。
3723秒は、1時2分3秒です。
やってみよー
さて、秒への変換の答えです。
- 1時2分3秒を、秒に計算して表示しなさい
hh=1
mm=2
ss=3
time = hh*60*60 + mm*60 + ss
print(f"{hh}時{mm}分{ss}秒は、{time}秒です。")
1時2分3秒は、3723秒です。
次がちょいムズだねー
次は、時分秒への変換の答えです。いろんな計算式があると思います。
- 3723秒が、何時何分何秒か計算して表示しなさい
time = 3723
hh = int(time/3600)
mm = int((time-hh*3600)/60)
ss = time - hh*3600 - mm*60
print(f"{time}秒は、{hh}時{mm}分{ss}秒です。")
3723秒は、1時2分3秒です。
int()がちょっとムズイー?
int()を使わないやり方もあり得ます。
time = 3723
hh = (time-time%3600)/3600
mm = ((time-hh*3600)-(time-hh*3600)%60)/60
ss = (time-hh*3600-mm*60)
print(f"{time}秒は、{hh}時{mm}分{ss}秒です。")
3723秒は、1.0時2.0分3.0秒です。
表記が実数(小数点あり)になってますが、これぐらいは気にせず。
ぼくはこの式をよく使うねー
簡単な計算 | うるう年の判定
ある西暦が、うるう年なのかを判断するプログラムを作ってみましょう。
課題は下記です。判断する式は、外部サイト様にあります。
- 4で割り切れるなら「うるう年」
- ただし、400で割り切れなくて、100で割り切れるなら「平年」
簡単にみえるけど
ちょっと複雑だよー
答えは下記です。
# https://www.jcwa.or.jp/etc/knowledge/leapyear.html
year=1900
flag=0 # 0:うるう年ではない。 1:うるう年
if year%4==0:
flag=1
if year%400!=0 and year%100==0:
flag=0
if flag==0:
print(f"{year}年は、うるう年ではない。")
else:
print(f"{year}年は、うるう年です。")
if文による条件の組み方も色々あり得ますがそれも勉強です。
ただし!必ずデバッグをせんといかんです。
特に、4で割り切れるけど「うるう年」ではない判定ができているかが大事です。
- 1900年と2100年は「平年」と判定されるか確認する。
- 2400年は「うるう年」と判定されるか確認する。
「エラーなく動いた!」で、プログラムが正しいというわけではないです。
処理が正しいのかを確認する必要性を教えましょう。
テストはしっかりしよー
ループ文 | 合計を計算する
ループを正しく制御したり、前の値を記録しておいたりする練習をします。
ループについては、最初と中間と最後がどうなっているかを把握することが大事です。
for文でループカウンタを回す
課題は以下です。
- range()を使って、for文を制御して合計を計算してください。
- 1~10までの合計を計算してください。
sum=0
for i in range(1,11):
sum = sum + i
print(sum)
55
超基本だよー
for文でリストを回す
次は、リストを使ってみましょう。課題は以下です。
- リストを使って、for文を制御して合計を計算してください。
- 1~10までの合計を計算してください。
ちなみに、使うリストは以下の通り。
num_arr=[1,2,3,4,5,6,7,8,9,10]
与えられたヒントからプログラムを作るということが大事です。
この能力を育成しないと、以下のようなことをやり始めます。
- 毎回広大なインターネットから探す
- 今やろうとしているコードと同じものを探す
答えを待つよりは、調べるようになったのは良いことだとは思いますが、授業内容や教科書など培ったことを無視して探し出すのは、どうかなぁと個人的には疑問です。
答えです。
num_arr=[1,2,3,4,5,6,7,8,9,10]
sum=0
for i in num_arr:
sum=sum+i
print(sum)
55
リストからの呼び出しループも
よく使うよー
ループ文 | 平均を計算する
課題は以下です。
- 1~10までの合計を計算するプログラムを改良してください。
- 平均を計算するプログラムにしてみてください。
- ヒント:数を数える変数を用意しましょう。
ここでは答えを2通り書いておきます。
- range()を使ったループ
- リストを使ったループ
今まで習得したことを
使ってみよー
答え1。よくあるループカウンタを使った合計計算です。
「合計が55になっていない人はなにか間違っています。」とアナウンスして考える時間を与えてください。
ポイントはrange(1,11)の「11」ができるか。理解しているか発見できるか。
sum=0
cnt=0
for i in range(1,11):
cnt = cnt + 1
sum = sum + i
print(sum/cnt)
5.5
今まで習得したことを
使ってみよー
次は配列を使った方法です。
また配列の方が、いろんなデータの合計を計算できます。
num_arr=[1,4,3,6]とかですね。
しかしrange()だと、1,2,3や1,3,5みたいな順番に並んだデータしかできません。
合計を計算するプログラムは、データを配列に読み込むのが一般的です。
num_arr=[1,2,3,4,5,6,7,8,9,10]
sum=0
for i in num_arr:
sum=sum+i
print(sum/len(num_arr))
5.5
色んな組み方が
あるからねー
ループ文 | 最小値と最大値
ループになれたと思うので、応用してみましょう。
最大値を導出する
課題は以下。
- 合計を計算したプログラムを改良してください。
- 与えられたデータの最大値を計算するプログラムを作ってください。
- データはリストに格納されています。
- arr_num = [3,5,7,1,4,8,9,5]
合計のプログラムを
活かしてやってみよー
arr_num = [3,5,7,1,4,8,9,5]
max = -1
for i in arr_num:
if max < i:
max = i
print(i)
9
ちょっとコツを
説明するねー
最大値に-1を入れていますが、データの範囲が予想できるのであれば、あり得ない小さいな値を最初に入れることになります。今回はarr_numには正の数だけが入っているので、必ずmaxが-1からデータの値に変わります。
データが10点満点のように範囲が分かるものだったら可能ですが、範囲が分からない場合は危険。
よって下記のように改良します。
arr_num = [3,5,7,1,4,8,9,5]
max = arr_num[0]
for i in arr_num:
if max < i:
max = i
print(max)
maxの初期値に、1番目のデータを入れるようにしました。
for文で「再度」1番目のデータを読み込んで比較処理がされて1回だけ無駄処理していますが、まぁ良いでしょう。
よく考えたもんだよねー
最小値を導出する
最大値のプログラムを活かして、最小値を計算するプログラムに挑戦してみましょう。
- 最大値を導出するプログラムを改良してください。
- 最小値を導出するプログラムを作ってください。
すぐにできれば、よく理解していますね。
arr_num = [3,5,7,1,4,8,9,5]
min = arr_num[0]
for i in arr_num:
if min > i:
min = i
print(min)
1
ループの最初をどうするかという工夫、なるべくループの中だけで処理したいという工夫を考える機会になればと思います。
できたかなー
sorted()を使う
元も子もないですが、pythonには大小順に並べてくれる関数が用意されています。
- sorted()を調べて使ってみてください。
- 最小値と最大値を導出してみてください。
sorted()について
調べてねー
答えです。
arr_num = [3,5,7,1,4,8,9,5]
arr_num02 = sorted(arr_num)
print("昇順(小さい順)にソート")
print(arr_num02[0])
print(arr_num02[len(arr_num02)-1])
arr_num02 = sorted(arr_num,reverse=True)
print("降順(大きい順)にソート")
print(arr_num02[0])
print(arr_num02[len(arr_num02)-1])
昇順(小さい順)にソート
1
9
降順(大きい順)にソート
9
1
今は理解しなくて良いのですが、下記を学ぶチャンスです。
- 関数に引数がある。そして省略されている場合がほとんど。
- 省略されている引数には「引数=パラメータ」として指定できる。
用意された関数を使うと
楽になるよー
ループ文 | 奇数や偶数を抽出する
課題は下記です。
- 1~10のうち奇数だけを表示してください。
色々やり方をしてOKですが、最後に剰余を使った方法を理解してくださいね。
後々、素数や円周率の演算などで使用します。
答え1 | range()の増分を2にする
for i in range(1,11,2):
print(i)
2個おきに
出現するからねー
答え2 | flagを使って1回置きに表示する
flag=1
for i in range(1,11):
if flag==1:
print(i)
flag=0
else:
flag=1
交互に現れるからねー
答え3 | 数式を使う
for i in range(1,6):
print(2*i-1)
作っていく感じだねー
答え4 | 剰余を使う
for i in range(0,11):
if i%2 == 1:
print(i) # 奇数
else:
pass # 偶数
これを理解してねー
色々使えるからー
剰余の活用 | 各桁の数値を抽出する
「秒数と時分秒の変換」と同じような考えで、int()や剰余「%」を使っていきます。
下記のように「各桁の数字を取り出してください」が課題です。
int()を使うのがヒント。
123 -> 1 2 3
考えてみてねー
答えです。
num = 123
digit1 = int(num/100)
digit2 = int((num-digit1*100)/10)
digit3 = num - digit1*100 - digit2*10
print(f"{num} -> {digit1} {digit2} {digit3}")
式は一行にする必要はないので、一つずつ分かるようにしてもらってOKです。
考えないと
分からないよー
剰余の活用 | 金種の計算
以下のように、120円を決めたら、金種を計算するプログラムを作ってみましょう。
金額は120円です。
100硬貨:1枚
10硬貨:2枚
就職での技術テストでよく良く出題されます。
今までの課題を
活かして考えてねー
答え1 | int()を使う
amount = 120
print(f"金額は{amount}円です。")
money100 = int(amount/100)
money010 = int((amount-money100*100)/ 10)
print(f"100硬貨:{money100}枚")
print(f" 10硬貨:{money010}枚")
amount = 120
money100 = int(amount/100)
amount = amount%100
money010 = int((amount)/ 10)
print(f"100硬貨:{money100}枚")
print(f" 10硬貨:{money010}枚")
できなかったら
必ず理解してねー
では、もっと大きくしてみましょう。
17696円の金種計算をするプログラムに拡張してみてください。
amount = 17696
money10000 = int(amount / 10000)
amount = amount - money10000*10000
money05000 = int(amount / 5000)
amount = amount - money05000* 5000
money01000 = int(amount / 1000)
amount = amount - money01000* 1000
money00500 = int(amount / 500)
amount = amount - money00500* 500
money00100 = int(amount / 100)
amount = amount - money00100* 100
money00050 = int(amount / 50)
amount = amount - money00050* 50
money00010 = int(amount / 10)
amount = amount - money00010* 10
money00005 = int(amount / 5)
amount = amount - money00005* 5
money00001 = int(amount / 1)
print(f"10000:{money10000}")
print(f" 5000:{money05000}")
print(f" 1000:{money01000}")
print(f" 500:{money00500}")
print(f" 100:{money00100}")
print(f" 50:{money00050}")
print(f" 10:{money00010}")
print(f" 5:{money00005}")
print(f" 1:{money00001}")
10000:1
5000:1
1000:2
500:1
100:1
50:1
10:4
5:1
1:1
コピペでちょっと変えたら
できたよねー
答え2 | divmod()を使う
divmod()を使うと、割り算の商と余を同時に得ることができます。
amount = 17696
money = amount
money10000, money = divmod(money, 10000)
money05000, money = divmod(money, 5000)
money01000, money = divmod(money, 1000)
money00500, money = divmod(money, 500)
money00100, money = divmod(money, 100)
money00050, money = divmod(money, 50)
money00010, money = divmod(money, 10)
money00005, money = divmod(money, 5)
money00001, money = divmod(money, 1)
print(f"金額は {amount}円です。")
print(f"10000:{money10000}")
print(f" 5000:{money05000}")
print(f" 1000:{money01000}")
print(f" 500:{money00500}")
print(f" 100:{money00100}")
print(f" 50:{money00050}")
print(f" 10:{money00010}")
print(f" 5:{money00005}")
print(f" 1:{money00001}")
金額は 17696円です。
10000:1
5000:1
1000:2
500:1
100:1
50:1
10:4
5:1
1:1
プログラムも表示も
見やすく揃えてみよー
配列 | 九九表
一次元配列ができるようになったので、二次元に挑戦しましょう。
データベース的な管理が可能になります。
下記のコードをうつしてください。配列に値を入力しています。
a = [[0 for j in range(9)] for i in range(9)]
課題は下記。
- 二次元リストに九九の値を格納してください。
- 二次元リストを九九表として分かりやすく表示してください。
- 表示で桁合わせもしてると見やすいですね。
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
学習効果は下記。
- 二次元配列の取り扱いに慣れる。
- 格納する値(1~)と配列のインデックス(0~)のずれについて。
- どっちが行で列なのかとか考える。
- print文について調べる。
- 表示の桁合わせについて調べる。
- 改行なしについて調べる。
a = [[0 for j in range(9)] for i in range(9)]
for i in range(1,10,1):
for j in range(1,10,1):
a[i-1][j-1]=i*j
for i in range(1,10,1):
for j in range(1,10,1):
print("%3d"%(a[i-1][j-1]),end="")
print("")
二次元三次元とチャレンジしていきましょう。
画像識別AIでの画像データは、三次元や四次元の配列として管理しています。
二次元のリストを使うのですが、最初に初期化しておかないといかんので。
配列理解したかなー
ループと分岐 | 素数を抽出する
課題文は下記です。
- 1~20の中から素数だけを表示してください。
- 「素数」とは1と自分以外では割り切れない数です。
- 2, 3, 5, 7, 11などが「素数」です。
答えです。今後素数を使ったプログラムがでるのでぜひマスターしてください。
for i in range(2,21):
flag=0
for j in range(2,i):
if i%j==0:
flag=1
if flag==0:
print(i)
2
3
5
7
11
13
17
19
ちょっと難しいでしょー
確率計算
ハノイの塔やモンテカルロシミュレーションなどのコンピュータシミュレーションもやりましょう。
また、計算結果を、数学・統計での数式的結果と比較することによって、誤差についても考える機会になります。
いよいよ
難しくなるよー
コインの確率
乱数を使いますので、下記の動作確認をしてください。
# 1-10のどれかが表示されます。
import random
print(random.randint(1,10))
課題文は下記です。
- コインの裏表の確立が50%,50%ぐらいになることを確認してください。
- コインは100回ぐらい振ります。
- 表が出た回数、裏が出た回数を数えます。
- 回数から確率を計算してください。
import random
cnt1=0
cnt2=0
cntmax=100
for i in range(0,cntmax):
dice=random.randint(1,2)
if dice==1:
cnt1 += 1
elif dice==2:
cnt2 += 1
print(f"{cnt1} {cnt2}")
print(f"{cnt1/cntmax*100:4.1f}% {cnt2/cntmax*100:4.1f}%")
出力結果です。単純にprint()でも良いのですが、桁合わせなどをしてみました。
51 49
51.0% 49.0%
ついでに、表示で用意する桁数・小数点桁数の設定法も学んでも良いです。
モンテカルロ法に
応用していくよー
リストを使ってみる
サイコロの場合は6つになるので大変です。
そこで、回数を変数ではなく、リストに格納することをやってみましょう。
学生へのアナウンスは下記です。
- サイコロを振って、各目の回数と確率を計算してください。
- 各目の回数はcnt_arr[]というリストに格納してください。
答えです。
cnt_arr[0]に1の目の数、cnt_arr[1]に2の目の数を格納する感じです。
import random
cnt_arr=[0,0,0,0,0,0]
cntmax=1000000
for i in range(0,cntmax):
dice=random.randint(1,6)
cnt_arr[dice-1] += 1
print(f"{cnt_arr[0]} {cnt_arr[1]} {cnt_arr[2]} {cnt_arr[3]} {cnt_arr[4]} {cnt_arr[5]}")
print(f"{cnt_arr[0]/cntmax*100:4.1f} {cnt_arr[1]/cntmax*100:4.1f} {cnt_arr[2]/cntmax*100:4.1f} {cnt_arr[3]/cntmax*100:4.1f} {cnt_arr[4]/cntmax*100:4.1f} {cnt_arr[5]/cntmax*100:4.1f}")
出たサイコロの目(1~6)を、リストのインデックス(0~5)に流用しています。
最後のprint()文もループを使えば良いかもしれませんが、それはお好みで。
コードが短く汎用性がでてくるかもですが、別の人がコード見た時に解読する必要があるので、表示は長くてもそのまま書いておくのも良いかなと思っています。
図に書き出してみて
しっかり理解してねー
まとめ | 基本的なアルゴリズムで「考える力」を育てよう!
今回は、pythonの基本文法を理解した後に、身近な計算処理を題材にプログラミング実習をしました。
題材としてはよくあるものですが、その教育的意義までお伝えしたつもりです。
自ら立式したり、話し合うことで、「動くもの」を作る実現経験。
与えられたヒントでやりくりしたり、調査したりして、作る開拓経験。
range()やリストのインデックスなど、数がどこから始まってどこで終わるのかという、境界テスト経験。
色んなアルゴリズムが考えられるし許されるし、特徴的な工夫も知れる、思考体験。
プログラミングの教育だけで終わらせず、学生の人間性や生き抜く力まで育てたいと想いを込めて教えてきました。
じゃ またー