Python100本ノック 92本目~96本目(91本目~95本目)
Python100本ノック、92本目から96本目についてです。
終わりが見えてきたぞおおお
92本目:1を何回書いたか
問題:高橋君は1以上N以下のすべての整数を10進表記で1回ずつ紙に書きました。
この作業で、高橋君は1という数字を何個書いたでしょうか。
特に問題無く解けました。
あまり時間をかけず、しかも関数内を3行で済ませることができました!
93本目:リモコン
問題:高橋君は、エアコンの設定温度を変更しようとしています。
現在の設定温度はA度ですが、これをB度に設定したいと思っています。
エアコンのリモコンは1回ボタンを押すことで、
1度設定温度を下げる、もしくは上げる
5度設定温度を下げる、もしくは上げる
10度設定温度を下げる、もしくは上げる
の、6種類の操作のいずれか1つを実行することが出来ます。
高橋君が設定温度をA度からB度に変更するために押すボタンの最小回数を求めなさい。
時間はかかりましたが特に問題無く解けました。
自分は、以下の方針を立てました。
現在の設定温度に6種類の操作をそれぞれ当てはめる
6種類の操作の内、B度に最も近づくことができる操作を選ぶ
= |B - 操作した後の温度|が最小となる操作
コーディングの内容としては、
def change_temperature(A, B): if not type(A) is int or not type(B) is int: # 引数の型がintでないとピッタリBになることは無いのでreturn return -1 operate_list = [-10, -5, -1, +1, +5, +10] now_temperature = A push_count = 0 while now_temperature != B: ## operate_listの中で、一番Bに近づくことができる操作を求める ## 現在の設定温度に対して操作を行った後、Bとの温度差の最小値を求める。それを実際に次の操作として選択する # now_temperatureに操作を行った後のBとの温度差 diffs_between_B = list(map(lambda x: abs(B - (now_temperature + x)) , operate_list)) # 温度差の情報のうちの最小値 min_diffs = min(diffs_between_B) # 最小値がdiffs_between_Bの何番目に格納されているか。これはoperate_listの並びと対応している min_diffs_idx = diffs_between_B.index(min_diffs) # 求めた最小値のインデックスをoperate_listに指定し、実際に操作を行う optimal_operation = operate_list[min_diffs_idx] now_temperature += optimal_operation # カウント push_count += 1
となっています。
while文から抜けたらB度に達したことになるので、return push_count
しています。
方針をコードに落とし込むのに時間がかかりましたが、達成感がすごかったです笑
~おまけ~
引数の数値がint型ではなかったら調査すらしないという処理を、関数の最初に加えました。
その際、type()
とisinstance()
について調べました。
参考サイト:https://note.nkmk.me/python-type-isinstance/
94本目:高橋くんと魔法の箱
問題:高橋くんは魔法の箱を持っています。
この箱に整数を入れるとそれに対応した整数が出てきます。
出てくる整数は入れた整数だけによって決まり、同じ整数を入れると毎回同じ結果が得られます。
高橋くんは任意の整数xについて、xを入れた時と2xを入れた時に出てくる整数が同じであることに気づきました。
高橋くんが入れた整数がN個与えられるので、最大で何種類の整数が出てくるか答えてください。
一応解けましたが、時間かかりました。
問題の内容を理解してから、実装の方針を立てるのに苦労しました。
立てた方針は以下の通りです。
任意の整数x, yについて、出てくる整数が同じかを確かめる関数
check(x, y)
を作る
最初は、メインの関数に書いていましたが、見づらかったので分裂させました。
yは問題文で言うと2xに該当します。メインとなる関数内で、高橋君が入れた整数のリストに対してfor文を回す
- 先頭の要素を見た時点でcountを+1する
リストに要素が1つでもあれば、出てくる整数は必ず1種類以上になるためです。 - i番目(i>0)では、nums_list[i] / nums_list[i-1] == 2が成り立つかどうか調べる
成り立てば、i-1番目の時の整数と同じ整数が出ると言えるので、何もしません。 成り立たなければ、カウントを増やします。
- 先頭の要素を見た時点でcountを+1する
これらの方針に則って、以下のコードを書きました。
def check(x, y): # x, yを入れた時に同じ整数が出るかどうかを確かめる if x > y: # x < yとなるように入れ替える t = y y = x x = t return y / x == 2 def magic_box(nums_list): count = 0 for i in range(len(nums_list)): if i == 0: count += 1 else: if not check(nums_list[i-1], nums_list[i]): count += 1 return count
私のコードは少し長くなってしまいましたが、Qiita記事のコードは非常に短かったです...!
95本目:123引き算ゲーム
問題:最初に、数字nが与えられます。
1, 2, 3の中から好きな数字を選び、与えられた数字に対し、引き算を行う、という処理を行うことができます。
この処理は100回まで行うことが可能であり、最終的に数字を0にすることが目標のゲームです。
しかし、計算途中でなってはいけないNG数字が3つ(リスト型で)与えられており、この数字に一時的にでもなってしまった瞬間、このゲームは失敗となります。NG数字がnと同じ場合も失敗となります。
あなたは、このゲームが、目標達成可能なゲームとなっているかを調べたいです。
目標達成可能な場合はYES、そうでない場合はNOと出力してください。
特に問題無く解けました。
と思いきや、n=300, NGワード=[57,121,244]の時のみうまく行きませんでした。
100回目の試行の後にwhile文を抜けた後、"NO"を出力し忘れていました..。
解き方は、Qiita記事のものとだいたい同じでした。
96本目:割り切れる日付
問題:高橋君は割り切れる日付が好きです。
割り切れる日付とは、年÷月÷日の計算結果が整数になる日付のことです。
例えば今日の日付は2012年5月2日ですが、2012÷5÷2=201.2となり整数ではないので、
今日の日付は割り切れる日付ではありません。
高橋君は割り切れる日付が好きでたまらないので、次の割り切れる日付を心待ちにして、
毎日今日が割り切れる日付かどうかをチェックしてしまいます。
彼に少しでも多くの仕事をしてもらうために、入力として与えられた日付以降で
最初に来る割り切れる日付を求めなさい。
ただし、入力として与えられた日付が割り切れる日付だった場合は、
与えられた日付が答えになります。
例:check_date("2012/05/02") ==> "2013/01/01"
以前にも‘datetime‘を使う問題がありましたが、まだ使い方を覚えていませんでした。
参考サイト:Pythonのdatetimeで日付や時間と文字列を変換(strftime, strptime) | note.nkmk.me
上記サイトを見ながらでしたが、問題無く解けました。
Qiita記事の解法を見たところ、以下の点が異なっていました。
日付が割り切れるかどうかのチェックについて
自分:日付の初期値は、while文の外で別にチェックしている
記事:日付の初期値も、while文の中でまとめてチェックしている
後者の方がが短く書けますね....。割り切れるかどうかの条件式について
自分:(year / month / day) % (year // month // day) == 0
記事:Y % M == 0 and (Y / M) % D == 0
後者の方が綺麗ですね(^_^;)
~おまけ~
求めた日付を出力する際、formatで書式を指定してみました。
こんな感じ。-> "{}/{:02}/{:02}".format(year, month, day)
参考サイト:Python, formatで書式変換(0埋め、指数表記、16進数など) | note.nkmk.me
いよいよここまで来たか、といった感じです。
夏休みに入ってわりと時間が作れるため、ペースが上がっています(卒論と同時進行w)。
魔法の箱の問題を解いて、
map()
とかリスト内包表記とか使いまくってコードを短くできたのは良いのですが、
基本に沿った書き方もできないと、処理の流れを理解しづらいのでは、と思いました。
速く動くコードの裏での処理内容もしっかり分かっていれば、
可読性とパフォーマンスのバランスをとりやすくなる気がしました。
...なんてそれっぽいことを語ってしまいましたが、Qiita記事も残るは1つ!
詰まっても、時間を掛けて考えたり調べたりして、乗り越えることができました。
最後のQiita記事も、粘り強く取り組みたいと思います!