縦横のラベルの数から図の再現ができないか?の確認ロジック3
■樹形図のロジックの考え方。
前回からの続き。樹形図のようなものを考えて、1つずつ確認していくイメージで作っていく。
図にすると下のような感じ。
階層が図の行部分にあたる。1行目(1階層)がOKなら次の行を確認。2行目(2階層)がOKなら3行目を確認。3行目(3階層)がNGなら、同じ階層の次のものをチェック。この流れで確認していき、最後まで条件に合うものを出力する。該当するものが無ければ階層を上がって次のものをチェック。
簡単な下のサンプルで考える。縦と横で[1, 3, 2, 4], [3, 2, 2, 3]との数字が与えられていて、それを満たす図は何かを調べる。
これを確認するコードが下のもの。チェック部分とか固定の数を入れたハードなコーディングになっているけど、とりあえず試しで。
import itertools
import numpy
def checkResult(target):
columnlist = [1, 3, 2, 4]
a = 0
b = 0
c = 0
d = 0
for i in target:
a = a + i[0]
b = b + i[1]
c = c + i[2]
d = d + i[3]
if a <= columnlist[0]:
if b <= columnlist[1]:
if c <= columnlist[2]:
if d <= columnlist[3]:
return True
return False
def checkline(parent, childrenList, columnlist, depth):
list = parent
if depth == 3:
for child in childrenList:
list.append(child)
result = checkResult(list)
if result == True:
print(list)
del list[len(list) - 1]
return list
for child in childrenList:
list.append(child)
result = checkResult(list)
if result == True:
depth = depth + 1
checkline(list, makeCombination(4, columnlist[depth]), columnlist, depth)
depth = depth - 1
del list[len(list) - 1]
return parent
def makeCombination(total, combNum):
result = []
list = range(total)
for comb in itertools.combinations(list, combNum):
list2 = numpy.zeros(total)
if len(list) > 0:
for n in comb:
list2[n] = 1
result.append(list2.tolist())
return result
rowlist = [1, 3, 2, 4]
columnlist = [3, 2, 2, 3]
start = []
list = [0, 0, 0, 0]
start.append(list)
d = makeCombination(4, 3)
c = checkline(start, d, columnlist, 0)
この実行結果が下のもの。
この1行が図を表し、8つのものが条件に合うことが分かった。
この数字をExcelで再現すると、下のようになる。それぞれ縦横の合計数が条件に合っている。
考え方としてはこれでできそう。もう少しコードを一般化した上で、前の9×9の図で試してみる。