From 036469499e69e21110bdbbd77af3e90de86a382a Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 8 Sep 2008 00:42:04 +0000 Subject: probsoln 3.0 (27aug08) git-svn-id: svn://tug.org/texlive/trunk@10474 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/tex/latex/probsoln/probsoln.sty | 470 +++++++++++++++------- 1 file changed, 332 insertions(+), 138 deletions(-) (limited to 'Master/texmf-dist/tex/latex/probsoln/probsoln.sty') diff --git a/Master/texmf-dist/tex/latex/probsoln/probsoln.sty b/Master/texmf-dist/tex/latex/probsoln/probsoln.sty index 768917f9a96..fe9a6d3b2b6 100644 --- a/Master/texmf-dist/tex/latex/probsoln/probsoln.sty +++ b/Master/texmf-dist/tex/latex/probsoln/probsoln.sty @@ -7,7 +7,7 @@ %% probsoln.dtx (with options: `probsoln.sty,package') %% %% probsoln.dtx -%% Copyright 2007 Nicola Talbot +%% Copyright 2008 Nicola Talbot %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3 @@ -21,7 +21,7 @@ %% %% The Current Maintainer of this work is Nicola Talbot. %% -%% This work consists of the files probsoln.dtx and probsoln.ins and the derived file probsoln.sty. +%% This work consists of the files probsoln.dtx and probsoln.ins and the derived files probsoln.sty, 1stprncp.tex, args.tex, easy.tex, easy2.tex, implicit.tex, mchoice.tex, newdata.tex, nosoln.tex, probspaces.tex, probspaces2.tex, sample.tex, sample2.tex, sample3.tex, sample4.tex, sample5.tex, tabmchoice.tex. %% %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z @@ -38,95 +38,287 @@ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} +%% randomly select 25 problems from derivatives.tex and add to +%% the data set called 'deriv' +%% Display the problems +%% You may need to change \theenumi back here +%% randomly select 25 problems from probspaces.tex and add to +%% the data set called 'spaces' +%% Display the problems +%% You may need to change \theenumi back here \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{probsoln}[2007/08/21 v2.04 Problems and their Solutions Package (NLCT)] +\ProvidesPackage{probsoln}[2008/08/25 v3.0 (NLCT)] \RequirePackage{ifthen} -\provideboolean{showanswers} -\let\showanswers=\showanswerstrue -\let\hideanswers=\showanswersfalse +\RequirePackage{substr} +\RequirePackage{amsmath} +\newif\ifshowanswers +\showanswersfalse +\let\showanswers\showanswerstrue +\let\hideanswers\showanswersfalse \DeclareOption{answers}{\showanswerstrue} \DeclareOption{noanswers}{\showanswersfalse} -\ExecuteOptions{noanswers} +\newcommand*{\prob@showdraftlabel}[2]{} +\newcommand*{\draftproblemlabel}[2]{[#1,#2]} +\DeclareOption{draft}{% +\renewcommand*{\prob@showdraftlabel}[2]{\draftproblemlabel{#1}{#2}}} +\DeclareOption{final}{% +\renewcommand*{\prob@showdraftlabel}[2]{}} \ProcessOptions -\newif\ifselectrandom \selectrandomfalse -\newif\iffirstpass -\newif\ifselected -\newcommand{\newproblem}{\@ifstar\@snewproblem\@newproblem} -\newcommand{\@newproblem}[4][0]{% -\ifselectrandom -\iffirstpass -\global\advance\@probN by 1 -\expandafter\gdef\csname @problabel\romannumeral\@probN\endcsname{#2}% -\else -\checkselected{#2}% -\ifselected -\@ifundefined{@prob@#2}{% -\ifnum#1=0 -\expandafter\gdef\csname @prob@#2\endcsname{% -#3 \ifshowanswers\begin{solution}#4\end{solution}\fi}% -\expandafter\gdef\csname @prob@#2@arg\endcsname{\relax}% -\else -\message{Problem #2 requires #1 argument(s), please specify (e.g. {5}{3}):}% -\read-1to\@tmp -\expandafter\xdef\csname @prob@#2@arg\endcsname{\@tmp}% -\expandafter\global\expandafter\newcommand\csname @prob@#2\endcsname[#1]{% -#3 \ifshowanswers\begin{solution}#4\end{solution}\fi}% -\fi -}{% -\PackageError{probsoln}{Label #2 already used}% -{Each problem must have a unique label identifier}% +\newcommand*{\prob@db@default}{} +\newcommand*{\prob@databases}{default} +\newcommand*{\prob@newdb}[1]{% +\@ifundefined{prob@db@#1}{% + \expandafter\gdef\csname prob@db@#1\endcsname{}% + \xdef\prob@databases{\prob@databases,#1}% + }{% + \PackageError{probsoln}{Data set `#1' is already defined}{}}} +\newcommand*{\prob@currentdb}{default} +\newcommand{\moveproblem}[3]{% +\@moveproblem{#1}{#2}{#3}% +\expandafter\let\expandafter\@tmpdblist + \csname prob@db@#2\endcsname +\expandafter\gdef\csname prob@db@#2\endcsname{}% +\@for\@tmplab:=\@tmpdblist\do{% + \ifthenelse{\equal{\@tmplab}{#1}}{}{% + \expandafter\ifx\csname prob@db@#2\endcsname\@empty + \expandafter\xdef\csname prob@db@#2\endcsname{\@tmplab}% + \else + \expandafter\xdef\csname prob@db@#2\endcsname{% + \csname prob@db@#2\endcsname,% + \@tmplab}% + \fi + }% }% -\fi -\fi -\else -\@ifundefined{@prob@#2}{% -\expandafter\global\expandafter\newcommand\csname @prob@#2\endcsname[#1]{% -#3 \ifshowanswers\begin{solution}#4\end{solution}\fi}% -}{% -\PackageError{probsoln}{Label #2 already used}% -{Each problem must have a unique label identifier}% } -\fi +\newcommand*{\@moveproblem}[3]{% + \expandafter\ifx\csname prob@db@#3\endcsname\@empty + \expandafter\xdef\csname prob@db@#3\endcsname{#1}% + \else + \expandafter\xdef\csname prob@db@#3\endcsname{% + \csname prob@db@#3\endcsname,#1}% + \fi + \edef\do@movedata{% + \noexpand\global\noexpand\let\expandafter\noexpand + \csname prob@data@#3@#1\endcsname=% + \expandafter\noexpand\csname prob@data@#2@#1\endcsname + \noexpand\global\noexpand\let + \expandafter\noexpand + \csname prob@data@#2@#1\endcsname=\noexpand\undefined + }% + \do@movedata + \edef\do@moveargN{% + \noexpand\global\noexpand\let\expandafter\noexpand + \csname prob@argN@#3@#1\endcsname=% + \expandafter\noexpand\csname prob@argN@#2@#1\endcsname + \noexpand\global\noexpand\let + \expandafter\noexpand + \csname prob@argN@#2@#1\endcsname=\noexpand\undefined + }% + \do@moveargN + \@ifundefined{prob@args@#2@#1}{}{% + \edef\do@moveargs{% + \noexpand\global\noexpand\let\expandafter\noexpand + \csname prob@args@#3@#1\endcsname=% + \expandafter\noexpand\csname prob@args@#2@#1\endcsname + \noexpand\global\noexpand\let + \expandafter\noexpand + \csname prob@args@#2@#1\endcsname=\noexpand\undefined + }% + \do@moveargs + }% } -\newcommand{\@snewproblem}[3][0]{% -\ifselectrandom -\iffirstpass -\global\advance\@probN by 1 -\expandafter\gdef\csname @problabel\romannumeral\@probN\endcsname{#2}% -\else -\checkselected{#2}% -\ifselected -\@ifundefined{@prob@#2}{% -\ifnum#1=0 -\expandafter\gdef\csname @prob@#2\endcsname{#3}% -\expandafter\gdef\csname @prob@#2@arg\endcsname{\relax}% +\newcommand{\prob@newproblem}[4]{% +\@ifundefined{prob@db@#2}{\prob@newdb{#2}}{}% +\@ifundefined{prob@data@#2@#3}{% +\let\@tmp=\undefined +\newcommand\@tmp[#1]{#4}% +\expandafter\global\expandafter\let + \csname prob@data@#2@#3\endcsname=\@tmp +\expandafter\xdef\csname prob@argN@#2@#3\endcsname{\number#1}% +\let\@tmp=\undefined +\expandafter\ifx\csname prob@db@#2\endcsname\@empty + \expandafter\xdef\csname prob@db@#2\endcsname{#3}% \else -\message{Problem #2 requires #1 argument(s), please specify (e.g. {5}{3}):}% -\read-1to\@tmp -\expandafter\xdef\csname @prob@#2@arg\endcsname{\@tmp}% -\expandafter\global\expandafter\newcommand\csname @prob@#2\endcsname[#1]{#3}% -\fi -}{% -\PackageError{probsoln}{Label #2 already used}% -{Each problem must have a unique label identifier}% -}% + \expandafter\xdef\csname prob@db@#2\endcsname{% + \csname prob@db@#2\endcsname,#3}% \fi +\ifnum#1>0\relax + \@prob@do@getargs{#1}{#2}{#3}% \fi + }{% + \PackageError{probsoln}{Problem `#3' is already defined for + data base `#2'}{Problem labels must be unique for each data base}}% +} +\newcommand{\@prob@gobblethree}[3]{} +\newcommand{\@prob@getargs}[3]{% +\message{Problem `#3' (in data base `#2') requires #1 argument(s).^^J +Please specify (e.g. {5}{3}):}% +\read-1to\@tmp +\expandafter\global\expandafter\let + \csname prob@args@#2@#3\endcsname=\@tmp +} +\let\@prob@do@getargs\@prob@gobblethree +\long\def\long@collect@body#1{% + \@envbody{\@xp#1\@xp{\the\@envbody}}% + \edef\process@envbody{\the\@envbody\@nx\end{\@currenvir}}% + \@envbody\@emptytoks \def\begin@stack{b}% + \begingroup + \@xp\let\csname\@currenvir\endcsname\long@collect@@body + \edef\process@envbody{\@xp\@nx\csname\@currenvir\endcsname}% + \process@envbody +} +\long\def\long@addto@envbody#1{\global\@envbody\@xp{\the\@envbody#1}} +\long\def\long@collect@@body#1\end#2{% + \edef\begin@stack{\long@push@begins#1\begin\end \@xp\@gobble\begin@stack}% + \ifx\@empty\begin@stack + \endgroup + \@checkend{#2}% + \long@addto@envbody{#1}% + \else + \long@addto@envbody{#1\end{#2}}% + \fi + \process@envbody +} +\long\def\long@push@begins#1\begin#2{% + \ifx\end#2\else b\@xp\long@push@begins\fi +} +\newenvironment{defproblem}[2][0]{% + \def\@prob@currentargN{#1}% + \def\@prob@currentlabel{#2}% + \long@collect@body\prob@do@defproblem +}{} +\newcommand{\prob@do@newproblem}[1]{% +\prob@newproblem\@prob@currentargN\prob@currentdb + \@prob@currentlabel{#1}} +\let\prob@do@defproblem=\prob@do@newproblem +\newenvironment{onlysolution}{% + \long@collect@body\do@onlysolution +}{} +\newcommand{\do@onlysolution}[1]{% +\ifshowanswers + #1% +\fi} +\newenvironment{onlyproblem}{% + \long@collect@body\do@onlyproblem +}{} +\newcommand{\do@onlyproblem}[1]{% +\ifshowanswers \else -\@ifundefined{@prob@#2}{% -\expandafter\global\expandafter\newcommand\csname @prob@#2\endcsname[#1]{#3}% + #1% +\fi} +\newcommand{\useproblem}[2][default]{% +\prob@showdraftlabel{#1}{#2}% +\let\@next=\relax +\@ifundefined{prob@data@#1@#2}{% + \PackageError{probsoln}{Problem `#2' is not defined in data set + `#1'}{}% }{% -\PackageError{probsoln}{Label #2 already used}% -{Each problem must have a unique label identifier}% + \def\@next{\csname prob@data@#1@#2\endcsname}% +}% +\@next} +\newcommand*{\loadallproblems}[2][default]{% +\bgroup + \let\par\relax + \edef\prob@currentdb{#1}% + \input{#2}% +\egroup +} +\newcommand{\prob@do@selectedproblem}[1]{% +\IfSubStringInString{,\@prob@currentlabel,}{,\prob@selectedlabels,}{% +\prob@do@newproblem{#1}}{}% +} +\newcommand{\loadselectedproblems}[3][default]{% +\bgroup + \let\par\relax + \edef\prob@currentdb{#1}% + \edef\prob@selectedlabels{#2}% + \let\prob@do@defproblem=\prob@do@selectedproblem + \input{#3}% +\egroup } +\newcommand{\prob@add@currentlabel}[1]{% +\ifx\prob@selectedlabels\@empty + \xdef\prob@selectedlabels{\@prob@currentlabel}% +\else + \xdef\prob@selectedlabels{\prob@selectedlabels,\@prob@currentlabel}% \fi } -\newcommand*{\useproblem}[1]{% -\@ifundefined{@prob@#1}{% -\PackageError{probsoln}{Label #1 undefined}% -{Can't find problem defined with label identifier `#1'}% -}{\csname @prob@#1\endcsname}% +\newif\iffirstpass +\firstpasstrue +\newcommand{\loadrandomproblems}[3][default]{% +\bgroup + \let\par\relax + \def\prob@db@reserved{}% + \def\prob@currentdb{reserved}% + \edef\prob@selectedlabels{}% + \let\prob@do@defproblem=\prob@add@currentlabel + \firstpasstrue + \input{#3}% + \@probselN=0\relax + \@for\@thislabel:=\prob@selectedlabels\do{% + \advance\@probselN by 1\relax + \expandafter + \edef\csname @prob@tmp@\romannumeral\@probselN\endcsname{% + \@thislabel}% + }% + \shuffle{@prob@tmp@}{\@probselN}% + \ifnum\@probselN<#2\relax + \PackageError{probsoln}{% + Can't select \number#2\space\space problem(s):^^J + '#3' only contains \number\@probselN\space problem(s)}{% + Only \number\@probselN\space problem(s) will be selected}% + \else + \@probselN=#2\relax + \fi + \@probN=0\relax + \def\prob@selectedlabels{}% + \whiledo{\@probN<\@probselN}{% + \advance\@probN by 1\relax + \ifx\prob@selectedlabels\@empty + \edef\prob@selectedlabels{% + \csname @prob@tmp@\romannumeral\@probN\endcsname}% + \else + \edef\prob@selectedlabels{% + \prob@selectedlabels,% + \csname @prob@tmp@\romannumeral\@probN\endcsname}% + \fi + }% + \let\prob@do@defproblem=\prob@do@selectedproblem + \firstpassfalse + \input{#3}% +\@ifundefined{prob@db@#1}{\prob@newdb{#1}}{}% +\@for\@thislabel:=\prob@selectedlabels\do{% + \@moveproblem{\@thislabel}{reserved}{#1}% +}% + \let\prob@selectedlabels=\undefined +\egroup +} +\newcommand{\foreachproblem}[2][default]{% +\@ifundefined{prob@db@#1}{% + \PackageError{probsoln}{Data base `#1' is not defined}{}% +}{% + \expandafter\let\expandafter\@tmp\csname prob@db@#1\endcsname + \@for\thisproblemlabel:=\@tmp\do{% + \expandafter\ifnum + \csname prob@argN@#1@\thisproblemlabel\endcsname>0\relax + \@ifundefined{prob@args@#1@\thisproblemlabel}{% + \expandafter\@prob@getargs + \csname prob@argN@#1@\thisproblemlabel\endcsname + {#1}{\thisproblemlabel}}{}% + \expandafter\let\expandafter\thisproblemargs + \csname prob@args@#1@\thisproblemlabel\endcsname + \else + \let\thisproblemargs\@empty + \fi + \expandafter\toks@\expandafter{\thisproblemargs}% + \edef\thisproblem{\noexpand\useproblem[#1]{\thisproblemlabel}% + \the\toks@}% + #2% + }% +}% } +\newcommand{\foreachdataset}[2]{% +\@for#1:=\prob@databases\do{#2}} \newcount\@probN \newcount\@probselN \newcount\@rndselctr \newcount\r@ndcur \newcount\@ps@randtmp @@ -134,21 +326,24 @@ \newcommand*{\PSNrandseed}[1]{% \ifnum#1=0\relax \PackageWarning{probsoln}{Can't have 0 as random seed, changing to 1}% - \r@ndcur=1\relax + \global\r@ndcur=1\relax \else - \r@ndcur=#1\relax + \global\r@ndcur=#1\relax \fi \PackageInfo{probsoln}{Random Seed = \number\r@ndcur}% } +\newcommand*{\PSNgetrandseed}[1]{#1=\r@ndcur\relax} \newcommand*{\PSNrand}{% \@ps@randtmp=\r@ndcur \multiply\@ps@randtmp by 16807\relax \r@ndcur=\@ps@randtmp -\divide\r@ndcur by 120001\relax -\multiply\r@ndcur by 120001\relax +\global\divide\r@ndcur by 120001\relax +\global\multiply\r@ndcur by 120001\relax \advance\@ps@randtmp by -\r@ndcur -\r@ndcur = \@ps@randtmp -\ifnum\r@ndcur=0\relax\r@ndcur=1\fi +\global\r@ndcur = \@ps@randtmp +\ifnum\r@ndcur=0\relax + \global\r@ndcur=1\relax +\fi } \newcommand{\PSNrandom}[2]{% \PSNrand @@ -171,64 +366,6 @@ \addtocounter{#1}{-1}% \fi } -\newcommand*{\selectallproblems}[1]{% -\global\@probN=0\relax -\selectrandomtrue -\firstpasstrue -\input{#1}% -\firstpassfalse -\selectrandomfalse -\input{#1}% -\global\@rndselctr=1\relax -\whiledo{\@rndselctr < \@probN \TE@or \@rndselctr = \@probN}{% -\edef\@tmp{\csname @problabel\romannumeral\@rndselctr\endcsname}% -\edef\@probargs{{\@tmp}\csname @prob@\@tmp @arg\endcsname}% -\PSNitem \expandafter\useproblem\@probargs \endPSNitem -\global\advance\@rndselctr by 1\relax -}} -\newcommand*{\selectrandomly}[2]{% -\global\@probselN=#2\relax -\global\@probN=0\relax -\selectrandomtrue -\firstpasstrue -\input{#1}% -\ifnum\@probselN>\@probN - \PackageError{probsoln}{Requested number too large}% - {You have asked for \the\@probselN \space problems, - but there are only \the\@probN \space problems defined in the - file #1. I will only select \the\@probN \space - problems.}% - \global\@probselN=\@probN -\fi -\shuffle{@problabel}{\@probN}% -\firstpassfalse -\input{#1}% -\selectrandomfalse -\global\@rndselctr=1\relax -\whiledo{\@rndselctr < \@probselN \TE@or \@rndselctr = \@probselN}{% -\edef\@tmp{\csname @problabel\romannumeral\@rndselctr\endcsname}% -\edef\@probargs{{\@tmp}\csname @prob@\@tmp @arg\endcsname}% -\PSNitem \expandafter\useproblem\@probargs \endPSNitem -\global\advance\@rndselctr by 1\relax -}% -} -\newcommand*{\PSNitem}{\item} -\@ifundefined{endPSNitem}{\def\endPSNitem{}}{% -\PackageError{probsoln}{\string\endPSitem\ already defined}{}} -\providecommand*{\solutionname}{Solution} -\@ifundefined{solution}{% -\newenvironment{solution}{\par\noindent\textbf{\solutionname:} }{}}{% -} -\newcount\@ckselctr -\newcommand*{\checkselected}[1]{% -\selectedfalse -\@ckselctr=1\relax -\whiledo{\@ckselctr < \@probselN \TE@or \@ckselctr = \@probselN}{% -\ifthenelse{\equal{#1}{\csname @problabel\romannumeral\@ckselctr\endcsname}}% -{\global\selectedtrue \global\@ckselctr=\@probselN}{}% -\advance\@ckselctr by 1\relax -}% -} \newcount\@shfctr \newcount\@shfA \newcount\@shfB \newcommand{\shuffle}[2]{% \@shfctr=1\relax @@ -269,6 +406,63 @@ are only \number\@ps@forrand item(s) in the list}% \fi \fi }} +\newcommand*{\newproblem}{\@ifstar\@snewproblem\@newproblem} +\newcommand{\@snewproblem}[3][0]{% +\begin{defproblem}[#1]{#2}% +#3% +\end{defproblem}} +\newcommand{\@newproblem}[4][0]{% +\begin{defproblem}[#1]{#2}% +#3% +\begin{onlysolution}% +\begin{solution}% +#4% +\end{solution}% +\end{onlysolution}% +\end{defproblem}} +\newcommand*{\selectallproblems}[1]{{\loadallproblems[#1]{#1}}% +\foreachproblem[#1]{\PSNitem\thisproblem\endPSNitem}} +\newcommand*{\selectrandomly}[2]{% +{\loadrandomproblems[#1]{#2}{#1}}% +\foreachproblem[#1]{\PSNitem\thisproblem\endPSNitem}% +} +\newenvironment{PSNitem}{\item}{} +\@ifundefined{solution}{% +\newenvironment{solution}{\par\noindent\textbf{\solutionname:}}{}% +}{} +\newcommand*{\solutionname}{Solution} +\newenvironment{textenum}{% +\ifnum\@enumdepth>\thr@@ + \@toodeep +\else + \advance\@enumdepth\@ne + \edef\@enumctr{enum\romannumeral\the\@enumdepth}% + \let\@item\@textitem + \def\@itemlabel{\refstepcounter{\@enumctr}% + \csname label\@enumctr\endcsname}% + \setcounter{\@enumctr}{0}% +\fi\ignorespaces}{% +\global\advance\@enumdepth\m@ne} +\def\@textitem[#1]{#1\space\ignorespaces} +\newcommand*{\correctitemformat}[1]{\fbox{#1}} +\newcommand*{\incorrectitemformat}[1]{% +\hspace{\fboxsep}\hspace{\fboxrule}#1} +\newcommand*{\correctitem}{\@inmatherr\correctitem +\@ifnextchar[\@correctitem{\@noitemargtrue\@correctitem[\@itemlabel]}} +\def\@correctitem[#1]{% +\ifshowanswers + \@item[\correctitemformat{#1}]% +\else + \@item[#1]% +\fi} +\newcommand*{\incorrectitem}{\@inmatherr\incorrectitem +\@ifnextchar[\@incorrectitem{\@noitemargtrue\@incorrectitem[\@itemlabel]}} +\def\@incorrectitem[#1]{% +\ifshowanswers + \@item[\incorrectitemformat{#1}]% +\else + \@item[#1]% +\fi} \endinput %% %% End of file `probsoln.sty'. -- cgit v1.2.3