18

I would like to produce quadratic equation with integer coefficients. Here's my code using pgfmath.

\documentclass{article}
\usepackage{tikz}
\pgfmathsetseed{\pdfuniformdeviate 10000000} 
\begin{document}
$\pgfmathdeclarerandomlist{signe}{{+}{-}}%
\pgfmathrandomitem{\s}{signe}%
\pgfmathparse{random(2)}%
\pgfmathparse{ifthenelse(\pgfmathresult==1,"-"," ")}\pgfmathresult
\pgfmathrandominteger{\a}{1}{6}
\pgfmathparse{ifthenelse(\a==1," x^{2} ","\a x^{2}")}\pgfmathresult % coeff a
\pgfmathdeclarerandomlist{lincoeff}{{}{2}{3}{4}{5}{6}}
\pgfmathrandomitem{\b}{lincoeff}%
\pgfmathrandomitem{\s'}{signe}%
\pgfmathsetmacro{\e}{random(0,6)}
\pgfmathparse{ifthenelse(\e==0," ", " \s' \b x ")}\pgfmathresult % coeff b
\pgfmathrandominteger{\c}{0}{6}
\pgfmathrandomitem{\s''}{signe}%
\pgfmathparse{ifthenelse(\c==0,"","\s'' \c")}\pgfmathresult % coeff c
=0$
\end{document}

It works but it seems to be not a good way, I had some pain with the x-coeficient and my solution looks complicated. I tried to use an ifthenelse inside an other ifthenelse but without success. Is there a better way ?

2
  • 1
    Welcome to TeX.sx! Do you have a pseudo code within reach? Instead of randomizing over + or - I would just randominteger between -6 and 6, for example. (If 0 is not allowed put it in a loop that is exited when the result is not 0.) Oct 30, 2012 at 23:39
  • 1
    Your question is similar to this one Maybe something useful in those answers as well?
    – DJP
    Oct 31, 2012 at 1:13

6 Answers 6

17

Lots of if :)

\documentclass{article}
\usepackage{tikz}

\pgfmathsetseed{\pdfuniformdeviate 10000000} 

