【问题标题】:I want a program that writes every possible combination to a different line of a text file我想要一个将所有可能的组合写入文本文件的不同行的程序
【发布时间】:2010-09-19 11:37:06
【问题描述】:

我想编写一个程序,将一组变量的每个组合打印到一个文本文件,创建一个单词列表。每个答案都应写在单独的行上,并将 1 位、2 位和 3 位的所有结果写入单个文本文件。

有没有一种简单的方法可以编写一个可以完成此任务的 python 程序?这是打印 1、2 和 3 位可能的所有二进制数字组合时我期望的输出示例:

Output:
0  
1

00  
01  
10  
11

000  
001  
010  
011  
100  
101  
110  
111

【问题讨论】:

  • 首先,如果您有任何编程经验,这将非常容易。其次,你为什么要这样做?我根本想不出有什么好的理由。也许如果您告诉我们原因,我们可以帮助您更好地指导您。
  • 除了了解其背后的基本概念外,我没有任何编程经验。这主要是为了我自己的好奇心,帮助我从理论的角度更好地理解编程。
  • 这绝对不是更好地理解编程理论概念的方法。如果您想这样做,请阅读一些书籍,搜索网络并尝试自己解决问题。在我看来,你只是想让我们为你做功课。
  • 你的老师允许你用python 2.6还是3.0?如果是,标准库会来救援。

标签: python recursion


【解决方案1】:

解决问题并且对于您可能拥有的任何应用程序都足够通用的简单解决方案是这样的:

def combinations(words, length):
    if length == 0:
        return []
    result = [[word] for word in words]
    while length > 1:
        new_result = []
        for combo in result:
            new_result.extend(combo + [word] for word in words)
        result = new_result[:]
        length -= 1
    return result

基本上,这会逐渐在所有组合的内存中建立一棵树,然后返回它们。然而,它是内存密集型的,因此对于大规模组合是不切实际的。

该问题的另一个解决方案确实是使用计数,然后将生成的数字转换为单词列表中的单词列表。为此,我们首先需要一个函数(称为number_to_list()):

def number_to_list(number, words):
    list_out = []
    while number:
        list_out = [number % len(words)] + list_out
        number = number // len(words)
    return [words[n] for n in list_out]

事实上,这是一个将十进制数转换为其他基数的系统。然后我们编写计数函数;这相对简单,将构成应用程序的核心:

def combinations(words, length):
    numbers = xrange(len(words)**length)
    for number in numbers:
        combo = number_to_list(number, words)
        if len(combo) < length:
            combo = [words[0]] * (length - len(combo)) + combo
        yield combo

这是一个 Python 生成器;使其成为生成器可以使其使用更少的 RAM。把数字变成单词列表后还有一点工作要做;这是因为这些列表需要填充,以便它们处于请求的长度。它会这样使用:

>>> list(combinations('01', 3))
[['0', '0', '0'], ['0', '0', '1'],
['0', '1', '0'], ['0', '1', '1'],
['1', '0', '0'], ['1', '0', '1'],
['1', '1', '0'], ['1', '1', '1']]

如您所见,您会返回一个列表列表。这些子列表中的每一个都包含一系列原始单词;然后,您可能会执行map(''.join, list(combinations('01', 3))) 之类的操作来检索以下结果:

['000', '001', '010', '011', '100', '101', '110', '111']

然后您可以将其写入磁盘;然而,更好的想法是使用生成器的内置优化并执行以下操作:

fileout = open('filename.txt', 'w')
fileout.writelines(
    ''.join(combo) for combo in combinations('01', 3))
fileout.close()

这只会使用尽可能多的 RAM(足以存储一个组合)。我希望这会有所帮助。

【讨论】:

    【解决方案2】:

    下面给出了生成列表所有排列的基本函数。在这种方法中,排列是使用生成器懒惰地创建的。

    def perms(seq):
        if seq == []:
            yield []
        else:
            res = []
            for index,item in enumerate(seq):
                rest = seq[:index] + seq[index+1:]
                for restperm in perms(rest):
                    yield [item] + restperm
    
    alist = [1,1,0]
    for permuation in perms(alist):
        print permuation
    

    【讨论】:

    • 您是否打算使用 [1,1,0] 而不仅仅是 [1,0]?如果有,请解释。
    • 问题似乎是关于幂集,而不是排列。此代码产生 n!结果,而不是 2**n 个结果。
    【解决方案3】:
    # Given two lists of strings, return a list of all ways to concatenate
    # one from each.
    def combos(xs, ys):
        return [x + y for x in xs for y in ys]
    
    digits = ['0', '1']
    for c in combos(digits, combos(digits, digits)):
        print c
    
    #. 000
    #. 001
    #. 010
    #. 011
    #. 100
    #. 101
    #. 110
    #. 111
    

    【讨论】:

    • 如果集合很大,这会占用大量存储空间 - 但您可能会有效地争辩说,同时存储到磁盘会变得昂贵。
    • 可能有一种方法可以用生成器推导代替列表推导来解决这个问题,但这需要制作输入迭代器的副本。 (你只能通过一次迭代器。该死的 Python 不是 Haskell!)
    • 所以我会编写没有生成器的明显递归代码。
    【解决方案4】:

    在大多数语言中应该不会太难。下面的伪代码有帮助吗?

    for(int i=0; i < 2^digits; i++)
    {
         WriteLine(ToBinaryString(i));
    }
    

    【讨论】:

    • 这适用于二进制数字字符串 - 并且可能适用于大多数数字字符串。它不会轻易适应更随意的事物,例如一组单词。
    • 如果你将 set 的每个单词都视为 n 基数系统中的一个数字,它会起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-11
    • 2023-03-17
    • 1970-01-01
    • 2015-04-13
    相关资源
    最近更新 更多