CheckiOやってみた〜HOME編〜
これの続き。
Non-unique Elements
与えられたリストでユニークな要素を消す問題。
■自分の回答
def checkio(data): a = [] for i in data: if i not in a: a.append(i) for i in a: if data.count(i) < 2: data.remove(i) return data
■すげーやつの回答
def checkio(data): return [x for x in data if data.count(x) > 1]
Σ(=ω= ;)
い、一行、、、だと、、、
内包表記(comprehension)
Pythonには内包表記という文法がある。
これを使うと、リストやディクショナリなどの加工をするような処理をブロックを使用せずに簡潔に記述できる。
内包表記にはリスト内包表記、ディクショナリ内包表記、set内包表記がある。
リスト内包表記(list comprehension)
基本構文
[ リストの要素 for シーケンスの要素 in シーケンス ]
例えば、「[x**2 for x in range(10)]」は
- range(10)
- 0から9までの整数のシーケンスを
- x in range(10)
- 小さい順から取り出して
- x**2 for x in range(10)
- 取り出した要素を二乗
- [x**2 for x in range(10)]
- してできるリスト
となる。
また、if文を使用してシーケンスの要素を絞ることができる。
[ リストの要素 for シーケンスの要素 in シーケンス if シーケンスの要素を絞る条件 ]
今回のすげー回答「[x for x in data if data.count(x) > 1]」は
- x in data
- dataリストの要素で
- x in data if data.count(x) > 1
- dataリスト内で1つより多い要素
- [x for x in data if data.count(x) > 1]
- のリスト
Median
リスト(int)の中央値(float)を求める問題。
■自分の回答
def checkio(data): listLength = len(data) data.sort() result = 0.0 if listLength%2 == 0: index = int(listLength/2) result += (data[index] + data[index-1]) / 2 else: result += data[int((listLength-1)/2)] return result
思ったこと
- int型を割り算すると勝手にfloat型扱いになっちゃうんだなー
- リストのインデックスを求める際
■他人の回答
def checkio(data): data.sort() l=len(data) if l%2 != 0: r = data[(l-1)//2] else: r = (data[l//2-1] + data[l//2])/2.0 return r
学んだこと
- 切り捨て除算
- 「//」は切り捨て除算といい、小数点以下を切り捨てて商はint型扱いになる。
- 小数点「.0」付きの数字で演算すると、明示的にfloat型扱いにできる
■他人の回答
def checkio(data): while len(data)>2: data.remove(max(data)) data.remove(min(data)) return sum(data)/len(data)
■他人の回答
def checkio(data): data = sorted(data) i, r = divmod(len(data), 2) return data[i] if r else .5 * (data[i-1] + data[i])
学んだこと
- divmod関数
- (a // b, a % b) = divmod(a, b)
- 三項演算子
- 「x = 真の場合の値 if 条件 else 偽の場合の値」
■すげーやつの回答
def checkio(data): y = lambda x: sorted(x)[(len(x)-1)/2] if len(x)%2==1 else (sorted(x)[len(x)/2] + sorted(x)[len(x)/2-1])/2.0 return y(data)
でた。ラムダさんですよ。そしてこれは三項演算子で式作ってますよ。パイソニアンだなー。
lambda式
基本構文
lambda 引数のリスト : 引数を使った式
House password
パスワードがセキュリティ要件を満たしているか確認する問題。
■自分の回答
def checkio(data): if len(data) < 10: return False containDigit = False containUpper = False containLower = False for i in data: if i.isdigit(): containDigit = True elif i.isupper(): containUpper = True elif i.islower(): containLower = True if containDigit & containUpper & containLower: return True return False
■他の回答
import string def checkio(data): 'Return True if password strong and False if not' dataset = set(data) long_enough = len(data) >= 10 has_digit = bool(len(dataset & set(string.digits))) has_upper = bool(len(dataset & set(string.ascii_uppercase))) has_lower = bool(len(dataset & set(string.ascii_lowercase))) return long_enough and has_digit and has_upper and has_lower
学んだこと
- setの論理和が計算できるのか
■すげーやつの回答
import re def checkio(data): return bool(len(data) >= 10 and re.search(r"\d", data) and re.search("[A-Z]", data) and re.search("[a-z]", data))
学んだこと
- 正規表現のモジュール
The Most Wanted Letter
一番多い文字を探す問題。
■自分の回答(愚直バージョン)
def checkio(text): dict = {} for i in text: letter = i if i.isupper(): letter = i.lower() if letter in dict.keys(): num = dict.get(letter) dict[letter] = num+1 elif letter.islower(): dict.setdefault(letter,1) valueList = sorted(dict.values()) max = valueList[len(valueList)-1] list = [] keys = dict.keys() for i in keys: num = dict.get(i) if num == max: list.append(i) list.sort() return list[0]
■自分の回答(学びを活かしたバージョン)
def checkio(text): dict = {y:text.lower().count(y) for y in [x for x in text.lower() if x.isupper() | x.islower()]} valueList = sorted(dict.values(),reverse=True) resultList = [x for x in dict.keys() if dict.get(x)==valueList[0]] return sorted(resultList)[0]
21行から4行に短縮してやった ( ・ー・`) ドヤッ!
Feed Pigeons
手持ちの餌で何羽の鳩に餌を与えられるか。
■自分の回答
def checkio(number): fed = 0 feed = number roop = 1 pigeonNum = 0 while feed > 0: pigeonNum += roop if feed - pigeonNum >= 0: fed += roop elif feed - pigeonNum + roop >= 0: fed += feed - pigeonNum + roop feed -= pigeonNum roop += 1 return fed
Speech Module
数字を文字にする問題。
■自分の回答
LETTER = {1:"one", 2:"two", 3:"three", 4:"four", 5:"five", 6:"six", 7:"seven", 8:"eight", 9:"nine", 10:"ten", 11:"eleven", 12:"twelve", 13:"thirteen", 14:"fourteen", 15:"fifteen", 16:"sixteen", 17:"seventeen", 18:"eighteen", 19:"nineteen", 20:"twenty", 30:"thirty", 40:"forty", 50:"fifty", 60:"sixty", 70:"seventy", 80:"eighty", 90:"ninety"} def checkio(number): result = [] if number//100>0: result.append(LETTER[number//100] + " " + "hundred") if number%100 >= 10: result.append(LETTER[number%100] if number%100<20 else LETTER[number-number//100*100-number%10]) if (number%100>=20 or number%100<10) and number%10!=0:result.append(LETTER[number%10]) r = "" for i in range(0,len(result)): if len(r)==0 and result[i]!="": r += result[i] elif result[i]!="": r += " " + result[i] return r
Xs and Os Referee
丸×ゲームの勝ちドロー判定。
■自分の回答
MATCH = ["012","345","678","036","147","258","048","246"] def checkio(game_result): list = [] for i in game_result: for j in i: list.append(j) for i in MATCH: if list[int(i[0])]==list[int(i[1])] and list[int(i[1])]==list[int(i[2])] and list[int(i[0])]!=".": return list[int(i[0])] return "D"
■賢いと思った回答
def checkio(game_result): g = game_result + [(game_result[0][i]+game_result[1][i]+game_result[2][i]) for i in range(3)] + [(game_result[0][0]+game_result[1][1]+game_result[2][2]), (game_result[0][2]+game_result[1][1]+game_result[2][0])] if "XXX" in g: return "X" elif "OOO" in g: return "O" else: return "D"
Roman numerals
数値をローマ数字に変換する問題。
■自分の回答
def checkio(data): result="" while data>0: if data>=1000: result+="M" data-=1000 elif data>=900: result+="CM" data-=900 elif data>=500: result+="D" data-=500 elif data>=400: result+="CD" data-=400 elif data>=100: result+="C" data-=100 elif data>=90: result+="XC" data-=90 elif data>=50: result+="L" data-=50 elif data>=40: result+="XL" data-=40 elif data>=10: result+="X" data-=10 elif data>=9: result+="IX" data-=9 elif data>=5: result+="V" data-=5 elif data>=4: result+="IV" data-=4 elif data>0: result+="I" data-=1 return result
■同じ発想だが賢い回答
roman_numeral_map = (('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)) def checkio(n): result = '' for numeral, integer in roman_numeral_map: while n >= integer: result += numeral n -= integer return result
タプルの使いどころはここか。。。
■すげーやつの回答
MAP = [ {'1': 'M', '2': 'MM', '3': 'MMM', '0': ''}, {'1': 'C', '2': 'CC', '3': 'CCC', '4': 'CD', '5': 'D', '6': 'DC','7': 'DCC', '8': 'DCCC', '9': 'CM', '0': ''}, {'1': 'X', '2': 'XX', '3': 'XXX', '4': 'XL', '5': 'L', '6': 'LX','7': 'LXX', '8': 'LXXX', '9': 'XC', '0': ''}, {'1': 'I', '2': 'II', '3': 'III', '4': 'IV', '5': 'V', '6': 'VI','7': 'VII', '8': 'VIII', '9': 'IX', '0': ''}, ] checkio = lambda data: ''.join([MAP[i][c] for i, c in enumerate(str(data).zfill(4))])
- MAP
- MAP[0]:1000の位の数字に対応するローマ数字
- MAP[1]: 100の位の数字に対応するローマ数字
- MAP[2]: 10の位の数字に対応するローマ数字
- MAP[3]: 1の位の数字に対応するローマ数字
- str(data).zfill(4)
- 文字列にした数字を4桁(左を0埋め)にして
- i, c in enumerate(str(data).zfill(4))
- 生成した文字のインデックス(i)と文字(c)を1000の位から順に取り出して
- MAP[i][c] for i, c in enumerate(str(data).zfill(4))
- マップに当てはめて
- ''.join([MAP[i][c] for i, c in enumerate(str(data).zfill(4))])
- 空文字にくっつけて、できあがり。
Open Labyrinth
迷路のスタートからゴールまでのルートを求める問題。
■自分の回答
D = ("E","S","W","N") DN = {"E":(1,0),"S":(0,1),"W":(-1,0),"N":(0,-1)} def cango(x,y,d,m): return m[y+DN[d][1]][x+DN[d][0]]==0 def go(x,y,d): return [x+DN[d][0],y+DN[d][1]] def turnright(d,n): return D[(D.index(d)+n)%4] def searchd(x,y,d,m): if cango(x,y,turnright(d,3),m): return turnright(d,3) if cango(x,y,d,m): return d if cango(x,y,turnright(d,1),m): return turnright(d,1) if cango(x,y,turnright(d,2),m): return turnright(d,2) def checkio(maze_map): x = 1 y = 1 d = "E" gy = len(maze_map)-2 gx = len(maze_map[0])-2 result = "" while not(x==gx and y==gy): d = searchd(x,y,d,maze_map) x,y = go(x,y,d) result += str(d) return result
■他人の回答
def checkio(maze): x = y = 1 dx, dy = 1, 0 route = '' while not (x == y == 10): dx, dy = dy, -dx while maze[y+dy][x+dx]: dx, dy = -dy, dx x += dx y += dy route += ' SEWN'[dx*2 + dy] return route
な、なるほどね^^;
回転とかとくに秀逸w