28

I was making a numbered list in LaTeX, but I was wondering whether I could make the numbers of the list prime numbers. So I'd like something like:

2. List item
3. List item
5. List item
7. List item

It is possible to do it by hand, but is it also possible to make it automatic?

4
  • If you provide an algorithm that calculates the prime numbers ;-)
    – user31729
    Apr 13, 2016 at 18:19
  • 2
    See also The TeXbook, p. 218.
    – GuM
    Apr 13, 2016 at 19:13
  • 4
    Is four a prime?
    – User
    Apr 13, 2016 at 21:31
  • 1
    @User, Markdown is funny. If you start a line with n., then it'll initialise a numbered list starting from n, and interpret subsequent lines that start with numbers as part of that numbered list, incrementing each by 1 in the way that humans count, regardless of what that number was. Check the post's source if you're interested.
    – ymbirtt
    Apr 14, 2016 at 7:34

4 Answers 4

21

I took a different approach, not using a list of primes but, rather, using pgfmath to find the primes instead. This was fun.

\documentclass{article}

\usepackage{pgfmath}
\usepackage{enumitem}

\newcounter{primecnt}

\newcommand{\nextprime}{%\
    \loop
        \stepcounter{primecnt}%
        \pgfmathsetmacro{\primeTF}{isprime(\theprimecnt)}%
    \ifnum\primeTF=0
        \repeat
}

\newlist{primeenumerate}{enumerate}{1}
\setlist[primeenumerate]{label=\theprimecnt.}

\makeatletter
\newenvironment{primeenum}{%
    \setcounter{primecnt}{0}%
    \def\item{%
        \nextprime
        \@inmatherr\item
        \@ifnextchar [\@item{\@noitemargtrue \@item[\@itemlabel]}%
    }%
    \begin{primeenumerate}
}{%
    \end{primeenumerate}
}
\makeatother

\begin{document}

\begin{primeenum}
\item one
\item two
\item three
\item four
\item five
\item six
\item seven
\item eight
\item nine
\item ten
\item eleven
\item twelve
\item thirteen
\item fourteen
\item fifteen
\item sixteen
\item seventeen
\end{primeenum}

\end{document}

The result:

Prime enumerate 2

Pointers on making this better code would be welcome...

1
  • Personally I prefer to use the build-in function like this.
    – Tawei
    Apr 14, 2016 at 10:58
20

Here's an enumitem version with a special \AddEnumerateCounter output named \primeenum which can be used label={\primeenum*.} style.

Basically, it just applies \ifcase... \or...\fi and lists some prime numbers up to 59, but this can be extended of course.

\documentclass{article}

\usepackage{enumitem}


\makeatletter
\def\primeenum#1{\expandafter\@primenum\csname c@#1\endcsname}
\def\@primenum#1{%
  \ifcase#1
  \or
  2\or 3\or 5\or 7\or 11\or 13\or 17\or 19\or 23\or 29\or 31\or 37\or 41\or 43\or 47\or 53\or 59\else\@ctrerr\fi
}

\AddEnumerateCounter*{\primeenum}{\@primenum}{100}

\makeatother


\newlist{primenumerate}{enumerate}{1}
\setlist[primenumerate,1]{label={\primeenum*.}}


\begin{document}

\begin{primenumerate}
\item Foo
\item Bar
\item Is
\item Nice
\item Foo
\item Bar
\item Is
\item Nice
\item Foo
\item Bar
\item Is
\item Nice
\item Foo
\item Bar
\item Is
\item Nice
\end{primenumerate}


\end{document}

enter image description here

2
  • 1
    Very nice! But I’d end the \ifcase with ... 59\else \@ctrerr \fi.
    – GuM
    Apr 15, 2016 at 16:31
  • @GustavoMezzetti: Thanks, that's a good suggestion. I've edited the code!
    – user31729
    Apr 15, 2016 at 16:39
15

This answer takes Christian's excellent answer (and who deserves the credit for developing the basic structure) and tweaks it to make the input of new primes more streamlined. It uses the \getargsC macro of the readarray package to take a space-separated list and plunk the list into the macros \argi, \argii, \argiii, etc. in romannumeral fashion. This greatly simplifies the definition of \primenum to the following: \def\@primenum#1{\csname arg\romannumeral\the#1\endcsname}.

The result is the same.

