ぺーぺーSEのブログ

備忘録・メモ用サイト。

CheckiOやってみた〜HOME編〜

これの続き。

blog.pepese.com

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