\newcommand{\rndcoeff}[1][1]{
\pgfmathrandominteger{\a}{\ifnum#1>1 1\else0\fi}{6}
\ifnum#1>1
    \pgfmathparse{rand>0?:"-"}\pgfmathresult\ifnum\a=1\else\a\fi x^2
\else
    \ifnum#1<1\relax
        \ifnum\a>0\relax
            \pgfmathparse{rand>0?"+":"-"}\pgfmathresult\a
        \fi
        \let\a\relax
    \else
    \ifnum\a>0\pgfmathparse{rand>0?"+":"-"}\pgfmathresult\ifnum\a=1\else\a\fi x\fi
    \fi
\fi
}
\newcommand{\givemesomequads}{
\rndcoeff[2]\rndcoeff\rndcoeff[0] = 0
}
\begin{document}
\foreach \x in {1,...,10}{
$\givemesomequads$ \par
}
\end{document}

enter image description here

14

Well, here is a solution that uses pgf only for the random integers.

Everything else is done with TeX's own conditionals and, in one instance, a loop.

Code

\documentclass{article}
\usepackage{pgf}

\pgfmathsetseed{\pdfuniformdeviate 10000000}

\newcommand*\MakeFirstTerm[2]{
    \loop\pgfmathrandominteger{\a}{#1}{#2}
        \ifnum\a<0\relax
            \let\iterate\relax
        \else\ifnum\a>0\relax
            \let\iterate\relax
        \fi
    \repeat
    \ifnum\a=1\relax\else
        \a
    \fi
}

\newcommand*\MakeTerm[3][]{
    \pgfmathrandominteger{\a}{#2}{#3}
    \ifnum\a=0\relax\else
        \ifnum\a<0\relax\else+\fi
        \a#1
    \fi
}
\newcommand*{\quadeq}{
    \MakeFirstTerm{-6}{6}x^2 \MakeTerm[x]{-6}{6} \MakeTerm{-6}{6} = 0
}
\begin{document}
$\quadeq$ \par $\quadeq$ \par $\quadeq$ \par $\quadeq$ \par $\quadeq$
\end{document}

Output

enter image description here

4
  • @Percusse \lbreak
    – Roland
    Oct 31, 2012 at 11:10
  • @Percusse Not easy for me to comment :-) I have learnt with your two codes. It seems necessary to use a TeX-primitive like \ifnum or \loop. I thought it was possible only with pgfmath commands.
    – Roland
    Oct 31, 2012 at 11:15
  • @Roland I just noticed that my solution gives leading 1 for all \MakeTerms. This is probably not allowed in front of x`. I can later post a correction … but I'm sure with all the answers here you can easily whip something up. Oct 31, 2012 at 11:29
  • I didn't see that first time, so I just add some lines in my answer, which is yours in fact. May be it is not the more compact way but it's simple.
    – Roland
    Oct 31, 2012 at 20:41
11

Here's a pair of lualatex solutions. Both provide \genrand which takes an optional integer argument that specifies the maximum (absolute) value of the coefficients, the default is 10. The first uses pattern matching and the second is a somewhat odd variation of the standard approach.

Pattern Matching:

\documentclass{article}
\usepackage{luacode}
\begin{luacode*}
local rand = math.random
function makequad(n)
    n = n or 10
    local a,b,c = rand(-n,n),rand(-n,n),rand(-n,n)
    while a==0 do a = rand(-n,n) end
    local s = a.."x^2".."+"..b.."x".."+"..c
    s = string.gsub(s,"%+%-","-") 
    s = string.gsub(s,"[%D]0[^%d]?","")
    s = string.gsub(s,"([+-])1x","%1x")
    s = string.gsub(s,"^([%D]?)1x","%1x")
    tex.sprint(s.."=0")
end
\end{luacode*}

\newcommand\genquad[1][]{\directlua{makequad(#1)}}

\begin{document}
$\genquad$\par
$\genquad[20]$
\end{document} 

Odd variation of standard approach (I was trying to be clever):

\documentclass{article}
\usepackage{luacode}
\begin{luacode*}
local rand = math.random

local function zapone(n)
    if math.abs(n)==1 then
        n = ""
    end -- if
    return n
end -- function

local function gensign(x)
    local n = rand(1,2)
    if n > 1 then 
        return "-"
    elseif x == nil then 
        return ""
    end -- if
    return "+"
end -- function

function makequad(n)
    n = n or 10
    local a,b,c = rand(1,n),rand(0,n),rand(1,n)
    if b==0 then
        tex.print(gensign()..zapone(a).."x^2"..gensign(1)..c.."=0")
    else
        tex.print(gensign()..zapone(a).."x^2"..gensign(1)..zapone(b).."x"..gensign(1)..c.."=0")
    end -- if
end -- function
\end{luacode*}

\newcommand\genquad[1][]{\directlua{makequad(#1)}}

\begin{document}
$\genquad$\par
$\genquad[20]$
\end{document} 

enter image description here

1
  • Your code tells me : learn lua ! :-) I need to do this, it will be easier than learn TeX ...
    – Roland
    Oct 31, 2012 at 11:18
6

Here is a version that is adapted from Generating a worksheet. I have enhanced this earlier solution by including an automatic conversion to a reduced faction for the case of equal roots using the techniques outlined in Automatically add fractions and reduce the result (if neccessary) (Many thanks to Qrrbrbirlbel for helping to locate my previous answers).

Notes:

  • I define \newcommand*{\Difficulty}{10}. This number is used to determine the range of the random numbers that are generated. In this case with it set to 10, the random numbers will be real numbers in the range 1...10.

Further Improvements:

  • Complete macros to generate only quadratic equations with distinct real and imaginary roots.
  • Generate negative numbers as well. In this case it would be advisable to include some logic so that we do not end up with + - as in the linked to example in the question. One way would be just to generate another random number from 0..1 and use a - sign instead of a + sign (or no sign as in the leading numbers) if the random number generated was greater than 0.6 (assuming you wanted approximately 40% of the questions to have negative signs, which also controls the level of difficulty dependent on the grade level).

enter image description here

Code:

\documentclass{article}
\usepackage{mathtools}
\usepackage{xstring}
\usepackage{enumitem}
\usepackage{tikz}

\usepackage{tkz-fct}

% https://tex.stackexchange.com/questions/28628/automatically-add-fractions-and-reduce-the-result-if-neccessary/
\newcommand*{\fracReducedTkz}[2]{\tkzReducFrac{#1}{#2}\frac{\tkzMathFirstResult}{\tkzMathSecondResult}}%


\newcommand*{\SuppresIfLeadingOne}[1]{%
    \IfEq{#1}{1}{}{\pgfmathprintnumber[int detect]{#1}}%
}%

% https://tex.stackexchange.com/questions/42173/generating-a-worksheet/
\newcommand*{\Difficulty}{10}%

\newcommand{\QuadraticEquations}[1]{%
    \foreach \i in {1,...,#1}{%
      \pgfmathtruncatemacro{\A}{random(\Difficulty)}%
      \pgfmathtruncatemacro{\B}{random(\Difficulty)}%
      \pgfmathtruncatemacro{\C}{random(\Difficulty)}%
      \item   $\SuppresIfLeadingOne{\A} x^2 + 
              \SuppresIfLeadingOne{\B} x + 
              \pgfmathprintnumber[int detect]{\C}% Don't suppress this if it is a one
              = 0$% 
    }%
}%

\newcommand{\QuadraticEquationsEqualRoots}[1]{%
    \foreach \i in {1,...,#1}{%
      \pgfmathtruncatemacro{\A}{random(\Difficulty)}%
      \pgfmathtruncatemacro{\B}{random(\Difficulty)}%
      \pgfmathtruncatemacro{\numerator}{\B*\B}
      \pgfmathtruncatemacro{\denominator}{4*\A}
      \item   $\SuppresIfLeadingOne{\A} x^2 + 
              \SuppresIfLeadingOne{\B} x + 
              \fracReducedTkz{\numerator}{\denominator}% Don't suppress this if it is a one
              = 0$%  
    }%
}%



\begin{document}
\section{Random Quadratic Equations:}
\begin{enumerate}
  \QuadraticEquations{4}
\end{enumerate}
%
\section{Random Quadratic Equations (Equal Roots):}
\begin{enumerate}
  \QuadraticEquationsEqualRoots{4}
\end{enumerate}
\end{document}
2
  • I save that to study later, there are a lot of commands I don't know and neither tkz-fct, although I use tkz-tab a lot.
    – Roland
    Oct 31, 2012 at 11:23
  • @Roland: tkx-fct is only need to be able to provided reduced fractions. Oct 31, 2012 at 16:57
5

Here's a solution using PythonTeX. If all you need is just random quadratics, then the lualatex and pgf solutions are probably better. But if you will ultimately be working with the equations, then access to Python's SymPy library for symbolic math may be useful. One advantage of this approach is that the code is very compact, since SymPy does all the work for us.

\documentclass{article} 

\usepackage{pythontex}

\begin{document}

\begin{sympycode}
from sympy.stats import DiscreteUniform, sample
x = Symbol('x')
a = DiscreteUniform('a', range(-10, 11))
b = DiscreteUniform('b', range(-10, 11))
c = DiscreteUniform('c', range(-10, 11))
def randquad():
    return Eq(sample(a)*x**2 + sample(b)*x + sample(c))
\end{sympycode}

\newcommand\randquad{\sympy{randquad()}}


\[ \randquad \]

\[ \randquad \]

\[ \randquad \]


\end{document}

sample equations

Currently, the Python code can't be in the preamble, but that will be fixed in the next release, which should be out soon.

1
  • It looks very compact indeed ! However I dont'have the pythontex package in TeXLive 2012 so I could not try your answer. There is a another problem, more important :-), I don't know Python et I am not a programmer at all, so if I can learn some simple features of TeX (like \ifnum) et a bit of luatex it will be already a lot !
    – Roland
    Oct 31, 2012 at 20:37
1

Here's Qrrbrbirlbel answer with some more if to avoid the 1 before x.

\documentclass{article}
\usepackage{pgf}

\pgfmathsetseed{\pdfuniformdeviate 10000000}

\newcommand*\MakeFirstTerm[2]{
\loop\pgfmathrandominteger{\a}{#1}{#2}
    \ifnum\a<0\relax
        \let\iterate\relax
    \else\ifnum\a>0\relax
        \let\iterate\relax
    \fi
\repeat
\ifnum\a=1\relax\else
\ifnum \a=-1 -\relax \else
   \a
  \fi
\fi
}

\newcommand*{\MakeSecondTerm}[2]{
\pgfmathrandominteger{\a}{#1}{#2}
\ifnum \a=0\relax \else
\ifnum \a>1 + \a x \relax \else
  \ifnum \a=1 +x\relax \else
     \ifnum \a=-1 -x\relax \else
         \a x \relax
     \fi
   \fi
 \fi
\fi
}

\newcommand*{\MakeThirdTerm}[2]{
\pgfmathrandominteger{\a}{#1}{#2}
\ifnum \a=0\relax \else
  \ifnum \a<0 \a\relax \else
    +\a\relax
  \fi
\fi
}

\newcommand*{\quadeq}{
\MakeFirstTerm{-6}{6}x^2 \MakeSecondTerm{-6}{6} \MakeThirdTerm{-6}{6} = 0
}
\begin{document}
$\quadeq$ \par $\quadeq$ \par $\quadeq$ \par $\quadeq$ \par $\quadeq$
\end{document}

You must log in to answer this question.

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