summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/randexam
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/randexam')
-rw-r--r--macros/latex/contrib/randexam/README3
-rw-r--r--macros/latex/contrib/randexam/randexam-a-answer.pdfbin0 -> 49561 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam-a-answer.tex359
-rw-r--r--macros/latex/contrib/randexam/randexam-a-blank.pdfbin0 -> 41354 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam-a-blank.tex6
-rw-r--r--macros/latex/contrib/randexam/randexam-b-answer.pdfbin0 -> 49564 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam-b-answer.tex6
-rw-r--r--macros/latex/contrib/randexam/randexam-b-blank.pdfbin0 -> 41312 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam-b-blank.tex6
-rw-r--r--macros/latex/contrib/randexam/randexam.cls942
-rw-r--r--macros/latex/contrib/randexam/randexam.pdfbin0 -> 45202 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam.tex541
12 files changed, 1863 insertions, 0 deletions
diff --git a/macros/latex/contrib/randexam/README b/macros/latex/contrib/randexam/README
new file mode 100644
index 0000000000..6fa060a3ac
--- /dev/null
+++ b/macros/latex/contrib/randexam/README
@@ -0,0 +1,3 @@
+Package: Make an exam paper and its randomized variants
+Author: Jianrui Lyu <tolvjr@163.com>
+License: The LaTeX Project Public License 1.3c \ No newline at end of file
diff --git a/macros/latex/contrib/randexam/randexam-a-answer.pdf b/macros/latex/contrib/randexam/randexam-a-answer.pdf
new file mode 100644
index 0000000000..732b941999
--- /dev/null
+++ b/macros/latex/contrib/randexam/randexam-a-answer.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam-a-answer.tex b/macros/latex/contrib/randexam/randexam-a-answer.tex
new file mode 100644
index 0000000000..d431b45732
--- /dev/null
+++ b/macros/latex/contrib/randexam/randexam-a-answer.tex
@@ -0,0 +1,359 @@
+% -*- coding: utf-8 -*-
+% !TEX program = xelatex
+\documentclass[12pt,most]{randexam}
+
+%\answerfalse % hide answers
+
+\SetExamOption{
+ seed = 19061116, % random seed
+}
+
+\begin{document}
+
+\examtitle{name=Math 1906 Final Exam,date=2018-06-28,version=A} % make exam title
+
+\gradetable
+
+\examgroup{Fill in the blanks.}{6 questions; 3 points for each; 18 points in total.}
+
+\answertable[3em]{6}{3} % make answer table: height 3em, six in total, three for each row
+
+\begin{question}
+The first question $k>0$, text $f(x)=\ln x-\frac{x}{\e}+k$ text $(0,+\infty)$
+text text text text text text text text text text text text text text text text
+text text text text text text text text text text text text text \fillout{$2$}.
+\end{question}
+
+\bigskip
+
+\begin{question}
+The second question $\va=(2,1,2)$, $\vb=(4,-1,10)$, $\vc=\vb-\lambda\va$,
+text text text $\va\bot\vc$, text text text text text text text text text
+text text text text text $\lambda=$ \fillout{$3$}.
+\end{question}
+
+\bigskip
+
+\begin{question}
+The third question $\left|\begin{array}{cc}
+ 1 & 2\\
+ -3 & x
+\end{array}\right|=0$, text text text text text text text text
+text text text text text text text text text $x=$ \fillout{$-6$}.
+\end{question}
+
+\bigskip
+
+\begin{question}
+The fourth question $\alpha_1=(1,1,0), \alpha_2=(0,1,1), \alpha_3=(1,0,1)$,
+text $\beta=(4, 5, 3)$ text $\alpha_1, \alpha_2, \alpha_3$ text text text text
+text text text text text text text text text text text text text text text text
+text text text text text text $\beta=$ \fillout{$3\alpha_1+2\alpha_2+\alpha_3$}.
+\end{question}
+
+\bigskip
+
+\begin{question}%[points=3]
+The fifth question $\xi$ text text text $E\xi=3, D\xi=2$, text text text text text
+text text text text text text text text text text $E\xi^2=$ \fillout{$11$}.
+\end{question}
+
+\bigskip
+
+\begin{question}
+The sixth question $\xi$ text text text text $\eta$ text text text text $\xi\sim N(1,4),
+\eta\sim N(2,5)$, text text text text text text text text text text text text text text
+text text text text text text text text text text $\xi-2\eta\sim$ \fillout{$N(-3,24)$}.
+\end{question}
+
+\bigskip
+
+\newpage
+
+\examgroup{Select one answer from four choices.}{6 questions; 3 points for each; 18 points in total.}
+
+\answertable{6}{6} % 生成答题栏:默认行高,总共8题,每行8题
+
+\begin{question}
+The first question text, text text text text text text text text text text
+text text text text text text text text text text text text text \pickout{C}
+\begin{abcd}
+\item first $\int f'(x)\dx=f(x)$
+\item second $\int \d f(x)=f(x)$
+\item third $\frac{\d}{\dx}\big(\int f(x)\dx\big)=f(x)$
+\item fourth $\d\big(\int f(x)\dx\big)=f(x)$
+\end{abcd}
+\end{question}
+
+\bigskip
+
+\begin{question}
+The second question $F(x)$ text $f(x)$ text, text \pickout{A}
+\begin{abcd}
+\item first choice $F(x)$ text $\Leftrightarrow$ $f(x)$ text
+\item second choice $F(x)$ text text $\Leftrightarrow$ $f(x)$ text
+\item third choice $F(x)$ text $\Leftrightarrow$ $f(x)$ text text
+\item fourth choice $F(x)$ text text $\Leftrightarrow$ $f(x)$ text text
+\end{abcd}
+\end{question}
+
+\bigskip
+
+\begin{question}
+The third question $A = \left(\begin{array}{ccc}
+ 1 & 1 & 0\\
+ 1 & x & 0\\
+ 0 & 0 & 1
+\end{array}\right)$ text text $\lambda_1 = 1$ text $\lambda_2
+= 2$, text $x=$ \pickout{B}
+\begin{abcd}
+\item $2$
+\item $1$
+\item $0$
+\item $-1$
+\end{abcd}
+\end{question}
+
+\bigskip
+
+\begin{question}
+The fourth question $f = 4 x_1^2 - 2 x_1 x_2 + 6 x_2^2$ text text text text text text
+text text text text text text text text text text text text text text text \pickout{C}
+\begin{abcd}
+\item $\left(\begin{array}{cc}
+ 4 & - 2\\
+ - 2 & 6
+\end{array}\right)$
+\item $\left(\begin{array}{cc}
+ 2 & - 2\\
+ - 2 & 3
+\end{array}\right)$
+\item $\left(\begin{array}{cc}
+ 4 & - 1\\
+ - 1 & 6
+\end{array}\right)$
+\item $\left(\begin{array}{cc}
+ 2 & - 1\\
+ - 1 & 3
+\end{array}\right)$
+\end{abcd}
+\end{question}
+
+\bigskip
+
+\begin{question}
+The fifth question \underline{wrong} text \pickout{B}
+\begin{abcd}
+\item first choice text text text text text text text text text
+\item second choice text text text text text text text text text
+\item third choice text text text text text text text text text
+\item fourth choice text text text text text text text text text
+\end{abcd}
+\end{question}
+
+\bigskip
+
+\begin{question}
+The sixth question $X$ text $(X_1,\cdots,X_n)$ text \underline{wrong} text text
+text text text text text text text text text text text text text text \pickout{D}
+\begin{abcd}
+\item text text text
+\item text $n$ text
+\item $X_1, \cdots, X_n$ text
+\item $X_1 = X_2 =\cdots = X_n$
+\end{abcd}
+\end{question}
+
+\bigskip
+
+\newpage
+
+\examgroup{Work out math questions.}{6 questions; 8 points for each; 48 points in total.}
+
+\begin{question}
+The first question $\int\e^{2x}\,(\tan x+1)^2\dx$.
+\end{question}
+
+\smallskip
+
+\begin{solution}
+$I$ \? $=\int\e^{2x}\,\sec^2 x\dx+2\int\e^{2x}\,\tan x\dx$ \points{2}
+\+ $=\int\e^{2x}\,\d(\tan x)+ 2\int\e^{2x}\,\tan x\dx$ \points{4}
+\+ $=\e^{2x}\,\tan x - 2\int\e^{2x}\,\tan x\dx+ 2\int\e^{2x}\,\tan x\dx$ \points{6}
+\+ $=\e^{2x}\,\tan x + C$ \points{8}
+\end{solution}
+
+\vfill
+
+\begin{question}
+The second question $A(1,2,-1), B(2,3,0),C(3,3,2)$ text $\triangle ABC$ text text text text text text.
+\end{question}
+
+\smallskip
+
+\begin{solution}
+Text $\overrightarrow{AB}=(1,1,1),\overrightarrow{AC}=(2,1,3)$, \points{2}
+text $\overrightarrow{AB}\times \overrightarrow{AC}=\begin{vmatrix}
+\vec{i}&\vec{j} &\vec{k}\\
+1&1&1\\
+2&1&3\\
+\end{vmatrix}=(2,-1,-1)$, \points{4}
+text $\triangle ABC$ text $S_{\triangle ABC}=\frac{1}{2}\big|\overrightarrow{AB}\times
+\overrightarrow{AC}\big|=\frac{1}{2}\sqrt{6}.$ \points{6}
+Text text $2(x-2)-(y-3)-z=0$, text $2x-y-z-1=0$. \points{8}
+\end{solution}
+
+\vfill
+
+\newpage
+
+\begin{question}
+The third question $A = \left|\begin{array}{cccc}
+ 0 & 1 & 2 & 3\\
+ 1 & 2 & 3 & 0\\
+ 2 & 3 & 0 & 1\\
+ 3 & 0 & 1 & 2
+\end{array}\right|$ text.
+\end{question}
+
+\smallskip
+
+\begin{solution}
+$A \? = \left|\begin{array}{cccc}
+ 0 & 1 & 2 & 3\\
+ 1 & 2 & 3 & 0\\
+ 2 & 3 & 0 & 1\\
+ 3 & 0 & 1 & 2
+ \end{array}\right| = \left|\begin{array}{cccc}
+ 0 & 1 & 2 & 3\\
+ 1 & 2 & 3 & 0\\
+ 0 & - 1 & - 6 & 1\\
+ 0 & - 6 & - 8 & 2
+ \end{array}\right| = 1 \cdot (- 1)^{2 + 1} \left|\begin{array}{ccc}
+ 1 & 2 & 3\\
+ - 1 & - 6 & 1\\
+ - 6 & - 8 & 2
+ \end{array}\right|$ \points{4}
+\+ $= -\left|\begin{array}{ccc}
+ 1 & 2 & 3\\
+ 0 & - 4 & 4\\
+ 0 & 4 & 20
+ \end{array}\right| = - \left|\begin{array}{cc}
+ - 4 & 4\\
+ 4 & 20
+ \end{array}\right| = -(-4\cdot20-4\cdot4) = 96$ \points{8}
+\end{solution}
+
+\vfill
+
+\begin{question}
+The fourth question, tex text $f = x_1^2 + 2 x_1 x_2 - 6 x_1 x_3 + 2 x_2^2 - 12
+x_2 x_3 + 9 x^2_3$ text text $f = d_1 y^2_1 + d_2 y^2_2 + d_3 y^2_3$.
+\end{question}
+
+\smallskip
+
+\begin{solution}
+$f \? = x_1^2 + 2 x_1 x_2 - 6 x_1 x_3 + 2 x_2^2 - 12 x_2 x_3 + 9 x^2_3$ \par
+ \+ $= x_1^2 + 2 x_1 (x_2 - 3 x_3) + (x_2 - 3 x_3)^2 + x_2^2 - 6 x_2 x_3 $ \par
+ \+ $= (x_1 + x_2 - 3 x_3)^2 + x_2^2 - 6 x_2 x_3$ \points{3}
+ \+ $= (x_1 + x_2 - 3 x_3)^2 + x_2^2 - 2 x_2 \cdot 3 x_3 + (3 x_3)^2 - 9x_3^2$ \par
+ \+ $= (x_1 + x_2 - 3 x_3)^2 + (x_2 - 3 x_3)^2 - 9 x_3^2$ \points{6}
+Text $y_1 = x_1 + x_2 - 3 x_3, y_2 = x_2 - 3 x_3, y_3 = x_3$, \newline
+text $f = y_1^2 + y_2^2 - 9y_3^2$ text.\points{8}
+\end{solution}
+
+\vfill
+
+\newpage
+
+\begin{question}
+The fifth question text text text $0.2$ text text, text text $100$ text text.\par
+(1) text text text text text text $\xi$ text $10$ text $30$ text.\par
+(2) text text text text text $\xi$ text $10$ text $30$ text.
+\end{question}
+
+\smallskip
+
+\begin{solution}
+$E\xi = n p = 100 \cdot 0.2 = 20, D\xi = n p q = 100 \cdot 0.2 \cdot 0.8 = 16$. \points{2}
+(1) $P (10 < \xi < 30) = P (|\xi - E\xi| < 10) \ge 1 - \frac{D\xi}{10^2}
+ = 1 - \frac{16}{100} = 0.84$. \points{4}
+(2) $P (10 < \xi < 30) \? \approx \Phi_0\left(\frac{30 - 20}{\sqrt{16}}\right)
+ - \Phi_0\left(\frac{10 - 20}{\sqrt{16}}\right)$ \points{6}
+ \+ $= 2 \Phi_0(2.5) - 1 = 2 \cdot 0.9938 - 1 =0.9876$ \points{8}
+\end{solution}
+
+\vfill
+
+\begin{question}
+The sixth question $N(\mu,\sigma^2)$ text text $16$ text, text text text $3160$, text text $100$.
+Text text $H_0:\mu=3140$ text text ($\alpha = 0.01$).
+\end{question}
+
+\smallskip
+
+\begin{solution}
+(1) Text text $H_0 : \mu = 3140$. \points{2}
+(2) Text text text $T = \frac{\widebar{X}-\mu}{S / \sqrt{n}} \sim t(n-1)$. \points{3}
+(3) Text text $t_{\alpha} = t_{\alpha} (n - 1) = t_{0.01} (15) =2.947$. \points{5}
+(4) Text text text $t = \frac{\widebar{x} - \mu_0}{s/\sqrt{n}} =\frac{3160-3140}{100/4} = 0.8$.\points{7}
+(5) Text $| t | < t_{\alpha}$, text text $H_0$, text text text. \points{8}
+\end{solution}
+
+\vfill
+
+\newpage
+
+\examgroup{Work out math proofs.}{2 questions; 16 points in total.}
+
+\renewcommand{\solutionname}{Proof} % 将“解”字改为“证”字
+
+\begin{question}[points=9]
+The first question $\{x_n\}$ text $x_1=\sqrt2$, $x_{n+1}=\sqrt{2+x_n}$.
+Text text text, text text text.
+\end{question}
+
+\smallskip
+
+\begin{solution}
+(1) Text, text $x_1<2$, text $x_k<2$ text
+$$x_{k+1}=\sqrt{2+x_k}<\sqrt{2+2}=2,$$
+Text text text text text $n$ text $x_n<2$, text text text.
+Text text
+$$\frac{x_{n+1}}{x_n}=\sqrt{\frac{2}{x_n^2}+\frac{1}{x_n}}>\sqrt{\frac{2}{2^2}+\frac{1}{2}}=1,$$
+Text text text text text. Text text text text text, Text text text text.\points{4}
+(2) Text text text text $A$, text text text text text text
+$$A=\sqrt{2+A}.$$
+Text text $A=2$, text text $\{x_n\}$ text text text $2$.\points{8}
+\end{solution}
+
+\vfill
+
+\begin{question}[points=7]
+The second question $A$ text $B$ text, text $A$ text $\widebar{B}$ text.
+\end{question}
+
+\smallskip
+
+\begin{solution}
+\? $P (A \cdot \widebar{B}) = P (A - B) = P (A - A B)$ \points{2}
+\< $= P (A) - P (A B) = P (A) - P (A) P (B)$ \points{4}
+\< $= P (A) (1 - P (B)) = P (A) P (\widebar{B})$ \points{6}
+Text text text $A$ text text text $\widebar{B}$ text text text.\points{8}
+\end{solution}
+
+\vfill
+
+\examdata{Some data may be used in the exam} % appendix data
+
+\begin{tabularx}{\linewidth}{*{4}{>{$}X<{$}}}
+\hline
+\Phi_0(0.5)=0.6915 & \Phi_0(1)=0.8413 & \Phi_0(2)=0.9773 & \Phi_0(2.5)=0.9938 \\
+t_{0.01}(8)=3.355 & t_{0.01}(9)=3.250 & t_{0.01}(15)=2.947 & t_{0.01}(16)=2.921 \\
+\chi_{0.005}^2(8)=22.0 & \chi_{0.005}^2(9)=23.6 & \chi_{0.005}^2(15)=32.8 & \chi_{0.005}^2(16)=34.3 \\
+\chi_{0.995}^2(8)=1.34 & \chi_{0.995}^2(9)=1.73 & \chi_{0.995}^2(15)=4.60 & \chi_{0.995}^2(16)=5.14 \\
+\hline
+\end{tabularx}
+
+\end{document}
diff --git a/macros/latex/contrib/randexam/randexam-a-blank.pdf b/macros/latex/contrib/randexam/randexam-a-blank.pdf
new file mode 100644
index 0000000000..2da2d3748f
--- /dev/null
+++ b/macros/latex/contrib/randexam/randexam-a-blank.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam-a-blank.tex b/macros/latex/contrib/randexam/randexam-a-blank.tex
new file mode 100644
index 0000000000..8285c0f95b
--- /dev/null
+++ b/macros/latex/contrib/randexam/randexam-a-blank.tex
@@ -0,0 +1,6 @@
+% -*- coding: utf-8 -*-
+% !TEX program = xelatex
+
+% Typeset original exam, hiding answers
+\PassOptionsToClass{noanswer}{randexam}
+\input{randexam-a-answer}
diff --git a/macros/latex/contrib/randexam/randexam-b-answer.pdf b/macros/latex/contrib/randexam/randexam-b-answer.pdf
new file mode 100644
index 0000000000..699a82d055
--- /dev/null
+++ b/macros/latex/contrib/randexam/randexam-b-answer.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam-b-answer.tex b/macros/latex/contrib/randexam/randexam-b-answer.tex
new file mode 100644
index 0000000000..8da410f859
--- /dev/null
+++ b/macros/latex/contrib/randexam/randexam-b-answer.tex
@@ -0,0 +1,6 @@
+% -*- coding: utf-8 -*-
+% !TEX program = xelatex
+
+% Generate version B from version A, shuffling questions
+\PassOptionsToClass{random}{randexam}
+\input{randexam-a-answer}
diff --git a/macros/latex/contrib/randexam/randexam-b-blank.pdf b/macros/latex/contrib/randexam/randexam-b-blank.pdf
new file mode 100644
index 0000000000..e9dd01eab3
--- /dev/null
+++ b/macros/latex/contrib/randexam/randexam-b-blank.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam-b-blank.tex b/macros/latex/contrib/randexam/randexam-b-blank.tex
new file mode 100644
index 0000000000..1669c2e851
--- /dev/null
+++ b/macros/latex/contrib/randexam/randexam-b-blank.tex
@@ -0,0 +1,6 @@
+% -*- coding: utf-8 -*-
+% !TEX program = xelatex
+
+% Typeset original exam, hiding answers
+\PassOptionsToClass{noanswer}{randexam}
+\input{randexam-b-answer}
diff --git a/macros/latex/contrib/randexam/randexam.cls b/macros/latex/contrib/randexam/randexam.cls
new file mode 100644
index 0000000000..8f5ae8bde9
--- /dev/null
+++ b/macros/latex/contrib/randexam/randexam.cls
@@ -0,0 +1,942 @@
+% -*- coding: utf-8 -*-
+% ----------------------------------------------------------------------------
+% Author: Jianrui Lyu <tolvjr@163.com>
+% License: The LaTeX Project Public License 1.3c
+% ----------------------------------------------------------------------------
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesClass{randexam}[2024-01-20 v2024B Make an exam paper and its randomized variants]
+
+%% Old LaTeX release could not recongnize date format like 2022-11-01
+%\@ifl@t@r\fmtversion{2022-11-01}{}{
+\@ifl@t@r\fmtversion{2022/11/01}{}{
+ \ClassError{randexam}{%
+ Your current TeX distribution is quite old.\MessageBreak
+ We need CTeX 3.0+ or MiKTeX 2023+ or TeXLive 2023+%
+ }{Please update your TeX distribution first.}
+}
+
+\RequirePackage{etoolbox}
+
+\newbool{plain} \boolfalse{plain} % use plain page style
+\newbool{twoinone} \boolfalse{twoinone} % use A3 paper
+\newbool{oneside} \boolfalse{oneside} % use single sided exam paper
+\newbool{resetnumber} \booltrue{resetnumber} % reset numbers in new exam groups
+\newbool{random} \boolfalse{random} % shuffle questions
+\newbool{answer} \booltrue{answer} % show answers
+\newbool{amsfonts} \boolfalse{amsfonts} % use ams fonts
+\newbool{freealign} \boolfalse{freealign} % load freealign package
+\newbool{medmath} \boolfalse{medmath} % use medium-size formulas
+\newbool{grader} \boolfalse{grader} % add grader line in the grade table
+
+\DeclareKeys{
+ plain .if = plain,
+ a3paper .if = twoinone,
+ a3input .code = \booltrue{twoinone}\booltrue{plain},
+ oneside .if = oneside,
+ random .if = random,
+ noanswer .ifnot = answer,
+ amsfonts .if = amsfonts,
+ freealign .if = freealign,
+ medmath .if = medmath,
+ grader .if = grader,
+ many .code = \booltrue{freealign},
+ most .code = \booltrue{freealign}\booltrue{medmath}
+}
+
+\DeclareUnknownKeyHandler{\PassOptionsToClass{\CurrentOption}{article}}
+
+\ProcessKeyOptions
+
+\LoadClass{article}
+
+\iftwoinone
+ \RequirePackage[a3paper,landscape,twocolumn,columnsep=60mm,left=30mm,right=30mm,top=25mm,bottom=25mm]{geometry}
+\else
+ \RequirePackage[a4paper,left=30mm,right=30mm,top=25mm,bottom=25mm]{geometry}
+\fi
+
+\RequirePackage{amsmath}
+\RequirePackage{array}
+\RequirePackage{calc}
+\RequirePackage{comment}
+\RequirePackage[inline]{enumitem}
+\RequirePackage{environ}
+\RequirePackage{fancyhdr}
+\RequirePackage{zref-user,zref-lastpage}
+\RequirePackage{tabularx}
+\RequirePackage{xcolor}
+\RequirePackage{xkeyval}
+
+\ifplain
+ \allowdisplaybreaks[4]
+\fi
+
+\ifamsfonts
+ \RequirePackage{amssymb}
+\else
+ \RequirePackage[utopia]{mathdesign} % charter, utopia
+ \renewcommand\bfdefault{bx}
+ \let\oldoiint\oiint\renewcommand{\oiint}{\oldoiint\nolimits}
+ \DeclareTextCommandDefault{\nobreakspace}{\leavevmode\nobreak\ }
+\fi
+
+\newcolumntype{Y}{>{\centering\arraybackslash}X}
+\newcolumntype{n}[1]{>{\centering\arraybackslash}m{#1}}
+
+\setlength{\parindent}{0em}
+\setlength{\lineskiplimit}{4pt}
+\setlength{\lineskip}{4pt}
+
+\NewDocumentCommand\SetExamOption{+m}{\SetKeys[randexam]{#1}}
+
+%% ---------------------------------------------------------------------------
+%% Command for exam title: \examtitle
+%% ---------------------------------------------------------------------------
+
+\newcommand{\underspace}[1]{\kern0pt\underline{\hspace{#1}}\kern0pt\relax}
+\newcommand{\underbox}[2]{\kern0pt\underline{\makebox[#1]{#2}}\kern0pt\relax}
+\newcommand{\underparbox}[2]{\kern0pt\underline{\parbox[b]{#1}{#2}}\kern0pt\relax}
+
+\newcommand{\ischeck}[1]{\ifnum#1>0\,$\checkmark$\,\else\quad\fi}
+\newcommand{\isquad}[1]{\ifnum#1=0\,$\checkmark$\,\else\quad\fi}
+
+\def\rdxm@temp@a{A}
+\def\rdxm@temp@c{C}
+\def\rdxm@empty{}
+
+\DeclareKeys[randexam-title]{
+ name .store = \@rdxm@title@name,
+ date .store = \@rdxm@title@date,
+ version .store = \@rdxm@title@version
+}
+
+\NewDocumentCommand\SetExamTitle{+m}{\SetKeys[randexam-title]{#1}}
+
+\SetExamTitle{name=Math 1906,date=\today,version=A}
+
+\newcommand\examtitle[1]{%
+ \SetExamTitle{#1}%
+ \thispagestyle{plain}
+ \ifbool{random}{%
+ \ifx\@rdxm@title@version\rdxm@temp@a\def\@rdxm@title@version{B}\fi
+ \ifx\@rdxm@title@version\rdxm@temp@c\def\@rdxm@title@version{D}\fi
+ }{}%
+ \begingroup
+ \Large\noindent
+ \ifbool{answer}{%
+ \textcolor{red!80!black}{\@rdxm@title@name\hfill Solutions}%
+ }{%
+ \@rdxm@title@name\hfill Name:\underspace{6em}%
+ }\par
+ \endgroup
+}
+
+%% ---------------------------------------------------------------------------
+%% Command for grade table: \gradetable
+%% ---------------------------------------------------------------------------
+
+%% You need to put .code:n before .initial:n
+\DeclareKeys[randexam]{%
+ groupnumber .code:n = \let\exam@group@number#1,
+ groupnumber .initial:n = \Roman,
+}
+
+\newcounter{@exam@grade@cnt}
+\newcommand\rdxm@group@number[1]{%
+ \stepcounter{@exam@grade@cnt}%
+ \exam@group@number{@exam@grade@cnt}%
+}
+
+\newcommand\insertgroupname{Part}
+\newcommand\insertscorename{Score}
+\newcommand\insertgradername{Grader}
+\newcommand\inserttotalname{Total}
+
+\newcommand\gradetable{%
+ \par\vspace{1em}%
+ \setcounter{@exam@grade@cnt}{0}%
+ \noindent\begin{tabularx}{\linewidth}{|*{8}{Y|}}
+ \hline
+ \textbf{\insertgroupname}
+ & \rdxm@group@number{1} & \rdxm@group@number{2} & \rdxm@group@number{3}
+ & \rdxm@group@number{4} & \rdxm@group@number{5} & \rdxm@group@number{6}
+ & \inserttotalname\\
+ \hline
+ \textbf{\insertscorename}\rule[-0.75em]{0pt}{2.5em} & & & & & & & \\
+ \hline
+ \ifbool{grader}{
+ \textbf{\insertgradername}\rule[-0.75em]{0pt}{2.5em} & & & & & & & \\
+ \hline
+ }{}
+ \end{tabularx}
+}
+
+%% ---------------------------------------------------------------------------
+%% Setting header and footer
+%% ---------------------------------------------------------------------------
+
+\newcommand{\rdxm@columnbox}[1]{\makebox[\columnwidth]{#1}}
+\newcommand{\rdxm@headleft}{\@rdxm@title@name}
+\newcommand{\rdxm@headright}{\ifbool{answer}{Solutions}{Name:\hspace{12em}}}
+\newcommand{\rdxm@headtext}{\rdxm@headleft\hfill\rdxm@headright}
+\newcommand{\rdxm@footleft}{\@rdxm@title@date}
+\newcommand{\rdxm@footcenter}{Page~\thepage~of~\zpageref{LastPage}}
+\newcommand{\rdxm@footright}{Version \@rdxm@title@version}
+\newcommand{\rdxm@foottext}{\rdxm@footleft\hfill\rdxm@footcenter\hfill\rdxm@footright}
+
+% fancy page style
+\fancyhf{} % clear head and foot
+\iftwoinone
+ \renewcommand{\headrulewidth}{0pt}%
+ \lhead{\small\underline{\rdxm@columnbox{\rdxm@headtext}\strut}}
+ \rhead{\small\underline{\rdxm@columnbox{\rdxm@headtext}\strut}}
+ \lfoot{\small\rdxm@columnbox{\rdxm@foottext}}
+ \rfoot{\small\rdxm@columnbox{\stepcounter{page}\rdxm@foottext}}
+\else
+ \lhead{\small\rdxm@headleft}
+ \rhead{\small\rdxm@headright}
+ \cfoot{\small\rdxm@foottext}
+\fi
+
+% plain page style
+\fancypagestyle{plain}{
+ \renewcommand{\headrulewidth}{0pt}%
+ \fancyhf{}
+ \iftwoinone
+ \rhead{\small\underline{\rdxm@columnbox{\rdxm@headtext\strut}}}
+ \lfoot{\small\rdxm@columnbox{\rdxm@foottext}}
+ \rfoot{\small\rdxm@columnbox{\stepcounter{page}\rdxm@foottext}}
+ \else
+ \cfoot{\small\rdxm@foottext}
+ \fi
+}
+
+\ifplain
+ \pagestyle{plain}
+\else
+ \pagestyle{fancy}
+\fi
+
+%% ---------------------------------------------------------------------------
+%% Class option for shuffling questions: random
+%% Class option for random seed: seed
+%% ---------------------------------------------------------------------------
+
+%% The random seed could not exceed 2147483647 = "7FFFFFFF
+%% You need to put .store before .initial:n
+\DeclareKeys[randexam]{
+ seed .store = \rdxm@random@seed,
+ seed .initial:n = 19061116
+}
+
+\ifrandom
+ \RequirePackage{pgf}
+ \RequirePackage{pgffor}
+ \newcommand*\exam@set@seed{%
+ %% 当\pgfmathrandom的参数为3的倍数时,对相邻种子生成的多个随机数分布不均匀
+ %\pgfmathsetseed{\numexpr\rdxm@random@seed+\value{rdxm@group}-1\relax}%
+ %% 因此我们改用下面的方法,用随机数种子生成下一个随机数种子
+ \pgfmathsetseed{\rdxm@random@seed}%
+ \pgfmathrandominteger\rdxm@random@seed{1}{2147483647}%
+ }
+\fi
+
+%% ---------------------------------------------------------------------------
+%% Command for exam groups: \examgroup
+%% Command for appendix data: \examdata
+%% Environment for questions: question
+%% Environment for solutions: solution
+%% ---------------------------------------------------------------------------
+
+\newif\ifonlyonequestion \onlyonequestionfalse % 此部分仅有一道题时不显示题目编号
+\xdef\allquestions{}
+\xdef\lastquestion{}
+\newcounter{question} % 当前题型的小题编号
+\newcounter{questionreal} % 实际显示的小题编号,在各题型小题统一编号时使用
+\newcounter{totalquestions} % 之前各题型小题总数,在各题型小题统一编号时使用
+\newcommand{\solutionname}{Solution}
+\newcounter{choice} % 后面选择题的 abcd 环境要用到
+\newcommand{\hangtext}{}
+\newlength{\hanglength}
+\colorlet{group number}{black}
+\colorlet{question number}{blue!80!black}
+\colorlet{solution name}{blue!80!black}
+
+\newcounter{rdxm@shuffle@temp@cnt}
+\newcounter{rdxm@list@temp@cnt}
+
+\newcommand\rdxm@list@print[1]{%
+ \par\renewcommand*{\do}[1]{(##1)}%
+ \dolistloop#1%
+}
+
+\newcommand\rdxm@list@remove[2]{%
+ %\rdxm@list@print\rdxm@shuffle@list
+ \setcounter{rdxm@list@temp@cnt}{0}%
+ \global\let\rdxm@tmpa@list=#1%
+ \gdef#1{}%
+ \par\renewcommand*{\do}[1]{%
+ \stepcounter{rdxm@list@temp@cnt}%
+ \ifnumequal{\value{rdxm@list@temp@cnt}}{#2}{%
+ \def\rdxm@list@item{##1}%
+ %[##1]%
+ }{
+ \listxadd#1{##1}%
+ }%
+ }%
+ \dolistloop\rdxm@tmpa@list
+}
+
+\newcommand\rdxm@shuffle@questions{%
+ \exam@set@seed
+ \ifnumgreater{\value{question}}{2}{%
+ \gdef\rdxm@shuffle@list{}%
+ \foreach \i in {1,...,\value{question}} {\listxadd\rdxm@shuffle@list{\i}}%
+ %% 首尾两个小题的位置总要改变
+ \pgfmathrandom{2,\value{question}}%
+ \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}%
+ \global\csletcs{rdxm@question@b@1}{rdxm@question@a@\rdxm@list@item}%
+ \ifnumequal{\rdxm@list@item}{\value{question}}{
+ \pgfmathrandom{\numexpr\value{question}-1\relax}%
+ \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}%
+ \global\csletcs{rdxm@question@b@\the\value{question}}{rdxm@question@a@\rdxm@list@item}%
+ }{%
+ \pgfmathrandom{\numexpr\value{question}-2\relax}%
+ \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}%
+ \global\csletcs{rdxm@question@b@\the\value{question}}{rdxm@question@a@\rdxm@list@item}%
+ }%
+ %% 其他小题的位置没有任何限制
+ \setcounter{rdxm@shuffle@temp@cnt}{1}%
+ \whileboolexpr{%
+ test{\ifnumless{\value{rdxm@shuffle@temp@cnt}}{\numexpr\value{question}-1\relax}}%
+ }{%
+ \stepcounter{rdxm@shuffle@temp@cnt}%
+ \pgfmathrandom{\numexpr\value{question}-\value{rdxm@shuffle@temp@cnt}\relax}%
+ \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}%
+ \global\csletcs{rdxm@question@b@\the\value{rdxm@shuffle@temp@cnt}}{%
+ rdxm@question@a@\rdxm@list@item
+ }%
+ }%
+ }{%
+ \ifnumequal{\value{question}}{2}{%
+ \global\csletcs{rdxm@question@b@1}{rdxm@question@a@2}%
+ \global\csletcs{rdxm@question@b@2}{rdxm@question@a@1}%
+ }{}%
+ }%
+}
+
+\newcommand{\printquestions}{%
+ \ifrandom
+ \rdxm@appto@questions
+ \rdxm@shuffle@questions
+ \setcounter{question}{0}%
+ \allquestions
+ \fi
+ \xdef\allquestions{}%
+ \xdef\lastquestion{}%
+}
+
+\newcounter{rdxm@group}
+
+\newcommand\insertgroup[2]{%
+ \noindent\textbf{\textcolor{group number}{Part~\Roman{rdxm@group}}: #1} (#2)%
+}
+
+\newcommand{\examgroup}[2]{%
+ \printquestions
+ \setcounter{totalquestions}{\value{totalquestions}+\value{question}}%
+ \setcounter{question}{0}%
+ \stepcounter{rdxm@group}%
+ \vspace{1em}%
+ \insertgroup{#1}{#2}%
+ \par\nopagebreak
+ \if\relax\detokenize{#1}\relax % #1 is empty
+ \onlyonequestiontrue
+ \else
+ \onlyonequestionfalse
+ \vspace{1em}%
+ \fi
+ %其中设定了\@nobreaktrue,保证在列表前也不分页,详情见 source2e
+ \@afterheading
+}
+
+\renewcommand\appendixname{Appendix}
+\newcommand{\examdata}[1]{%
+ \printquestions\rdxm@stop@random
+ \centerline{\textbf{\appendixname}\quad #1}\smallskip
+}
+
+\preto{\@enddocumenthook}{\printquestions\rdxm@stop@random}
+
+\newcommand\ignorepars{\@ifnextchar\par{\expandafter\ignorepars\@gobble}{}}
+
+% 局部定义,仅在当前题目内有效
+\define@key{exam@question}{points}[-1]{\def\rdxm@question@points{#1}}
+\define@key{exam@question}{level}[]{\def\rdxm@question@level{#1}}
+\define@key{exam@question}{year}[]{\def\rdxm@question@year{#1}}
+
+\newcommand\pointname{point}
+\newcommand\pointsname{points}
+\newcommand\pointorpoints[1]{\ifnumgreater{#1}{1}{\pointsname}{\pointname}}
+
+\newcommand{\questionpointstext}[1]{ (#1 \pointorpoints{#1}) }
+
+\newcommand\rdxm@hook@exec@other@keys{}
+
+\newcommand{\execute@question@keys}[1]{%
+ \setkeys{exam@question}{#1}%
+ \rdxm@hook@exec@other@keys
+ \ifdefvoid{\rdxm@question@points}{}{\questionpointstext{\rdxm@question@points}}%
+}
+
+\newenvironment{questionreal}[1][]{%
+ \stepcounter{question}\setcounter{choice}{0}%
+ \ifresetnumber
+ \ifonlyonequestion
+ \renewcommand{\hangtext}{\qquad}%
+ \else
+ \renewcommand{\hangtext}{\textbf{\textsf{\textcolor{question number}{\arabic{question}}.}}\;\,}%
+ \fi
+ \else
+ \setcounter{questionreal}{\value{totalquestions}+\value{question}}%
+ \renewcommand{\hangtext}{\textbf{\textsf{\textcolor{question number}{\arabic{questionreal}}.}}\;\,}%
+ \fi
+ \settowidth{\hanglength}{\hangtext}%
+ \description[leftmargin=\hanglength,labelwidth=0pt,labelsep=0pt,topsep=0pt,parsep=0pt]
+ \item[\hangtext]\execute@question@keys{#1}%
+}{\enddescription}
+\newenvironment{solutionreal}{%
+ \renewcommand{\hangtext}{\textbf{\textsf{\textcolor{solution name}{\solutionname}.}}\;\,}%
+ \settowidth{\hanglength}{\hangtext}%
+ \description[leftmargin=\hanglength,labelwidth=0pt,labelsep=0pt,topsep=0pt,parsep=0pt]
+ \item[\hangtext]
+}{\enddescription}
+
+\let \oldnewpage = \newpage
+\let \oldvfill = \vfill
+\let \oldsmallskip = \smallskip
+\let \oldmedskip = \medskip
+\let \oldbigskip = \bigskip
+
+\ifrandom
+ \newcommand\rdxm@appto@questions{%
+ \xappto\allquestions{\expandonce\lastquestion}%
+ }%
+ \NewEnviron{question}{%
+ \stepcounter{question}%
+ \rdxm@appto@questions
+ \csxdef{rdxm@question@a@\the\value{question}}{%
+ \unexpanded{\begin{questionreal}}%
+ \unexpanded\expandafter{\BODY}%
+ \unexpanded{\end{questionreal}}%
+ }%
+ \csxdef{rdxm@question@b@\the\value{question}}{%
+ \expandonce{\csname rdxm@question@a@\the\value{question}\endcsname}%
+ }%
+ \xdef\lastquestion{%
+ \expandonce{\csname rdxm@question@b@\the\value{question}\endcsname}%
+ }%
+ }
+ \NewEnviron{solution}{%
+ \csxappto{rdxm@question@a@\the\value{question}}{%
+ \unexpanded{\begin{solutionreal}}%
+ \expandonce{\BODY}%
+ \unexpanded{\end{solutionreal}}%
+ }%
+ }
+ \renewcommand{\newpage}{\gappto\lastquestion{\oldnewpage}}
+ \renewcommand{\vfill}{\csgappto{rdxm@question@a@\the\value{question}}{\oldvfill}}
+ \renewcommand{\smallskip}{\csgappto{rdxm@question@a@\the\value{question}}{\oldsmallskip}}
+ \renewcommand{\medskip}{\csgappto{rdxm@question@a@\the\value{question}}{\oldmedskip}}
+ \renewcommand{\bigskip}{\csgappto{rdxm@question@a@\the\value{question}}{\oldbigskip}}
+\else
+ \newenvironment{question}[1][]{\questionreal[#1]}{\endquestionreal}
+ %\newenvironment{solution}{\solutionreal}{\endsolutionreal}
+ \NewEnviron{solution}{\begin{solutionreal}\BODY\end{solutionreal}}
+\fi
+
+\newcommand{\rdxm@stop@random}{%
+ \ifrandom
+ \renewenvironment{question}{\questionreal}{\endquestionreal}%
+ \renewenvironment{solution}{\solutionreal}{\endsolutionreal}%
+ \let \newpage = \oldnewpage
+ \let \vfill = \oldvfill
+ \let \smallskip = \oldsmallskip
+ \let \medskip = \oldmedskip
+ \let \bigskip = \oldbigskip
+ \fi
+}
+
+\def\CommentCutFile{\jobname.cut}
+
+\AtBeginDocument{%
+ \ifanswer\else
+ \excludecomment{solution}
+ \fi
+}
+
+%% ---------------------------------------------------------------------------
+%% Command for answer tables: \answertable
+%% ---------------------------------------------------------------------------
+
+\gdef\answer@lines@temp{}%
+\newcommand{\answer@lines@add}[1]{%
+ \xdef\answer@lines@temp{\answer@lines@temp#1}%
+}
+
+\newcommand\insertnumbertext{Number}
+\newcommand\insertanswertext{Answer}
+\newcommand\insertanswertabletext{%
+ Notice: you MUST write the answers in the following tables.%
+}
+
+\newrobustcmd{\answer@number@hided}[1]{\insertnumbertext} % 在 PDFLaTeX 中需要保护中文
+\newrobustcmd{\answer@cell@strut}[1]{\parbox[c][#1][c]{2em}{\hbox{\insertanswertext}}}
+
+\newcounter{answer@col}
+\newcounter{answer@row}
+\newcounter{answer@total}
+
+\newcommand{\answer@lines}[3]{%
+ % #1 答题栏各栏指定高度
+ % #2 答题栏总共答案个数
+ % #3 答题栏每行答案个数
+ \setcounter{answer@row}{(#2-1)/#3+1}% 除法向下取整,改为向上取整
+ \begingroup
+ \let\hline=\relax \let\\=\relax % 禁止展开
+ \gdef\answer@lines@temp{}%
+ \setcounter{answer@total}{1}%
+ \whileboolexpr{
+ test{\ifnumgreater{\value{answer@row}}{0}}
+ }{%
+ \addtocounter{answer@row}{-1}%
+ \answer@lines@add{\answer@number@hided}%
+ \setcounter{answer@col}{1}%
+ \unlessboolexpr{%
+ test{\ifnumgreater{\value{answer@col}}{#3}}%
+ }{%
+ \answer@lines@add{&}%
+ \ifnumgreater{\value{answer@total}}{#2}{}{%
+ \answer@lines@add{\arabic{answer@total}}%
+ }%
+ \stepcounter{answer@col}%
+ \stepcounter{answer@total}%
+ }%
+ \answer@lines@add{\\ \hline \answer@cell@strut{#1}}%
+ \setcounter{answer@col}{1}%
+ \unlessboolexpr{
+ test{\ifnumgreater{\value{answer@col}}{#3}}
+ }{%
+ \answer@lines@add{&}%
+ \stepcounter{answer@col}%
+ }%
+ \answer@lines@add{\\ \hline}%
+ }%
+ \endgroup
+ \answer@lines@temp
+}
+
+\newcommand{\answertable}[3][1em]{%
+ \insertanswertabletext\par
+ \begin{tabularx}{\linewidth}{|c|*{#3}{Y|}}
+ \hline
+ \answer@lines{#1}{#2}{#3}
+ \end{tabularx}%
+ \par\vspace{0.8em}%
+}
+
+%% ---------------------------------------------------------------------------
+%% Command for toggling answers: \answer
+%% Command for true-or-false questions: \tickin and \tickout
+%% Command for fill-in-the-blank questions: \fillin and \fillout
+%% Command for multiple-choice questions: \pickin and \pickout
+%% ---------------------------------------------------------------------------
+
+\newcommand{\answer}[1]{\ifanswer#1\else\phantom{#1}\fi}
+
+\newcommand*{\cdotfill}{\leavevmode\xleaders\hbox to 0.5em{\hss$\cdot$\hss}\hfill\kern0pt\relax}
+
+\newcommand*{\tick@box}[1]{[\makebox[1.5em]{\color{blue}\answer{#1}}]}
+\newcommand*{\tick@text@t}{$\checkmark$}
+\newcommand*{\tick@text@f}{{\large$\times$}}
+\newcommand*{\tick@text@T}{\sffamily T}
+\newcommand*{\tick@text@F}{\sffamily F}
+\newcommand*{\tickin}[1]{\tick@box{\csname tick@text@#1\endcsname}}
+\newcommand*{\tickout}[1]{\unskip\nobreak\cdotfill\tick@box{\csname tick@text@#1\endcsname}}
+
+\newcommand*{\ulinefill}[1]{\xleaders\hbox{\underline{\vphantom{#1}\kern1pt}}\hfill\kern0pt}
+\newcommand*{\minwidthbox}[2]{\makebox[{\ifdim#1<\width\width\else#1\fi}]{#2}}
+
+\newcommand*{\fillout}[1]{\allowbreak\hbox{}\nobreak\ulinefill{#1}\underline{\color{blue}\answer{#1}}\ulinefill{#1}}
+\newcommand*{\fillin}[1]{\underline{\hspace{1em}\color{blue}\minwidthbox{2em}{\answer{#1}}\hspace{1em}}}
+
+\newcommand*\pickoutreal[1]{%
+ \unskip\nobreak\cdotfill(\makebox[1.5em]{\color{blue}\answer{#1}})%
+}
+\newcommand*\pickinreal[1]{%
+ \unskip\nobreak
+ \hspace{0.3em}(\makebox[1.5em]{\color{blue}\answer{#1}})\hspace{0.3em}%
+ \ignorespaces
+}
+
+%% 选择题四个选项打乱顺序,用三种方法即可保证答案不同
+%% 1:ABCD -> CDAB; 2:ABCD -> BADC; 3: ABCD -> DCBA
+%% 即在两行排列时仅用到上下交换以及左右交换,这样可以保持两行长度不变
+
+\csdef{rdxm@shuffle@1@A}{C} \csdef{rdxm@shuffle@2@A}{B} \csdef{rdxm@shuffle@3@A}{D}
+\csdef{rdxm@shuffle@1@B}{D} \csdef{rdxm@shuffle@2@B}{A} \csdef{rdxm@shuffle@3@B}{C}
+\csdef{rdxm@shuffle@1@C}{A} \csdef{rdxm@shuffle@2@C}{D} \csdef{rdxm@shuffle@3@C}{B}
+\csdef{rdxm@shuffle@1@D}{B} \csdef{rdxm@shuffle@2@D}{C} \csdef{rdxm@shuffle@3@D}{A}
+
+\def\@rdxm@choice@random{0}
+\newcommand\rdxm@shuffle@abcd[1]{\csuse{rdxm@shuffle@\@rdxm@choice@random @#1}}
+
+\newcommand*\pickout[1]{%
+ \ifbool{random}{%
+ \exam@set@seed
+ \pgfmathrandominteger\@rdxm@choice@random{1}{3}%
+ %\@rdxm@choice@random
+ \pickoutreal{\rdxm@shuffle@abcd{#1}}%
+ }{%
+ \pickoutreal{#1}%
+ }%
+}
+\newcommand*\pickoutfixed[1]{%
+ \pickoutreal{#1}%
+ \randomfalse
+}
+\newcommand*\pickin[1]{%
+ \ifbool{random}{%
+ \exam@set@seed
+ \pgfmathrandominteger\@rdxm@choice@random{1}{3}%
+ %\@rdxm@choice@random
+ \pickinreal{\rdxm@shuffle@abcd{#1}}%
+ }{%
+ \pickinreal{#1}%
+ }%
+}
+\newcommand*\pickinfixed[1]{%
+ \pickinreal{#1}%
+ \randomfalse
+}
+
+%% ---------------------------------------------------------------------------
+%% Environment abcd for typesetting options of multiple-choice questions
+%% Put them in one, two, or four rows according to the lengths of the choices
+%% ---------------------------------------------------------------------------
+
+\newlength{\rdxm@item@len}
+\newlength{\rdxm@label@len}
+
+\newcommand\rdxm@item@temp{%
+ \unskip\cr\stepcounter{choice}(\Alph{choice})\ %
+}
+\newcommand\rdxm@item@box{%
+ \hfill\egroup\hfill\hbox to \rdxm@item@len\bgroup
+ \stepcounter{choice}(\Alph{choice})\ \ignorespaces
+}
+\newcommand\rdxm@item@par{%
+ \stepcounter{choice}%
+ \def\rdxm@label@text{(\Alph{choice})\ }%
+ \settowidth{\rdxm@label@len}{\rdxm@label@text}%
+ \par \parshape 2 \hanglength \linewidth
+ \dimexpr\hanglength + \rdxm@label@len\relax
+ \dimexpr\linewidth - \rdxm@label@len\relax
+ \rdxm@label@text\ignorespaces
+}
+
+\NewEnviron{abcdreal}{
+ \unskip
+ \setlength{\parindent}{0pt}%
+ \setlength{\parskip}{0pt}%
+ \setcounter{choice}{0}%
+ \let\item=\rdxm@item@temp
+ \settowidth{\rdxm@item@len}{\vbox{\halign{##\hfil\cr\BODY\crcr}}}%
+ \setcounter{choice}{0}%
+ \ifdim\rdxm@item@len>0.486\linewidth
+ \setlength{\rdxm@item@len}{\linewidth}%
+ \let\item=\rdxm@item@par
+ \BODY\par
+ \else
+ \ifdim\rdxm@item@len>.243\linewidth
+ \setlength{\rdxm@item@len}{0.5\linewidth}%
+ \else
+ \setlength{\rdxm@item@len}{0.25\linewidth}%
+ \fi
+ \let\item=\rdxm@item@box
+ \par\bgroup\BODY\hfill\egroup\par
+ \fi
+}
+
+\newcommand\rdxm@item@one@line{%
+ \unskip
+ \ifnumequal{\value{choice}}{0}{}{\hfill}
+ \stepcounter{choice}(\Alph{choice})\ %
+}
+\newcommand\rdxm@item@two@line{%
+ \unskip
+ \ifnumodd{\value{choice}}{&}{\unskip\cr}%
+ \stepcounter{choice}(\Alph{choice})\ %
+}
+
+\NewEnviron{abcd*real}{
+ \unskip
+ \setlength{\parindent}{0pt}%
+ \setlength{\parskip}{0pt}%
+ \setcounter{choice}{0}%
+ \let\item=\rdxm@item@one@line
+ \settowidth{\rdxm@item@len}{\BODY}%
+ \ifdim\rdxm@item@len<0.95\linewidth
+ \setcounter{choice}{0}%
+ \par\bgroup\BODY\hfill\hfill\par\egroup\par
+ \else
+ \setcounter{choice}{0}%
+ \let\item=\rdxm@item@two@line
+ \settowidth{\rdxm@item@len}{\vbox{\halign{##&##\hfil\cr\BODY\crcr}}}%
+ \ifdim\rdxm@item@len<0.975\linewidth
+ \setcounter{choice}{0}%
+ \par\bgroup\nointerlineskip
+ \vbox{\halign to\linewidth{##\hfil\tabskip=0pt plus 1fil&##\hfil\cr\BODY\crcr}}%
+ \egroup\par
+ \else
+ \setcounter{choice}{0}%
+ \let\item=\rdxm@item@par
+ \par\bgroup\BODY\hfill\egroup\par
+ \fi
+ \fi
+}
+
+\ifbool{random}{%
+ \csdef{rdxm@swap@items@1}#1#2#3#4{\item#3\item#4\item#1\item#2}
+ \csdef{rdxm@swap@items@2}#1#2#3#4{\item#2\item#1\item#4\item#3}
+ \csdef{rdxm@swap@items@3}#1#2#3#4{\item#4\item#3\item#2\item#1}
+ \long\def\rdxm@swap@items#1\item#2\item#3\item#4\item#5\@rdxm@stop@mark{%
+ #1\csuse{rdxm@swap@items@\@rdxm@choice@random}{#2}{#3}{#4}{#5}%
+ }
+}{}
+
+\NewDocumentEnvironment{abcd}{+b}{%
+ \ifbool{random}{%
+ \begin{abcdreal}\rdxm@swap@items#1\@rdxm@stop@mark\end{abcdreal}%
+ }{%
+ \begin{abcdreal}#1\end{abcdreal}%
+ }%
+}{}
+\NewDocumentEnvironment{abcd*}{+b}{%
+ \ifbool{random}{%
+ \begin{abcd*real}\rdxm@swap@items#1\@rdxm@stop@mark\end{abcd*real}%
+ }{%
+ \begin{abcd*real}#1\end{abcd*real}%
+ }%
+}{}
+
+%% ---------------------------------------------------------------------------
+%% Use hangindent in enumerate lists, and remove extra vertical space
+%% The itemjoin set space between items in inline enumerate* environment
+%% ---------------------------------------------------------------------------
+
+\setlist[enumerate]{labelindent=0pt,labelsep=0.2em,itemindent=0pt,leftmargin=*,nosep,itemjoin=\quad}
+\setlist[enumerate,1]{label=(\arabic*)}
+\setlist[enumerate,2]{label=(\alph*),widest*=1}
+
+%% ---------------------------------------------------------------------------
+%% Use freealign package to align math formulas in different lines
+%% ---------------------------------------------------------------------------
+
+\AtBeginDocument{%
+ \ifbool{freealign}{\RequirePackage{freealign}}{}%
+}
+
+%% ---------------------------------------------------------------------------
+%% Command for giving points in solutions: \points
+%% ---------------------------------------------------------------------------
+
+\PassOptionsToPackage{tbtags}{amsmath}
+\RequirePackage{amsmath}
+
+\newcommand{\solutionpointstext}[1]{%
+ \textcolor{red}{#1\kern0.15em\pointorpoints{#1}}%
+}
+
+\newcommand{\pointstext}[1]{%
+ \mbox{}\nobreak\hfill$\cdots\cdots$\solutionpointstext{#1}%
+ \par\noindent\ignorespaces
+}
+\newcommand{\pointseqno}[1]{\eqno{\cdots\cdots\text{\solutionpointstext{#1}}}}
+\newcommand{\pointstag}[1]{\tag*{$\cdots\cdots$\solutionpointstext{#1}}}
+
+\newrobustcmd{\points}[1]{%
+ \ifbool{mmode}{%
+ \ifdefstrequal{\tag}{\dft@tag}{\pointseqno{#1}}{\pointstag{#1}}%
+ }{%
+ \pointstext{#1}%
+ }%
+}
+
+%% ---------------------------------------------------------------------------
+%% Use medium-size fractions and operators in both inline and displayed formulas
+%% ---------------------------------------------------------------------------
+
+\AtBeginDocument{%
+ \ifbool{medmath}{\RequirePackage{medmath}}{}%
+}
+
+%% ---------------------------------------------------------------------------
+%% Load more packages, define more commands
+%% ---------------------------------------------------------------------------
+
+\AtBeginDocument{
+ \setlength{\abovedisplayskip}{4pt minus 2pt}
+ \setlength{\belowdisplayskip}{4pt minus 2pt}
+ \setlength{\abovedisplayshortskip}{2pt}
+ \setlength{\belowdisplayshortskip}{2pt}
+}
+
+\setlength\arraycolsep{4pt}
+
+\RequirePackage{diagbox}
+%% 修正 \diagbox 在 array 环境中使用的问题
+\newrobustcmd{\diagboxtwo}[3][]{%
+ \ifbool{mmode}{%
+ \hbox{\let\tabcolsep=\arraycolsep\diagbox[#1]{$#2$}{$#3$}}%
+ }{%
+ \diagbox[#1]{#2}{#3}%
+ }
+}
+\newrobustcmd{\diagboxthree}[4][]{%
+ \ifbool{mmode}{%
+ \hbox{\let\tabcolsep=\arraycolsep\diagbox[#1]{$#2$}{$#3$}{$#4$}}%
+ }{%
+ \diagbox[#1]{#2}{#3}{#4}%
+ }
+}
+
+\RequirePackage{mathtools} % \mathllap 命令,pmatrix* 环境等
+\RequirePackage{extarrows}
+
+\AtBeginDocument{%
+ \let\rdxm@saved@lim=\lim \def\lim{\rdxm@saved@lim\limits}%
+ \let\rdxm@saved@sum=\sum \def\sum{\rdxm@saved@sum\limits}%
+ \let\rdxm@saved@prod=\prod \def\prod{\rdxm@saved@prod\limits}%
+}
+
+\newcommand{\e}{\mathrm{e}}
+\newcommand{\R}{\mathbb{R}}
+
+\DeclareMathOperator{\arccot}{arccot}
+\DeclareMathOperator{\Corr}{\rho}
+\DeclareMathOperator{\Cov}{Cov}
+\DeclareMathOperator{\diag}{diag}
+\DeclareMathOperator{\grad}{grad}
+\DeclareMathOperator{\Prj}{Prj}
+\DeclareMathOperator{\tr}{tr}
+\DeclareMathOperator{\Var}{Var}
+
+\DeclareMathOperator{\diver}{div}
+\let\division=\div
+\let\div=\diver
+
+\newcommand{\diff}{\mathop{}\!\mathrm{d}}
+\newcommand{\dx}{\diff x}
+\newcommand{\dy}{\diff y}
+\def\dz{\diff z} % 不确定命令是否已经定义
+\newcommand{\du}{\diff u}
+\newcommand{\dv}{\diff v}
+\newcommand{\dr}{\diff r}
+\newcommand{\ds}{\diff s}
+\newcommand{\dt}{\diff t}
+\newcommand{\dS}{\diff S}
+% 有些宏包比如 hyperref 会修改 \d 的定义,所以放在 document 开始处
+% 利用 etoolbox 将 \d 定义为健壮命令,以避免在 align 等环境中错误地展开
+\AtBeginDocument{%
+ \let\oldd=\d
+ \renewrobustcmd{\d}{\ifbool{mmode}{\diff}{\oldd}}%
+}
+
+\let\pd=\partial
+\newcommand{\pdf}{\pd f}
+\newcommand{\pdg}{\pd g}
+\newcommand{\pdh}{\pd h}
+\newcommand{\pdl}{\pd l}
+\newcommand{\pdn}{\pd n}
+\newcommand{\pdu}{\pd u}
+\newcommand{\pdv}{\pd v}
+\newcommand{\pdx}{\pd x}
+\newcommand{\pdy}{\pd y}
+\newcommand{\pdz}{\pd z}
+\newcommand{\pdF}{\pd F}
+\newcommand{\pdL}{\pd L}
+\newcommand{\pdP}{\pd P}
+\newcommand{\pdQ}{\pd Q}
+\newcommand{\pdR}{\pd R}
+
+% from mathabx package
+\DeclareFontFamily{U}{mathx}{\hyphenchar\font45}
+\DeclareFontShape{U}{mathx}{m}{n}{<-> mathx10}{}
+\DeclareSymbolFont{mathx}{U}{mathx}{m}{n}
+\DeclareMathAccent{\widebar}{0}{mathx}{"73}
+
+\newcommand{\va}{\vec{a}}
+\newcommand{\vb}{\vec{b}}
+\newcommand{\vc}{\vec{c}}
+\newcommand{\vd}{\vec{d}}
+\newcommand{\ve}{\vec{e}}
+\newcommand{\vi}{\vec{i}}
+\newcommand{\vj}{\vec{j}}
+\newcommand{\vk}{\vec{k}}
+\newcommand{\vn}{\vec{n}}
+\newcommand{\vs}{\vec{s}}
+\newcommand{\vv}{\vec{v}}
+
+\let\ov=\overrightarrow
+
+\let\le=\leqslant
+\let\ge=\geqslant
+
+\let\lb=\{
+\let\rb=\}
+
+\def\T{\mathrm{T}\kern-.5pt}
+
+% 分数线长一点的分数,\wfrac[2pt]{x}{y} 表示左右加 2pt
+% 和前面的 medmath 一样,将代码放在 \AtBeginDocument 里
+\AtBeginDocument{%
+ \newrobustcmd{\wfrac}[3][2pt]{%
+ \frac{\hspace{#1}#2\hspace{#1}}{\hspace{#1}#3\hspace{#1}}%
+ }%
+ \newrobustcmd{\wdfrac}[3][2pt]{%
+ \dfrac{\hspace{#1}#2\hspace{#1}}{\hspace{#1}#3\hspace{#1}}%
+ }%
+ \newrobustcmd{\wtfrac}[3][2pt]{%
+ \tfrac{\hspace{#1}#2\hspace{#1}}{\hspace{#1}#3\hspace{#1}}%
+ }%
+}
+
+% 使用 stix font 中的 white arrows
+\AtBeginDocument{\@ifpackageloaded{fontspec}{%
+ %\IfFileExists{STIX-Regular.otf}{% 在 TeXLive 中无效
+ \IfFileExists{stix.sty}{%
+ \newfontfamily{\@rdxm@stix}{STIX} % stix v1.1
+ }{%
+ \newfontfamily{\@rdxm@stix}{STIXGeneral} % stix v1.0
+ }
+ \newrobustcmd\leftwhitearrow{%
+ \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E6}}}%
+ }
+ \newrobustcmd\upwhitearrow{%
+ \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E7}}}%
+ }
+ \newrobustcmd\rightwhitearrow{%
+ \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E8}}}%
+ }
+ \newrobustcmd\downwhitearrow{%
+ \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E9}}}%
+ }
+}{%
+ \let \leftwhitearrow = \Leftarrow
+ \let \rightwhitearrow = \Rightarrow
+ \let \upwhitearrow = \Uparrow
+ \let \downwhitearrow = \Downarrow
+}}
+
diff --git a/macros/latex/contrib/randexam/randexam.pdf b/macros/latex/contrib/randexam/randexam.pdf
new file mode 100644
index 0000000000..0c7f83abdf
--- /dev/null
+++ b/macros/latex/contrib/randexam/randexam.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam.tex b/macros/latex/contrib/randexam/randexam.tex
new file mode 100644
index 0000000000..9e38395b94
--- /dev/null
+++ b/macros/latex/contrib/randexam/randexam.tex
@@ -0,0 +1,541 @@
+% -*- coding: utf-8 -*-
+
+\documentclass[12pt,plain,most]{randexam}
+\geometry{b5paper,margin=2cm}
+
+\newcommand*{\myversion}{2024B}
+\newcommand*{\mydate}{\the\year-\mylpad\month-\mylpad\day}
+\newcommand*{\mylpad}[1]{\ifnum#1<10 0\the#1\else\the#1\fi}
+
+\cfoot{\small\thepage}
+
+\setlength{\parindent}{0pt}
+\setlength{\parskip}{7pt plus 1pt minus 1pt}
+
+\usepackage{arevtext}
+\usepackage{iftex}
+\usepackage{ninecolors}
+\usepackage{hyperref}
+\hypersetup{
+ colorlinks=true,
+ urlcolor=blue3,
+ linkcolor=blue3,
+}
+
+\renewcommand\familydefault{\sfdefault}
+
+\renewcommand{\baselinestretch}{1}
+\renewcommand{\arraystretch}{1.3}
+
+\usepackage{tabularx}
+
+\newcommand{\fillbox}[1]{\ulinefill{#1}\underline{#1}\ulinefill{#1}}
+
+\usepackage{fancyvrb}
+
+\DefineVerbatimEnvironment{code}{Verbatim}{%
+ formatcom=\color{blue!50!red}%
+}
+
+\usepackage{codehigh}
+
+\NewDocumentCommand\mypkg{m}{\textcolor{blue3}{\mbox{#1}}}
+\NewDocumentCommand\myopt{m}{\textcolor{yellow3}{\mbox{#1}}}
+\NewDocumentCommand\mycmd{m}{\textcolor{green3}{\ttfamily\fakeverb{#1}}}
+\NewDocumentCommand\myenv{m}{\textcolor{green3}{\ttfamily#1}}
+\NewDocumentCommand\myfile{m}{\textcolor{purple3}{\mbox{#1}}}
+\NewDocumentCommand\mykey{m}{\textcolor{brown3}{\mbox{\fakeverb{#1}}}}
+\NewDocumentCommand\myval{m}{\textcolor{azure3}{\mbox{\fakeverb{#1}}}}
+
+\begin{document}
+
+{%
+ \renewcommand{\arraystretch}{2}%
+ \noindent\Large
+ \begin{tabularx}{\linewidth}{|X|}
+ \hline
+ Title: \fillbox{\color{blue3}The randexam class for LaTeX}\\
+ Author: \fillbox{Jianrui Lyu (tolvjr@163.com)}\\
+ Version: \fillbox{\myversion{} (\mydate)}\\
+ \hline
+ \end{tabularx}%
+}
+
+\tableofcontents
+
+\section{Introduction}
+
+Document class \mypkg{randexam} is an exam class for LaTeX.
+With this class you could easily make an exam paper and its randomized variants.
+
+The class mainly focuses on making math exam papers, but you could use it to make other exam papers.
+
+The latest release of this package can be downloaded from here: \newline
+\textcolor{blue}{\href{https://ctan.org/pkg/randexam}{\ttfamily https://ctan.org/pkg/randexam}}.
+
+\section{Basic Structure}
+
+\subsection{A randexam document}
+
+The following is the basic structure of a \mypkg{randexam} document:
+\begin{code}
+\documentclass{randexam}
+% document preamble
+\begin{document}
+% document body
+\end{document}
+\end{code}
+In document preamble you could set some options for the exam.
+In document body you write the contents of the exam.
+
+\subsection{Document preamble}
+
+In document preamble you normally set some class options with \mycmd{\SetExamOption} command.
+For example, you could change the random seed with \myopt{seed} key. The seed is used only when
+you add class option \myopt{random} (see Subsection \ref{opt:random}):
+\begin{code}
+\SetExamOption{
+ seed = 19061116, % random seed
+}
+\end{code}
+
+\subsection{Document body}
+
+In document body you normally write an \mycmd{\examtitle},
+multiple \mycmd{\examgroup}, and an optional \mycmd{\examdata} commands:
+
+\begin{code}
+\examtitle{name=Math Final Exam,date=2018-06-28,version=A}
+......
+\examgroup{Fill in the blanks.}{3 points for each.}
+......
+\examgroup{Select one answer.}{3 points for each.}
+......
+\examgroup{Work out math calculations.}{8 points for each.}
+......
+\examdata{Some data may be used in the exam}
+......
+\end{code}
+
+\subsection{Exam title}
+
+In calling \mycmd{\examtitle} command,
+you need to provide some basic informations of the exam:
+
+\begin{code}
+\examtitle{name=Math Final Exam,date=2018-06-28,version=A}
+\end{code}
+
+If the \mykey{date} key is missing, it has the default value \myval{\today}.
+When class option \myopt{random} is passed, the value of \mykey{version} key
+will be modified from \myval{A} to \myval{B}.
+
+\subsection{Exam groups}
+
+The questions in an exam could be separated into several groups:
+
+\begin{code}
+\examgroup{Fill in the blanks.}{3 points for each.}
+......
+\examgroup{Select one answer.}{3 points for each.}
+......
+\examgroup{Work out math calculations.}{8 points for each.}
+......
+\end{code}
+
+\subsection{Exam data}
+
+At the end of the exam, you could add some appendix data with \mycmd{\examdata} command:
+
+\begin{code}
+\examdata{Some data may be used in the exam}
+......
+\end{code}
+
+You must put appendix data after \mycmd{\examdata} command,
+or the exam variants will be incorrect.
+
+\section{Types of questions}
+
+\subsection{True-or-false questions}
+
+\begin{code}
+\examgroup{True-or-false questions}{3 points for each.}
+
+\begin{question}
+The first true-or-false question. \tickout{T}
+\end{question}
+
+\begin{question}
+The second true-or-false question. \tickout{F}
+\end{question}
+\end{code}
+
+\begin{question}
+The first true-or-false question. \tickout{T}
+\end{question}
+
+\begin{question}
+The second true-or-false question. \tickout{F}
+\end{question}
+
+With \mycmd{\tickout{T}} and \mycmd{\tickout{F}}, you get \textcolor{blue}{\textsf{T}}
+and \textcolor{blue}{\textsf{F}}; with \mycmd{\tickout{t}} and \mycmd{\tickout{f}},
+you get \textcolor{blue}{$\checkmark$} and \textcolor{blue}{\large$\times$}.
+
+You must put answers inside \mycmd{\tickout} command,
+so as to make \mypkg{randexam} hide them in generating blank exam papers.
+
+\subsection{Fill-in-the-blank questions}
+
+\begin{code}
+\examgroup{Fill in the blanks.}{3 points for each.}
+
+\begin{question}
+The first fill-in-the-blank question \fillout{answer}.
+\end{question}
+
+\begin{question}
+The second fill-in-the-blank question \fillout{answer}.
+\end{question}
+\end{code}
+
+\begin{question}
+The first fill-in-the-blank question \fillout{answer}.
+\end{question}
+
+\begin{question}
+The second fill-in-the-blank question \fillout{answer}.
+\end{question}
+
+With \mycmd{\fillout} command, the underline will fill the whole line;
+with \mycmd{\fillin} command, the underline will be minimal.
+
+You must put answers inside \mycmd{\fillout} or \mycmd{\fillin} command,
+so as to make \mypkg{randexam} hide them in generating blank exam papers.
+
+\subsection{Multiple-choice questions}
+
+\begin{code}
+\examgroup{Select one answer.}{3 points for each.}
+
+\begin{question}
+The first multiple-choice questions \pickout{A}.
+\begin{abcd}
+ \item First
+ \item Second
+ \item Third
+ \item Fourth
+\end{abcd}
+\end{question}
+
+\begin{question}
+The second multiple-choice questions \pickout{C}.
+\begin{abcd}
+ \item First choice
+ \item Second choice
+ \item Third choice
+ \item Fourth choice
+\end{abcd}
+\end{question}
+\end{code}
+
+\begin{question}
+The first multiple-choice questions \pickout{A}.
+\begin{abcd}
+ \item First
+ \item Second
+ \item Third
+ \item Fourth
+\end{abcd}
+\end{question}
+
+\begin{question}
+The second multiple-choice questions \pickout{C}.
+\begin{abcd}
+ \item First choice
+ \item Second choice
+ \item Third choice
+ \item Fourth choice
+\end{abcd}
+\end{question}
+
+With \mycmd{\pickout} command, the answer will be printed on the right edge of the line;
+with \mycmd{\pickin} command, the answer will be printed on current position.
+
+You must put answers inside \mycmd{\pickout} or \mycmd{\pickin} command,
+so as to make \mypkg{randexam} hide them in generating blank exam papers.
+
+The four choices of multiple-choice questions could be typeset with \myenv{abcd} environment.
+And \myenv{abcd} environment will put them in one, two, or four rows
+according to the lengths of the choices.
+
+\subsection{Subjective questions}
+
+For subjective questions, you could put answers inside \myenv{solution} environment.
+
+\begin{code}
+\examgroup{Work out math calculations.}{8 points for each.}
+
+\begin{question}
+The first math calculation question.
+\end{question}
+
+\begin{solution}
+Answer to the first question.
+\end{solution}
+
+\begin{question}
+The second math calculation question.
+\end{question}
+
+\begin{solution}
+Answer to the second question.
+\end{solution}
+\end{code}
+
+\begin{question}
+The first math calculation question.
+\end{question}
+
+\begin{solution}
+Answer to the first question.
+\end{solution}
+
+\begin{question}
+The second math calculation question.
+\end{question}
+
+\begin{solution}
+Answer to the second question.
+\end{solution}
+
+\subsection{Other questions}
+
+You can write other types of questions. For example:
+
+\begin{code}
+\examgroup{Some question type}{4 points for each.}
+
+\begin{question}
+First question text. \answer{Answer text.}
+\end{question}
+
+\begin{question}
+Second question text. \answer{Answer text.}
+\end{question}
+\end{code}
+
+\begin{question}
+First question text. \answer{Answer text.}
+\end{question}
+
+\begin{question}
+Second question text. \answer{Answer text.}
+\end{question}
+
+You must put answer text inside \mycmd{\answer} command,
+so as to make \mypkg{randexam} hide them in generating blank exam papers.
+
+\section{Other components}
+
+\subsection{Grade tables}
+
+Normally you need a grade table after exam title.
+You can get it by using \mycmd{\gradetable} command.
+
+\begin{code}
+\gradetable
+\end{code}
+
+\gradetable
+
+\subsection{Answer tables}
+
+Before true-or-false, fill-in-the-blank, or multiple-choice questions,
+you may use \mycmd{\answertable} to generate an blank answer table:
+
+\begin{code}
+\answertable[3em]{6}{3}
+\end{code}
+
+\answertable[3em]{6}{3}
+
+The meanings of the three arguments of \verb!\answertable! commands are as follows:
+\begin{itemize}
+ \item The first one means the strut height of the answer rows; its default value is \verb!1em!.
+ \item The second one means the total number of questions in this exam group.
+ \item The third one means the number of questions in each row.
+\end{itemize}
+
+\subsection{Vertical space}
+
+You could leave some vertical space after a \myenv{question} or \myenv{solution} environment.
+At this time \mypkg{randexam} class supports the following commands for adding vertical space:\par
+
+\renewcommand{\arraystretch}{1.3}%
+\begin{tabularx}{\linewidth}{l<{\qquad}X}
+ \hline
+ \texttt{\string\smallskip} & Add small vertical space\\
+ \hline
+ \texttt{\string\medskip} & Add medium vertical space\\
+ \hline
+ \texttt{\string\bigskip} & Add big vertical space\\
+ \hline
+ \texttt{\string\vfill} & Fill vertical space available\\
+ \hline
+\end{tabularx}\par
+
+Of course, you could use multiple commands in the above tables.
+
+In the exam body, you could use \mycmd{\newpage} to make a page break,
+but you should \underline{NOT} use other page breaking commands, such as \mycmd{\clearpage},
+or the exam variants may be wrong.
+
+\section{Writing questions}
+
+\subsection{points key}
+
+The \myenv{question} environment accepts a \mykey{points} key:
+
+\begin{code}
+\begin{question}[points=4]
+This is a question.
+\end{question}
+\end{code}
+
+\begin{question}[points=4]
+This is a question.
+\end{question}
+
+\section{Writing solutions}
+
+\subsection{Solution name}
+
+If you want to change the name of \myenv{solution} environment,
+you could redefine \mycmd{\solutionname} command.
+The following example changes it from "Solution" to "Proof":
+
+\begin{code}
+\renewcommand{\solutionname}{Proof}
+\end{code}
+
+\subsection{Points command}
+
+Inside \myenv{solution} environment, you could use \mycmd{\points} to give points for each step.
+For example:
+
+\begin{code}
+\begin{solution}
+$1+1=2$ \points{4}
+$2+2=4$ \points{8}
+\end{solution}
+\end{code}
+
+\begin{solution}
+$1+1=2$ \points{4}
+$2+2=4$ \points{8}
+\end{solution}
+
+You can also use \mycmd{\points} command inside displayed formulas or \myenv{align*} environment.
+And the point text will be printed at the right edge of the line.
+
+\subsection{Alignment commands}
+
+With class option \myopt{many}, \mypkg{randexam} will load \mypkg{freealign} package.
+and \mypkg{freealign} package provides several commands for aligning math formulas in different lines.
+
+Here is the first example:
+
+\begin{code}
+We have $(a+b)^2 \? = (a+b)(a+b)$ \\
+ \+$= a^2+2ab+b^2$ \points{2}
+\end{code}
+
+\hrule
+We have $(a+b)^2 \? = (a+b)(a+b)$ \\
+ \+$= a^2+2ab+b^2$ \points{2}
+\hrule\vskip0.5em
+
+The \mycmd{\?} command \underline{inside} the first formula saves current horizontal position,
+and the \mycmd{\+} command \underline{before} the second formula jumps to previously saved position.
+
+Here is another example:
+
+\begin{code}
+We have \? $(a+b)^2 = (a+b)(a+b)$ \\
+ \< $= a^2+2ab+b^2$ \points{2}
+\end{code}
+
+\hrule
+We have \? $(a+b)^2 = (a+b)(a+b)$ \\
+ \< $= a^2+2ab+b^2$ \points{2}
+\hrule\vskip0.5em
+
+The \mycmd{\?} command \underline{before} the first formula saves current horizontal position,
+and the \mycmd{\<} command \underline{before} the second formula jumps to the left
+of previously saved position by the width of $=$.
+
+Because \mypkg{freealign} package uses \mypkg{zref} package to save positions,
+you need two compilations to get correct results.
+
+\section{Class options}
+
+\subsection{Blank exam papers}
+
+Assume \myfile{exam-a-answer.tex} is an exam paper with answers.
+You can easily get an blank exam paper with answers removed,
+by creating an \myfile{exam-a-blank.tex} file with the following lines:
+
+\begin{code}
+\PassOptionsToClass{noanswer}{randexam}
+\input{exam-a-answer}
+\end{code}
+
+That is to say, when adding \myopt{noanswer} option to \mypkg{randexam} class,
+The answers will be hidden in the compiled exam paper.
+
+\subsection{Randomized variants}\label{opt:random}
+
+Assume \myfile{exam-a-answer.tex} is an exam paper.
+You can get an randomized variant with all questions in the same group shuffled,
+by creating an \myfile{exam-b-answer.tex} file with the following lines:
+
+\begin{code}
+\PassOptionsToClass{random}{randexam}
+\input{exam-a-answer}
+\end{code}
+
+That is to say, when adding \myopt{random} option to \mypkg{randexam} class,
+The questions in the same group will be shuffled in the compiled exam paper.
+Furthermore, four choices in an \myenv{abcd} environment will be shuffled too.
+
+\subsection{Two column exam papers}
+
+Assume \myfile{exam-a-blank.tex} is the TeX file of an exam paper of A4 size.
+You could get an exam paper of A3 size,
+by creating a new TeX file with the following lines:
+
+\begin{code}
+\PassOptionsToClass{a3paper}{randexam}
+\input{exam-a-blank}
+\end{code}
+
+That is to say, when adding \myopt{a3paper} option to \mypkg{randexam} class,
+The result paper will be a two column document in A3 size.
+
+Assume \myfile{exam-a-blank.pdf} is the PDF file of an exam paper of A4 size.
+You could get an exam paper of A3 size,
+by creating a new TeX file with the following lines:
+\begin{code}
+
+\documentclass[a3input]{randexam}
+\begin{document}
+\includepdf[pages=-,nup=2x1]{exam-a-blank}
+\end{document}
+\end{code}
+
+That is to say, you can make an exam of A3 size from an exam of A4 size,
+even if you have only the PDF file.
+
+\end{document}