确定所有翻转硬币的组合,而不使用" itertools.product"

时间:2018-04-08 14:21:32

标签: python-3.x recursion lambda probability itertools

我在论坛上发过类似帖子,但他们都建议使用itertools.product,但我想知道是否可以在不使用它的情况下解决。

我想打印N个硬币的所有结果组合。如果事先知道N,则可以这样做。所以嵌套循环的数量只是N.但是如果N必须动态确定(input()函数),那么我就不能在代码中实现它了。用简单的英语很容易想象for循环的数量与N成正比,但我该如何实现呢?我必须使用lambda或递归吗?以下是N = 4的示例代码。

results = ["H", "T"]
outcomes = []
for l1 in results:
    for l2 in results:
        for l3 in results:
            for l4 in results:
                outcomes.append(l1+l2+l3+l4)

for o in outcomes:
    print(o)  

提前致谢。

1 个答案:

答案 0 :(得分:3)

DIY与发电机

这是在不使用内置功能的情况下计算product列表的一种方法

def product (*iters):
  def loop (prod, first = [], *rest):
    if not rest:
      for x in first:
        yield prod + (x,)
    else:
      for x in first:
        yield from loop (prod + (x,), *rest)
  yield from loop ((), *iters)

for prod in product ("ab", "xyz"):
  print (prod)

# ('a', 'x')
# ('a', 'y')
# ('a', 'z')
# ('b', 'x')
# ('b', 'y')
# ('b', 'z')

在python中,我们可以使用list构造函数收集列表中生成器的输出。请注意,我们还可以计算两个以上输入的乘积,如下所示

print (list (product ("+-", "ab", "xyz")))
# [ ('+', 'a', 'x')
# , ('+', 'a', 'y')
# , ('+', 'a', 'z')
# , ('+', 'b', 'x')
# , ('+', 'b', 'y')
# , ('+', 'b', 'z')
# , ('-', 'a', 'x')
# , ('-', 'a', 'y')
# , ('-', 'a', 'z')
# , ('-', 'b', 'x')
# , ('-', 'b', 'y')
# , ('-', 'b', 'z')
# ]

由于product接受 iterables 的列表,因此可以在产品中使用任何可迭代的输入。它们甚至可以混合,如下所示

print (list (product (['@', '%'], range (2), "xy")))
# [ ('@', 0, 'x')
# , ('@', 0, 'y')
# , ('@', 1, 'x')
# , ('@', 1, 'y')
# , ('%', 0, 'x')
# , ('%', 0, 'y')
# , ('%', 1, 'x')
# , ('%', 1, 'y')
# ]

由于product被定义为生成器,因此即使编写更复杂的程序,我们也可以获得很大的灵活性。考虑这个程序,找到由整数组成的直角三角形Pythagorean triple。另请注意,product允许您重复可迭代作为输入,如下面的product (r, r, r)所示

def is_triple (a, b, c):
  return a * a + b * b == c * c

def solver (n):
  r = range (1, n)
  for p in product (r, r, r):
    if is_triple (*p):
      yield p

print (list (solver (20)))
# (3, 4, 5)
# (4, 3, 5)
# (5, 12, 13)
# (6, 8, 10)
# (8, 6, 10)
# (8, 15, 17)
# (9, 12, 15)
# (12, 5, 13)
# (12, 9, 15)
# (15, 8, 17)

现在很容易实现你的掷硬币计划。

def toss_coins (n):
  sides = [ 'H', 'T' ]
  coins = [ sides ] * n
  yield from product (*coins)

print (list (toss_coins (2)))
# [ ('H', 'H'), ('H', 'T'), ('T', 'H'), ('T', 'T') ]

print (list (toss_coins (3)))
# [ ('H', 'H', 'H'), ('H', 'H', 'T'), ('H', 'T', 'H'), ('H', 'T', 'T'), ('T', 'H', 'H'), ('T', 'H', 'T'), ('T', 'T', 'H'), ('T', 'T', 'T') ]

没有发电机

但是生成器是一种非常高级的语言特性,我们想知道如何使用纯递归来表示productproduct以下def map (f, lst): if not lst: return [] else: first, *rest = lst return [ f (first ) ] + map (f, rest) def flat_map (f, lst): if not lst: return [] else: first, *rest = lst return f (first) + flat_map (f, rest) def product (*iters): def loop (acc, iters): if not iters: return acc else: first, *rest = iters return flat_map (lambda c: map (lambda x: [x] + c, first), loop (acc, rest)) return loop ([[]], iters) 重新实现,不使用生成器,现在返回一个包含所有计算子产品的填充数组

yield

我们现在可以跳过您计划中的listdef toss_coins (n): sides = [ 'H', 'T' ] coins = [ sides ] * n return product (*coins) print (toss_coins (2)) # [('H', 'H'), ('H', 'T'), ('T', 'H'), ('T', 'T')] print (toss_coins (3)) # [('H', 'H', 'H'), ('H', 'H', 'T'), ('H', 'T', 'H'), ('H', 'T', 'T'), ('T', 'H', 'H'), ('T', 'H', 'T'), ('T', 'T', 'H'), ('T', 'T', 'T')] 来电

map

上面,我们定义flat_mapreduce尽可能少的依赖关系,但每个实现中只有一个细微的区别。下面,我们将每个代表为 fold (使用map),以便我们更容易地看到语义差异。另请注意,Python包含自己的reducefunctools版本(def concat (xs, ys): return xs + ys def append (xs, x): return xs + [ x ] def reduce (f, init, lst): if not lst: return init else: first, *rest = lst return reduce (f, f (init, first), rest) def map_reduce (m, r): return lambda acc, x: r (acc, m (x)) def map (f, lst): return reduce (map_reduce (f, append), [], lst) def flat_map (f, lst): return reduce (map_reduce (f, concat), [], lst) def product (*iters): # this stays the same ),与此处提供的版本略有不同。

String uint64ToString(uint64_t input) {
  String result = "";
  uint8_t base = 10;

  do {
    char c = input % base;
    input /= base;

    if (c < 10)
      c +='0';
    else
      c += 'A' - 10;
    result = c + result;
  } while (input);
  return result;
}