我正在寻找一个 LaTeX 软件包,它允许我使用从特定题库中抽取的问题生成考试。题库中的每个问题都是一个独立的 LaTeX 代码块。
例如,本着该exam
方案的精神,我可能会有以下问题:
\question
$2+2=$
\begin{choices}
\choice 3
\choice 0
\choice 4
\choice $\sqrt{2}$
\choice $-\pi$
\end{choices}
\question
$\int_0^1 x^2\,dx=$
\begin{choices}
\choice $-1$
\choice $1/3$
\choice $\infty$
\choice $1/2$
\choice None of the above.
\end{choices}
这将是一个包含两个问题的库。每个问题都是一个 LaTeX 代码块,如果将其从库中“取出”并插入“父”可编译 LaTeX 文件,则会生成一份考试(大概是此类软件包的作用)。
出于贪心,我真的很想指定从问题库 $B_1$ 中抽取的问题数量 $q_1$,从 $B_2$ 中抽取的问题数量 $q_2$,等等,其中每个库 $B_i$ 都涉及一个特定的主题。
如果这个已经存在,我还没能找到。保留 documentclass exam
(或类似的东西)的功能将使分配分数和/或生成答案键与(随机)考试创建同时进行。
答案1
假设你有A其中的问题库bankA.tex
具有以下格式:
\begin{questionblock}
Question 1
\end{questionblock}
\begin{questionblock}
Question 2
\end{questionblock}
\begin{questionblock}
Question 3
\end{questionblock}
\begin{questionblock}
Question 4
\end{questionblock}
\begin{questionblock}
Question 5
\end{questionblock}
\begin{questionblock}
Question 6
\end{questionblock}
\begin{questionblock}
Question 7
\end{questionblock}
\begin{questionblock}
Question 8
\end{questionblock}
\begin{questionblock}
Question 9
\end{questionblock}
\begin{questionblock}
Question 10
\end{questionblock}
用某种形式的块/环境 (在本例中) 来表示每个问题很重要questionblock
。最终,您会将每个银行保存在单独的文件中,例如bankA.tex
,,bankB.tex
... 对于环境中可以包含的内容不应有任何限制questionblock
。
我们从该库中生成一组随机问题的算法如下:
读取文件并存储在宏中(感谢
catchfile
;计算银行里有多少个问题(使用
environ
将整个questionblock
环境作为一个\stepcounter
机制来处理)。拨打此号码totalquestions
;创建一个从 1 到
totalquestions
(作为参考,请参阅生成无重复的随机数));重复以下步骤:
从随机列表中选择一个数字;
处理整个银行,直到找到与所选数字相匹配的问题并将其打印出来;
通过删除选定的数字来修剪随机列表。
上述过程可能会进行大量额外处理,但我相信它不会过于繁琐。以下是一家银行的完整最小示例:
\documentclass{article}
\usepackage{multicol}% Just for this example
\usepackage{filecontents}
\begin{filecontents*}{bankA.tex}
\begin{questionblock}
Question 1
\end{questionblock}
\begin{questionblock}
Question 2
\end{questionblock}
\begin{questionblock}
Question 3
\end{questionblock}
\begin{questionblock}
Question 4
\end{questionblock}
\begin{questionblock}
Question 5
\end{questionblock}
\begin{questionblock}
Question 6
\end{questionblock}
\begin{questionblock}
Question 7
\end{questionblock}
\begin{questionblock}
Question 8
\end{questionblock}
\begin{questionblock}
Question 9
\end{questionblock}
\begin{questionblock}
Question 10
\end{questionblock}
\end{filecontents*}
\usepackage{catchfile,environ,tikz}
\makeatletter% Taken from https://tex.stackexchange.com/q/109619/5764
\def\declarenumlist#1#2#3{%
\expandafter\edef\csname pgfmath@randomlist@#1\endcsname{#3}%
\count@\@ne
\loop
\expandafter\edef
\csname pgfmath@randomlist@#1@\the\count@\endcsname
{\the\count@}
\ifnum\count@<#3\relax
\advance\count@\@ne
\repeat}
\def\prunelist#1{%
\expandafter\xdef\csname pgfmath@randomlist@#1\endcsname
{\the\numexpr\csname pgfmath@randomlist@#1\endcsname-1\relax}
\count@\pgfmath@randomtemp
\loop
\expandafter\global\expandafter\let
\csname pgfmath@randomlist@#1@\the\count@\expandafter\endcsname
\csname pgfmath@randomlist@#1@\the\numexpr\count@+1\relax\endcsname
\ifnum\count@<\csname pgfmath@randomlist@#1\endcsname\relax
\advance\count@\@ne
\repeat}
\makeatother
% Define how each questionblock should be handled
\newcounter{questionblock}
\newcounter{totalquestions}
\NewEnviron{questionblock}{}%
\newcommand{\randomquestionsfrombank}[2]{%
\CatchFileDef{\bank}{#1}{}% Read the entire bank of questions into \bank
\setcounter{totalquestions}{0}% Reset total questions counters ***
\RenewEnviron{questionblock}{\stepcounter{totalquestions}}% Count every question ***
\bank% Process file ***
\declarenumlist{uniquequestionlist}{1}{\thetotalquestions}% list from 1 to totalquestions inclusive.
\setcounter{totalquestions}{#2}% Start the count-down
\RenewEnviron{questionblock}{%
\stepcounter{questionblock}% Next question
\ifnum\value{questionblock}=\randomquestion
\par% Start new paragraph
\BODY% Print question
\fi
}%
\foreach \uNiQueQ in {1,...,#2} {% Extract #2 random questions
\setcounter{questionblock}{0}% Start fresh with question block counter
\pgfmathrandomitem\randomquestion{uniquequestionlist}% Grab random question from list
\xdef\randomquestion{\randomquestion}% Make random question available globally
\prunelist{uniquequestionlist}% Remove picked item from list
\bank% Process file
}}
\begin{document}
\begin{multicols}{3}
\foreach \x in {1,...,6} {
\bigskip
\randomquestionsfrombank{bankA.tex}{6}
}
\end{multicols}
\end{document}
调用 会从 中随机\randomquestionsfrombank{<file>}{<num>}
挑选问题。如果您不想第一次处理 以获取问题数量,您可以删除用 突出显示的行。<num>
<file>
<file>
***
答案2
也许我来晚了。我在寻找一种自动创建随机考试的方法时发现了这个旧帖子。正如@vonbrand所建议的,Python脚本可以解决问题。这是我想到的解决方案:
import sys
import os
import random
exam = sys.argv[1]
folder = sys.argv[2]
questions = []
for bank, number in zip(sys.argv[3::2], map(int, sys.argv[4::2])):
qfiles = [
os.path.join(dirpath, fname)
for dirpath, dirnames, filenames in os.walk(os.path.join(folder, bank))
for fname in filenames
if os.path.splitext(fname)[-1].lower() == '.tex'
]
for qfile in random.sample(qfiles, number):
with open(qfile, 'r') as qfh:
questions.append(qfh.read())
with open(exam, 'w') as efh:
for question in questions:
print(question, file=efh)
演示
假设我们有3个题库,分别是ch1
,ch2
和ch3
,分别有5,10和100道模拟题,按照以下文件树:
C:
├── exams
└── banks
├── ch1
│ ├── ch1q1.tex
│ ├── ...
│ └── ch1q5.tex
├── ch2
│ ├── ch2q1.tex
│ ├── ...
│ └── ch2q10.tex
└── ch3
├── ch3q1.tex
├── ...
└── ch3q100.tex
如果我们希望通过从中随机挑选一道题ch1
、从中随机挑选一道题ch2
和从中随机挑选两道题来创建考试ch3
,我们可以在命令行中输入以下指令来完成这项工作:
C:\>python exam.py C:\exams\sample_exam.tex C:\banks ch1 1 ch2 1 ch3 2
sample_exam.tex
最终文件看起来如下:
\question Chapter 1 -- Question 4
\begin{choices}
\choice Choice a
\CorrectChoice Choice b
\choice Choice c
\choice Choice d
\end{choices}
\question Chapter 2 -- Question 8
\begin{choices}
\choice Choice a
\choice Choice b
\CorrectChoice Choice c
\end{choices}
\question Chapter 3 -- Question 75
\begin{choices}
\CorrectChoice Choice a
\choice Choice b
\choice Choice c
\choice Choice d
\choice Choice e
\end{choices}
\question Chapter 3 -- Question 23
\begin{choices}
\choice Choice a
\choice Choice b
\CorrectChoice Choice c
\end{choices}
需要指出的是,您可以<bank_i> <number_i>
在命令行参数列表中放入与问题库数量相同的对。还值得注意的是,没有什么可以阻止您将问题库组织成部分(子目录):
C:
├── exams
└── banks
├── ch1
│ ├── ch1q1.tex
│ ├── ...
└── ch2
├── sec1
│ ├── ch2sec1q1.tex
│ ├── ch2sec1q2.tex
│ ├── ...
├── sec2
│ ├── ch2sec2q1.tex
│ ├── ch2sec2q2.tex
│ ├── ...
├── ...
因为问题搜索是递归进行的。
答案3
我不确定您是否仍在寻找这样的包,但如果是的话,请查看 probsoln 包:https://ctan.org/pkg/probsoln?lang=en。过去几年我一直在使用它,我认为它完全满足你的要求。
答案4
我曾经编写过一个代码,用于从“库”中随机选择方程式,并将试卷中的几乎所有细节随机化。该代码可在以下网址免费下载: https://github.com/LiuGangKingston/Personalized-Test-Creator.git
具体来说,它可以随机化
- 从“问题库”中选择问题;
- 从多项选择题的“选择库”中选择选项;
- 给定问题或分组问题的顺序;
- 多项选择题的选择顺序;
- 计算问题中的任何整数、实数或其他数字;等等。
当然,老师可以完全控制随机化的方式和程度。因此,老师可以得到他/她想要的任意数量的试卷。同时,任何生成的试卷中任何问题的答案和/或解决方案也将在单独的文件中生成。为了使用它,老师应该在 Latex 中提供一份原始试卷和一些特殊命令。例如,特殊命令“PTC-RRR(2.00, 5.51, .25)”将被随机替换为 (2.00, 2.25, 2.50, 2.75, 3.00, 3.25, 3.50, 3.75, 4.00, 4.25, 4.50, 4.75, 5.00, 5.25, 5.50) 中的一个数字。请注意,根据命令的用法,它们都在小数点后有两位数字。缺点是它是用 FORTRAN 语言编写的,因此为了生成答案,老师也应该编写一点 FORTRAN 代码。因为为了得到答案,只需要非常有限的 FORTRAN 语言的简单编程子集。例如,Variable_A = Variable_B + Variable_C * sin(Variable_D) / Variable_E + Variable_F ** Variable_G 计算结果并将其与其他变量一起保存到 Variable_A。然后,所有这些都可以直接用于在 Latex 文件中编写答案。
最后一点,它是通用的Latex编码,目前试卷的格式完全由老师设计,可以任意选择,后续版本可能会全面支持试卷文档类,更加方便。