share
TeX - LaTeXRandom quadratic equation
[+18] [6] Roland
[2012-10-30 21:27:45]
[ pgfmath ]
[ https://tex.stackexchange.com/questions/79775/random-quadratic-equation ]

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 ?

(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.) - Qrrbrbirlbel
(1) Your question is similar to this one Maybe something useful in those answers as well? - DJP
[+17] [2012-10-31 00:22:04] percusse [ACCEPTED]

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


1
[+14] [2012-10-31 00:11:01] Qrrbrbirlbel

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


@Percusse \lbreak - Roland
@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
@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. - Qrrbrbirlbel
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
2
[+11] [2012-10-31 00:37:19] Scott H.

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


Your code tells me : learn lua ! :-) I need to do this, it will be easier than learn TeX ... - Roland
3
[+6] [2012-10-31 02:12:30] Peter Grill

Here is a version that is adapted from Generating a worksheet [1]. 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) [2] (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}
[1] https://tex.stackexchange.com/questions/42173/generating-a-worksheet/
[2] https://tex.stackexchange.com/questions/28628/automatically-add-fractions-and-reduce-the-result-if-neccessary

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
@Roland: tkx-fct is only need to be able to provided reduced fractions. - Peter Grill
4
[+5] [2012-10-31 15:44:59] G. Poore

Here's a solution using PythonTeX [1]. 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] https://github.com/gpoore/pythontex

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
5
[+1] [2012-10-31 21:03:51] Roland

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}

6