読者です 読者をやめる 読者になる 読者になる

CodeIQ Blog

自分の実力を知りたいITエンジニア向けの、実務スキル評価サービス「CodeIQ(コードアイキュー)」の公式ブログです。

PyCon Taiwanから出題「Python: Word Transformer!」問題の一言評価フィードバック~面白い解答コード12名分公開 #pycontw

問題解説

CodeIQ中の人、millionsmileです。

2013年5月25日~26日に台湾でPyCon(Python Conference)が開催され、その主催者であるTim HsuさんとYung-Yu Chenさんから「Word Transformer!」というPython問題が出題されました。

問題はわずか5日の掲載期間だったにもかかわらず、39名ものPythonistaの方々に挑戦いただきました!ありがとうございます。

出題者のTimさんからは、どの解答もレベルが高く素晴らしい!と感動の声が届いております。

After review these solution, I surprisingly find there are a lot of possible way to solve the problem. These submission extend my understanding about python. I hope I can see more works from these wonderful programmers.

どんな解答が提出されたのでしょうね。

問題文には、

Please write the code as fun as possible :)

とありましたので、代表して面白いコードを書いた12名の方のコードを公開いたします!!
※この問題は一意に決まる正解がありませんので、特に面白かった12名の方に絞らせていただきました。

問題文

問題文はAからZの文字を並び替える問題で、それをできるだけ面白く書け、というものでした。

How will you transform the sequence

'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

to

['ADGJMPSVY', 'BEHKNQTWZ', 'CFILORUX'] ?

Please write the code as fun as possible :)

This question can be solved in a lot of way. 
We admire all the way you solve it. 
Please show the power of python!!

解答コード公開

提出の早い順に12名の解答コードと、出題者Timさんの一言コメントです。
絵文字付きのコメントがカワイイ☆彡

■cielさんの解答コード

Timさんより:it is very amazing, you can write technical article about how to use zip. (⊙0⊙)

#!/usr/bin/python
#Fully compatible on both Python2 and Python3
import sys,itertools
if sys.version_info[0]<3: itertools.zip_longest=itertools.izip_longest
print([''.join(x) for x in zip(*itertools.zip_longest(*[iter('ABCDEFGHIJKLMNOPQRSTUVWXYZ')]*3,fillvalue=''))])
#http://ideone.com/HeXUdG
■okashoiさんの解答コード

Timさんより:A very explicit implementation, full of python's simplicity

seq = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
n = 3

print [seq[i::n] for i in range(n)]
■しみずかわさんの解答コード

Timさんより:It is indeed full of fun, you can write an advanced article about how to use python's zip (⊙0⊙)

from itertools import izip_longest
s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
it = iter(s)
map(''.join, zip(*izip_longest(*[it]*3, fillvalue='')))
■梅濁酒さんの解答コード

Timさんより:I like the way you write a code with test. you must be a guy really cares about quality (  ̄□ ̄)/ <( ̄ㄧ ̄ ) <( ̄ㄧ ̄ )

if __name__ == '__main__':
    s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    expected = ['ADGJMPSVY', 'BEHKNQTWZ', 'CFILORUX']

    len_s = len(s)
    L_len = (len_s + 3 - 1) // 3

    a = b = c = ''
    for i in range(L_len):
        a += s[i*3+0:i*3+1]
        b += s[i*3+1:i*3+2]
        c += s[i*3+2:i*3+3]

    print('a =', a)
    print('b =', b)
    print('c =', c)
    print('expected =', expected)
    print('a, b, c == expected =', [a, b, c] == expected)

  # Ls = [s[i*L_len:(i+1)*L_len] for i in range(3)]
  # for a, b, c in zip(*Ls):
  #     print(a, b, c)

  # print('Ls =', Ls)
■raydiveさんの解答コード

Timさんより:It is a fun abstraction of the function alphabet_to_threestrings, it is a good tier.

def alphabet_to_threestrings(index):
    alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    return ''.join(alphabet[f+index] for f in range(0, len(alphabet)-index) if f%3 == 0)
    
print [alphabet_to_threestrings(i) for i in range(0, 3)]
■rokujyouhitomaさんの解答コード

