【问题标题】:Going through all binary combinations with some numbers as "?"遍历所有二进制组合,其中一些数字为“?”
【发布时间】:2019-06-01 14:19:29
【问题描述】:

我必须生成给定字符串的所有可能的二进制表示,其中一些字符是“?”其他为 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 无法正常工作。我似乎无法弄清楚这一点。

【问题讨论】:

  • 使用 python itertools.product 为 all 生成 1 和 0 的所有组合?位置并一一分配给数组并推送到anslist
  • 如果你不想使用 itertools.product 你可以使用嵌套循环(对于固定数量的位置)或更一般的递归
  • 我不想使用内置工具。另外,我不知道元素的数量(=循环的数量),所以递归是要走的路。
  • @PatrickArtner 不,我是来学习的。

标签: python recursion binary


【解决方案1】:

a list 是一个可变 类型,这意味着您只有一个 列表,所有修改都在其中进行。这会导致您的第一个电话 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)

【讨论】:

    【解决方案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']
    

    【讨论】:

    • 这很好:)
    • 看到你的回答有多好,我想删除我的:D,但我很高兴听到这个消息 :)
    【解决方案3】:
    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 将我们的产品替换为我们的原始字符串,代替我们的问号

    这里是repl 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
    

    最后我们需要编写自己的自定义子程序

    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))
    

    【讨论】:

      【解决方案4】:

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

      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
      
      []
      >
      

      【讨论】:

        【解决方案5】:

        使用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'))
        

        【讨论】:

          猜你喜欢
          • 2019-03-18
          • 1970-01-01
          • 2011-09-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-03-21
          相关资源
          最近更新 更多