遍历所有二进制组合,其中一些数字为“?”

时间:2019-01-06 20:18:26

标签: python recursion binary

我必须生成给定字符串的所有可能的二进制表示形式,其中某些字符是“?”其他为1或0。

我正在尝试进行递归搜索,但是遇到了一些我无法弄清的怪异问题。

userInput = list(input())
anslist = []
def fill(inp):
    #print(inp)
    if inp.count("?") == 0:
        print(inp, "WAS ADDED")
        anslist.append(inp)
        return


    for a in range(0, len(userInput)):
        if inp[a] == "?":
            inp[a] = 1
            fill(inp)
            inp[a] = 0
            fill(inp)
            return
print(anslist)   

对于输入?01?1我应该得到: 00101、00111、10101和10111 但我明白了 10111 10101 00101已打印出来。此外,anslist无法正常运行。我似乎无法弄清楚。

5 个答案:

答案 0 :(得分:2)

这里是不使用内置工具的示例解决方案。在这里,当发生“?”时,我们使用递归。在迭代我们的输入时,我们将其替换为“ 0”和“ 1”,并添加fill()的结果到当前索引之后。

userInput = input()

def fill(inp):
    ret = []
    for idx, i in enumerate(inp):
        if i == '?':
            for rest in fill(inp[idx+1:]):
                ret.append(inp[:idx] + '0' + rest)
                ret.append(inp[:idx] + '1' + rest)
            break
    else:
        return [inp]
    return ret

print(fill(userInput))

输出

?01?1 -> ['00101', '10101', '00111', '10111']
???   -> ['000', '100', '010', '110', '001', '101', '011', '111']

答案 1 :(得分:2)

import itertools
import re

inp = "?01?1"
for combination in itertools.product("01", repeat=inp.count("?")):
    i_combination = iter(combination)
    print(re.sub("\?",lambda m: next(i_combination),inp))

这仅使用内置的itertools.product来创建所有可能的长度为N的“ 01”字符串(但是字符串中有很多问号)

然后将它们中的每一个转换为一个迭代器,在该迭代器中,每项商品一被看到就被消耗掉,

然后我们使用re.sub将产品替换为我们的原始字符串,以代替问号

这里是一个副本https://repl.it/@JoranBeasley/AssuredAncientOpengroup

我在这里的评论中看到您不想使用内置函数...所以没关系,我想

如果您不想使用内置的itertools.product ..。只需编写自己的

def my_product(s,r):
  if r < 1:
    yield ""
  for i in range(r):
    for c in s:
      for partial in  my_product(s,r-1):
        yield c+partial

与内置迭代器相同

def my_iter(s):
    for c in s:
        yield c

最后,我们需要编写自己的自定义subber

def my_substitute(s,replacement):
    iter_replacement = my_iter(replacement)
    while s.count("?"):
         s = s.replace("?",next(iter_replacement))
    return s

现在我们以相同的方式将它们绑在一起

inp = "?01?1"
for combination in my_product("01", inp.count("?")):
    print(my_substitute(inp,combination))

答案 2 :(得分:2)

避免使用全局或库的简单解决方案:

def fill(digits):

    if not digits:
        return []

    first, *rest = digits

    strings = fill(rest) if rest else ['']

    if first == '?':
        return ['0' + string for string in strings] + ['1' + string for string in strings]

    return [first + string for string in strings]

userInput = input()

print(fill(userInput))

尝试拼写而不是进行最有效的数组操作,这是OP的练习。

输出

> python3 test.py
?01?1
['00101', '00111', '10101', '10111']
> python3 test.py
???
['000', '001', '010', '011', '100', '101', '110', '111']
> python3 test.py
?
['0', '1']
> python3 test.py

[]
>

答案 3 :(得分:2)

list mutable 类型,这意味着您只有一个列表,可以在列表上进行所有修改。这会导致您的第一个通话fill(inp)也填写剩余的“?” inp中的值,因此只为您提供一个结果,而第一个选择是第二个选项? (第一个?= 1:两个结果,第一个?= 0:一个结果,因为第一个?的最后一个结果仍保存在列表中)

要解决此问题,请使用list.copy()。这样会将列表的副本传递到fill(),从而使原始列表保持原样。

具有.copy()和其他较小修改的完整代码:

anslist = []
def fill(inp):
    if inp.count("?") == 0:
        print(inp, "WAS ADDED")
        anslist.append(inp)
        return

    for a in range(len(inp)):  # range(0, x) is equivalent to range(x); try to limit global variables
        if inp[a] == "?":
            inp[a] = 1
            fill(inp.copy())  # list is mutable
            inp[a] = 0
            fill(inp.copy())  # see above
            return
user_input = list(input())
fill(user_input)
print(anslist)

答案 4 :(得分:1)

使用itertools.product采样python代码(您可以使用等效的实现,但这很好)

from itertools import product

def generate_combinations(inp):
   count = 0 
   for a in range(0, len(inp)):
      if inp[a] == "?": count += 1
   combinations = []
   for comb in product(range(2), repeat=count):
      pos = 0
      cinp = inp[:]
      for a in range(len(cinp)):
         if cinp[a] == '?':
           cinp[a] = str(comb[pos])
           pos += 1
       combinations.append(cinp)
    return combinations

用法示例:

print(generate_combinations('?01?1'))