38

I would like to typeset the top part of Pascal's triangle. To get the triangle with the names of the binomial coefficients, i.e., {n \choose k}, I used the following code

\begin{tikzpicture}
\foreach \n in {0,...,4} {
  \foreach \k in {0,...,\n} {
    \node at (\k-\n/2,-\n) {${\n \choose \k}$};
  }
}
\end{tikzpicture}

The result is this enter image description here

Now I want to be equally lazy and do something like this for the values of the binomial coefficients, i.e., replace {\n \choose \k} in the node label with \CalculateBinomialCoefficient{\n}{\k} where \CalculateBinomialCoefficient is a hypothetical macro that calculates the binomial coefficient. Has anyone done something like that?

The result should look like this: enter image description here

2
  • The code in Triangle de Pascal could give you some ideas; note the use of the \FPpascal macro implemented in fp-pas.sty (part of the fp package). May 6 '11 at 0:49
  • 3
    For a better result I suggest to use the command \binom{a}{b} from the amsmath package instead of {a \choose b} for binomial coefficients
    – Spike
    May 6 '11 at 8:44
33

Here is a solution using TeX integer arithmetic. I am reusing counters defined by PGF in order to avoid having to declare new ones.

\documentclass{article}
\usepackage{tikz}

\makeatletter
\newcommand\binomialCoefficient[2]{%
    % Store values 
    \c@pgf@counta=#1% n
    \c@pgf@countb=#2% k
    %
    % Take advantage of symmetry if k > n - k
    \c@pgf@countc=\c@pgf@counta%
    \advance\c@pgf@countc by-\c@pgf@countb%
    \ifnum\c@pgf@countb>\c@pgf@countc%
        \c@pgf@countb=\c@pgf@countc%
    \fi%
    %
    % Recursively compute the coefficients
    \c@pgf@countc=1% will hold the result
    \c@pgf@countd=0% counter
    \pgfmathloop% c -> c*(n-i)/(i+1) for i=0,...,k-1
        \ifnum\c@pgf@countd<\c@pgf@countb%
        \multiply\c@pgf@countc by\c@pgf@counta%
        \advance\c@pgf@counta by-1%
        \advance\c@pgf@countd by1%
        \divide\c@pgf@countc by\c@pgf@countd%
    \repeatpgfmathloop%
    \the\c@pgf@countc%
}
\makeatother

\begin{document} 
\begin{tikzpicture}
\foreach \n in {0,...,15} {
  \foreach \k in {0,...,\n} {
    \node at (\k-\n/2,-\n) {$\binomialCoefficient{\n}{\k}$};
  }
}
\end{tikzpicture}

\end{document}

enter image description here

If you want, you can wrap \pgfmathdeclarefunction around that to have the function available in pgfmath (see Section 65 “Customizing the Mathematical Engine” in the manual (v2.10)).

2
  • Nice solution! It works up to the first 30 rows! May 6 '11 at 2:42
  • Is it easy to change this triangle to this one here with a slight change to the addiction $N=2R+L$?
    – hhh
    Feb 5 '15 at 2:45
30

From texample.net. The author is Paul Gaborit.

Triangle de Pascal

enter image description here

4
  • Such a pity this can't do more than the 16 rows shown here. Someone needs to write an arbitrary integer type for TikZ ;)
    – Christian
    Sep 22 '13 at 14:00
  • Is it easy to change this triangle to this one here with a slight change to the addiction $N=2R+L$?
    – hhh
    Feb 5 '15 at 2:49
  • Any idea how to draw parallel arrows but in reverse orientation? I'd like 2 arrows instead of one connecting the nodes.
    – Sigur
    Apr 14 '16 at 12:39
  • 1
    @Sigur I don't have enough time to study the code but you can ask the question to Paul Apr 14 '16 at 13:16
9

Second answer

The earlier answer used a macro computing individual binomial coefficients.

I now address the matter building row by row of the Pascal Triangle, as in the other answers.

For this as an exercise of translation I have taken an exact copy of the metapost code of @fpast's answer, and translated it into TeX. Up the the 34th row we can use TeX arithmetic. For simplicity I used \numexpr. Starting with the 34th row (actually there only the middle three coefficients exceeds 2^31-1) I use big integer arithmetic.

