python Checkio.org Homeを解く その1

##参考元のCheckio.org
https://py.checkio.org

今日も解く。SendGridステージはsendGrid社？のAPIを使ってと言われるけど、審査中とか言われ面倒くさいのでパス。
今日からHomeのステージを主に解こうと思う。解いた後なら、他人の解答を見れるので参考理解もしてみる。
他人のコードは自分のしらないモノがばかりと昨日改めて実感。

##Q. House Password
https://py.checkio.org/mission/house-password/
パスワードが強いかどうかを検査する関数を作る。
強いパスワードの条件は：
・10文字以上
・少なくとも一つ以上の数字、一つ以上の大文字、一つの以上の小文字を含む。

入力: パスワード、文字列

出力: パスワードが安全かどうか、ブール値もしくはブール値に変換できるかブール値として処理できる任意のデータ型。 

前提条件： パスワードはASCIIの英文字または数字のみを含む

例:

```py

checkio('A1213pokl') == False
checkio('bAse730onE') == True
checkio('asasasasasasasaas') == False
checkio('QWERTYqwerty') == False
checkio('123456123456') == False
checkio('QwErTy911poqqqq') == True
```

###自分の解答：

```py
def checkio(data):
    if len(data) >= 10:
        l1 = [c for c in data if c.isupper() == True]
        l2 = [d for d in data if d.islower() == True]
        l3 = [e for e in data if e.isdigit() == True]
        #print([*l1, *l2, *l3])
        #print(all([0, 1, 2]))
        if all([all([len(f) for f in [l1, l2, l3]]), all([*l1, *l2, *l3])]):
            return True
        else:
            return False
    else:
        return False
```

1. 覚えたリスト内包表記とか使ってみた。`all()`は`any()`と同様シークエンスを引数に受け取る。戻り値はBool値。引数のシークエンス内部の値が、全てそれぞれのデータ型において、Trueの振る舞いをする場合。Trueを返す。
2. 一つわかった。上記コードは2,3行にまとめて書くことが可能。でも、あえて分けるほうがわかりやすい。可読性があがる。これは確定的に明らか。`all()`当たりとかすでに読みにくい。
3. リスト内包表記は便利。次はlambdaを使いたい
4. `str.isdigit()`: 文字列が数字かどうか判別する。

###他人の回答①
```py
import re
def checkio(password):
    return True if re.match(r'((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{10,})', password) else False
```

1. `return`の中でもif節が使えるのか。
2. `re`モジュールは正規表現と呼ばれる。Dive into Python進めるかぁ。
3. `match`関数で特定のシークエンス?文字列に対して、文字があるかの判定、長さの判定までまとめることができるみたい。
4. `[a-z]`や`[0-5][0-9] は 00 から 59`のように正規表現特有の表現方法がある

###他人の解答② これ好み
```py
    if len(data) >= 10 and not data.isalpha() and not data.isnumeric() and not data.islower() and not data.isupper():
        return True
    return False
```
1. 面白いぞ。特定の条件を否定していくことで、結果的に元の条件を満たしているか判定している。
2. `str.isalpha()`なら英字のみ。`str.isnumeric()`なら数字のみ。`data.islower()`なら小文字のみ。`data.isupper()`なら大文字のみ。１つでもTrueならその集合に確定。全部の条件が否定された場合のみ、問題の前提条件を満たす。かしこいなー。

3.やっぱ問題に対する解答の中身がかっこいいと、コードもかっこいい気がする。
ただこれ一度別の人の解答を見ると、同じ人の解答をみれないのが難点・・・。


##Q. The Most Wanted Letter
https://py.checkio.org/mission/most-wanted-letter/
英字と記号を含むテキストから、最も出現頻度が高いものを探し出してください。
条件：
・　テキストのなかで大文字と小文字は区別しません。"A" == "a"。
・　記号、数字、空白は数えません。
・　二文字以上が同じ頻度のとき、アルファベットで最初に来る文字を返す。"one"なら"e"を返す。
 [a,b,c,d,"e",f,g,h,i,j,k,l,m,"n","o",p,q,r,s,t,u,v,w,x,y,z]

入力： テキスト。文字列
出力： 小文字返してください。
例: 

```py
checkio("Hello World!") == "l"
checkio("How do you do?") == "o"
checkio("One") == "e"
checkio("Oops!") == "o"
checkio("AAaooo!!!!") == "a"
checkio("abe") == "a"
checkio("a" * 9000 + "b" * 1000) == "a", "Long."
```

`"a" * 9000 + "b" * 1000`こんなふうに出力できるの初めて知った。

###自分の解答：
突然だが、
回答とは。質問や要求、要望に答えること。あるいはその答え。
解答とは。問題をといて答えを出すことだとか。んー、微妙なニュアンス。