Timさんより:The code is full of fun, you are very good at iteration protocol

class Assignment(object):
    def __init__(self, data, quota):
        self.data = data
        self.quota = quota
        self.length = len(data) / quota
        self.index = 0
    def __iter__(self):
        return self
    def next(self):
        if self.index > self.length:
            raise StopIteration
        pointer = self.index * self.quota
        res = self.data[pointer:pointer+self.quota]
        self.index = self.index + 1
        return res

def main():
    ass = Assignment('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 3)
    first = []
    second = []
    third = []
    for seq in ass:
        first.append(seq[0:1])
        second.append(seq[1:2])
        third.append(seq[2:3])

    print map(lambda x: ''.join(x), (first, second, third))

if __name__ == '__main__':
    main()
■YUUさんの解答コード

Timさんより:Your thought is very clear and maintainble, I like it !

s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
a,b,c = "","",""
count = 0
for i in s:
    if count%3 == 0:
        a += i
    elif count % 3 == 1:
        b += i
    else:
        c += i
    count += 1
res = []
res.append(a)
res.append(b)
res.append(c)
print res
■ghisxさんの解答コード

Timさんより:it indeed very fun, the author must be very good at math ‧★,:*:‧\( ̄▽ ̄)/‧:*‧°★* 

#!/usr/bin/env python

import math
from itertools import groupby

L = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

X = [ (math.fmod(x,3), x) for x in range(0, len(L)) ]
S = sorted(X, key= lambda x:x[0])
G = groupby(S, lambda y:y[0])

h = {}
for t in [ (k,[ L[j] for _, j in v]) for k,v in G ]:
  h[t[0]] = t[1]
a = []
for k,v in h.items():
  a.append("".join(v))
print a


n0 = "".join( L[x] for x in range(0, len(L)) if x % 3 == 0 )
n1 = "".join( L[x] for x in range(0, len(L)) if x % 3 == 1 )
n2 = "".join( L[x] for x in range(0, len(L)) if x % 3 == 2 )
print [n0, n1, n2]
■suageさんの解答コード

Timさんより:Both of your answer are quite good and smart, and I like the explicit way you enumerate A to Z.

solution1: use 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' string directly

>>> ["".join(['ABCDEFGHIJKLMNOPQRSTUVWXYZ'[i] for i in range(len('ABCDEFGHIJKLMNOPQRSTUVWXYZ')) if i%3==j]) for j in range(3)]



solution2: using chr function

>>> sorted(["".join([chr(i) for i in range(65,91) if i%3==j]) for j in range(3)])


solution1 is faster but I think solution2 is more funny
■masatanaさんの解答コード

Timさんより:Code structure is beautiful and has a good abstraction, look forward a better name for the function f

# -*- coding: utf-8 -*-
SEQUENCE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
def f(j):
    return ''.join([x for i, x in enumerate(list(SEQUENCE)) if i % 3 == j])
    
def main():
    l = [f(0), f(1), f(2)]
    print l

if __name__ == '__main__':
    main()
■melponさんの解答コード

Timさんより:God ! is it pyton? it is so amazing Σヽ(゚Д ゚; )ノ

#coding: rot13
frdhrapr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
cevag [frdhrapr[a::3] sbe a va enatr(3)]
■こばすきさんの解答コード

Timさんより:It indeed full of fun with the random power and it extend the imagination of the original question

s = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')

import random

rand = random.Random('fun')

rand.shuffle(s)

funs = []

p = 0
while(p < len(s)):
    j = (int)(rand.random()*len(s))
    funs.append(''.join(s[p:p+j]))
    p += j

print funs

実にいろんな解答がありますね。個人的にはmelponさんのコードが神すぎると思いました。

ここに掲載されていなくても、挑戦した39名の方には全員個別にフィードバックしておりますので、CodeIQのマイページをご確認ください。

https://codeiq.jp/ace/tim_hsu/q280
f:id:codeiq:20130619145636p:plain

CodeIQ中の人の一言:「コード書けて、英語もできるってカッコイイですね」と思ったのだけど、英語圏のエンジニアって全員この条件満たすんだよなぁ…

エンジニアのための新しい転職活動!CodeIQのウチに来ない?の特集ページを見る