%%
%% This is file `probsoln.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% probsoln.dtx  (with options: `probsoln.sty,package')
%% 
%%  probsoln.dtx
%%  Copyright 2013 Nicola Talbot
%% 
%%  This work may be distributed and/or modified under the
%%  conditions of the LaTeX Project Public License, either version 1.3
%%  of this license of (at your option) any later version.
%%  The latest version of this license is in
%%    http://www.latex-project.org/lppl.txt
%%  and version 1.3 or later is part of all distributions of LaTeX
%%  version 2005/12/01 or later.
%% 
%%  This work has the LPPL maintenance status `maintained'.
%% 
%%  The Current Maintainer of this work is Nicola Talbot.
%% 
%%  This work consists of the files probsoln.dtx and probsoln.ins and the derived files probsoln.sty, sample-exclude.tex, sample.tex, sample2.tex, sample3.tex, sample4.tex, sample5.tex, sample6.tex, sample7.tex, sample8.tex, prob-1stprncp.tex, prob-args.tex, prob-easy.tex, prob-easy2.tex, prob-implicit.tex, prob-mchoice.tex, prob-mixed.tex, prob-newdata.tex, prob-nosoln.tex, prob-probspaces.tex, prob-probspaces2.tex, prob-tabmchoice.tex, prob-verb.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
%%   Lower-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
%%   Digits        \0\1\2\3\4\5\6\7\8\9
%%   Exclamation   \!     Double quote  \"     Hash (number) \#
%%   Dollar        \$     Percent       \%     Ampersand     \&
%%   Acute accent  \'     Left paren    \(     Right paren   \)
%%   Asterisk      \*     Plus          \+     Comma         \,
%%   Minus         \-     Point         \.     Solidus       \/
%%   Colon         \:     Semicolon     \;     Less than     \<
%%   Equals        \=     Greater than  \>     Question mark \?
%%   Commercial at \@     Left bracket  \[     Backslash     \\
%%   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}[2012/08/23 v3.04 (NLCT)]
\RequirePackage{ifthen}
\RequirePackage{amsmath}
\RequirePackage{etoolbox}
\newif\ifshowanswers
\showanswersfalse
\let\showanswers\showanswerstrue
\let\hideanswers\showanswersfalse
\DeclareOption{answers}{\showanswerstrue}
\DeclareOption{noanswers}{\showanswersfalse}
\newif\ifusedefaultprobargs
\DeclareOption{usedefaultargs}{\usedefaultprobargstrue}
\DeclareOption{nousedefaultargs}{\usedefaultprobargsfalse}
\usedefaultprobargsfalse
\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
\RequirePackage{xkeyval}
\define@boolkey{probsoln}[@prob@]{fragile}[true]{}
\newcommand*{\ProbSolnFragileExt}{vrb}
\newcommand*{\ProbSolnFragileFile}{\jobname}
\newwrite\probsoln@write
\newcount\probsoln@startyear
\newcommand*{\SetStartYear}[1]{%
   \probsoln@startyear=#1\relax
   \renewcommand\SetStartMonth[1]{%
      \PackageError{probsoln}{\string\SetStartMonth\space
        can't be used after \string\SetStartYear}{}}%
}
\newcommand*{\GetStartYear}{\probsoln@startyear}
\newcount\probsoln@startmonth
\newcommand*{\SetStartMonth}[1]{%
  \probsoln@startmonth=#1\relax
  \probsoln@startyear=\year\relax
  \ifnum\month<\probsoln@startmonth
    \advance\probsoln@startyear by -1\relax
  \fi
}
\SetStartMonth{9}
\newwrite\probsoln@prev
\newwrite\probsoln@used
\newcount\probsoln@prev@cutoff
\newcommand*{\@probsoln@usedfilename}{\jobname.prb}
\newcommand*{\SetUsedFileName}[1]{%
  \renewcommand*{\@probsoln@usedfilename}{#1}%
}
\newcommand*{\ClearUsedFile}[1]{%
  \probsoln@prev@cutoff=0\relax
  \@probsoln@readprev{#1}%
  \@for\@this@db:=\prob@databases\do{%
    {%
      \edef\@prev@list{\csname probsoln@prev@list@\@this@db\endcsname}%
      \ifdefempty{\@prev@list}%
      {}%
      {%
        \@for\@this@label:=\@prev@list\do{%
          \ifcsundef{@used@problem@\@this@db @\@this@label}%
          {%
            \immediate\write\probsoln@prev{%
              \string\previousproblem{\@this@label}{\@this@db}%
               {\csname @prev@problem@\@this@db @\@this@label\endcsname}}%
          }%
          {}%
        }%
      }%
    }%
  }%
  \immediate\closeout\probsoln@prev
  \immediate\closeout\probsoln@used
  \@disable@exclude@prev
}
\newcommand*{\ExcludePreviousFile}[2][3]{%
  \probsoln@prev@cutoff=\probsoln@startyear\relax
  \advance\probsoln@prev@cutoff by -#1\relax
  \@probsoln@readprev{#2}%
  \@write@prev
  \def\ExcludePreviousFile[2][3]{\PackageError{probsoln}{Only one
    instance of \string\ExcludePreviousFile\space allowed}{You've
    already used this command. You are only allowed to use it once}}%
  \def\ClearUsedFile[1]{%
     \PackageError{probsoln}%
       {\string\ClearUsedFile\space may not be used after
          \string\ExcludePreviousFile}{}}%
}
\newcommand*{\@probsoln@readprev}[1]{%
  \@enable@exclude@prev
  \InputIfFileExists{#1}%
     {\PackageInfo{probsoln}%
        {Excluded problem file `#1' found}}%
     {\PackageInfo{probsoln}%
        {Excluded problem file `#1' not found. A new one will be
            created}}%
  \InputIfFileExists{\@probsoln@usedfilename}%
     {\PackageInfo{probsoln}%
        {Current problems file `\@probsoln@usedfilename' found}}%
     {\PackageInfo{probsoln}%
        {No current problem file `\@probsoln@usedfilename' found. A new one will be created}}%
  \immediate\openout\probsoln@prev=#1
  \immediate\openout\probsoln@used=\@probsoln@usedfilename
}
\newcommand*{\probsoln@prev@list@default}{}
\newcommand*{\@write@prev}{%
  \@for\@this@db:=\prob@databases\do{%
    {%
      \edef\@prev@list{\csname probsoln@prev@list@\@this@db\endcsname}%
      \ifdefempty{\@prev@list}%
      {}%
      {%
        \@for\@this@label:=\@prev@list\do{%
          \immediate\write\probsoln@prev{%
            \string\previousproblem{\@this@label}{\@this@db}%
             {\csname @prev@problem@\@this@db @\@this@label\endcsname}}%
        }%
      }%
    }%
  }%
}
\newcommand*{\@enable@exclude@prev}{%
  \renewcommand*{\@add@used@problem}[2]{%
    \immediate\write\probsoln@used{\string\usedproblem{##1}{##2}{\number\probsoln@startyear}}%
    \ifcsundef{@prev@problem@##2@##1}%
    {%
      \immediate\write\probsoln@prev{%
          \string\previousproblem{##1}{##2}{\number\probsoln@startyear}}%
      \expandafter\xdef\csname @prev@problem@##2@##1\endcsname{%
          \number\probsoln@startyear}%
    }%
    {%
      \expandafter\ifnum\csname @prev@problem@##2@##1\endcsname
         <\probsoln@startyear
      \immediate\write\probsoln@prev{%
          \string\previousproblem{##1}{##2}{\number\probsoln@startyear}}%
      \expandafter\xdef\csname @prev@problem@##2@##1\endcsname{%
          \number\probsoln@startyear}%
      \fi
    }%
  }%
  \renewcommand*{\@fetch@excluded@list}[2]{%
    \def##1{}%
    \ifcsdef{probsoln@prev@list@##2}%
    {%
      \edef\@prev@list{\csname probsoln@prev@list@##2\endcsname}%
      \@for\@this@label:=\@prev@list\do{%
       \ifcsundef{@used@problem@##2@\@this@label}%
       {%
          \ifcsempty{##1}%
          {\edef##1{\@this@label}}%
          {\edef##1{##1,\@this@label}}%
       }%
       {}%
      }%
    }%
    {}%
  }%
  \renewcommand*{\@add@newprevlist}[1]{%
     \expandafter\gdef\csname probsoln@prev@list@##1\endcsname{}%
  }%
  \renewcommand*{\close@probsoln@prev}{%
    \closeout\probsoln@prev
    \closeout\probsoln@used
  }%
}
\newcommand*{\@disable@exclude@prev}{%
  \renewcommand*{\@add@used@problem}[2]{}%
  \renewcommand*{\@fetch@excluded@list}[2]{\def##1{}}%
  \renewcommand*{\@add@newprevlist}[1]{}%
  \renewcommand*{\close@probsoln@prev}{}%
}
\newcommand*{\@add@used@problem}[2]{}
\newcommand*{\@fetch@excluded@list}[2]{%
  \def#1{}%
}
\newcommand*{\@add@newprevlist}[1]{}
\newcommand*{\close@probsoln@prev}{}
\AtEndDocument{\close@probsoln@prev}
\newcommand*{\previousproblem}[3]{%
  \ifnum#3>\probsoln@prev@cutoff
    \ifcsundef{prob@db@#2}{\prob@newdb{#2}}{}%
    \expandafter\gdef\csname @prev@problem@#2@#1\endcsname{#3}%
    \edef\@prev@list{\csname probsoln@prev@list@#2\endcsname}%
    \ifdefempty{\@prev@list}%
    {%
       \expandafter\xdef\csname probsoln@prev@list@#2\endcsname{#1}%
    }%
    {%
       \expandafter\xdef\csname probsoln@prev@list@#2\endcsname{%
         \@prev@list,#1}%
    }%
  \fi
}
\newcommand*{\usedproblem}[3]{%
  \ifnum#3=\probsoln@startyear
    \expandafter\def\csname @used@problem@#2@#1\endcsname{#3}%
  \fi
}
\newcommand*{\prob@db@default}{}
\newcommand*{\prob@databases}{default}
\newcommand*{\prob@db@default@solutions}{}
\newcommand*{\prob@newdb}[1]{%
  \ifcsundef{prob@db@#1}%
  {%
    \expandafter\gdef\csname prob@db@#1\endcsname{}%
    \xdef\prob@databases{\prob@databases,#1}%
    \expandafter\gdef\csname prob@db@#1@solutions\endcsname{}%
    \@add@newprevlist{#1}%
  }%
  {%
    \PackageError{probsoln}{Data set `#1' is already defined}%
      {Data set names must be unique}%
  }%
}
\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
 }%
}%
}
\newcommand*{\@moveproblem}[3]{%
  \ifcsempty{prob@db@#3}%
  {%
    \expandafter\xdef\csname prob@db@#3\endcsname{#1}%
  }%
  {%
    \expandafter\xdef\csname prob@db@#3\endcsname{%
      \csname prob@db@#3\endcsname,#1}%
  }%
  \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{\prob@newproblem}[5]{%
  \@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
      \expandafter\xdef\csname prob@db@#2\endcsname{%
        \csname prob@db@#2\endcsname,#3}%
    \fi
    \ifx\@empty#5\@empty
    \else
       \edef\thisprob@currentdb{#2}%
       \edef\thisprob@currentlabel{#3}%
       \expandafter\@setdefaultprobargs\expandafter{#5}%
    \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. \csname @prob@getargs@eg@\romannumeral#1\endcsname):}%
\read-1to\@tmp
\expandafter\global\expandafter\let
  \csname prob@args@#2@#3\endcsname=\@tmp
}
\def\@prob@getargs@eg@i{{12}}
\def\@prob@getargs@eg@ii{{5}{3}}
\def\@prob@getargs@eg@iii{{4}{5}{2}}
\def\@prob@getargs@eg@iv{{5}{3}{10}{8}}
\def\@prob@getargs@eg@v{{5}{3}{10}{8}{4}}
\def\@prob@getargs@eg@vi{{5}{3}{10}{8}{4}{24}}
\def\@prob@getargs@eg@vii{{5}{3}{10}{8}{4}{24}{32}}
\def\@prob@getargs@eg@viii{{5}{3}{10}{8}{4}{24}{32}{9}}
\def\@prob@getargs@eg@ix{{5}{3}{10}{8}{4}{24}{32}{9}{2}}
\let\@prob@do@getargs\@prob@gobblethree
\newcommand*{\setprobargs}[3][default]{%
  \expandafter\gdef\csname prob@args@#1@#2\endcsname{#3}%
}
\newcommand*{\@setdefaultprobargs}[1]{%
  \ifusedefaultprobargs
    \setprobargs[\thisprob@currentdb]{\thisprob@currentlabel}{#1}%
  \fi
}
\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
  \if@prob@fragile
    \obeylines\obeyspaces
    \@makeother\#
    \@makeother\%
  \fi
  \@xp\let\csname\@currenvir\endcsname\long@collect@@body
  \edef\process@envbody{\@xp\@nx\csname\@currenvir\endcsname}%
  \process@envbody
}
\long\def\long@addto@envbody#1{%
  \toks@{#1}%
  \edef\@psn@tmp{\the\@envbody\the\toks@}%
  \global\@envbody\@xp{\@psn@tmp}%
}
\long\def\long@collect@@body#1\end#2{%
  \protected@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
}
{\obeylines
 \gdef\@char@M{^^M}%
}
\@onelevel@sanitize\@char@M
\def\@beg@env@string{\begin}
\@onelevel@sanitize\@beg@env@string
\def\@end@env@string{\end}
\@onelevel@sanitize\@end@env@string
\edef\def@replace@markers{%
 \noexpand\def\noexpand\do@replace@charM##1\@char@M##2\noexpand\end@replace@marker{%
    \noexpand\expandafter\noexpand\toks@\noexpand\expandafter{\noexpand\replace@text}%
    \noexpand\ifx\noexpand\relax##2\noexpand\relax
      \noexpand\edef\noexpand\replace@text{\noexpand\the\noexpand\toks@##1}%
      \noexpand\let\noexpand\do@replacenext\noexpand\replace@mark@noop
    \noexpand\else
      \noexpand\edef\noexpand\replace@text{\noexpand\the\noexpand\toks@##1^^J}%
      \noexpand\let\noexpand\do@replacenext\noexpand\do@replace@charM
    \noexpand\fi
    \noexpand\do@replacenext##2\noexpand\end@replace@marker
  }%
 \noexpand\def\noexpand\doreplace@begverb##1\@beg@env@string##2\noexpand\end@replace@marker{%
    \noexpand\expandafter\noexpand\toks@\noexpand\expandafter{\noexpand\replace@text}%
    \noexpand\ifx\noexpand\relax##2\noexpand\relax
      \noexpand\edef\noexpand\replace@text{\noexpand\the\noexpand\toks@##1}%
      \noexpand\let\noexpand\do@replacenext\noexpand\replace@mark@noop
    \noexpand\else
      \noexpand\edef\noexpand\replace@text{\noexpand\the\noexpand\toks@
        ##1\expandafter\@gobble\string\\begin}%
      \noexpand\let\noexpand\do@replacenext\noexpand\doreplace@begverb
    \noexpand\fi
    \noexpand\do@replacenext##2\noexpand\end@replace@marker
  }%
 \noexpand\def\noexpand\doreplace@endverb##1\@end@env@string##2\noexpand\end@replace@marker{%
    \noexpand\expandafter\noexpand\toks@\noexpand\expandafter{\noexpand\replace@text}%
    \noexpand\ifx\noexpand\relax##2\noexpand\relax
      \noexpand\edef\noexpand\replace@text{\noexpand\the\noexpand\toks@##1}%
      \noexpand\let\noexpand\do@replacenext\noexpand\replace@mark@noop
    \noexpand\else
      \noexpand\edef\noexpand\replace@text{\noexpand\the\noexpand\toks@
        ##1\expandafter\@gobble\string\\end}%
      \noexpand\let\noexpand\do@replacenext\noexpand\doreplace@endverb
    \noexpand\fi
    \noexpand\do@replacenext##2\noexpand\end@replace@marker
  }%
  \noexpand\def\noexpand\replace@markers##1{%
    \noexpand\def\noexpand\replace@text{}%
    \noexpand\expandafter\noexpand\do@replace@charM##1\@char@M\relax\noexpand\end@replace@marker
    \noexpand\let##1\noexpand\replace@text
    \noexpand\def\noexpand\replace@text{}%
    \noexpand\expandafter\noexpand\doreplace@begverb##1\@beg@env@string\relax\noexpand\end@replace@marker
    \noexpand\let##1\noexpand\replace@text
    \noexpand\def\noexpand\replace@text{}%
    \noexpand\expandafter\noexpand\doreplace@endverb##1\@end@env@string\relax\noexpand\end@replace@marker
    \noexpand\let##1\noexpand\replace@text
  }
}
\def\replace@mark@noop#1\end@replace@marker{}
\def@replace@markers
\newenvironment{defproblem}[1][0]{%
  \edef\@prob@currentargN{\number0#1}%
  \@defproblem@beginenv
}{}
\newcommand*{\@defproblem@beginenv}[2][]{%
  \def\@prob@currentdefaultargs{#1}%
  \def\@prob@currentlabel{#2}%
  \@defproblem@beginenv@
}
\newcommand*{\@defproblem@beginenv@}[1][]{%
  \setkeys{probsoln}{#1}%
  \long@collect@body\prob@do@defproblem
}
\newcommand{\prob@do@newproblem}[1]{%
  \if@prob@fragile
    \probsoln@process@fragile{#1}%
    \protected@edef\do@def@new@problem{%
      \noexpand\prob@newproblem
        {\@prob@currentargN}%
        {\prob@currentdb}%
        {\@prob@currentlabel}%
        {%
          \noexpand\probsoln@write@tmp{\@prob@tmp@problem}%
          \noexpand\probsoln@read@tmp
        }%
        {\@prob@currentdefaultargs}%
    }%
  \else
    \toks@{#1}%
    \protected@edef\do@def@new@problem{%
      \noexpand\prob@newproblem
      {\@prob@currentargN}%
      {\prob@currentdb}%
      {\@prob@currentlabel}%
      {\the\toks@}%
      {\@prob@currentdefaultargs}%
    }%
  \fi
  \do@def@new@problem
}
\let\prob@do@defproblem=\prob@do@newproblem
\newenvironment{onlysolution}[1][]{%
   \setkeys{probsoln}{#1}%
   \long@collect@body\do@onlysolution
}{}
\newcommand{\do@onlysolution}[1]{%
  \ifshowanswers
    \probsoln@do@body{#1}%
  \fi
  \@ifundefined{@prob@currentlabel}
  {}%
  {%
    \expandafter
     \psn@add@unique@label
       \csname prob@db@\prob@currentdb @solutions\endcsname{%
         \@prob@currentlabel
       }%
  }%
}
\newcommand*{\psn@add@unique@label}[2]{%
  \ifx#1\@empty
    \xdef#1{#2}%
  \else
    \edef\@tmp@label{#2}%
    \expandafter\DTLifinlist\expandafter{\@tmp@label}{#1}%
    {}% ignore
    {\xdef#1{#1,\@tmp@label}}%
  \fi
}
\providecommand{\DTLifinlist}[4]{%
  \def\@dtl@doifinlist##1,#1,##2\end@dtl@doifinlist{%
     \def\@before{##1}%
     \def\@after{##2}%
  }%
  \expandafter\@dtl@doifinlist\expandafter,#2,#1,\@nil
    \end@dtl@doifinlist
  \ifx\@after\@nnil
    #4%
  \else
    #3%
  \fi
}
\newenvironment{onlyproblem}[1][]{%
   \setkeys{probsoln}{#1}%
   \long@collect@body\do@onlyproblem
}{}
\newcommand{\do@onlyproblem}[1]{%
  \ifshowanswers
  \else
    \probsoln@do@body{#1}%
  \fi
}
\newcommand{\probsoln@do@body}[1]{%
  \if@prob@fragile
    \probsoln@process@fragile{#1}%
    \probsoln@write@tmp{\@prob@tmp@problem}%
    \probsoln@read@tmp
  \else
    #1%
  \fi
}
\newcommand{\probsoln@process@fragile}[1]{%
  \def\@prob@tmp@problem{#1}%
  \@onelevel@sanitize\@prob@tmp@problem
  \replace@markers\@prob@tmp@problem
}
\newcommand{\probsoln@write@tmp}[1]{%
  \immediate\openout\probsoln@write=\ProbSolnFragileFile.\ProbSolnFragileExt
  \immediate\write\probsoln@write{#1}%
  \immediate\closeout\probsoln@write
}
\newcommand{\probsoln@read@tmp}{%
  \input{\ProbSolnFragileFile.\ProbSolnFragileExt}%
}
\newcommand{\useproblem}[2][default]{%
  \def\@prob@currentlabel{#2}%
  \def\prob@currentdb{#1}%
  \prob@showdraftlabel{#1}{#2}%
  \@add@used@problem{#2}{#1}%
  \let\@useprob@next=\relax
  \@ifundefined{prob@data@#1@#2}%
  {%
    \PackageError{probsoln}%
      {Problem `#2' is not defined in data set `#1'}{}%
  }%
  {%
    \def\@useprob@next{\csname prob@data@#1@#2\endcsname}%
  }%
  \@useprob@next
}
\newcommand*{\loadallproblems}[2][default]{%
\bgroup
 \let\par\relax
 \edef\prob@currentdb{#1}%
 \input{#2}%
\egroup
}
\newcommand{\prob@do@selectedproblem}[1]{%
  \expandafter\DTLifinlist\expandafter{\@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@do@exceptedproblem}[1]{%
  \expandafter\DTLifinlist\expandafter{\@prob@currentlabel}{\prob@selectedlabels}%
  {}%
  {%
    \prob@do@newproblem{#1}%
  }%
}
\newcommand{\loadexceptproblems}[3][default]{%
\bgroup
 \let\par\relax
 \edef\prob@currentdb{#1}%
 \edef\prob@selectedlabels{#2}%
 \let\prob@do@defproblem=\prob@do@exceptedproblem
 \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
}
\newif\iffirstpass
\firstpasstrue
\newcommand{\loadrandomproblems}[3][default]{%
  \@fetch@excluded@list{\@excl@list}{#1}%
  \@loadrandomproblems{#1}{#2}{#3}{\@excl@list}%
}
\newcommand{\loadrandomexcept}[4][default]{%
  \@loadrandomproblems{#1}{#2}{#3}{#4}%
}
\newcommand{\@loadrandomproblems}[4]{%
\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{%
   \edef\@if@in@list{\noexpand\DTLifinlist{\@thislabel}{#4}}%
   \@if@in@list
   {}%
   {%
     \advance\@probselN by 1\relax
     \expandafter
       \edef\csname @prob@tmp@\romannumeral\@probselN\endcsname{%
         \@thislabel}%
   }%
 }%
 \edef\@do@excludedlist{#4}%
 \ifdefempty{\@do@excludedlist}%
   {}%
   {\def\@do@excludedlist{(Excluded list: #4.) }}%
 \ifnum\@probselN=0\relax
     \PackageWarning{probsoln}{You have requested
       \number#2\space\space problem(s) but there are no available
       problems in `#3'. \@do@excludedlist No problems will be selected}%
 \else
   \shuffle{@prob@tmp@}{\@probselN}%
   \ifnum\@probselN<#2\relax
     \ifnum\@probselN=1\relax
       \PackageWarning{probsoln}{You have requested
         \number#2\space\space problem(s) but there is only
         1 problem available in `#3'. \@do@excludedlist
         Only 1 problem will be selected}%
     \else
       \PackageWarning{probsoln}{You have requested
         \number#2\space\space problem(s) but there are only
         \number\@probselN\space problems available in `#3'.
           \@do@excludedlist
           Only \number\@probselN\space problems will be selected}%
     \fi
   \else
     \@probselN=#2\relax
   \fi
 \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{\foreachsolution}[2][default]{%
\@ifundefined{prob@db@#1}{%
  \PackageError{probsoln}{Data base `#1' is not defined}{}%
}{%
  \expandafter\let\expandafter\@tmp\csname prob@db@#1@solutions\endcsname
  \@for\thisproblemlabel:=\@tmp\do{%
    \ifx\thisproblemlabel\@empty
    \else
      \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%
    \fi
  }%
}%
}
\newcommand{\foreachdataset}[2]{%
\@for#1:=\prob@databases\do{#2}}
\newcount\@probN \newcount\@probselN \newcount\@rndselctr
\newcount\r@ndcur
\newcount\@ps@randtmp
\r@ndcur=1\relax
\newcommand*{\PSNrandseed}[1]{%
  \ifnum#1=0\relax
    \PackageWarning{probsoln}{Can't have 0 as random seed, changing to 1}%
    \global\r@ndcur=1\relax
  \else
    \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 16811\relax
  \r@ndcur=\@ps@randtmp
  \global\divide\r@ndcur by 39989\relax
  \global\multiply\r@ndcur by 39989\relax
  \advance\@ps@randtmp by -\r@ndcur
  \global\r@ndcur = \@ps@randtmp
  \ifnum\r@ndcur=0\relax
    \global\r@ndcur=1\relax
  \fi
}
\newcommand*{\PSN@old@rand}{%
  \@ps@randtmp=\r@ndcur
  \multiply\@ps@randtmp by 16807\relax
  \r@ndcur=\@ps@randtmp
  \global\divide\r@ndcur by 120001\relax
  \global\multiply\r@ndcur by 120001\relax
  \advance\@ps@randtmp by -\r@ndcur
  \global\r@ndcur = \@ps@randtmp
  \ifnum\r@ndcur=0\relax
    \global\r@ndcur=1\relax
  \fi
}
\newcommand*{\PSNuseoldrandom}{%
  \let\PSNrand\PSN@old@rand
}
\newcommand{\PSNrandom}[2]{%
  \PSNrand
  #1=\r@ndcur
  \@ps@randtmp=\r@ndcur
  \divide\@ps@randtmp by #2\relax
  \multiply\@ps@randtmp by #2\relax
  \advance#1 by -\@ps@randtmp
  \advance#1 by 1\relax
}
\newcommand{\random}[3]{%
\ifnum#2=1\relax
  \PSNrandom{\value{#1}}{#3}%
\else
  \@rndselctr=#3%
  \advance\@rndselctr by -#2\relax
  \advance\@rndselctr by 1\relax
  \PSNrandom{\value{#1}}{\@rndselctr}%
  \addtocounter{#1}{#2}%
  \addtocounter{#1}{-1}%
\fi
}
\newcount\@shfctr \newcount\@shfA \newcount\@shfB
\newcommand{\shuffle}[2]{%
  \@shfctr=1\relax
  \whiledo{\@shfctr < 101}%
  {%
    \PSNrandom{\@shfA}{#2}\PSNrandom{\@shfB}{#2}%
    \ifnum\@shfA=\@shfB
    \else
      \edef\@@tmpA{\csname#1\romannumeral\@shfA\endcsname}%
      \let\@tmpA=\@@tmpA
      \edef\@@tmpB{\csname#1\romannumeral\@shfB\endcsname}%
      \let\@tmpB=\@@tmpB
      \expandafter\xdef\csname#1\romannumeral\@shfA\endcsname{\@tmpB}%
      \expandafter\xdef\csname#1\romannumeral\@shfB\endcsname{\@tmpA}%
    \fi
    \advance\@shfctr by 1\relax
  }%
}
\newcount\@ps@forrand
\newcount\@ps@forrand@level
\newcommand{\doforrandN}[4]{%
  \global\advance\@ps@forrand@level by 1\relax
  {%
    \@ps@forrand=0\relax
    \@for#2:=#3\do{%
      \advance\@ps@forrand by 1\relax
      \expandafter
        \edef\csname @doforrandN@\number\@ps@forrand@level @\romannumeral\@ps@forrand\endcsname{#2}%
    }%
    \ifnum\@ps@forrand<#1\relax
      \PackageError{probsoln}{Can't randomly select \number#1\space item(s)}{You
      have requested \number#1\space item(s), but there
      are only \number\@ps@forrand\space item(s) in the list: #3}%
    \else
      \shuffle{@doforrandN@\number\@ps@forrand@level @}{\@ps@forrand}%
      \ifnum#1>0\relax
        \@ps@forrand=0\relax
        \loop
          \advance\@ps@forrand by 1\relax
          \edef#2{\csname @doforrandN@\number\@ps@forrand@level @\romannumeral\@ps@forrand\endcsname}%
           #4%
        \ifnum\@ps@forrand<#1\relax
        \repeat
      \fi
    \fi
  }%
  \global\advance\@ps@forrand@level by -1\relax
}
\newcommand*{\newproblem}{\@ifstar\@snewproblem\@newproblem}
\newcommand{\@snewproblem}[1][0]{%
  \def\@newprob@argN{#1}%
  \@s@newproblem
}%
\newcommand{\@s@newproblem}[3][]{%
  \begin{defproblem}[\@newprob@argN][#1]{#2}%
    #3%
  \end{defproblem}%
}
\newcommand{\@newproblem}[1][0]{%
  \def\@newprob@argN{#1}%
  \@ns@newproblem
}
\newcommand{\@ns@newproblem}[4][]{%
  \begin{defproblem}[\@newprob@argN][#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:}\space
    \ignorespaces}{}%
}{}
\newcommand*{\solutionname}{Solution}
\newenvironment{textenum}{%
  \ifnum\@enumdepth>\thr@@
    \@toodeep
  \else
    \advance\@enumdepth by 1\relax
    \edef\@enumctr{enum\romannumeral\the\@enumdepth}%
    \let\@item\@textitem
    \def\@itemlabel{%
      \refstepcounter{\@enumctr}%
      \csname label\@enumctr\endcsname
    }%
    \setcounter{\@enumctr}{0}%
  \fi
  \ignorespaces
}%
{%
}
\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'.
