生成连续成员之间任意距离的序列

时间:2017-07-31 21:56:19

标签: python recursion

我正在尝试编写一个函数,它将输入长度L和距离D(两个整数> 1)并输出符合以下参数的所有可能序列:

  1. 以数字1
  2. 开头
  3. 拥有L元素
  4. 每个元素与以下元素之间的距离为1D
  5. 因此,对于L = 4D = 2,可能的序列是:

    1 2 3 4   (distance of 1 between each consecutive element)  
    1 2 3 5  
    1 2 4 5  
    1 2 4 6  
    1 3 4 5  
    1 3 4 6  
    1 3 5 6  
    1 3 5 7   (distance of 2 between each consecutive element)
    

    或者,对于L = 3D = 3,可能的顺序是:

    1 2 3   (distance of 1 between each consecutive element)  
    1 2 4  
    1 2 5  
    1 3 4  
    1 3 5   (distance of 2 between each consecutive element)  
    1 3 6  
    1 4 5  
    1 4 6  
    1 4 7   (distance of 3 between each consecutive element)
    

    通过手动编码其中的几个,可能的序列数似乎是D ** (L-1)。起初我只需要2\**7,并且128个序列并不难以手工创建。但是,我现在需要3**7,甚至可能需要更大的数量,所以我需要编写一个函数。

    Python是我正在学习的语言。递归似乎是这样做的方法,但我只是在简单的递归上练习,而且我仍然坚持写这个是多么精确。尽我所能,我需要一个在for循环中调用自身的函数。这有意义吗?同样结构化的功能的方向也将受到高度赞赏。

3 个答案:

答案 0 :(得分:2)

您可以使用itertools.productitertools.accumulate来实现所需的功能:

import itertools

def f(l, d):
    for sub in itertools.product(range(1, d+1), repeat=l-1):
        yield tuple(itertools.accumulate((1,) + sub))

for l in f(4, 2):
    print(l)

(1, 2, 3, 4)
(1, 2, 3, 5)
(1, 2, 4, 5)
(1, 2, 4, 6)
(1, 3, 4, 5)
(1, 3, 4, 6)
(1, 3, 5, 6)
(1, 3, 5, 7)

答案 1 :(得分:0)

这是一个快速而肮脏的实现

def gen_seq(D, L):
    for uple in itertools.product(range(1, D+1), repeat=L-1):
        yield tuple(numpy.cumsum((1,) + uple))

答案 2 :(得分:0)

递归的关键不仅在于以递归的方式形式化代码,而且还以递归的方式定位你的思想。仔细比较长度3和长度4的结果与距离2。

一个。长度3

1 2 3
1 2 4
1 3 4
1 3 5

湾长度4

1 2 3 | 4
1 2 3 | 5
1 2 4 | 5
1 2 4 | 6
1 3 4 | 5
1 3 4 | 6
1 3 5 | 6
1 3 5 | 7

在长度为4的结果中,|的右侧只是长度为3的结果。这意味着N长度的结果可以从N-1长度导出。

假设我们已经有一个解决k-1长度solve_part(k-1)的过程,通过将k-1的结果扩展到下一个长度k next_len(solve_part(k-1) ...),这个问题自然会以递归的方式解决。

import itertools

def flatmap(func, *iterable):
    return itertools.chain.from_iterable(map(func, *iterable))

def next_distance(eachlist, D):
  return map(lambda eachdis: eachlist + [eachlist[-1] + eachdis], range(1,D+1))

def next_len(L,D):
  return flatmap(lambda eachlist: next_distance(eachlist, D), L)

def solve_it(leng,dis):
  def solve_part(k):
    if k == 0:
      return [[]]
    elif k == 1:
      return [[1]]
    else:
      return next_len(solve_part(k-1),dis)
  return solve_part(leng)

result=solve_it(4,2)

print([[i for i in j] for j in result])