\documentclass{article}
\usepackage{readarray, enumitem}
\makeatletter
\getargsC{2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53}
\def\@primenum#1{\csname arg\romannumeral\the#1\endcsname}
\def\primeenum#1{\expandafter\@primenum\csname c@#1\endcsname}
\AddEnumerateCounter*{\primeenum}{\@primenum}{100}
\makeatother
\newlist{primenumerate}{enumerate}{1}
\setlist[primenumerate,1]{label={\primeenum*.}}
\begin{document}
\begin{primenumerate}
\item Foo
\item Bar
\item Is
\item Nice
\item Foo
\item Bar
\item Is
\item Nice
\item Foo
\item Bar
\item Is
\item Nice
\item Foo
\item Bar
\item Is
\item Nice
\end{primenumerate}
\end{document}
2
  • Code stealer (;-) +1)
    – user31729
    Apr 13, 2016 at 18:48
  • 11
    @ChristianHupfer Guilty as charged. I should have stolen from several people at once, and then I could call it "research". Apr 13, 2016 at 18:48
8

Just for fun, a version that asks Pari-GP to increase the list of primes, using the function nextprime.

The final list is written out in the .aux file, so it can be recycled at initialization time. Note that shell escape is needed if the list has to be made larger. Of course, a working Pari-GP installation is needed.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\seq_new:N \g_primecount_list_seq % the primes to use
\int_new:N \g_primecount_max_int  % how many primes we need

% initialize
\seq_gset_from_clist:Nn \g_primecount_list_seq
 {
  2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53
 }

% if necessary, ask Pari-GP to make the list larger
\AtBeginDocument
 {
  \int_compare:nT { \seq_count:N \g_primecount_list_seq < \g_primecount_max_int }
   {
    \prg_replicate:nn { \g_primecount_max_int - \seq_count:N \g_primecount_list_seq }
     {
      \int_set:Nn \l_tmpa_int { \seq_item:Nn \g_primecount_list_seq { -1 } }
      \tl_set_from_file:Nnn \l_tmpa_tl { \endlinechar=-1 }
       { "|echo~'nextprime(\int_eval:n { \l_tmpa_int + 1 })'|gp~-q" }
      \seq_gput_right:NV \g_primecount_list_seq \l_tmpa_tl
     }
   }
 }

% the primeenum environment
\NewDocumentCommand{\maxprime}{m}
 {
  \int_compare:nT { #1 > \g_primecount_max_int }
   {
    \int_gset:Nn \g_primecount_max_int { #1 }
   }
 }

\DeclareExpandableDocumentCommand{\primecount}{m}
 { % #1 is the name of a counter
  \int_compare:nTF { \value{#1} > \seq_count:N \g_primecount_list_seq }
   {
    ???
   }
   {
    \seq_item:Nn \g_primecount_list_seq { \value{#1} }
   }
 }
\NewDocumentCommand{\checkprimes}{}
 {
  \int_compare:nT { \value{enumi} > \seq_count:N \g_primecount_list_seq }
   {
    \iow_shipout:cx { @auxout } { \maxprime { \int_to_arabic:n { \value{enumi} } } }
   }
 }
\cs_new_protected:Nn \primecount_dump_list:
 {
  \iow_now:cx { @auxout }
   {
    \buildprimelist { \seq_use:Nn \g_primecount_list_seq { , } }
   }
 }
\NewDocumentCommand{\buildprimelist}{m}
 {
  \seq_gset_from_clist:Nn \g_primecount_list_seq { #1 }
 }
\AtEndDocument
 {
  \primecount_dump_list:
  \cs_set_eq:NN \maxprime \use_none:n
  \cs_set_eq:NN \buildprimelist \use_none:n
 }
\ExplSyntaxOff

\NewDocumentEnvironment{primeenum}{}
 {\enumerate\renewcommand{\theenumi}{\primecount{enumi}}}
 {\checkprimes\endenumerate}

\begin{document}

\begin{primeenum}
\ExplSyntaxOn
\prg_replicate:nn { 199 } { \item X }
\ExplSyntaxOff
\item\label{Y} Y
\end{primeenum}

\ref{Y} is the 200th prime

\end{document}

enter image description here

Here's the contents of the .aux file, the list can be used also for the other presented implementations.

\relax 
\buildprimelist {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223}
\newlabel{Y}{{1223}{8}}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .