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

牌語備忘録 -pygo

あくまでもメモです。なるべくオフィシャルの情報を参照してください。

牌語備忘録 -pygo

関数のみで書いたコードをクラスを使ったコードに簡易変換するスクリプトを何となくつくってみた

Python
  • 関数 def_to_cls(クラス名, テキスト)を作る
    1. 関数の第一引数にself(def hogehoge(self,~))
    2. 使用する関数にself.を追加(self.hogehoge())
    3. 関数たちのインデントを右にシフト
    4. 「class Hogehoge」とかクラス名を挿入。

サンプルコードは「『マッチ箱の脳』人工知能ジェネテックアルゴリズムをPythonでやってみた - 牌語備忘録 - pygo」を使用
わかりやすくするため関数の名前を一部変更(「def genetic_algorithm」を「def answer_display」に)

とりあえず変換スクリプト

#!/usr/bin/env python
# *-# -*- coding: utf-8 -*-
#def_to_cls.py

import re

def def_to_cls(cls_name, text):
    #def "name" to list
    r = re.compile("(?<=^def )\w+", re.M)
    def_lst = re.findall(r, text)

    #"def xxx" to "def xxx(self, "
    r = re.compile("(?<=^def )(\w+\()", re.M)
    result_txt = re.sub(r, r"\1self, ", text)

    #non "def xxx" lines "name" to "self.name"
    for def_name in def_lst:
        r = re.compile("(?<!def )(?<!\w)(%s)(?!\w)" % def_name)
        result_txt = re.sub(r, r"self.\1", result_txt)

    #indent shift right
    r = re.compile("^", re.M)
    result_txt = re.sub(r, "    ", result_txt)

    print "\nclass %s:\n%s" % (cls_name, result_txt)


#test
if __name__ == '__main__':
    t = r"""
def matchbox(num = 10, kind = 1, to_kind = 3):
    return [random.randint(kind, to_kind) for n in range(num)]

def amount_of_box(amount = 10):
    return [matchbox() for count in range(amount)]
aa_matchbox
matchbox_bb
"""
    def_to_cls("ClsName", t)

実行してみる

(サンプルコードから一部抜粋したもの)

>>> 
class ClsName:
    
    def matchbox(self, num = 10, kind = 1, to_kind = 3):
        return [random.randint(kind, to_kind) for n in range(num)]
    
    def amount_of_box(self, amount = 10):
        return [self.matchbox() for count in range(amount)]
    aa_matchbox
    matchbox_bb
    
サンプルコードを変換してみた
  1. 頭に「#!/usr/bin/env python 〜 import random」
  2. 変換したコード
  3. 最後に少々書き換えた「if __name__ == 〜」
#!/usr/bin/env python
# *-# -*- coding: utf-8 -*-
# Genetic Algorithm
# ga2.py

import random

class GeneticAlgorithm:
    def matchbox(self, num = 10, kind = 1, to_kind = 3):
        return [random.randint(kind, to_kind) for n in range(num)]
    
    def amount_of_box(self, amount = 10):
        return [self.matchbox() for count in range(amount)]
    
    def del_duplication(self, box_seq):
        set_tu = set(map(tuple,box_seq))
        set_lst = map(list, set_tu)
        n = len(set_lst)
        if n < 10:
            add_box = [self.matchbox() for i in range(10 - n)]
            return set_lst + add_box
        return box_seq
    
    def rating(self, ans, box_seq):
        point_lst = []
        for box in box_seq:
            point = 0
            for a, b in zip(ans, box):
                if a == b:
                    point += 10
            point_lst.append([point, box])
        return sorted(point_lst, reverse = True)
    
    def parent(self, rate_seq, choice = 2):
        return [rate_seq[0][1], rate_seq[1][1]]
    
    def mutation(self, kids_seq):
        p = random.randint(0, len(kids_seq))
        if p < 10:
            change = lambda x:x + 1 if x < 3 else x - 2
            kids_seq[p] = change(kids_seq[p])
        return kids_seq
    
    def recombination(self, parent_seq):
        crossing = random.randint(0, 10)
        kid_a = parent_seq[1][:crossing] + parent_seq[0][crossing:]
        kid_b = parent_seq[0][:crossing] + parent_seq[1][crossing:]
        return [self.mutation(kid_a), self.mutation(kid_b)]
    
    def answer_display(self, ans, count = 200):
        log = []
        all_box = self.amount_of_box()
        for i in range(count):
            dd_box = self.del_duplication(all_box)
            rate_seq = self.rating(ans, dd_box)[:]
            log.append("Generation: %d" % (i + 1))
            log.append("\n".join(["%d %s" % (n,l) for n,l in rate_seq]))
            all_box = [l for n,l in rate_seq]
            parent_seq = self.parent(rate_seq)
            top = all_box[:2]
            tail = all_box[2:-2]
            all_box = self.recombination(parent_seq) + tail + top
            if rate_seq[0][0] == 100:
                break
        else:
            log.append("break: over %d Generation!" % count)
        return "\n".join(log)
    

if __name__ == "__main__":
    answer = [3, 1, 2, 2, 2, 3, 1, 3, 2, 1]
    ga = GeneticAlgorithm()
    print ga.answer_display(answer)

実行して問題なければ、できあがり(゚Д゚)b
簡単に済ますはずが、ややこしくなった(つдT)