views:

1639

answers:

21

Generate a list of lists (or print, I don't mind) a Pascal's Triangle of size N with the least lines of code possible!

Here goes my attempt (118 characters in python 2.6 using a trick):

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)]

Explanation:

  • the first element of the list comprehension (when the length is 0) is [1]
  • the next elements are obtained the following way:
  • take the previous list and make two lists, one padded with a 0 at the beginning and the other at the end.
    • e.g. for the 2nd step, we take [1] and make [0,1] and [1,0]
  • sum the two new lists element by element
    • e.g. we make a new list [(0,1),(1,0)] and map with sum.
  • repeat n times and that's all.

usage (with pretty printing, actually out of the 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)))

output:

             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
+11  A: 

Haskell, 58 characters:

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

Output:

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

More readable:

-- # 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]
sth
Shorter: `r n=take(n+1)$iterate(\a->zipWith(+)(0:a)$a++[0])[1]`
ephemient
+2  A: 

Haskell, 164C with formatting:

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

Without formatting, 52C:

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

A more readable form of it:

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

And perl, 111C, no centering:

$n=<>;$p=' 1 ';for(1..$n){print"$p\n";$x=" ";while($p=~s/^(?= ?\d)(\d* ?)(\d* ?)/$2/){$x.=($1+$2)." ";}$p=$x;}
bdonlan
Needs `{-# LANGUAGE ParallelListComp #-}`, which IMO should count into your character totals... ouch.
ephemient
Or -fglasgow-exts on the command line... in any case, it can be written with zipWith using only one additional character
bdonlan
In that case, `zipWith(+)(0:l)$l++[0]` gets you that one character back :)
ephemient
Nice one, updated :)
bdonlan
+15  A: 

K (Wikipedia), 15 characters:

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

Example output:

  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)

It's also easily explained:

p:{x {+':x,0} \ 1}
   ^ ^------^ ^ ^
   A    B     C D
  • p is a function taking an implicit parameter x.

  • p unfolds (C) an anonymous function (B) x times (A) starting at 1 (D).

  • The anonymous function simply takes a list x, appends 0 and returns a result by adding (+) each adjacent pair (':) of values: so e.g. starting with (1 2 1), it'll produce (1 2 1 0), add pairs (1 1+2 2+1 1+0), giving (1 3 3 1).


Update: Adapted to K4, which shaves off another two characters. For reference, here's the original K3 version:

p:{x{+':0,x,0}\1}
earl
Wonderful! I have strong doubts that is going to be anything shorter than this.
Ionuț G. Stan
A: 

The following is just a Scala function returning a List[List[Int]]. No pretty printing or anything. Any suggested improvements? (I know it's inefficient, but that's not the main challenge now, is it?). 145 C.

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(_))}

Or perhaps:

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(_))
}

(I'm a Scala noob, so please be nice to me :D )

André Laszlo
+6  A: 

Python: 75 characters

def G(n):R=[[1]];exec"R+=[map(sum,zip(R[-1]+[0],[0]+R[-1]))];"*~-n;return R
Triptych
nice one, with this you don't need the locals trick :-)
fortran
nice use of single space indentation to save a few characters
Jared Updike
+9  A: 

F#: 81 chars

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

Explanation: I'm too lazy to be as clever as the Haskell and K programmers, so I took the straight forward route: each element in Pascal's triangle can be uniquely identified using a row n and col k, where the value of each element is n!/(k! (n-k)!.

Juliet
+10  A: 

69C in C:

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;}

Use it like so:

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;
}
caf
You're cheating here! :p the function just computes 1 row, you should include in your character count the code for generating in memory (or printing, whichever is shorter/easier for you) the whole triangle
fortran
Hmm? No it doesn't, the function fills out the left-hand-side of the array that it's passed with the entire triangle.
caf
+1  A: 

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

test:

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>
Andrew Y
+1  A: 

I wrote this C++ version a few years ago:

#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));}

Skizz

Skizz
+13  A: 

J, another language in the APL family, 9 characters:

p=:!/~@i.

This uses J's builtin "combinations" verb.

Output:

   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
earl
I wonder how much work it would take to get rid of the 0's. Also, you might want to transpose the result.
Jimmy
earl
A shorter way to strip the leading zeros and print it out nicely: `p=:":@(!~i.@>:)"0@i.`
ephemient
+1  A: 

Another try, in prolog (I'm practising xD), not too short, just 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).

explanation:

  • s = sum lists element by element
  • l = the Nth row of the triangle
  • p = the whole triangle of size N
fortran
A: 

a Perl version (139 chars 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";
}

output starts from 1 2 1

pavium
changed the code format :-)
fortran
(btw, you can remove your other answer now :p)
fortran
I will when I figure out how. (I'm new here and still reading the FAQs)
pavium
A: 

And in the previous Perl version, the two naked $ signs following the push @q should be $_

and the initial 'my' could be dispensed with since we're playing golf.

+2  A: 

Scheme — compressed version of 100 characters

(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)))
This is it in a more readable form (269 characters):
(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)))
Cirno de Bergerac
+2  A: 

VBA/VB6 (392 chars w/ formatting)

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
DJ
A: 

PHP, 115 chars

$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;}

If you don't care whether print_r() displays the output array in the correct order, you can shave it to 113 chars like

$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];}
Hugh Bothwell
A: 

Another python solution, that could be much shorter if the builtin functions had shorter names... 106 characters.

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)]
fortran
A: 

Perl, 63 characters:

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

Shorter prolog version (112 instead of 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).
Jerome
good one, now I have to try to understand it xD
fortran
A: 

My attempt in C++ (378c). Not anywhere near as good as the rest of the posts.. but I'm proud of myself for coming up with a solution on my own =)

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";
  }
}
Stephen Brown
the purpose of a code golf is to make short programs xD try at least removing the superfluous whitespace :-p
fortran
I removed most of the whitespace and made other minor changes.
Stephen Brown
+1  A: 

VBA, 122 chars:

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
Joel