python勉強6日目 0 から 9 までの数について、円周率の小数部分 (第千位まで) に表れる回数をそれぞれ求め出力するプログラム

これは、僕が最高のエンジニアになるまでの物語だ。

今日はこちらの問題を僕なりに解釈する。

問題

円数率の小数点以下1000位までにおいて、「0〜9」の各数字が何回出現したかカウントして、順番に出力するプログラムを書け。

解き方

# ここにコードを書いてください
en = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989"

zero = 0
one = 0
two = 0
three = 0
four = 0
five = 0
six = 0
seven = 0
eight = 0
nine = 0

for number in en[2:]:
    if(number == "0"):
         zero += 1
    elif (number == "1"):
        one += 1
    elif(number == "2"):
        two += 1
    elif(number == "3"):
        three += 1
    elif(number == "4"):
        four += 1
    elif(number == "5"):
        five += 1
    elif(number == "6"):
        six += 1
    elif(number == "7"):
        seven += 1
    elif(number == "8"):
        eight += 1
    else:
        nine += 1
print(zero)
print(one)
print(two)
print(three)
print(four)
print(five)
print(six)
print(seven)
print(eight)
print(nine)              

僕が頑張って捻り出した答え。かなり長い。
仕組みとしては

まず、各数字が出現したときにカウントする変数を定義する。

次に変数enに円周率(小数点以下第1000位まで)をstr型(文字列)として代入する。
次に変数numに円周率の小数点以下第1000位までをstr型として代入する。
次に文字列を1つ1つ調べて、各数字をカウントする変数の値を+1ずつ変化させる(※)
最後に、各数字の出現回数を変数を介して出力する。

※文字列に対してfor文を用いると、1文字単位でスライスできる

for i in "Hello":
    print(i)
#
H
e
l
l
o

模範解答

PI = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989"

num_dict = dict()
for number in PI[2:]: # 小数部分 (第千位まで) をカウントする
    num_dict[number] = num_dict.get(number, 0) + 1

# 0 から 9 までの数字について答えを順に出力する
# number_dict は数字を文字として扱っていることに注意!
for number in range(10):
    print(num_dict.get(str(number), 0))

なるほど、分からん。
コードを一行ずつ見ていこう。

一行目。

PI = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989"

これは変数PIに円周率をstr型として代入しているということ。

二行目

num_dict = dict()

これは変数num_dictに空の辞書を代入しているということ。
dict()関数は、中身が空っぽの辞書を作る関数だ。
実際、print(num_dict)を実行するとこうなる。

num_dict = dict()
print(num_dict)
# {}

三行目

for number in PI[2:]:

変数numberに小数点以下を1文字ずつ代入する。

四行目

num_dict[number] = num_dict.get(number, 0) + 1

空の辞書に名前(key)と値(value)を入れたりしている。
ここで、辞書に新しくkey:valueを入れる方法をおさらいする。

例えば以下のような辞書があったとする

yatai = {"焼きそば":300,"かき氷":100}

この辞書に新しく、要素(「"フランクフルト":200」)を追加したい場合
辞書名["key"]= バリュー
といった形でコードを書く。
具体的には以下のような感じだ。

yatai["フランクフルト"] = 300
# {'焼きそば': 300, 'かき氷': 100, 'フランクフルト': 200}

つまり四行目の前半

num_dict[number] =

この部分の「num_dict」は辞書名で、[number]は変数number(の値)をkeyとして辞書に登録(追加する)という意味だ。
=があるので変数の定義だと勘違いしないように注意。

そして四行目の後半

num_dict.get(number, 0) + 1

変数num_dict(の値)+1をvalueとして辞書に登録する(追加する)という意味になるが、「get()メソッドに関する知識」と「辞書の上書きの知識」が必要だ。

まず、get()メソッドについて。
辞書で特定の要素にアクセスしたい時は[key名]でアクセスするが

yatai = {"焼きそば":300, "かき氷":100 , "フランクフルト":200}
print(yatai["フランクフルト"])
#200

この際、要素にないキーを指定するとエラーとなる。

yatai = {"焼きそば":300, "かき氷":100 , "フランクフルト":200}
print(yatai["焼き鳥"])
# File "./main.py", line 2, in <module>
    print(yatai["焼き鳥"])
KeyError: '焼き鳥'

そこで活躍するのがget()メソッド。
これを使えば要素にないキーを指定した時に何を表示表示するか(値)を設定することが出来る。

get()メソッドを使う場合は
「[key名]」
ではなく
「辞書名.get(key名,keyがない場合に表示する値)」
とコーディングする。

yatai = {"焼きそば":300, "かき氷":100 , "フランクフルト":200}
print(yatai.get("焼き鳥","売ってません"))
#売ってません

といった感じだ。

次に辞書の上書きについて。
「辞書名[ key名] = 値」
とコーディングすることで、valueを変更できる

yatai = {"焼きそば":300, "かき氷":100 , "フランクフルト":200}
yatai["焼きそば"] = 250
print(yatai)
#{'焼きそば': 250, 'かき氷': 100, 'フランクフルト': 200}


つまり四行目

num_dict[number] = num_dict.get(number, 0) + 1

は、keyとして変数numberの値を、valueとして変数num_dict + 1の値を追加する(変数num_dictの値がない場合は0をvalueに追加する)という意味となる。

つまり、この時点で辞書は完成している。
実際辞書を出力「print(num_dict)」するとこうなる。

PI = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989"

num_dict = dict()
for number in PI[2:]: 
    num_dict[number] = num_dict.get(number, 0) + 1
print(num_dict)
#{'1': 116, '4': 93, '5': 97, '9': 106, '2': 103, '6': 94, '3': 102, '8': 101, '7': 95, '0': 93}

あとは、これをどう整えて出力するかだ。
考え方としては
「print(num_dict["0"])」「print(num_dict["1"])」
…とkeyの値を0から順番に指定して出力すればいい。
ということは、そうだ。「for 変数名 in range(10):」だ。

実際、模範解答も

for number in range(10):

このようになっている。
そしてこの下(最後のコード)がまた複雑だ。

print(num_dict.get(str(number), 0))

まず、注目すべきはstr(number)の部分。
ここで、数字をint型からstr型に変換している。(「0」という数字から「"0"」という文字列に変換している)これはもちろん、辞書のkeyが文字列(str型)だからだ。

次に、get()メソッドでエラー回避をしているが…正直意味不明だ。

print(num_dict[str(number)])

で問題なく出力できる。(アルゴ式でも正解判定となる)
range()の範囲を間違えた時対策だろうか?
なぜget()メソッドが使われているか、分かる方いたらコメントで教えてほしい。




この記事が気に入ったらサポートをしてみませんか?