```py
def checkio(text):
    
    l1 = ([a for a in "".join(text.rsplit()).lower() if "a" <= a <= "z"])
    d1 = {b:l1.count(b) for b in l1} #辞書内包表記すれば１発。#辞書のkeyはユニーク
    count = 0
    for key in d1:
        if d1[key] >= count:
            count = d1[key]
    return sorted([c for c in d1 if d1[c] == count])[0]
```
1. リスト内包表記。`rsplit()`で空白を消したものを`join()`。小文字にして。アルファベットならリストに入れる。`isalpha()`をつかっても良かった。
2. 辞書内包表記も使ってみた。リスト内包表記と対して変わらない。pythonの辞書のkeyはユニーク。いいかえると同じデータ型で同じ値をkeyに持つことはできない。便利。同じアルファベットを数えないってこと。思い出せてよかったわぃ。
3. １番大きなcountを探して、そのkeyを取り出す。複数あった場合は、`sorted()`で１番若いアルファベットを提出する。

振り返り：
for節のcountのところをもっとうまく書けたんじゃないかと思ったり。
チェック関門で5０００字くらいのtextあってお腹抱えて笑った。


###他人の解答:creative
https://py.checkio.org/mission/most-wanted-letter/publications/review/puzzle/

```py
①
from collections import Counter
checkio=lambda t:Counter(filter(str.isalpha,sorted(t.lower()))).most_common(1)[0][0]

>>> l1 
['a', 'a', 'a', 'a', 'b', 'd', 'f', 'n', 's']
>>> filter(str.isalpha, l1)
<filter object at 0x10406c7f0> #ここどうなってんの？←イテレータなオブジェクトには違いないっぽい。データ型がfilter?
>>> Counter(l1)
Counter({'a': 4, 'f': 1, 's': 1, 'd': 1, 'b': 1, 'n': 1})
>>> Counter(l1).most_common(1)
[('a', 4)]
```
①

1. 　`collections`モジュールの`Counter(iterable or mapping)`関数。"C"ounterと大文字。dictのサブクラス。要素を辞書のキーとして保存し、そのカウントを辞書の値として保存する。←おれがやったのとまったく同じやんけ！pythonライブラリ便利なのしかねぇ！
2. `filter(function, iterable)`関数。iterable(複数の要素をもったオブジェクト)の要素のうち、functionが真を返すものでイテレータ（リストとかタプルとか文字列指定できる？)を構築する=戻り値はイテレータ。functionには条件を判定する関数。つまり戻り値がBool値の関数を引数に指定できる。今回は、`str.isalpha()`を使っている。`str.isalpha`と形が変わってるのは`filter()`関数のために必要なのだろうか。試しに()つけたらErrorでた。
 ・`sorted()`はリストを返す。今回はチェックするtextの小文字をソートしたリスト。つまり、ソートされた小文字のリストができる。
3. `most_common(n)`は`Counter`オブジェクトで定義されたメソッド。`Counter()`の戻り値の辞書から、カウントが多いものから少ないものまでを順に並べたリストを返す。nは戻り値の要素数。1なら１つの要素を返す。３なら３つの要素を返す。nが省略されたら、カウント対象のすべての要素を返す。

`filter`への理解度が足りないぜ。
filterの参考https://docs.python.jp/3/library/functions.html#filter
戻り値のfilter objectがまあ得体の知れない感じ。
`list()`とかで変換はできる。

Q. サブクラスとは？
A. 他のクラスから派生したクラス。`Counter`は`dict`クラスから派生したクラスだから、dictの機能を受け継いでいるということなのでは？

```py
②
def checkio(text):
    numbers = [text.lower().count(chr(c + 97)) for c in range(26)]
    return chr(numbers.index(max(numbers)) + 97)

>>> l1 = [1,2,3,4,5,10,255,65535]
>>> max(l1)
65535
>>> max(1,5,100,33)
100
>>> min(l1)
1
```

1. `chr(int)`Unicodeコードポイントが整数intである文字を表す文字列を返す。例`che(97)`は文字列"a"を返す。こんなん知らんがな。97~123はアルファベットのa-zが割り当てられてるみたい。あー。この発想は面白いなー。好きだぞ。リスト内包表記でリストに入れる時、aから順番に各count数を入れてるわけだ=リスト名numbers。
2. `max()`は初めて見た。引数にはiterableか、複数の要素を,で区切って与えることができる。それら引数の中で最大のものを返す。最大の要素が複数ある場合は、最初に現れたものを返す。オプションでkey引数は,新しく引数を必要とするlist.sort()のために引数を指定する。deafult引数で与えられたiterableが空の場合に返す値を指定できる。
`list.index(value)`
`max()`の説明： https://docs.python.jp/3/library/functions.html?highlight=max#max
3. で,`max()`の使用どおり、最大値があれば若い要素を返す。`index()`でその値の要素番号を調べて、97を足した数値を引数に`chr()`で文字を返す。ピタゴラスイッチみたいだよ。

