递归Python函数生成一个字谜列表

时间:2014-03-02 18:03:24

标签: python recursion return permutation

经过大量的头部刮擦和谷歌搜索后,我仍然无法弄明白这一点。我是Python的新手,我正在努力学习语法。从概念上讲,我认为我对我想要做什么以及如何以递归方式这样做有一个相当不错的想法。但从技术上讲,将其编码为Python却被证明是一场噩梦。

基本上我想添加一个单词的所有排列列表(不允许重复的字符),然后可以被另一个程序或函数调用。

返回命令以及如何处理空白区域让我很困惑。我希望递归函数在它展开后“返回”某些东西但我不希望它停止函数,直到所有字符都迭代并且所有的排列都在这些迭代中递归生成。当我在下面运行代码时似乎没有发生任何事情。

def permutations(A, B = ''):
    assert len(A) >= 0
    assert len(A) == len(set(A))
    res = []
    if len(A) == 0: res = res.extend(B)
    else:
        for i in range(len(A)):
            permutations(A[0:i] + A[i+1:], B + A[i])
    return res

permutations('word'))

如果我运行下面的代码,它会将OK打印到我的显示窗格,但我无法弄清楚如何将其转换为可供其他程序(如列表)使用的输出格式。

def permutations(A, B = ''):
    assert len(A) >= 0
    assert len(A) == len(set(A))
    if len(A) == 0: print(B)
    else:
        for i in range(len(A)):
            permutations(A[0:i] + A[i+1:], B + A[i])

permutations('word')

请有人可以告诉我这件事,而我还有一些头发!非常感谢收到。

谢谢

乔恩

4 个答案:

答案 0 :(得分:1)

喜欢这个吗?

from itertools import permutations
a = [x for x in permutations('word')]
print a

输出:

>>[('w', 'o', 'r', 'd'), ('w', 'o', 'd', 'r'), ('w', 'r', 'o', 'd'),
>>('w', 'r', 'd', 'o'), ('w', 'd', 'o', 'r'), ('w', 'd', 'r', 'o'), 
>>('o', 'w', 'r', 'd'), ..............

编辑: 我刚才意识到你说没有允许重复的字符。这对'单词'来说并不重要,但是假设你有'wordwwwdd'。然后你可以这样做:

[x for x in permutations(''.join(set('wordwwwdd')))] 

但由于使用set会导致订单混乱,所以它看起来像:

>> [('r', 'o', 'w', 'd'), ('r', 'o', 'd', 'w'), ('r', 'w', 'o', 'd')....

答案 1 :(得分:0)

基本上你的错误在

res = res.extend(B)

.extend()不会返回新列表,但会修改实例。

另一个问题是您不使用递归调用的返回值。 以下是修复代码的一种方法:

def permutations(A, B = ''):
    assert len(A) >= 0
    assert len(A) == len(set(A))
    if len(A) == 0:
        return [B]
    else:
        res = []        
        for i in range(len(A)):
            res.extend(permutations(A[0:i] + A[i+1:], B + A[i]))

        return res

print permutations('word')

答案 2 :(得分:0)

我会这样做:

def permute_nondupe_letters_to_words(iterable):
    return (''.join(i) for i in itertools.permutations(set(iterable)))

使用它:

word = 'word'
permutation_generator = permute_nondupe_letters_to_words(word)

bucket_1, bucket_2 = [], []
for i in permutation_generator:
    bucket_1.append(i)
    if i == 'owdr':
        break

for i in permutation_generator:
    bucket_2.append(i)

并且

print(len(bucket_1), len(bucket_2))

打印:

(10, 14)

答案 3 :(得分:0)

以下是解决此问题的另一种方法:

  • 兼容Python 2.7和3.3(尚未与其他版本一起测试)

  • 它将接受包含重复项的输入,并仅返回唯一输出  (即permutations("woozy")只会返回" oowzy"一次)

  • 它按排序顺序返回输出(并允许您指定排序键和升序或降序)

  • 它返回字符串输入

  • 的字符串输出
  • 它作为生成器运行,即不会将所有组合存储在内存中。如果那是你想要的,你必须明确说出来(例子如下所示)

  • 编辑:我发现我省略了一个长度参数,所以我添加了一个。你现在可以用六个字母的字符串来询问所有独特的4个字母的排列。

没有进一步的麻烦:

from collections import Counter
import sys

if sys.hexversion < 0x3000000:
    # Python 2.x
    dict_items_list = lambda d: d.items()
    is_string       = lambda s: isinstance(s, basestring)
    rng             = xrange
else:
    # Python 3.x
    dict_items_list = lambda d: list(d.items())
    is_string       = lambda s: isinstance(s, str)
    rng             = range

def permutations(lst, length=None, key=None, reverse=False):
    """
    Generate all unique permutations of lst in sorted order

        lst        list of items to permute
        length     number of items to pick for each permutation (defaults to all items)
        key        sort-key for items in lst
        reverse    sort in reverse order?
    """
    # this function is basically a shell, setting up the values
    # for _permutations, which actually does most of the work
    if length is None:
        length = len(lst)
    elif length < 1 or length > len(lst):
        return []     # no possible answers

    # 'woozy' => [('w', 1), ('o', 2), ('z', 1), ('y', 1)]  # unknown order
    items = dict_items_list(Counter(lst))
    # => [('o', 2), ('w', 1), ('y', 1), ('z', 1)]          # now in sorted order
    items.sort(key=key, reverse=reverse)

    if is_string(lst):
        # if input was string, return generator of string
        return (''.join(s) for s in _permutations(items, length))
    else:
        # return generator of list
        return _permutations(items, length)

def _permutations(items, length):
    if length == 1:
        for item,num in items:
            yield [item]
    else:
        for ndx in rng(len(items)):
            # pick an item to start with
            item, num = items[ndx]

            # make new list of remaining items
            if num == 1:
                remaining_items = items[:ndx] + items[ndx+1:]
            else:
                remaining_items = items[:ndx] + [(item, num-1)] + items[ndx+1:]

            # recurse against remaining items
            for perm in _permutations(remaining_items, length-1):
                yield [item]+perm

# test run!
words = list(permutations("woozy"))

结果

['oowyz',
 'oowzy',
 'ooywz',
 'ooyzw',
 'oozwy',
 'oozyw',
 'owoyz',
 # ...
 'zwooy',
 'zwoyo',
 'zwyoo',
 'zyoow',
 'zyowo',
 'zywoo']   # 60 items = 5!/2!, as expected