0

I am trying to create a macro that can generate complex trinomials.

What I've made compiles as desired about 80% of the time and gives me a whole bunch of error messages about 20% of the time. You can see everything at this ShareLaTeX link. If you simply press "Recompile", a bunch of times, you will see that it sometimes compiles and sometimes does not.

The errors include:

  • Missing Number Treated as Zero
  • Illegal Unit of Measure
  • Extra \else
  • missing end \csname
  • extra \endcsname
  • undefined control sequence
  • runaway argument

Here is a picture of the first few of them:enter image description here

i.e. A whole bunch of things go wrong at once during the 15% of time things don't compile.

What's wrong with my code? I'm assuming it has something to do with random numbers/items/lists not being codified properly, but I'm not sure.

\documentclass{article}

\usepackage[margin=1cm]{geometry}
\usepackage{ifthen}
\usepackage{pgf}
\usepackage{pgffor}

\setlength{\parindent}{0pt}

\pagestyle{empty}

\pgfmathsetseed{\number\pdfrandomseed}

\newcommand{\InitVariablesCTPP}
{% 
 % I want the equation to be in the form (ax+b)(cx+d)=Ax^2+Bx+C.
 %but I want there to be NO common factors.
 %So, these lists mean that if, say, c=2, then d is selected randomly from 1,3,5, or 7.... at least that was the intention.
 \pgfmathdeclarerandomlist{IfOne}{{1}{2}{3}{4}{5}{6}{7}}
 \pgfmathdeclarerandomlist{IfTwo}{{1}{3}{5}{7}}
 \pgfmathdeclarerandomlist{IfThree}{{1}{2}{4}{5}{7}}
 \pgfmathdeclarerandomlist{IfFour}{{1}{3}{5}{7}}
 \pgfmathdeclarerandomlist{IfFive}{{1}{2}{3}{4}{6}{7}}

 \pgfmathsetmacro{\a}{int(random(1,5))}
 \ifcase\a\relax%
  \or \pgfmathrandomitem{\b}{IfOne}
  \or \pgfmathrandomitem{\b}{IfTwo}
  \or \pgfmathrandomitem{\b}{IfThree}
  \or \pgfmathrandomitem{\b}{IfFour}
  \or \pgfmathrandomitem{\b}{IfFive} \fi

 \pgfmathsetmacro{\c}{int(random(2,5))}
 \ifcase\c\relax%
   \or \pgfmathrandomitem{\d}{}
   \or \pgfmathrandomitem{\d}{IfTwo}
   \or \pgfmathrandomitem{\d}{IfThree}
   \or \pgfmathrandomitem{\d}{IfFour}
   \or \pgfmathrandomitem{\d}{IfFive}
 \fi

 \pgfmathsetmacro{\A}{int(\a*\c)}
 \pgfmathsetmacro{\B}{int(\a*\d+\b*\c)}
 \pgfmathsetmacro{\C}{int(\b*\d)}
}

