「自作Python100本ノック」11日目（71本〜80本目）

「自作Python100本ノック」11日目です。

昨日はマラソンリレーの本番で、肉体的に限界だったので記事作成できませんでした。。
ちなみに、結果は1.6kmで7分40秒でした。かなり自分的には満足です。
朝起きたら風邪を引いており、しかも肩が超絶痛いという最悪な状況です。


さて、今日から最後の100本目にかけていよいよ文章題をやっていきます（ネタが尽きなければ）。
「自作Python100本ノック」とはそもそも何ぞや？
どの程度のレベル感なのか？
どのように進めて行くのか？
など気になる方は詳しくは[こちら](https://qiita.com/ahpjop/items/373f807d68044cda1c9b#%E8%87%AA%E4%BD%9Cpython100%E6%9C%AC%E3%83%8E%E3%83%83%E3%82%AF1%E6%9C%AC5%E6%9C%AC%E7%9B%AE)に整理してありますのでまずはそちらを確認するようお願いします。
それでは始めていきます。

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

```q71.py
def good_number(n):
    n = str(n)
    if n[0] == n[1] == n[2] or n[1] == n[2] == n[3]:
        print("Yes, it is a good number")
    else:
        print("No, it isn't good nomber")
        
good_number(1116)
```
[参考][やるだけPython競プロ日誌](http://delta114514.hatenablog.jp/entry/2017/11/19/023344)

##Q72:　リュカ数

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

上の説明でもわからない人のために補足すると、リュカ数とは、原理はフィボナッチ数列と同じなんですが１番目が2,2番目が1と決められている数列になります。
　　　


```q72.py
def lucas(n):
    n = int(n)
    if n == 0:
        return 2
    elif n == 1:
        return 1
    else:
        return lucas(n - 1) + lucas(n - 2)

lucas(4)
```
[参考][やるだけPython競プロ日誌](http://delta114514.hatenablog.jp/entry/2017/11/19/023344)

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


```q73.py
def put_formula(n):
    a,b,c,d = list(str(n))
    sign = "+-"
    aws_list = []
    for i in range(2):  # 1つ目の記号
        for j in range(2):  # 2つ目の記号
            for k in range(2):  # 3つ目の記号
                if eval(a+sign[i]+b+sign[j]+c+sign[k]+d) == 7:
                    aws = (str(a+sign[i]+b+sign[j]+c+sign[k]+d)+"=7")
                    aws_list.append(aws)
                    print(aws)
    if len(aws_list) == 0:
        print("impossible")
        
put_formula(1161)
```
[参考][やるだけPython競プロ日誌](http://delta114514.hatenablog.jp/entry/2017/11/19/023344)

##Q74: Wikipediaにある車種をすベてスクレイピングせよ
Pythonでのスクレイピングの方法です。
超便利です。
　　　　

```q74.py
import requests
from bs4 import BeautifulSoup

r = requests.get('https://hikkoshi.suumo.jp/sankaku/')
soup = BeautifulSoup(r.text, 'html.parser')
titleTags = soup.select('a')
names = []
for titleTag in titleTags:
    name = titleTag.text.strip()
    names.append(name)
#distinct_names = list(set(names))

names_uniq = []
for d_name in names:
    if d_name not in names_uniq:
        names_uniq.append(d_name)


print(names_uniq)
```

##Q75 :文章の最初の文字を表示
問題：　与えられた文章の内、最初の文字を表示しなさい
条件：　'.'や','や空白は文字としてカウントしない。
例：　
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"
　　　　

```q75.py
def first_word(text: str) -> str:
    if text.find(",")>= 0:
        text2= text.replace(',', ' ')
    if text.find(".")>=0:
        text2=text.replace('.', ' ')
    texts = text2.split()
    return texts[0]

first_word("..... greetings, friends")
```
[出典][ChekiO:Elementary](https://py.checkio.org/ja/mission/first-word/)

##Q76 :テキスト内で２回目にシンボルが出てくるのは何番目か
問題：テキスト文と文字がそれぞれ与えられる。
　　　与えられたテキスト文のうち、文字が２回目に出てくるのはテキスト文のうち何番目かを表示せよ。
　　　　

```q76.py
def second_index(text, symbol):
    count = 0
    for i in range(len(text)):
        if text[i] == symbol:
            count += 1
            if count == 2:
                return i
    return None

second_index("I am a good student but you are not a good student", "g")
```
[出典][ChekiO:Elementary](https://py.checkio.org/ja/mission/second-index/)

##Q77:　１番高いストックは何か
問題：株名と株価が辞書型で与えられる、1番高いストックを表示せよ。
　　　　

```q77.py
#株名と株価の辞書
stock_dict = {
    'CAC': 10.0,
    'ATX': 390.2,
    'WIG': 1.2
}

#１番高いストックを表示する関数
def best_stock(data):
    max = 0
    code = ""
    for stock in data:
        print(stock)
        if data[stock] > max:
            max = data[stock]
            code = stock
    return code

best_stock(stock_dict)
```
[出典][ChekiO:Elementary](https://py.checkio.org/ja/mission/best-stock/)

##Q78:単語の出現頻度を表示せよ
問題：文章と、いくつかの単語が与えられる。
文章のうち、それぞれの単語が何回含まれているか表示せよ。
例：popular_words('''When I was OneI had just begunWhen I was TwoI was nearly new
''', ['i', 'was', 'three', 'near']) == {'i': 4, 'near': 0, 'three': 0, 'was': 3}

nearがnearlyにカウントされないようにするのが意外と大変でした。（`split()`を使うだけ）
　　　　

```q78.py
def popular_words(text: str, words: list) -> dict:
    text = text.lower().split()
    count_list = []
    for word in words:
        count = text.count(word)
        count_list.append(count)
    aws = dict(zip(words, count_list))
    return aws
```
[出典][ChekiO:Elementary](https://py.checkio.org/ja/mission/popular-words/)

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

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

　　
答え

```q79.py
def check_osxs(result):
    judge = "D"
    for i in range(3):
        if result[i][0] == result[i][1] == result[i][2] != ".":
            judge = result[i][0]
        elif result[0][i] == result[1][i] == result[2][i] != ".":
            judge = result[0][i]
    if result[0][0] == result[1][1] == result[2][2] != ".":
            judge = result[0][0]
    elif result[0][2] == result[1][1] == result[2][0] != ".":
            judge = result[0][2]
    return judge

check_osxs([
        "X.O",
        "XX.",
        "XOO"])
```
[出典][ChekiO:Home](https://py.checkio.org/ja/mission/x-o-referee/)

##Q80: 守られるチェスのコマ（ポーン）の個数を計算
問題：チェスのボーンが置かれているマスがいくつか与えられる。そのうち、守られているボーンの個数を答えよ。

ちょっと流石に、これだけじゃ問題文として不足しているのですが、画像なしだときついんで、[本家のこちら](https://py.checkio.org/ja/mission/pawn-brotherhood/)を見てください。
　　　

```q80.py
def safe_pawns(pawns):
    pwans = list(pawns)
    cols = {"a":0,"b":1,"c":2,"d":3,"e":4,"f":5,"g":6,"h":7}
    s_pwans = []
    for i in pawns:
        target = []
        for j in pwans:
            if int(i[1])+1 == int(j[1]):
                target.append(j)
        for k in target:
            if abs(cols.get(k[0]) - cols.get(i[0])) == 1:
                s_pwans.append(k)
                if s_pwans.count(k) > 1:
                    s_pwans.pop()
    return len(s_pwans)

aws = {"b4","c4","d4","e4","f4","g4","e3"}
safe_pawns(aws)
```
[出典][ChekiO:Home](https://py.checkio.org/ja/mission/pawn-brotherhood/)

##感想
まじで肩が痛くて作業にならないんでマッサージを予約しました。
ホットペッパービューティーってすごいですね。

それとスタンディングデスク買おうかと悩んでおります。
あ、それか大学の図書館に置いてくれないか頼んでみよ。

にしても、文章問題だと同じ10問でもかかるエネルギー量が全然違うんで大変です。
誰か私に問題を分けてください。。。

それでは！

→ [12日目](https://qiita.com/ahpjop/items/e86f361e903e3adb6f84)