mocchaso note

サーバーエンジニアが何か色々呟いているところ。

Python100本ノック 72本目~81本目(71本目~80本目)

Python100本ノック、72本目から81本目についてです。

qiita.com


72本目:連続した数かどうか


問題:1118のような、3つ以上の同じ数字が連続して並んだ4桁の整数を良い整数とします。
4桁の整数Nが与えられるので、Nが良い整数かどうかを答えてください。

特に問題無く解けました。
整数が4桁では無かったらその時点でFalseをreturnする処理を加えてみましたが、それ以外は記事内の解法と同じ解き方でした。


73本目:リュカ数


問題:整数Nが与えられるので、N番目のリュカ数を求めてください。
ただし、リュカ数は、i番目のリュカ数をL_iとすると、L_0=2, L_1=1, L_i=L(i−1)+L(i−2) (i≧2) と定義される数とします。

最初、リュカ数とは何ぞや??となりましたが、説明を書いてくださっていました。
フィボナッチ数の問題の時と同じ感覚で解けました。
Qiita記事の解法では再帰を使っていました。再帰の方がスマートですねー...。


74本目:途中式の自動作成


問題:4 つの0以上9以下の整数A, B, C, Dを順に受けとります。A op1 B op2 C op3 D = 7となるように、op1, op2, op3に+か-を入れて式を自動で作り表示しなさい。
なお、答えが存在しない場合は"impossible"と表示し、また答えが複数存在する場合は全て表示させなさい。

この問題は、知識系というよりは考えるものでした。...と言うものの、if文でゴリ押しになってしまいました(-_-;) Qiita記事では、よりスッキリとした方法で解いていました。

  • 関数の引数を1つにし、関数内で文字列に変換した後、4つの変数a, b, c, dにまとめて格納している。

  • +か-を表すための変数signを"+-"として定義している。これをリストとして扱うと、インデックスを指定するだけで使い分けられる。

  • 1つの式で記号は3つ出てくるので、signについての三重のfor文を使っている。
    この中で、a, b, c, dと、対応するsignの要素を結合し、それにevalを適用している。

文字列の結合の後に一気に数式評価をするところが上手いと思いました!
解を格納するリストにappendするところや、"impossible"を出力するところの実装は同じでした。


75本目:Wikipediaにある車種をすべてスクレイピングせよ


Wikipediaに載っている車種が思いの外多く、別のWebページにしました笑
ソフトテニス経験者ということで自分が使っているラケットのページにしました)

BeautifulSoupurllibを使ってスクレイピングをやったことはありましたが、「BeautifulSoupにあるメソッドって何があったっけ?」となりました笑
Google先生にはお世話になりっぱなしです。
入れ子のタグ内のテキスト抽出に一番時間がかかりましたが、他は問題無く解けました。

※記事内の解法では、urllibライブラリではなくrequestsライブラリを使っていました。
Google先生に聞いてみたところ、requestsライブラリはurlliburllib2よりも便利になっているようです。
参考サイト:HTTPリクエストならurllib2じゃなくてRequestsを使え【Python】 - Phosphophyllite


76本目:文章の最初の文字を表示


問題:与えられた文章の内、最初の文字を表示しなさい
条件:'.'','や空白は文字としてカウントしない。
例:

first_word("Hello world") == "Hello"
first_word(" a word ") == "a"
first_word("greetings, friends") == "greetings"
first_word("... and so on ...") == "and"
first_word("Hello.World") == "Hello"


split()で区切ってやる前に、",""."を空白に置き換える方法だけ調べました。
方法は何種類かあるみたいですが、replaceが一番手軽かな、となりました。
参考サイト:Pythonで文字列を置換(replace, translate, re.sub, re.subn) | note.nkmk.me
(このサイト結構見やすい)

replace使っているけどうまくできない!?...と思ったら、これは元の文字列を書き換えないで文字列を返すメソッドでした。メソッド内で元の文字列を書き換えると思っていたため、正常に置き換えられていませんでした。

また、defの横の-> strは、引数の型に関するアノテーションのようです。親切!
参考サイト:Pythonではじまる、型のある世界


77本目:テキスト内で2回目にシンボルが出てくるのは何番目か


問題:テキスト文と文字がそれぞれ与えられる。与えられたテキスト文のうち、文字が2回目に出てくるのはテキスト文のうち何番目かを表示せよ。

