python中的Pascal三角形而不使用任何循环

时间:2018-10-26 03:39:11

标签: python recursion pascals-triangle

所以我试图实现一个帕斯卡三角形,该三角形在python中产生以下结果:

pascal_triangle(5) prints:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1

问题是我试图在不使用任何类型的循环的情况下执行此操作,但无法弄清楚该如何执行。任何帮助,将不胜感激。比你。

这是我到目前为止所拥有的:

   def factorial(x):
            if x == 0:
                    return 1
            else: 
                    x * factorial(x - 1)

    def pascal_triangle(n):`

已更新:

print_pascal_line(r):
    if r == 0:
        return 1
    else:
        R = print_pascal_line(r-1)
        return 1 +

6 个答案:

答案 0 :(得分:1)

首先创建一个打印帕斯卡三角形的第N行的方法,我建议您使用组合,而不是使用阶乘来手动计算每行中的值,这样会更加有效。假设此方法称为print_pascal_line(接收整数,即行号)。

那么你就拥有:

def pascal_triangle(n):
    aux(0, n)


def aux(current_line, n):
    if current_line < n):
        print_pascal_line(current_line)
        aux(current_line + 1, n)

答案 1 :(得分:1)

使用binomial coefficient评估Pascal三角形的每个元素。此值通常称为nCr,它询问“给定的n个项目,您可以C选择多少种r的方式?”

例如,使用项目abc。我们可以通过多种方式创建以下尺寸的组合?

     
  1. 只有一种方法可以选择0个项目:{}
  2.  
  3. 有3种可能的组合:{a}{b}{c}
  4.  
  5. 再次使用3种方式:{a, b}{a, c}{b, c}
  6.  
  7. {a, b, c}

您会知道,这恰好是Pascal三角形的3 *级水平:1 3 3 1!事实证明,我们可以在每个级别上使用它。

0: nCr(0, 0)
1: nCr(1, 0) nCr(1, 1)
2: nCr(2, 0) nCr(2, 1) nCr(2, 2)
3: nCr(3, 0) nCr(3, 1) nCr(3, 2) nCr(3, 3)
etc
etc

那么,我们如何为此编码?查看this answer,我们得到了nCr函数

In [454]: import functools as ft

In [455]: import operator as op

In [456]: def nCr(n, r):
     ...:     r = min(r, n-r)
     ...:     numer = ft.reduce(op.mul, range(n, n - r, -1), 1)
     ...:     denom = ft.reduce(op.mul, range(1, r + 1), 1)
     ...:     return numer // denom
     ...:

最后,让我们创建一个递归函数,将其结合在一起。

In [457]: def pascal(n):
     ...:     if n >= 1:
     ...:         pascal(n - 1)
     ...:         print(' '.join(str(nCr(n - 1, r)) for r in range(n)))
     ...:

In [463]: pascal(5)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1

从技术上讲,这应该是pascal(4),因为Pascal的三角形是零索引*,但是我只是按照OP的要求进行操作。如果我们要更改此设置,可以将pascal函数更改为

In [468]: def pascal(n):
     ...:     if n >= 0:
     ...:         pascal(n - 1)
     ...:         print(' '.join(str(nCr(n, r)) for r in range(n + 1)))
     ...:

答案 2 :(得分:1)

纯递归解决方案(无循环,无赋值,无外部模块,只有sum使用的python函数也可以避免)。此代码可以轻松地翻译为LISP家庭语言。

def pascal_line(n):
    def nextline(thisline):
        if thisline == []:
            return []
        else:
            return [sum(thisline[:2])] + nextline(thisline[1:])
    if n == 1:
        return [1]
    elif n == 2:
        return [1, 1]
    else:
        return [1]+nextline(pascal_line(n-1))

def pascal_triangle(n):
    def printline(m):
        if m <= n:
            print(*pascal_line(m))
            printline(m+1)
    return printline(1)

pascal_triangle(6)
# output =>
# 1
# 1 1
# 1 2 1
# 1 3 3 1
# 1 4 6 4 1
# 1 5 10 10 5 1

内部函数nextline会基于当前行递归地导出Pascal三角形中的下一行(不带前导1)。

函数pascal_line通过用(n-1)行(其递归调用)nextline来得出帕斯卡三角形中的 n 行自己以前的解决方案)。

函数pascal_triangle通过递归调用pascal_line来打印出Pascal三角形中的行。

三个递归函数一起很好地说明了递归方法的典型划分和征服性质。

答案 3 :(得分:0)

怎么样?

Declare
  a number := 5; b number := null; c number := 10;
Begin
  if a > b AND a < c then
    a := c * a;
  end if;
End;

答案 4 :(得分:0)

我在here之前回答了这个问题。请点击链接以获取有关如何设计像这样的递归函数的说明。

def pairs (xs):
  if 2 > len(xs):
    return []
  else:
    return [xs[0:2]] + pairs(xs[1:])

def pascal (n):
  def compute (prev):
    return [1] + [x + y for (x,y) in pairs(prev)] + [1]
  def aux (m, prev):
    if (m > n):
      return []
    else:
      return [prev] + aux(m + 1, compute(prev))
  return aux(1, [1])

for line in pascal(5):
  print(line)
# [1]
# [1, 1]
# [1, 2, 1]
# [1, 3, 3, 1]
# [1, 4, 6, 4, 1]

上面,我们在三个地方创建了一个新的[1]单例;其中两个是compute循环的一部分。我们应该创建一次并重用它。

def pascal (n):
  one = [1]
  def compute (prev):
    return one + [x + y for (x,y) in pairs(prev)] + one
  def aux (m, prev):
    if (m > n):
      return []
    else:
      return [prev] + aux(m + 1, compute(prev))
  return aux(1, one)

我可能建议的最后一项改进是使用生成器,而不是急切地返回所有行

def pascal (n):
  one = [1]
  def compute (prev):
    return one + [x + y for (x,y) in pairs(prev)] + one
  def aux (m, prev):
    if (m > n):
      return
    else:
      yield prev
      yield from aux(m + 1, compute(prev))
  yield from aux(1, one)

现在,由于消耗了输出,因此可以延迟计算输出。但是,如果一次全部需要,可以使用list

list(pascal(5))
# [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]]

答案 5 :(得分:0)

一种更简单的递归解决方案,它使用数学来构造没有任何隐藏循环的三角形:

def pascal(n, row=0):

    def pascal_row(numerator, denominator=1, number=1):
        if numerator > 0:
            number = number * numerator // denominator
            return [number, *pascal_row(numerator - 1, denominator + 1, number)]

        return []

    if row < n:
        return [[1, *pascal_row(row)], *pascal(n, row + 1)]

    return []

print(*pascal(10), sep='\n')

输出

% python3 test.py
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
%