“10 PRINT” in TikZ

The book 10 PRINT CHR$(205.5+RND(1)); : GOTO 10, by Nick Montfort, et. al., uses a one-line Commodore 64 BASIC program “as a gateway into a deeper understanding of how computing works in society and what the writing, reading, and execution of computer code mean” (p. 4). The focus is on the titular program, which the authors call 10 PRINT for short:

10 PRINT CHR$(205.5+RND(1)); : GOTO 10

This program prints an infinite random sequence made up of the box-drawing characters ╱ and ╲ (that’s U+2571 and U+2572, respectively, encoded in the Commodore character set PETSCII as 205 and 206.), in order to make a random maze. This produces an output similar to the following, except that the characters on a Commodore screen are more square:

(The book’s web site gives a better idea how the output on a Commodore would look.)

It’s not hard to reproduce 10 PRINT in Python, albeit using more than one line:

#! /usr/bin/env python3

import random

for j in range(0, 24):
    print("".join([random.choice(["\u2571","\u2572"])
        for k in range(0, 40)]))

(Instead of an infinite string, my program only outputs a 40 × 24 block of characters.) To get the output to look right, you might need to mess with the font settings in your Terminal. I found that that Melno Regular font on my Mac works.

But I really thought it would be more fun to obtain a 10 PRINT-like output using TikZ, as TikZ is capable of generating random numbers! Instead of using the characters ╱ and ╲, I will draw the lines directly:

\documentclass{standalone}

\usepackage{tikz}

\begin{document}

  \begin{tikzpicture}

    % Draw background
    \fill[blue!75!black] (0, 0) -- (0, 24) --
    (40, 24) -- (40, 0) -- cycle;

    % Draw maze
    \foreach \y in {0, ..., 23}{
      \foreach \x in {0, ..., 39}{

        % Randomly choose a = 0 or a = 1
        \pgfmathrandominteger{\a}{0}{1};

        % If a = 0, then will draw SW-NE line
        % If a = 1, then will draw NW-SE line
        \draw[very thick, white] (\x, \y + \a)
          -- (\x + 1, \y + 1 - \a);
      }
    }

  \end{tikzpicture}

\end{document}

I really like the output:

LaTeX mailmerge package

The LaTeX mailmerge package is super useful, especially for creating multiple versions of tests.

Before I discovered mailmerge, my workflow for writing a test was basically:

  • Write one version of the test.
  • Make a duplicate of the file.
  • Edit the file to change all the constants.

At least, that was my intended workflow. But typically I would also:

  • Realize that there was some change I wanted to make to the test.
  • Painstakingly make the same change to both versions of the test, double-checking that the wording remained consistent between versions.

Sometimes I would repeat the last two steps multiple times. This was obnoxiously inefficient.

Then I discovered the mailmerge package.

Here is a basic (silly) example illustrating how the package works:

\documentclass[letterpaper, 12pt]{amsart}

%% packages
\usepackage{mailmerge}
\usepackage{fouriernc}
\usepackage{url}
\usepackage{tikz}

\title{Some U.S.~state capital facts}

