Sony GO FOR IT 4)旋律に隠された特徴

隣り合う音の差(半音を1とする)の和+付点の個数%2 を特徴量とした。

# coding: utf-8
# ライセンス:このプログラムは、好きに使ってください。

# 特徴量の計算
def compute(s):
    # 譜面データ形式を、0:A, 1:A#, 2:B, 3:C, 4:C#, 5:D, 6:D#, 7:E, 8:F, 
    # 9:F#, 10:G, 11:G# に変換
    r = []
    # 付点の数
    d = 0
    for n in s.split(","):
        t = n.split(":")
        if t[0]!="":
            a = int(t[0])
            r += [(a+8)/7*12+[0,2,3,5,7,8,10][(a+1)%7]
                  +{"":0,"s":+1,"x":+2,"b":-1,"d":-2}[t[2]]]
        if t[1][-1]==".":
            d += 1
    # 差の絶対値の和+付点の個数%2を特徴量とする
    return sum(abs(r[i+1]-r[i]) for i in range(len(r)-1)) + d%2

A = "-3:4:,-2:4:,-1:4:,0:4:b,-1:4:,-2:4:,-3:4:,:4:,-1:4:,0:4:b,1:4:," \
    "2:4:,1:4:,0:4:b,-1:4:,:4:"
B = "3:4:,2:4:,1:4:,0:4:b,1:4:,2:4:,3:4:,:4:,1:4:,0:4:b,-1:4:,-2:4:," \
    "-1:4:,0:4:b,1:4:,:4:"
C = "3:4:,2:4:,1:4:,0:4:,1:4:,2:4:,3:4:,:4:,1:8:,0:4.:,-1:4:,-2:4:,:" \
    "8:,-1:4.:,0:8:,1:8:"
D = "-6:8:,-6:8:,-6:8:,-4:8:,-2:8:,-2:8:,-2:8:,:8:,-5:8:,-5:8:,-5:8:" \
    ",-3:8:,-2:8:,-2:8:,-2:8:,:8:,:8:,-2:8:,-2:8:,-1:8:b,-1:8:,-1:8:" \
    ",-1:8:,-1:8:b,-2:4:,0:4:,1:4:,:4:"
E = "-6:8.:,-7:16:,-6:8:,-5:8:,-4:8:,-4:8:,-4:4:,-3:8.:,-4:16:,-5:8:" \
    ",-6:8:,-5:4:,:4:,-3:8:,-5:4:,-5:8:,-4:8:,-4:8:,-3:8:,-3:8:,-4:8" \
    ":,-4:8:,-5:8:,-5:8:,-6:4:,:4:"
F = "-6:2:,-5:4:,-6:8:,-5:8:,-4:4:,-2:4:,-4:4:,:4:,-5:4:,-5:4:,-6:4:" \
    ",-5:4:,-4:2.:,:4:"
G = "-2:8.:,-1:16:,-2:8.:,-1:16:,-2:4:,-4:4:,-4:8.:,-3:16:,-4:8.:,-3" \
    ":16:,-4:4:,-6:4:,-4:8:,:8:,-6:8.:,-5:16:,-4:8:,:8:,-6:8.:,-5:16" \
    ":,-4:8.:,-4:16:,-2:8.:,-2:16:,-5:8.:,-4:16:,-5:4:"

# 各旋律の特徴量
print "A",compute(A)
print "B",compute(B)
print "C",compute(C)
print "D",compute(D)
print "E",compute(E)
print "F",compute(F)
print "G",compute(G)

# 作曲
def compose():
    # 音を譜面データ形式に変換
    def f(n):
        return "%s:%s:%s"%(
            [-1,-1,0,1,1,2,2,3,4,4,5,5][n%12]+n/12*7-7,
            4,
            ["","s","","","s","","s","","","s","","s"][n%12])
    
    # Gの特徴量
    Gf = compute(G)
    s = []
    s += [f(10),f(10+Gf/2),f(10)]
    # 特徴量が奇数なら付点で補正
    if Gf%2!=0:
        s += [":8.:",":16:"]
    # 旋律の長さを全音符4つ分にする
    s += [":4:"]*(16-len(s))
    
    return ",".join(s)

print compose()