全「???48」を生成してみる

課題1

  • 大文字のアルファベット3文字 + '48' の全パターンのリストを作る

解答 その1

単純にループの入れ子で
# まず大文字のアルファベットのリストを作る
al = [chr(a) for a in range(65, 91)]

# 全パターンのジェネレータ
def akb():
    for a1 in al:
        for a2 in al:
            for a3 in al:
                yield a1 + a2 + a3 + '48'
# リストで取得
allptns = [p for p in akb()]

allptns.index('AKB48') #=> 本家は261番目に出てきた

解答 その2

リスト内包表記の入れ子
# al は大文字アルファベットのリスト
# 全パターンのリスト
allPtns = [a1 + a2 + a3 + '48' for a1 in al for a2 in al for a3 in al]

解答その3

アルファベットの桁数を指定できるようにしてみる

# al は大文字アルファベットのリスト

# 2個のリストを組み合わせる関数
getprd = lambda list1, list2 : [a1 + a2 for a1 in list1 for a2 in list2]

# 全パターンのリストを生成する関数
def akb(num):
    temp = ['']
    def _akb(tl, n):
        if n == 0:
            return getprd(tl, ['48'])
        else:
            return _akb(getprd(tl, al), n - 1)
    return _akb(temp, num)
allPtns = akb(3)

なんかいまいちだなー。もっとかっこよい解答求む。

課題2

課題1に制限を加える

アルファベット3文字は別々のアルファベットを使う(AAAとかAABはダメ)

解答

課題1の解答3のリストを組み合わせる関数(getprd)を以下に修正すれば対応できる。

# 2個のリストを組み合わせる関数(重複省く)
getprd = lambda list1, list2 : [a1 + a2 for a1 in list1for a2 in list2 if a2 not in a1]

課題2の場合は本家は216番目に出てきた。

やってみた感想

ループとか関数とか考えながら書けるので、初めてのプログラミング言語に取り組むときはHello Worldよりこの課題やると楽しそう。

別解

ちなみに標準モジュールのitertoolsを使えば以下のように書ける。
至れり尽くせり!

import itertools
# al は大文字アルファベットのリスト

# 課題1
allptns1 = [''.join(a) + '48' for a in itertools.product(al, al, al)]
# 課題2
allptns2 = [''.join(a) + '48' for a in itertools.permutations(al, 3)]