日常1(プロフィールの追加アプリ)
このページはマス旅の一部です。
今回は、「プログラミングで脳トレ」の初回です。
身近なネタを使って、数学にも関係のある小物をプログラミングしてみよう。
数学もプログラミングも、ちょっとした脳トレの道具にできたらいいね。
1.BMIとか干支って話題に上ることってありませんか?
ということで、お題は次の通り。
課題:プロフィール追加アプリ
詳細:
「身長(cm)、体重(kg)、和暦の生年月日(M/T/S/H/R yy/mm/dd)」
を入力すると、
「BMIと体型(低体重、標準、肥満度)、西暦の生まれ年、干支」
を表示してくれる。
2.使う数学外の知識
#BMI
BMI=W(kg)/(H(m))^2
#体型
BMIから判定基準(日本肥満学会)
18.5未満:低体重(やせ)
18.5〜25未満:普通体重(標準)
25〜30未満:肥満(1度)
30〜35未満:肥満(2度)
35〜40未満:肥満(3度)
40以上:肥満(4度)
#西暦ADの生まれ年
M,T,S,H,R
==>明治,大正,昭和,平成,令和
元年{1868,1912,1926,1989,2019
末 45 15 64 31
末年 1912 1926 1989 2019
#干支
子(ね)、丑(うし)、寅(とら)、卯(う)、
辰(たつ)、巳(み)、午(うま)、未(ひつじ)、
申(さる)、酉(とり)、戌(いぬ)、亥(い)
西暦から3を引いて12で割った余りが1が子という人がいます。
以下が子になる西暦
1876年(明治9年)
1888年(明治21年)
1900年(明治33年)
.....
3.数学・言語・プログラミングの知識
#BMI計算
身長の入力が㎝なので、100で割ってから2乗して、体重を割る。
見やすくするために、四捨五入して小数第1の数にします。
xの小数第2位を四捨五入した値は、floor(10x+0.5)/10で求められるね。
#体型判断
Case文がないと、if-elseを入れ子にするのが普通の発想ですね。
しかし、判定基準の仕切りが
18.5以外は25,30、35、40と5刻みになっていることを活用したい。
5の倍数の判定境界値を5で割ると 5,6,7,8となる。
この特殊性に目をつけて、「リスト的な発想」で取り組む。
体型ランクのリストを作る。
ランクに入れるためにはBMI値を5で割って切り捨てると、
たとえば、BMI=25.5ならfloor(BMI/5)=5となり、インデックス5を指せる。
だから、最初から判定語(体型ランク)を9個作り、それが1から9の番号で指せるようにしよう。
もし、低体重なら無条件にインデックスは1で、
floor(BMI/5)が9を超えないように最大値が9となるようにしたい。
そのため、9と比べて小さい方をインデックスにする。
「ガードの発想」ですね。
#西暦の生まれ年
和暦文字はM,T,S,H,Rを入れる。
X={"M","T","S","H","R"}を作っておけば、インデックスIdをみつけられます。
Idの和暦ごとのゼロ年の西暦Cがわかれば、
Cにyyをたせば生まれ年の西暦が出ます。
C1={1868,1912,1926,1989,2019}
元年リストC1から1引いた0年リストC0を作れたら楽ですね。
#干支
西暦から3を引いて12で割った余りが1が子という人がいます。
というのは面倒ですね。
(X-3)=1 mod 12 が子(1)
X=4 mod 12 のときのXが子(1)
Xを9増やすと巡回シフトする。
X=4+8≡0 mod 12 のときのXは申さる(9)
干支を申さる(9)スタートひつじ未(0)終わりにすると、
X(mod 12)で0スタート11エンドの繰り返しになります。
こうすれば、Xを12の倍数をスタートの周期にできますね。
(脱線)
12=3×4で、下4桁が4の倍数で各位の和が3の倍数です。
西暦は18YY,19YY,20YYの3通りしかありません。
申年だけを知りたいとしましょう。
1+8=9は3の倍数だから、18YYのYYは12の倍数です。1896が最後の申年。
19YYのYYは4の倍数で3の倍数ー1。1992が最後の申年
20YYのYYは4の倍数で3の倍数ー2です。2004が最初の申年。
4.コード化
<geogebraのアプレット>
「要素を追加>geogebra>作成>関数グラフ」
数式ビューの入力...に
1行づつ貼り付けてEnter
#入力ボックスの挿入で、見出し、コントロール名を選びます。
それをInputBox(見出し、コントロール名)と表示しています。
(InputBoxコマンドから入力するときは、コントロール名だけを引数にとるので、
見出しは設定の変更が必要になります。)
H=180
W=70
Era="H"
YY=20
InputBox("身長(cm)",H)
InputBox("体重(kg)",W)
InputBox("和暦",Era)
InputBox("年YY",YY)
text0="「和暦」は明治はM,大正はT,昭和はS,平成はH、令和はRで、"
text1="「年YY」は、5年生まれならば05と入力してください。"
#計算部分
BMI=((floor(10*((W)/((((H)/(100)))^(2)))+0.5))/(10))
BodyTypes={"低体重","標準","標準","標準","肥満1","肥満2","肥満3","肥満4","肥満4"}
BodyTypeIndex = if(BMI<18.5, 1,floor(BMI/5))
BodyType=Element(BodyTypes, min(BodyTypeIndex,9))
Eras={"M","T","S","H","R"}
base1={1868,1912,1926,1989,2019}
base0=base1-1
eraBase=Element(base0,IndexOf(Era,Eras))
YearAD=eraBase+YY
etos={"申(さる)","酉(とり)","戌(いぬ)","亥(い)",
"子(ね)","丑(うし)","寅(とら)","卯(う)",
"辰(たつ)","巳(み)","午(うま)","未(ひつじ)"}
etoId=Mod(YearAD,12)+1
eto=Element(etos,etoId)
#結果表示
text2="あなたのBMI: "+BMI
text3="あなたの体型判定: "+BodyType
text4="西暦の生まれ年: "+YearAD
text5="干支: "+eto
プロフィール追加アプリ
<Pythonへの移植コード>
jupyter notebook のセルにまるごと貼り付けて、Run。
# 入力ラインが表示される
H = float(input("身長(cm): "))
W = float(input("体重(kg): "))
Era = input("和暦(M/T/S/H/R): ").upper()
YY = int(input("年YY: "))
# 計算部分
BMI = round(W / ((H / 100) ** 2), 1)
BodyTypes = ["低体重", "標準", "標準", "標準", "肥満1", "肥満2", "肥満3", "肥満4", "肥満4"]
if BMI < 18.5:
BodyTypeIndex = 0 # Pythonは0-indexed
else:
BodyTypeIndex = int(BMI // 5)-1
BodyType = BodyTypes[min(BodyTypeIndex, len(BodyTypes) - 1)]
Eras = ["M", "T", "S", "H", "R"]
base1 = [1868, 1912, 1926, 1989, 2019]
base0 = [b - 1 for b in base1]
eraBase = base0[Eras.index(Era)]
YearAD = eraBase + YY
etos = ["申(さる)", "酉(とり)", "戌(いぬ)", "亥(い)",
"子(ね)", "丑(うし)", "寅(とら)", "卯(う)",
"辰(たつ)", "巳(み)", "午(うま)", "未(ひつじ)"]
eto = etos[YearAD % 12]
# 結果表示
print(f"\nあなたのBMI: {BMI}")
print(f"あなたの体型判定: {BodyType}")
print(f"西暦の生まれ年: {YearAD}")
print(f"干支: {eto}")