Python非图形唯一性

时间:2013-07-16 03:47:26

标签: python

我正在尝试编写一个Python脚本来确定给定的非图形是否是唯一的。我目前的脚本运行时间太长,所以我想知道是否有人有任何想法。

我知道一般的非图形问题是NP难的。但是,我知道有关我给出的非图形的两条信息:

  1. 当分别将黑/白框表示为0和1时,我知道每个盒子有多少。
  2. 我只考虑6x6非图。
  3. 我最初使用蛮力方法(所以2 ^ 36个案例)。然而,知道(1),我能够将其缩小到n-choose-k(36选择零个数)的情况。然而,当k接近18时,这仍然是~2 ^ 33个案例。需要几天时间。

    我有什么想法可以加快速度吗?它甚至可能吗?

    同样,我不在乎解决方案是什么 - 我已经拥有它。我想要确定的是,该解决方案是否是唯一的。

    编辑: 这不完全是完整的代码,但有一般的想法:

    def unique(nonogram):
        found = 0
        # create all combinations with the same number of 1s and 0s as incoming nonogram
        for entry in itertools.combinations(range(len(nonogram)), nonogram.count(1)):
            blank = [0]*len(nonogram)   # initialize blank nonogram
            for element in entry:
                blank[element] = 1   # distribute 1s across nonogram
            rows = find_rows(blank)  # create row headers (like '2 1')
            cols = find_cols(blank)  
            if rows == nonogram_rows and cols == nonogram_cols:
                found += 1    # row and col headers same as original nonogram
            if found > 1:
                break     # obviously not unique
        if found == 1:
            print('Unique nonogram')
    

1 个答案:

答案 0 :(得分:1)

除了解决问题之外,我无法想出一种巧妙的方法来证明唯一性,但6x6足够小,我们基本上可以做一个强力解决方案。为了加快速度,我们可以循环遍历所有令人满意的行,而不是遍历每个可能的非图形。这样的事情(注意:未经测试)应该有效:

from itertools import product, groupby
from collections import defaultdict

def vec_to_spec(v):
    return tuple(len(list(g)) for k,g in groupby(v) if k)

def build_specs(n=6):
    specs = defaultdict(list)
    for v in product([0,1], repeat=n):
        specs[vec_to_spec(v)].append(v)
    return specs

def check(rowvecs, row_counts, col_counts):
    colvecs = zip(*rowvecs)
    row_pass = all(vec_to_spec(r) == tuple(rc) for r,rc in zip(rowvecs, row_counts))
    col_pass = all(vec_to_spec(r) == tuple(rc) for r,rc in zip(colvecs, col_counts))
    return row_pass and col_pass

def nonosolve(row_counts, col_counts): 
    specs = build_specs(len(row_counts))
    possible_rows = [specs[tuple(r)] for r in row_counts]
    sols = []
    for poss in product(*possible_rows):
        if check(poss, row_counts, col_counts):
            sols.append(poss)
    return sols

我们从中了解到

>>> rows = [[2,2],[4], [1,1,1,], [2], [1,1,1,], [3,1]]
>>> cols = [[1,1,2],[1,1],[1,1],[4,],[2,1,],[3,2]]
>>> nonosolve(rows, cols)
[((1, 1, 0, 0, 1, 1), (0, 0, 1, 1, 1, 1), (1, 0, 0, 1, 0, 1), 
(0, 0, 0, 1, 1, 0), (1, 0, 0, 1, 0, 1), (1, 1, 1, 0, 0, 1))]
>>> len(_)
1

是唯一的,但

>>> rows = [[1,1,1],[1,1,1], [1,1,1,], [1,1,1], [1,1,1], [1,1,1]]
>>> cols = rows
>>> nonosolve(rows, cols)
[((0, 1, 0, 1, 0, 1), (1, 0, 1, 0, 1, 0), (0, 1, 0, 1, 0, 1), (1, 0, 1, 0, 1, 0), (0, 1, 0, 1, 0, 1), (1, 0, 1, 0, 1, 0)), 
((1, 0, 1, 0, 1, 0), (0, 1, 0, 1, 0, 1), (1, 0, 1, 0, 1, 0), (0, 1, 0, 1, 0, 1), (1, 0, 1, 0, 1, 0), (0, 1, 0, 1, 0, 1))]
>>> len(_)
2

不是

[请注意,对于这个问题,这不是一个非常好的解决方案,因为它丢弃了大部分信息,但它很简单。]