To organize the loops I use \xintFor from package xinttools. This package also defines \odef which does a definition + expansion and \oodef which does a definition + double expansion. They are used in the code together with various mixes of \numexpr, \dimexpr, \@namedef, @nameuse etc... pure TeX/LaTeX joys with its subtleties at times about where spaces are allowed or not (most spaces do not matter much as we are in a TikZ picture).

The code for the first 80 lines compile not too slowly (about 9 seconds on my laptop).

I only display the largest numbers of the triangle.

Notice that we are close to the TeX limits for the maximal dimension as each number is separated horizontally by 6cm from its neighbour.

The original metapost code of fpast is shown alongside its translation into TeX.

edit the code tested the line number to use only \numexpr for the first 33 lines (as only integers <2^31 are then evaluated) but actually doing all the computations with xint and not checking for the line number to decide to use \numexpr or xint is faster! (about 2% faster when computing 80 lines of the triangle). I thus comment out the conditionals.

\documentclass[12pt, tikz, border=5mm]{standalone}
\usepackage{tikz}
\usepackage{xint}
\usepackage{xinttools}
\makeatletter
\newdimen\X
\newdimen\Y
\def\PascalTriangle #1#2#3{% #1=n (integer) #2=u (dimension) #3=v (dimension)
 %    save b, mid; numeric b[][], mid; clearxy;  
 %    b[0][0] = b[1][0] = b[1][1] = 1;
 %    label("1", origin); label("1", (-.5u, -v)); label("1", (.5u, -v));
    \edef\U {\the\numexpr\dimexpr #2\relax }% convert to sp units
    \edef\V {\the\numexpr\dimexpr #3\relax }%
    \@namedef{dali@0@0}{1}%
    \@namedef{dali@1@0}{1}%
    \@namedef{dali@0@1}{1}%
    \node at (0,0) {$1$};%
    \node at (-.5*#2,-#3) {$1$};
    \node at (.5*#2,-#3)  {$1$};
  % for i = 2 upto n:
    \xintFor ##1 in {\xintegers[2+1]}\do {%
    \ifnum #1<##1\expandafter\xintBreakFor\fi
  %        mid := i div 2;
          \odef\Mid  {\the\numexpr (##1+1)/2 -1\relax }%
  %       x := -u*i/2;
          \X = \dimexpr\the\numexpr (-##1*\U)/2\relax sp
  %       y := -i*v ;
          \Y = \dimexpr\the\numexpr -##1*\V\relax sp
  %       b[i][0] = 1; label("1", z); label("1", (-x, y));
          \@namedef{dali@\the##1@0}{1}%
          \node at (\X,\Y)  {$1$};
          \node at (-\X,\Y) {$1$};
  %       for k = 1 upto mid:
          \xintFor ##2 in {\xintegers[1+1]}\do {%
          \ifnum\Mid<##2\expandafter\xintBreakFor\fi
  %           x := x + u;
              \advance\X by #2\relax
              \let\next\@secondoftwo
  %           if (k < mid) or (odd i):
              \ifnum \Mid>##2\let\next\@firstoftwo\fi
              \ifodd      ##1\let\next\@firstoftwo\fi
              \next
            {%
  %               b[i][k] = b[i-1][k-1] + b[i-1][k]; 
  %          \ifnum ##1<34 % binomial coefficients are < 2^31
  %          % EDIT DROPS THIS CONDITIONAL
  %             \expandafter\odef\csname dali@\the##1@\the##2\endcsname
  %             {\the\numexpr\@nameuse{dali@\the\numexpr##1-1@\the\numexpr##2-1}
  %                         +\@nameuse{dali@\the\numexpr##1-1@\the##2}\relax }%
  %          \else % 34 choose 17 is 2333606220 > 2^31-1 = 2147483647
               \expandafter\oodef\csname dali@\the##1@\the##2\endcsname
               {\xintiiAdd{\@nameuse{dali@\the\numexpr##1-1@\the\numexpr##2-1}}
                          {\@nameuse{dali@\the\numexpr##1-1@\the##2}}}%
  %          \fi 
  %               label(decimal b[i][k], z); label(decimal b[i][k], (-x, y));
            \node at (\X,\Y)  {$\@nameuse{dali@\the##1@\the##2}$};
            \node at (-\X,\Y) {$\@nameuse{dali@\the##1@\the##2}$};
            }%
  %           else:
            {%
  %               b[i][k] = 2b[i-1][k-1];
  %          \ifnum ##1<34   % EDIT DROPS THIS CONDITIONAL
  %             \expandafter\odef\csname dali@\the##1@\the##2\endcsname
  %             {\the\numexpr2*\@nameuse{dali@\the\numexpr##1-1@\the\numexpr##2-1}\relax}%
  %          \else
               \expandafter\oodef\csname dali@\the##1@\the##2\endcsname
               {\xintDouble{\@nameuse{dali@\the\numexpr##1-1@\the\numexpr##2-1}}}%
  %          \fi 
  %               label(decimal b[i][k], z);
            \node at (\X,\Y) {$\@nameuse{dali@\the##1@\the##2}$};
            }%
  %           fi
  %       endfor
          }%
    % endfor
    }%
}
\makeatother

\begin{document}
\begin{tikzpicture}
   \PascalTriangle{80}{6cm}{1cm}
\end{tikzpicture}
\end{document}

binomial coefficients around binomial(80,40)


Earlier answer

(computes individual binomial coefficients)

You can do this

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{tikz}


% \binomialb macro from https://tex.stackexchange.com/a/161863/4686
% expandably computes binomial coefficients with \numexpr

% START OF CODE
\catcode`_ 11

\def\binomialb #1#2{\romannumeral0\expandafter
    \binomialb_a\the\numexpr #1\expandafter.\the\numexpr #2.}

\def\binomialb_a #1.#2.{\expandafter\binomialb_b\the\numexpr #1-#2.#2.}

\def\binomialb_b #1.#2.{\ifnum #1<#2 \expandafter\binomialb_ca
                            \else   \expandafter\binomialb_cb
                            \fi {#1}{#2}}

\def\binomialb_ca #1{\ifnum#1=0 \expandafter \binomialb_one\else 
                    \expandafter \binomialb_d\fi {#1}}

\def\binomialb_cb #1#2{\ifnum #2=0 \expandafter\binomialb_one\else
                      \expandafter\binomialb_d\fi {#2}{#1}}

\def\binomialb_one #1#2{ 1}

\def\binomialb_d #1#2{\expandafter\binomialb_e \the\numexpr #2+1.#1!}

% n-k+1.k! -> u=n-k+2.v=2.w=n-k+1.k!
\def\binomialb_e #1.{\expandafter\binomialb_f \the\numexpr #1+1.2.#1.}

% u.v.w.k!
\def\binomialb_f #1.#2.#3.#4!%
{\ifnum #2>#4 \binomialb_end\fi
 \expandafter\binomialb_f
 \the\numexpr #1+1\expandafter.%
 \the\numexpr #2+1\expandafter.%
 \the\numexpr #1*#3/#2.#4!}

\def\binomialb_end #1*#2/#3!{\fi\space #2}
\catcode`_ 8
% END OR \binomialb code

\begin{document}\thispagestyle{empty}


\begin{tikzpicture}
\foreach \n in {0,...,4} {
  \foreach \k in {0,...,\n} {
    \node at (2*\k-\n,-\n) {${\n \choose \k} = \binomialb\n\k$};
  }
}
\end{tikzpicture}

\bigskip\bigskip

\begin{tikzpicture}
\foreach \n in {21,...,24} {
  \foreach \k in {10,...,\the\numexpr\n-11\relax} {
    \node at (3*\k-1.5*\n,-\n) {${\n \choose \k} = \binomialb\n\k$};
  }
}
\end{tikzpicture}


%\bigskip\bigskip

% arithmetic overflow, use xint and \binomialB !
% \begin{tikzpicture}
% \foreach \n in {30,...,34} {
%   \foreach \k in {15,...,\the\numexpr\n-15\relax} {
%     \node at (4*\k-2*\n,-\n) {${\n \choose \k} = \binomialb\n\k$};
%   }
% }
% \end{tikzpicture}

\end{document}

enter image description here

3
  • Wow! I am dazzled by your skills in TeX programming. All this seems most complicated to me, even more so knowing that it is translated from my own MetaPost program. And I never imagined that TeX could handle such big numbers. Mar 16 '15 at 12:16
  • Package xint does expandable arithmetic with "arbitrarily big" integers. An earlier package was bigintcalc. Expandability allows among other things intuitive "composition of macros" rather than the style of \pgfmathparse or \FPadd to cite other mathematical engines. Expandability is implemented in the strongest sense by xint. Starting with numbers having hundreds of digits this makes the macro slower. If one were to drop expandability, it would be possible to implement much faster routines.
    – user4686
    Mar 16 '15 at 16:10
  • @fpast Package xintfrac extends xint to handle exactly fractions A/B or decimal numbers. Packages with non expandable arbitrary precision fixed point arithmetic exist, but this does not mean that they are faster than the expandable xintfrac for numbers with less than one hundred digits. To the contrary in the case of xintfrac \xintXTrunc which admittedly is completely expandable, but not in the strongest sense as for the other xint macros.
    – user4686
    Mar 16 '15 at 16:13
9

Done with MetaPost, several years too late.

The Pascal_triangle macro defined below takes three arguments, the number of rows n (starting from 0), the horizontal space between consecutive coefficients in the same row and the vertical space between two consecutive rows. It uses the well-known recursive relation between binomial coefficients, in an iterative way and a straightforward manner (it doesn't take any symmetry into account), yet it is more efficient than I expected: it works up to the first 56 rows.

\documentclass[12pt, border=5mm]{standalone}
\usepackage{luatex85,luamplib}
    \mplibnumbersystem{double}
    \mplibtextextlabel{enable}
\begin{document}
\begin{mplibcode}
vardef Pascal_triangle(expr n, u, v) =
    save b; numeric b[][]; clearxy;
    b[0][0] = 1; b[0][1] = 0; label("1", origin);
    for i = 1 upto n:
        x := -u*i/2; y := -i*v;
        b[i][0] = 1; label("1", z);
        for k = 1 upto i:
            x := x + u;
            b[i][k] = b[i-1][k-1] + b[i-1][k]; label(decimal(b[i][k]), z);
        endfor b[i][i+1]=0;
    endfor
enddef;

beginfig(1);
    Pascal_triangle(19, 1.4cm, 1cm);
endfig;
\end{mplibcode}
\end{document}

To be executed with LuaLaTeX. This example shows the first 20 rows of the triangle (n=19):

enter image description here

Edit Here is a version which makes use of the symmetry of Pascal's triangle, with the same output as before, of course. It was quite a bit more difficult for me to sort that one out (probably because I have not found the most clever way of doing it ;-)), and I have not noticed any difference in speed nor in efficiency with the previous version.

\documentclass[12pt, border=5mm]{standalone}
\usepackage{luatex85,luamplib}
    \mplibnumbersystem{double}
    \mplibtextextlabel{enable}
\begin{document}
\begin{mplibcode}
vardef Pascal_triangle(expr n, u, v) =
    save b, mid; numeric b[][], mid; clearxy;  
    b[0][0] = b[1][0] = b[1][1] = 1;
    label("1", origin); label("1", (-.5u, -v)); label("1", (.5u, -v)); 
    for i = 2 upto n:
        mid := i div 2; 
        x := -u*i/2; y := -i*v; 
        b[i][0] = 1; label("1", z); label("1", (-x, y));
        for k = 1 upto mid:
            x := x + u;
            if (k < mid) or (odd i):
                b[i][k] = b[i-1][k-1] + b[i-1][k]; 
                label(decimal b[i][k], z); label(decimal b[i][k], (-x, y));
            else:
                b[i][k] = 2b[i-1][k-1];
                label(decimal b[i][k], z);
            fi
        endfor
  endfor
enddef;

beginfig(1);
    Pascal_triangle(19, 1.4cm, 1cm);
endfig;
\end{mplibcode}
\end{document}

Edit I've added the loading of the luatex85 package, since LuaLaTeX is not compatible with the standalone class anymore without this package.

6
\documentclass[a4paper,12pt]{article}%
    \usepackage[dvipsnames]{xcolor} 
    \usepackage{tikz}
    \usepackage{pdfpages}
    \makeatletter
    \newcommand\binomialCoefficient[2]{%
        % Store values 
        \c@pgf@counta=#1% n
        \c@pgf@countb=#2% k
        %
        % Take advantage of symmetry if k > n - k
        \c@pgf@countc=\c@pgf@counta%
        \advance\c@pgf@countc by-\c@pgf@countb%
        \ifnum\c@pgf@countb>\c@pgf@countc%
            \c@pgf@countb=\c@pgf@countc%
        \fi%
        %
        % Recursively compute the coefficients
        \c@pgf@countc=1% will hold the result
        \c@pgf@countd=0% counter
        \pgfmathloop% c -> c*(n-i)/(i+1) for i=0,...,k-1
            \ifnum\c@pgf@countd<\c@pgf@countb%
            \multiply\c@pgf@countc by\c@pgf@counta%
            \advance\c@pgf@counta by-1%
            \advance\c@pgf@countd by1%
            \divide\c@pgf@countc by\c@pgf@countd%
        \repeatpgfmathloop%
        \the\c@pgf@countc%
    }
    \makeatother
    \begin{document}
    \begin{center} 
    \newdimen\R
    \R=.4cm
    \newcommand\mycolor{gray}
    \begin{tikzpicture}[line width=.8pt]
    \foreach \k in {0,...,12}{
        \begin{scope}[shift={(-60:{sqrt(3)*\R*\k})}]
         \pgfmathtruncatemacro\ystart{12-\k}
          \foreach \n in {0,...,\ystart}{
            \pgfmathtruncatemacro\newn{\n+\k}
            \ifthenelse{\k=0}{\def\mycolor{pink}}{}
            \ifthenelse{\k=1}{\def\mycolor{yellow}}{}
            \ifthenelse{\k=2}{\def\mycolor{blue}}{}
            \ifthenelse{\k=3}{\def\mycolor{green}}{}
            \ifthenelse{\k=8 \AND \n < 4}{\def\mycolor{purple}}{}
            \ifthenelse{\k=9 \AND \n = 3}{\def\mycolor{purple}}{}
            \begin{scope}[shift={(-120:{sqrt(3)*\R*\n})}]
               \draw[top color=\mycolor!20,bottom color=\mycolor!60] 
          (30:\R) \foreach \x in {90,150,...,330} {
                    -- (\x:\R)}
                    --cycle (90:0) node {\tiny $\mathbf{\binomialCoefficient{\newn}{\k}}$};
             \end{scope}
           }
         \end{scope}
    }
    \end{tikzpicture} 
    \end{center} 
    \end{document}

enter image description here

2
  • I love this hexagonal Pascal triangle, but I couldn't make it work. I copied the code verbatim, but it gives me plenty of errors. The first error is "Missing number, treated as zero" on line 69. What's the problem? Thank you very much in advance. Jan 1 '18 at 22:21
  • I'd recommend changing \newdimen\R to \newlength\R and \R=.4cm to \setlength\R{.4cm}. A handful of math documents have the definition \newcommand{\R}{\mathbb{R}} and when the \newdimen\R definition comes through, it doesn't check to see whether \R is defined already. If an author continues through their document using \R as if it denotes the reals, they'll end up getting a ! Missing number... error.
    – user45054
    Dec 19 '18 at 14:21
4

Why not? This should work to construct up to the first 100 lines of the triangle. It will work for higher values (subject to capacity etc.), but the alignment would need adjusting in that case.

\documentclass[border=10pt]{standalone}
\usepackage{forest}
\begin{document}
\newlength\pwidth
\settowidth\pwidth{$99 \choose 99$}
\forestset{
  declare count={pk}{0},
  my phantom/.style={, no edge, inner sep=0pt, calign with current, my node},
  my node/.style={},
  pascal triangle/.style={
    if={>n_>{#1}{9}}{%
      my node/.style={text width=\pwidth},
    }{},
    before computing xy={
      for tree={
        l'=\baselineskip,
      },
    },
    before typesetting nodes={
      for tree={
        content/.process={OOw2}{level}{pk}{##1 \choose ##2},
        math content,
        s sep'=0pt,
        inner sep=0pt,
        my node,
        no edge,
        if n children=1{
          prepend={[, my phantom]},
        }{},
      },
      for nodewalk={fake=r,F}{insert after={[, my phantom]}},
    },
    delay={
      for root={
        append={[]},
        append={[, pk'=1]},
      },
      repeat={>n{#1-1}}{
        delay={
          do dynamics,
          for leaves={
            append={[, pk/.option=!u.pk, pk'+=1]},
          },
          for first leaf={
            prepend={[]},
          },
        },
      },
    }
  },
}
\begin{forest}
  pascal triangle=2,
  []
\end{forest}
\begin{forest}
  pascal triangle=3,
  []
\end{forest}
\begin{forest}
  pascal triangle=4,
  []
\end{forest}
\begin{forest}
  pascal triangle=5,
  []
\end{forest}
\begin{forest}
  pascal triangle=6,
  []
\end{forest}
\begin{forest}
  pascal triangle=7,
  []
\end{forest}
\begin{forest}
  pascal triangle=8,
  []
\end{forest}
\begin{forest}
  pascal triangle=9,
  []
\end{forest}
\begin{forest}
  pascal triangle=10,
  []
\end{forest}
\end{document}

Pascal's Triangle (But will he vote for it? Some people are never grateful ....)

2
\documentclass[border=5pt,tikz]{standalone}
    \begin{document}
        \begin{tikzpicture}[rotate=-90]
            \foreach \x in {0,1,...,5}
            {
                \foreach \y in {0,...,\x}
                {
                    \pgfmathsetmacro\binom{factorial(\x)/(factorial(\y)*factorial(\x-\y))}
                    \pgfmathsetmacro\shift{\x/2}
                        \node[xshift=-\shift cm] at (\x,\y) {\pgfmathprintnumber\binom};
                }
            }
        \end{tikzpicture}
    \end{document}

Output:

Screenshot

1
  • Elegant solution, but falls apart for n >= 8.
    – ppareit
    Dec 29 '18 at 11:20
0

Here is a fully expandable solution (two expansions of \BinomialCoefficient{From}{By} are enough; From and By may be arithmetic expressions).

\documentclass{article} % binomial(N,K) from N by K as N/1*(N-1)/2*(N-3)/3...  Here the denominator is denoted as k
% Works for all cases (but 0 for N<0) when N, K, and the answer fit into 32-bit signed integers

\def\binomialCoefficient#1#2{%  #1 >= 0 (otherwise 0); (K=#2 out of N=#1); expandable (needs 2 expansion); leaves no \else/\fi junk
  \the\numexpr 1\expandafter\bKN\expandafter{\the\numexpr #2\relax}{#1}\relax}
\def\bKN#1#2{% #1 not an expression, expanded at most twice per call; 
  \ifnum #1<0 *0% may leave at most 5 dangling \else or \fi
  \else    \ifnum 0<\numexpr 2*#1-(#2)\relax \expandafter\bKN\expandafter{\the\numexpr #2-(#1)\relax}{#2}%
           \else  \bkNK 1{#2}{#1}\fi\fi}
\def\bkNK#1#2#3{% 1,3 not expressions
  \ifnum #1>#3 % end: falls through to \relax
  \else  *(#2)/#1\expandafter\bNkKfi\expandafter{\the\numexpr#2-1\relax}{#1+1}{#3}%
  \fi}      % Inserting \fi then exchanging it is needed for the pre-else branch
\def\bNkKfi#1#2#3#4{%  4 is \fi, 3 may not be an expression; avoids unexpanded \fi's at end
 #4\expandafter\bkNK\expandafter{\the\numexpr#2\relax}{#1}{#3}}

\usepackage{pgffor} % For testing only
\begin{document}

\def\LAST{33}   % 33 is the max which does not overflow
\edef\L{\the\numexpr\LAST+3\relax}

\foreach \I in {0,...,\LAST} { (\the\numexpr 1\bKN {\I}{\LAST-3+3})}

\foreach \I in {1,...,\L} { (\binomialCoefficient {\L-3}{\I-2})}

\foreach \I in {2,...,7} { (\binomialCoefficient {190}{190-\I+2})}

\expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\A\expandafter\expandafter\expandafter
  {\binomialCoefficient {200-10}{190-5}}  % ->1956800538.
%  {\binomialCoefficient {33}{16}}  % ->1166803110.
\show\A

\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.