\newcommand{\ManyCTPP}[1]
 {%
  \foreach \x in {1,2,3,...,#1}
  {
   \InitVariablesCTPP
    a=\a\\
    b=\b\\
    c=\c\\
    d=\d\\
    A=\A =\a * \c \\
    B=\B =\a * \d + \b * \c\\
    C=\C =\b * \d\\

\(({\a}x+{\b})({\c}x+{\d})={\A}x^2+{\B}x+{\C}\)
\\

\vspace{1cm}}
 }

\begin{document}

\section{Complex Trinomials}

\ManyCTPP{5}

\end{document}
  • What is the exact text of the first error message? The others are probably irrelevant. And how can we reproduce it? Does it depend on the seed? If so, which value do we need to use? – cfr May 19 '17 at 1:13
  • I hope you don't need any of the macros you're redefining in your document. Don't use \\ to break lines outside tabulars, arrays etc. – cfr May 19 '17 at 1:15
  • I edited the OP to include a pic of the first few error messages. I also gave a link and instructions to replicate the error: recompile, say, 10 or 15 times and it should work some of the time and fail some of the time. – WeCanLearnAnything May 19 '17 at 3:28
  • Yes, but you should change it so it fails every time. Just set the random seed appropriately. I.e. use a non-random value for the MWE. – cfr May 19 '17 at 3:41
  • It is trying, I think, to pick the sixth item from a list of 5. Use 158474446 as seed. – cfr May 19 '17 at 3:44
3

What appears to be happening that you are choosing two random list elements, \b and \d, and when you go to use them the last "index" of the random list is being used for both \b and \d. This is problematic because, for example, if \d is using list item number 6 and \b is an item in the list IfTwo then you get a missing number because IfTwo does not have an item 6.

One way to fix the issue is to force \b, and \d to expand when they defined using something like:

\xdef\b{\b}

There are some other issues with your code:

  • Using \a, \b, \c, \d, \A, \B, \C, \x for macro/variables names is not such a good idea because some of them conflict with internal macros used by latex
  • As David points out in the comments, the \pgfmathrandomitem{\d}{} line is wrong. It should be \pgfmathrandomitem{\d}{IfOne}. (OK, since \c is between 2 and 5 this code never gets executed...)
  • You only need to define your random lists once, so you should take the \pgfmathdeclarerandomlist lines out of your Init macro
  • Rather than using \pgfmathsetmacro{\a}{int(random(1,5))} you can use \pgfmathrandominteger{\a}{1}{5}
  • Rather than \foreach \x in {1,2,3,...,#1} it is enough to write \foreach \x in {1,...,#1}
  • \\ is a bad way to end a line ...

Taking these points into account your code becomes:

\documentclass{article}

\usepackage[margin=1cm]{geometry}
\usepackage{ifthen}
\usepackage{pgf}
\usepackage{pgffor}

\setlength{\parindent}{0pt}

\pagestyle{empty}

\pgfmathsetseed{\number\pdfrandomseed}

 % I want the equation to be in the form (ax+b)(cx+d)=Ax^2+Bx+C.
 %but I want there to be NO common factors.
 %So, these lists mean that if, say, c=2, then d is selected randomly from 1,3,5, or 7.... at least that was the intention.
 \pgfmathdeclarerandomlist{IfOne}{{1}{2}{3}{4}{5}{6}{7}}
 \pgfmathdeclarerandomlist{IfTwo}{{1}{3}{5}{7}}
 \pgfmathdeclarerandomlist{IfThree}{{1}{2}{4}{5}{7}}
 \pgfmathdeclarerandomlist{IfFour}{{1}{3}{5}{7}}
 \pgfmathdeclarerandomlist{IfFive}{{1}{2}{3}{4}{6}{7}}

\newcommand{\InitVariablesCTPP}{
 \pgfmathrandominteger{\avar}{1}{5}
 \ifcase\avar\relax%
  \or \pgfmathrandomitem{\bvar}{IfOne}
  \or \pgfmathrandomitem{\bvar}{IfTwo}
  \or \pgfmathrandomitem{\bvar}{IfThree}
  \or \pgfmathrandomitem{\bvar}{IfFour}
  \or \pgfmathrandomitem{\bvar}{IfFive}
 \fi
 \xdef\bvar{\bvar}

 \pgfmathrandominteger{\cvar}{2}{5}
 \ifcase\cvar\relax%
   \or \pgfmathrandomitem{\dvar}{IfOne}
   \or \pgfmathrandomitem{\dvar}{IfTwo}
   \or \pgfmathrandomitem{\dvar}{IfThree}
   \or \pgfmathrandomitem{\dvar}{IfFour}
   \or \pgfmathrandomitem{\dvar}{IfFive}
 \fi
 \xdef\dvar{\dvar}

 \pgfmathsetmacro{\Avar}{int(\avar*\cvar)}
 \pgfmathsetmacro{\Bvar}{int(\avar*\dvar+\bvar*\cvar)}
 \pgfmathsetmacro{\Cvar}{int(\bvar*\dvar)}
}

\newcommand{\ManyCTPP}[1]
 {%
  \foreach \x in {1,...,#1}
  {
   \InitVariablesCTPP
    a=\avar\\
    b=\bvar\\
    c=\cvar\\
    d=\dvar\\
    A=\Avar =\avar * \cvar\relax \\
    B=\Bvar =\avar * \dvar + \bvar * \cvar\relax\\
    C=\Cvar =\bvar * \dvar\relax\\

\(({\avar}x+{\bvar})({\cvar}x+{\dvar})={\Avar}x^2+{\Bvar}x+{\Cvar}\)
\\

\vspace{1cm}}
 }

\begin{document}

\section{Complex Trinomials}

\ManyCTPP{5}

\end{document}

The code above does fix the problem but my theory about what is going wrong is more than a little suspect because if I was right then the following should sometimes result in an error, yet it always compiles without any problem:

\documentclass{article}
\usepackage{pgf}
\usepackage{pgffor}

\pgfmathdeclarerandomlist{one}{{1}{2}{3}{4}{5}{6}{7}{8}{9}}
\pgfmathdeclarerandomlist{two}{{1}{2}{3}{4}}
\pgfmathdeclarerandomlist{three}{{1}{2}{3}{4}{5}{6}}

\begin{document}

% test case
\foreach \n in {1,...,100} {
    \pgfmathrandomitem{\oneval}{one}
    \pgfmathrandomitem{\twoval}{two}
    \pgfmathrandomitem{\threeval}{three}
    \pgfmathparse{int(\oneval*\threeval+\oneval)}
    \n: \pgfmathresult
}

\end{document}

I should carefully reduce the OPs code down to a MWE but I have work to do...

| improve this answer | |
  • Thank you for all your suggestions! I don't think I fully understand your main critique, but the code as you suggested is working and I will study your post more tonight. – WeCanLearnAnything May 22 '17 at 23:15

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.