You need to display Pascal's Triangle in a LaTeX document and whenever you hear ‘ampersand’ or ‘smallskip’, you go into a homicidal rage, leaving behind you a trail of viscera and blood-stained Lion Book pages. Also, you're lazy. Put that chainsaw down, this recipe is for you. Although, really, with that kind of reaction to ampersands, what are you doing using the world's best Turing-complete typesetting software?
Solution
This recipe uses a small Python script to generate a Pascal triangle of arbitrary size in a tabular
environment — it's entirely up to you to make it fit on your page, of course. If you're interested in the pure Pascal's Triangle code, without typesetting embellishments, there's a recipe devoted to just this. Here's the Python code for the script:
import sys
def pascal(n):
"""
Yield up to row ``n`` of Pascal's triangle, one row at a time.
The first row is row 0.
"""
if not isinstance (n, int):
raise TypeError ('n must be an integer')
if n < 0:
raise ValueError ('n must be an integer >= 0')
def newrow(row):
"Calculate a row of Pascal's triangle given the previous one."
prev = 0
for x in row:
yield prev + x
prev = x
yield 1
prevrow = [1]
yield prevrow
for x in range(n):
prevrow = list(newrow(prevrow))
yield prevrow
def pascal_latex(n, out=sys.stdout):
"""
Generate a Pascal triangle for LaTeX embedding.
Sends output to the file-like object ``out`` (default: sys.stdout).
"""
out.write('\\begin{tabular}{r%s}\n' % ('c' * (2 * n + 1)))
for i, row in enumerate(pascal(n)):
out.write('$n=%d$:& ' % i)
out.write(' & ' * (n - i))
out.write(' & & '.join ('%2d' % coeff for coeff in row))
out.write('\\\\\\noalign{\\smallskip\\smallskip}\n')
out.write ('\\end{tabular}\n')
if __name__ == '__main__':
try:
pascal_latex (int(sys.argv[1]))
except ValueError:
sys.stderr.write ('Please specify a positive integer.\n')
sys.exit (1)
range()
to xrange()
to avoid exploding memory usage with large triangles.Usage
Turn this into an executable script (this depends on your operating system — on Unix, chmod +x some_filename.py
works well), and run it:
python some_filename.py 4
If you made this into an executable, you can leave python
out of the command line and run it as ./some_filename.py 4
.You'll get something like this:
\begin{tabular}{rccccccccc}
$n=0$:& & & & & 1\\\noalign{\smallskip\smallskip}
$n=1$:& & & & 1 & & 1\\\noalign{\smallskip\smallskip}
$n=2$:& & & 1 & & 2 & & 1\\\noalign{\smallskip\smallskip}
$n=3$:& & 1 & & 3 & & 3 & & 1\\\noalign{\smallskip\smallskip}
$n=4$:& 1 & & 4 & & 6 & & 4 & & 1\\\noalign{\smallskip\smallskip}
\end{tabular}
Which, of course, renders this:
You can place the LaTeX code fragment in a pascals_triangle.tex
file on its own, and then include it into your other documents by saying:
\input{pascals_triangle}
Obviously, you can also copy and paste it.
You can also call the triangle-generating routine from another Python program by saying pascal_latex(4)
. Optionally, you may specify a file-like object to output to: pascal_latex(4, out=open('some_file', 'w'))
, and you'll get output sent to some_file
.
Discussion
The script is written in three, visibly distinct parts. The first part is the pascal()
function. For a better discussion of how this works, please refer to .
The second function, pascal_latex()
, is where we put all the strings together to build the LaTeX code. It's the usual ugly-looking code present whenever this kind of string manipulation is needed. The table header lists all the column alignments (r
for the first column, c
for each triangle coefficient). The trickiest bit is remembering that the tabular form of an n-row Pascal's Triangle has 2n+1 columns because of its symmetry.
The rest of the function merely prints out consecutive rows of the triangle, prepending tabular
alignment characters (&
) to align the triangle's columns properly. Finally, the coefficients are all printed in one fell swoop, and terminated with \\
(end of table row) and \noalign{\smallskip\smallskip}
, to add enough vertical space between rows (otherwise the triangle looks squashed).
The third and smallest part of the script simply parses (without much checking) the command-line arguments, when the program is used as a script (not a module to be included in another Python program).