首页 文章

Code-golf:生成帕斯卡的三角形

提问于
浏览
37

生成一个列表列表(或打印,我不介意),其大小为 N,且行数最少的帕斯卡的三角形

这是我的尝试(在 python 2.6 **中使用一个恶作剧的 118 个字符):

c,z,k=locals,[0],'_[1]'
p=lambda n:[len(c()[k])and map(sum,zip(z+c()[k][-1],c()[k][-1]+z))or[1]for _ in range(n)]

说明:

  • 列表理解的第一个元素(长度为 0 时)是[1]

  • 接下来的元素是通过以下方式获得的:

  • 取上一个列表,然后创建两个列表,一个列表的开头以 0 填充,另一个列表的末尾填充。

  • e.g. 对于第二步,我们取[1]并设为[0,1][1,0]

  • 将两个新列表逐个元素相加

  • e.g. 我们创建一个新列表[(0,1),(1,0)]并映射总和。

  • 重复 n 次,仅此而已。

用法(打印精美,实际上不在 code-golf xD 中):

result = p(10)
lines = [" ".join(map(str, x)) for x in result]
for i in lines:
    print i.center(max(map(len, lines)))

输出:

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

23 回答

  • 3

    另一个刺(python):

    def pascals_triangle(n):
        x=[[1]]
        for i in range(n-1):
            x.append(list(map(sum,zip([0]+x[-1],x[-1]+[0]))))
        return x
    
  • 0

    旧线程,但是我写这是为了回应今天在另一个论坛上的挑战:

    def pascals_triangle(n):
        x=[[1]]
        for i in range(n-1):
            x.append([sum(i) for i in zip([0]+x[-1],x[-1]+[0])])
        return x
    
    for x in pascals_triangle(5):
        print('{0:^16}'.format(x))
    
          [1]       
         [1, 1]     
       [1, 2, 1]    
      [1, 3, 3, 1]  
    [1, 4, 6, 4, 1]
    
  • 15

    J,APL 系列的另一种语言,9 个字符:

    p=:!/~@i.
    

    它使用 J 的内置“组合”动词。

    输出:

    p 10
    1 1 1 1 1  1  1  1  1   1
    0 1 2 3 4  5  6  7  8   9
    0 0 1 3 6 10 15 21 28  36
    0 0 0 1 4 10 20 35 56  84
    0 0 0 0 1  5 15 35 70 126
    0 0 0 0 0  1  6 21 56 126
    0 0 0 0 0  0  1  7 28  84
    0 0 0 0 0  0  0  1  8  36
    0 0 0 0 0  0  0  0  1   9
    0 0 0 0 0  0  0  0  0   1
    
  • 17

    K(维基百科),15 个字符:

    p:{x{+':x,0}\1}
    

    输出示例:

    p 10
    (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
     1 10 45 120 210 252 210 120 45 10 1)
    

    也很容易解释:

    p:{x {+':x,0} \ 1}
       ^ ^------^ ^ ^
       A    B     C D
    
    • p是采用隐式参数x的函数。

    • p展开(C)匿名函数(B)x次(A)从1(D)开始。

    • 匿名函数仅获取列表x,附加0并通过将相邻的每个值对(':)相加(+)来返回结果:e.g. 从(1 2 1)开始,它将产生(1 2 1 0),添加对(1 1+2 2+1 1+0),得到(1 3 3 1)


    更新:改编为 K4,可删除另外两个字符。作为参考,这是原始的 K3 版本:

    p:{x{+':0,x,0}\1}
    
  • 14

    Haskell,58 个字符:

    r 0=[1]
    r(n+1)=zipWith(+)(0:r n)$r n++[0]
    p n=map r[0..n]
    

    输出:

    *Main> p 5
    [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1],[1,5,10,10,5,1]]
    

    更具可读性:

    -- # row 0 is just [1]
    row 0     = [1]
    -- # row (n+1) is calculated from the previous row
    row (n+1) = zipWith (+) ([0] ++ row n) (row n ++ [0])
    -- # use that for a list of the first n+1 rows
    pascal n  = map row [0..n]
    
  • 12

    C 中的 69C:

    f(int*t){int*l=t+*t,*p=t,r=*t,j=0;for(*t=1;l<t+r*r;j=*p++)*l++=j+*p;}
    

    像这样使用它:

    int main()
    {
    #define N 10
        int i, j;
        int t[N*N] = {N};
    
        f(t);
    
        for (i = 0; i < N; i++)
        {
            for (j = 0; j <= i; j++)
                printf("%d ", t[i*N + j]);
            putchar('\n');
        }
        return 0;
    }
    
  • 9

    F#:81 个字符

    let f=bigint.Factorial
    let p x=[for n in 0I..x->[for k in 0I..n->f n/f k/f(n-k)]]
    

    说明:我太懒了,不能像 Haskell 和 K 程序员一样聪明,所以我采取了直接的方法:Pascal 三角形中的每个元素都可以使用 n 行和 col k 唯一地标识,其中每个元素的值为n!/(k! (n-k)!

  • 7

    Python:75 个字符

    def G(n):R=[[1]];exec"R+=[map(sum,zip(R[-1]+[0],[0]+R[-1]))];"*~-n;return R
    
  • 4

    较短的序言版本(从 112 代替 164):

    n([X],[X]).
    n([H,I|T],[A|B]):-n([I|T],B),A is H+I.
    p(0,[[1]]):-!.
    p(N,[R,S|T]):-O is N-1,p(O,[S|T]),n([0|S],R).
    
  • 2

    Haskell,164C,格式为:

    i l=zipWith(+)(0:l)$l++[0]
    fp=map (concatMap$(' ':).show)f$iterate i[1]
    c n l=if(length l<n)then c n$' ':l++" "else l
    cl l=map(c(length$last l))l
    pt n=cl$take n fp
    

    不格式化,52C:

    i l=zipWith(+)(0:l)$l++[0]
    pt n=take n$iterate i[1]
    

    更具可读性的形式:

    iterateStep row = zipWith (+) (0:row) (row++[0])
    pascalsTriangle n = take n $ iterate iterateStep [1]
    
    -- For the formatted version, we reduce the number of rows at the final step:
    formatRow r = concatMap (\l -> ' ':(show l)) r
    formattedLines = map formatRow $ iterate iterateStep [1]
    centerTo width line =
        if length line < width
            then centerTo width (" " ++ line ++ " ")
            else line
    centerLines lines = map (centerTo (length $ last lines)) lines
    pascalsTriangle n = centerLines $ take n formattedLines
    

    Perl,111C,不居中:

    $n=<>;$p=' 1 ';for(1..$n){print"$p\n";$x=" ";while($p=~s/^(?= ?\d)(\d* ?)(\d* ?)/$2/){$x.=($1+$2)." ";}$p=$x;}
    
  • 2

    方案-100 个字符的压缩版本

    (define(P h)(define(l i r)(if(> i h)'()(cons r(l(1+ i)(map +(cons 0 r)(append r '(0))))))(l 1 '(1)))
    

    它以更易读的形式显示(269 个字符):

    (define (pascal height)
      (define (next-row row)
        (map +
             (cons 0 row)
             (append row '(0))))
    
      (define (iter i row)
        (if (> i height)
            '()
            (cons row
                  (iter (1+ i)
                        (next-row row)))))
    
      (iter 1 '(1)))
    
  • 2

    VBA/VB6(392 个字符,带格式)

    Public Function PascalsTriangle(ByVal pRows As Integer)
    
    Dim iRow As Integer
    Dim iCol As Integer
    Dim lValue As Long
    Dim sLine As String
    
      For iRow = 1 To pRows
        sLine = ""
        For iCol = 1 To iRow
          If iCol = 1 Then
            lValue = 1
          Else
            lValue = lValue * (iRow - iCol + 1) / (iCol - 1)
          End If
          sLine = sLine & " " & lValue
        Next
        Debug.Print sLine
      Next
    
    End Function
    
  • 2

    PHP 100 个字符

    $v[]=1;while($a<34){echo join(" ",$v)."\n";$a++;for($k=0;$k<=$a;$k++)$t[$k]=$v[$k-1]+$v[$k];$v=$t;}
    
  • 1

    Ruby,83c:

    def p(n);n>0?(m=p(n-1);k=m.last;m+[([0]+k).zip(k+[0]).map{|x|x[0]+x[1]}]):[[1]];end
    

    测试:

    irb(main):001:0> def p(n);n>0?(m=p(n-1);k=m.last;m+[([0]+k).zip(k+[0]).map{|x|x[0]+x[1]}]):[[1]];end
    => nil
    irb(main):002:0> p(5)
    => [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1], [1, 5, 10, 10, 5, 1]]
    irb(main):003:0>
    
  • 1

    另一个python解决方案,如果内置函数的名称较短,则可能会更短... 106字符。

    from itertools import*
    r=range
    p=lambda n:[[len(list(combinations(r(i),j)))for j in r(i+1)]for i in r(n)]
    
  • 1

    另一个尝试,在prolog(我正在练习 xD)中,不太短,只有 164c:

    s([],[],[]).
    s([H|T],[J|U],[K|V]):-s(T,U,V),K is H+J.
    l([1],0).
    l(P,N):-M is N-1,l(A,M),append(A,[0],B),s(B,[0|A],P).
    p([],-1).
    p([H|T],N):-M is N-1,l(H,N),p(T,M).
    

    说明:

    • s =总和逐元素列出

    • l =三角形的第 N 行

    • p =大小为 N 的整个三角形

  • 1

    VBA,122 个字符:

    Sub p(n)
    For r = 1 To n
    l = "1"
    v = 1
    For c = 1 To r - 1
    v = v / c * (r - c)
    l = l & " " & v
    Next
    Debug.Print l
    Next
    End Sub
    
  • 1

    我几年前写了这个 C 版本:

    #include <iostream>
    int main(int,char**a){for(int b=0,c=0,d=0,e=0,f=0,g=0,h=0,i=0;b<atoi(a[1]);(d|f|h)>1?e*=d>1?--d:1,g*=f>1?--f:1,i*=h>1?--h:1:((std::cout<<(i*g?e/(i*g):1)<<" "?d=b+=c++==b?c=0,std::cout<<std::endl?1:0:0,h=d-(f=c):0),e=d,g=f,i=h));}
    
  • 0

    以下只是一个返回List[List[Int]]的 Scala 函数。没有漂亮的印刷或任何东西。有任何建议的改进吗? (我知道它的效率很低,但这不是现在的主要挑战,是吗?)。 145℃。

    def p(n: Int)={def h(n:Int):List[Int]=n match{case 1=>1::Nil;case _=>(0::h(n-1) zipAll(h(n-1),0,0)).map{n=>n._1+n._2}};(1 to n).toList.map(h(_))}
    

    也许:

    def pascal(n: Int) = {
      def helper(n: Int): List[Int] = n match {
        case 1 => 1 :: List()
        case _ => (0 :: helper(n-1) zipAll (helper(n-1),0,0)).map{ n => n._1 + n._2 }
      }
      (1 to n).toList.map(helper(_))
    }
    

    (我是 Scala 新手,所以请对我好:D)

  • 0

    Perl 版本(139 个字符 w/o shebang)

    @p = (1,1);
    while ($#p < 20) {
        @q =();
        $z = 0;
        push @p, 0;
        foreach (@p) {
            push @q, $_+$z;
            $z = $_
        }
        @p = @q;
        print "@p\n";
    }
    

    输出从 1 2 1 开始

  • 0

    PHP,115 个字符

    $t[][]=1;
    for($i=1;$i<$n;++$i){
    $t[$i][0]=1;
    for($j=1;$j<$i;++$j)$t[$i][$j]=$t[$i-1][$j-1]+$t[$i-1][$j];
    $t[$i][$i]=1;}
    

    如果您不关心 print_r()是否以正确的顺序显示输出数组,则可以将其剃除为 113 个字符,例如

    $t[][]=1;
    for($i=1;$i<$n;++$i){
    $t[$i][0]=$t[$i][$i]=1;
    for($j=1;$j<$i;++$j)$t[$i][$j]=$t[$i-1][$j-1]+$t[$i-1][$j];}
    
  • 0

    Perl,63 个字符:

    for(0..9){push@z,1;say"@z";@z=(1,map{$z[$_-1]+$z[$_]}(1..$#z))}
    
  • 0

    我在 C(378c)中的尝试。虽然没有其他文章那么好。.但是我为自己提出的=)解决方案而感到自豪

    int* pt(int n)
    {
      int s=n*(n+1)/2;
      int* t=new int[s];
    
      for(int i=0;i<n;++i)
        for(int j=0;j<=i;++j)
          t[i*n+j] = (!j || j==i) ? 1 : t[(i-1)*n+(j-1)] + t[(i-1)*n+j];
      return t;
    }
    
    int main()
    {
      int n,*t;
      std::cin>>n;
      t=pt(n);
    
      for(int i=0;i<n;++i)
      {
        for(int j=0;j<=i;j++)
          std::cout<<t[i*n+j]<<' ';
        std::cout<<"\n";
      }
    }
    

相关问题