【问题标题】:Combinations (Again)组合(再次)
【发布时间】:2018-08-20 16:24:38
【问题描述】:

除了一些函数式编程和数学算法实现外,我是编程方面的新手。无论如何,我开始了在线编程课程并提出了这个问题。给定整数 A 和 B 按字母顺序返回数组 [1,..,A] 中 B 元素的所有可能组合 (ie [[1,...,B] , [1,...B-1, B+1], [1,..,B-1,A],...]))。现在我知道库 itertools 并且我已经看到了一些解决方案,但是我想自己解决它,因为一位朋友告诉我它是通过递归完成的。

def combinations(A,B):
# Three ideas:

# Combination using recursion should look as follows:
# combinations[1,2,3,4,5]
#          = [[[1] + combinations[2,3,4,5]], 
#            [[2] + combinations[3,4,5]]...].
# Terminating condition combination[x] = [x]

# Another idea: print all binary permutations
# with fixed B numbers of ones. Binary combin-
# ations (1,0,0) for A = 3, B = 1 are [(1,0,0),
# (0,1,0), (0,0,1)] Cartesian product of these
# with [1,2,3] would give [1] [2] [3] after rem-
# oving zeroes. In this cas the recursion should
# look as follows: perm([1,0,0]) = [[1, perm([0,
# 0])], [0, perm([1,0])]] In this case terminat-   
# ing condition should looks as : perm(x) = x.

# Simplest idea: for element A, either add to
# some array in helper or not. helper(A,B) if value is A appended
# helper(A-1,B-1) and append B-1 values, if A value is not appended
# helper(A-1,B) until now append A or when A==B 
# append A and B till array filled. B == 0 helper.append([])

array = [[]]
def helper(array,A,B):

    if not B:
        array.append([])
        # return ??
    for i in range(0,1):
        if i or A == B: # A == B means add elements until B empty.
            array[-1].append(A)
             #something helper(A-1,B-1)
            return # ?? return 
        else:
            #something helper(A-1,B)
            return # ?? return #don't append value A to array
    return array
array = helper(array,A,B)

至少有人可以解释如何实施“简单”的解决方案吗?我真的很喜欢这个想法,并且想了解如何实现我自己的递归。谢谢!

【问题讨论】:

  • 错误的论坛 - 我们关心带有特定问题和特定答案的损坏代码。不是提供教程或解释基本代码。阅读How to debug small programs (#1) 并调试代码,直到你摸索为止。请再次查看how to ask 和on-topic,如果您有任何问题,请将您的代码提供为mvce。
  • 值得注意的是,itertools.combinations 的文档包含做同样事情的 python 代码。

标签: python-3.x recursion combinations permutation


【解决方案1】:

至少有人可以解释如何实施“简单”的解决方案吗?

“简单”是主观的,但我发现combinations 的以下实现很容易理解。延续传递风格使我们可以写出这样的一厢情愿

combinations (some_list, lambda result: print (result))
# some output ...

其中result 是从some_list 生成的有序组合。使用这种风格,我们可以像你想象的那样编写程序

# combinations [1,2,3,4,5]
# = [ [1] + combinations[2,3,4,5] ]
#   , [2] + combinations[3,4,5]
#   , ...
#   ]

def combinations (l, cont = ???):
  ???
  head, *tail = l
  return combinations (tail, lambda result:
                               cont ([ [ head ] + r for r in result ] + result))

我们添加了一个条件来确保我们不会解构空列表l。这是我们返回空结果[ [] ] 的基本情况 - bold

的变化
def combinations (l, cont = ???):
  if not l:
    return cont ([ [] ])
  else:
    head, *tail = l
    return combinations (tail, lambda result:
                                 cont ([ [ head ] + r for r in result

最后,添加一个默认的延续cont = identity,这样我们的函数就可以使用直接风格或延续传递风格 - 粗体

的变化
def identity (x):
  return x

def combinations (l, cont = identity):
  if not l:
    return cont ([ [] ])
  else:
    head, *tail = l
    return combinations (tail, lambda result:
                                 cont ([ [ head ] + r for r in result ] + result))

现在就在这里

def identity (x):
  return x

def combinations (l, cont = identity):
  if not l:
    return cont ([ [] ])
  else:
    head, *tail = l
    return combinations (tail, lambda result:
                                 cont ([ [ head ] + r for r in result ] + result))


print (combinations (range (0)))
# [[]]

print (combinations (range (1)))
# [[0, []]

print (combinations (range (2)))
# [[0, 1], [0], [1], []]

print (combinations (range (3)))
# [[0, 1, 2], [0, 1], [0, 2], [0], [1, 2], [1], [2], []]

我们在上面调用print (combinations (list)),但是因为我们使用延续传递风格定义了我们的函数,所以我们也可以使用延续从外部调用它,即combinations (list, print)

combinations (range (4), print)
# [ [0, 1, 2, 3]
# , [0, 1, 2]
# , [0, 1, 3]
# , [0, 1]
# , [0, 2, 3]
# , [0, 2]
# , [0, 3]
# , [0]
# , [1, 2, 3]
# , [1, 2]
# , [1, 3]
# , [1]
# , [2, 3]
# , [2]
# , [3]
# , []
# ]

print (combinations (range (4), len))
# 16

【讨论】:

  • 作为一个函数式程序员,我想你会喜欢这个答案的。作为一名 python 程序员,我想你会发现 python 社区更喜欢一种命令式的方法。
  • 哇,我发现它的工作原理令人震惊。谢谢你。我知道你解决的问题。我想在上一个问题之后转到这个问题,它只要求所有具有固定长度的组合。像 list(filter(lambda: x: len(x) == 2, combination(range(4), cont = identity))) ??我称之为最后一个最简单的,因为我实际上已经让它工作了,只是它给了我一些元素。再次感谢你:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-25
  • 1970-01-01
  • 1970-01-01
  • 2018-12-28
  • 1970-01-01
  • 2018-07-05
  • 2013-07-24
相关资源
最近更新 更多