\begin{document}

  \maketitle

  \mailrepeat{
    The capital of \field{state} is \field{capital}.
    The U.S. Census Bureau estimates that in mid-2017,
    there were \field{population} people living in
    \field{capital}\footnote{\field{cite}}.

  }

  \mailfields{state,capital,population,cite}

  \mailentry{Illinois,Springfield,%
    {167,376},\url{https://goo.gl/YGDdE6}}

  %% Draw a square:
  \vskip 1 em
  \begin{tikzpicture}
    \draw (0, 0) -- (1, 0)
      -- (1, 1) -- (0, 1) -- cycle;
  \end{tikzpicture}
  \vskip 1 em

  \mailentry{Minnesota,St.~Paul,%
    {306,621},\url{https://goo.gl/F6rXZ7}}

  \mailentry{Oregon,Salem,%
    {169,798},\url{https://goo.gl/Zc4tDC}}

  \mailentry{Pennsylvania,Harrisburg,%
    {49,192},\url{https://goo.gl/NQypQG}}

\end{document}

This produces:

SOME U.S. STATE CAPITAL FACTS

The capital of Illinois is Springfield. The U.S. Census Bureau estimates that in mid-2017, there were 167,376 people living in Springfield1.

The capital of Minnesota is St. Paul. The U.S. Census Bureau estimates that in mid-2017, there were 306,621 people living in St. Paul2.

The capital of Oregon is Salem. The U.S. Census Bureau estimates that in mid-2017, there were 169,798 people living in Salem3.

The capital of Pennsylvania is Harrisburg. The U.S. Census Bureau estimates that in mid-2017, there were 49,192 people living in Harrisburg4.

This is followed by the appropriate footnotes.

Typeset output from first example.

Notice:

  • The text you want repeated is specified as the argument of the \mailrepeat macro.
  • Within the \mailrepeat, we specify the mail-merged info with \field{[field name]}
  • The names of the mail merge fields are given as a comma-delimited list with the \mailfields macro.
  • The actual mail-merge is accomplished with the \mailentry macro. The argument to this macro is a comma-delimited list of the material to place into the fields.

I put the silly TikZ square in this example to illustrate that the mail-merged text is placed where the \mailentry occurs in the code.

Spacing is significant in the \mailentry macro. If there is a space next to \field{[field name]} in the \mailrepeat and after the comma the corresponding field in the \mailentry, this will produce an awkward amount of space in the output. For example,

\mailentry{Minnesota, St.~Paul,
{306,621},\url{https://goo.gl/F6rXZ7}}

will produce:

Notice the extra space before the two instances of “St. Paul” and before the population. Compare to what is produced when there is no space before the comma and there is a % before the line break (which prevents the line break from being treated as a space):

\mailentry{Minnesota,St.~Paul,%
{306,621},\url{https://goo.gl/F6rXZ7}}


It’s very subtle, but I am a perfectionist.

If you have many fields, the comma-delimited list argument to the \mailentry can get unwieldy. One trick I use is to end each entry with a comment containing the field name:

  \mailentry{Minnesota%state
    ,St.~Paul%capital
    ,{306,621}%population
    ,\url{https://goo.gl/F6rXZ7}%cite
    }

Especially when the fields are difficult to tell apart based on content (e.g., when they are different constants for math problems), this makes it easier to know which field you are changing. Also, the comments prevent any space or line break before the comma from affecting the output.

For a test, each version would correspond to a single \mailentry. Consider this made-up quiz, which has two versions (Form A and B):

\documentclass[letterpaper, 11pt]{article}

%% packages
\usepackage{amsmath}
\usepackage{mailmerge}
\usepackage{fouriernc}
\usepackage{enumitem}
\usepackage{fullpage}

\begin{document}

  \mailrepeat{
    \setcounter{page}{1}
    \centerline{\textbf{Quiz \#1}, Form \field{form}}
    \vskip 1 em

    \begin{enumerate}
      \item (2 points) Expand
      \(\left(x^{\field{exponent1}} + 2x\right)^2\).


      \vfill

      \item (3 points) Suppose
      \(f(x) =
        \field{coeff1}x^2 + \field{coeff2}x + 1\).
      Find \(f(5)\).
      \vfill

    \end{enumerate}

    \newpage

    \begin{enumerate}[resume]
      \item (5 points) Solve for \(x\):
      \[\field{coeff3}x^4 - \field{coeff4}x^3
        = 0\]

      \vfill

    \end{enumerate}
    \newpage
  }


  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %%% Mail merge info:

  \mailfields{form, coeff1, coeff2,
    coeff3, coeff4, exponent1}

  \mailentry{A%form
  ,6%coeff1
  ,8%coeff2
  ,2%coeff3
  ,7%coeff4
  ,3%exponent1
  }

  \mailentry{B%form
  ,5%coeff1
  ,9%coeff2
  ,3%coeff3
  ,5%coeff4
  ,5%exponent1
  }
\end{document}

At the start of the \mailrepeated code is the macro \setcounter{page}{1}, which resets the page number to 1; otherwise, Form B would start on Page 3. Also, I ended the \mailrepeated code with a \newpage, ensuring that each version is on a separate page.

If you print \(\lceil N/2\rceil\) copies of the resulting PDF (where N is the number of students in your course), two-sided, then the pile of quizzes will be alternated by version as they come out of the printer, ready to hand out to your class.