特に問題無く解けました。
Qiita記事掲載の解法とほぼ同じ解き方でした。


78本目:1番高いストックは何か


問題:株名と株価が辞書型で与えられる。1番高いストックを表示せよ。

辞書の値の最大値を求めて、それに対応するキーを出力する問題でした。
辞書のメソッドをうまく使えば1行で書けるのでは?と思ってやってみました。

少し苦戦しながらも、何とか1行で表すことはできました。
dict.keys()dict.values()list()で変換して...とかでゴリ押しではありますが笑
もう少しうまい方法が思い浮かべば良かったのですが(-_-;)


79本目:単語の出現頻度を表示せよ


問題:文章と、いくつかの単語が与えられる。文章のうち、それぞれの単語が何回含まれているか表示せよ。
例:

popular_words('''When I was One I had just begun When I was Two I was nearly new''', ['i', 'was', 'three', 'near']) == {'i': 4, 'near': 0, 'three': 0, 'was': 3}


特に問題無く解けました。
以下の3点が特にポイントだったんじゃないかなと思います。

  • 最初に文章の正規化(lower()で全て小文字に変換)して、split()をするところ

  • 文字数カウント用のリストにカウント結果を格納して、zip()で検索ワードのリストと結合するところ

  • 結合したリストを引数にしたdictをreturnするところ


80本目:三目並べの自動判定


問題:下の例のように、"O"と"X"が並べられた三目並べの結果を自動で表示させる関数を作りなさい。
勝った方を結果として表示し、引き分けの場合は"D"と表示させなさい。
例:

checkio([
    "X.O",
    "XX.",
    "XOO"]) == "X"
checkio([
    "OO.",
    "XOX",
    "XOX"]) == "O"
checkio([
    "OOX",
    "XXO",
    "OXX"]) == "D"


特に問題無く解けました。
pythonの授業の課題で同じ問題をやりましたが、その時はただif文を並べるだけしかできませんでした...。今回はfor文を組み合わせてif文の数を減らすことができました。
また、74本目で出てきた、符号を文字列のリストとして扱う手法で最適化を図りました。

Qiita記事では、条件式を「"."以外の時」とすることでコードを短くしていました。
こっちの方がスマートだ...(>_<)


81本目:守られるチェスのコマ(ポーン)の個数を計算


問題:チェスのポーンが置かれているマスがいくつか与えられる。そのうち、守られているポーンの個数を答えよ。
(問題の詳細 → Pawn Brotherhood - python コーディングのための演習 - Py.CheckiO

この問題は、めっちゃ時間かかりました(3日ぐらい笑)。CheckiOで以前やって問題は知っていましたが、当時は分からなすぎて完全にヒントありきでした。
そして今回、問題の以下の部分がしっくり来ず、どういうことがずっと考えていました。
「この戦略ではひとつのポーンは別のポーンを守っている。 別のポーンが取れるマスではポーンは安全(safe)である。」

チェス未経験なので、チェスのルールをググりつつ考えたことが以下の3点です。

  • 相手側の何らかのコマがsafeマスのポーンの近くまで来た時、そのポーンが取られても、斜め手前の別のポーンがやり返してくれるってこと?
    → だから、手前側ではなく奥側が守られる立場になる?

  • この隊形はポーンチェーンというものに近い?
    → 参考サイト:チェスわくわく戦略入門 - 第4回 ポーン : MetalPhaetonチェス戦記

  • 盤面に置いてあるのは自分側のコマ?相手側の駒?
    → 「あなたはのポーンが置かれているマスの座標のセット(set)が与えられる」と書かれているから、自分側のコマのみだろう。

細かいことを考えすぎましたね...。
でも、プログラム自体は無事に実装できたので良かったです!
「とりあえず斜め手前に別のポーンがいる時にsafeって判定すれば良いんでしょ...」と割り切ってからは、特に問題無く解けました笑




やっと80本まで来ました。今回の記事結構長いですね...笑
これまで「こんな風に書けば効率良くなるんじゃないか?」ということを意識してやってきて、その勘が少しずつ鋭くなってきていると感じています。
考えることに重きを置いた問題が増えてきてエネルギーを使いますが、あと20本、完走目指して頑張ります!

あと、@ahpjopさんにTwitterでべた褒めされてて嬉しかったです(知らん)。