Q. コードポイントとは？
A. 文字コードにおいて、1つ１つの文字に割り当てられた数値のこと。


##Q. Non-unique Elements
空ではない整数のリストを与えられる。このリスト内部から、ユニークな要素（リストの別の値と重複していない)を排除したリストを作成してください。

前提条件： 戻り値のリストの順番は変更されてちゃだめ。
入力： list of Integer
出力： list of Integer
例：

```py
checkio([1, 2, 3, 1, 3]) == [1, 3, 1, 3]
checkio([1, 2, 3, 4, 5]) == []
checkio([5, 5, 5, 5, 5]) == [5, 5, 5, 5, 5]
checkio([10, 9, 10, 10, 9, 8]) == [10, 9, 10, 10, 9]
```
###自分の解答：

```py
①
def checkio(data):
    return [a for a in data if data.count(a) > 1]

②
checkio = lambda data : [i for i in data if data.count(i)-1] 

③
def checkio(data):
    if len(data) == 1:
        return []
    else:
        l1 = [sorted(data)[a] for a in range(-1, len(sorted(data))-1) if sorted(data)[a] != sorted(data)[a-1] and sorted(data)[a] != sorted(data)[a+1]] 
        return [b for b in data if b not in l1]
```

1. なんか言うこと特にない。
2. `if 0:`　はFalseになる。0以外の数値はTrue。ラムダ式にちょっと憧れるあるぅ。
3. すげぇ醜い。`sorted()`したリストの前後を比べてもユニークかは分かる。index　out of rangeを避けるために、`range(-1, len(sorted(data))-1)`。-1からはじまってるのは引数のリストの最後の要素も調べるため。`in`をちょっとど忘れしてた。

###他人の解答：
今回はなし。いいのが見つからなかった。


##Q. Monkey Typing
無限の猿定理から：https://ja.wikipedia.org/wiki/%E7%84%A1%E9%99%90%E3%81%AE%E7%8C%BF%E5%AE%9A%E7%90%86
要約：猿「シェイクスピアのハムレット？書けらぁ！！」

意味のある単語が含まれているかもしれないテキストと、いくつかの単語が与えられる。いくつの単語が、与えられたテキストに含まれているか調べる。

前提条件：　given word is lower
入力： ２つの引数。text, set of string
出力： 現れた単語の種類の数。
例：

```py
count_words("How aresjfhdskfhskd you?", {"how", "are", "you", "hello"}) == 3
count_words("Bananas, give me bananas!!!", {"banana", "bananas"}) == 2
count_words("Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
            {"sum", "hamlet", "infinity", "anything"}) == 1
````
###自分の解答：

```py
def count_words(text, words):
    return len([a for a in words if a in text.lower()])
```

1.　リスト内包表記がすげぇ楽。あとから見直して鳴くかもしれないけど。悲鳴を。

###他人の解答

```py
def count_words(text, words):
    return sum(w in text.lower() for w in words)
```

1.　こいつTrueを足してやがる。いや、Trueは１でFalseは0で足したり引けたりできるの知ってたけどさ。Dive into pythonで避けるべき言われてたからなぁ。まぁ便利ちゃ便利なきがする。ピタゴラスイッチ感好き。

```py
count_words = lambda st, words: len(list(filter(lambda x: st.lower().find(x) != -1, words)))

>>> "howaresjfhdskfhskdyou".find("are")
3
>>> "howaresjfhdskfhskdyou".find("oppai")
-1
```

1. ちょっと疑問だった`lambda`式に引数を2つ取れるのだろうか？が解決した瞬間。またlambdaの中でlambdaを使ってる。正確には、`filter()`の関数をlambdaで促成栽培してる。
2. `str.find(string)`は引数がstr内部にある場合は、最初に現れるインデックスを返す。引数のパターンが存在しない場合は、-1を返す。
3. x　はなんぞこれ？どっからきて何を渡された？あ、これ関数としての定義にすぎないのか?`filter()`で使うための判定用関数に変形している状態？かな。xという引数にはwordsが入って、`filter object`を返す。それを`list()`でリストに変換。リストの長さを`len()`で返している。

・`filter()`: 複数の要素ををもったオブジェクトから、条件にあった要素を、引数のfunction(関数)を使って選別して取り出す関数。
今回は`lambda x: st.lower().find(x) != -1`がfunction。wordsの中から取り出した。



##終わりに
お腹すいたから一旦終了。Homeを終わらすまではCheckioをやろうかな。
Dive into Pythonは情報量がやべぇから頭ポップコーンになる。ゆっくり読む。