有没有更好的方法在考试类中生成单独的解决方案文件?

有没有更好的方法在考试类中生成单独的解决方案文件?

我为我教授的课程编写了很多考试、测验和家庭作业问题。每当我写评估时,我总是希望编写foo.tex一个单独的解决方案文件。这是我的工作流程的一个示例。foo-solutions.tex

我首先将评估结果与解决方案一起写在一个文件中foo-solutions.tex

\documentclass{exam}
\printanswers

\newcommand{\checkforstudent}[1]{%
  \ifcsname#1\endcsname%
  \noprintanswers%
  \else%  ... command '#1' does not exist ...%
  \fi%
}


\begin{document}

\checkforstudent{studentmode}

\begin{questions}
  \question What is the first sentence of \emph{Moby Dick}?
  \begin{solution}
    \emph{Call me Ishmael.}
  \end{solution}
\end{questions}

\end{document}

该命令\checkforstudent测试输入是否存在命令。如果存在,则关闭答案。使用后的第一行\begin{document}用于\checkforstudent检查命令

编译此文件会生成foo-solutions.pdf

foo-solutions.pdf 的屏幕截图

我还有一个文件foo.tex

\newcommand{\studentmode}{}\input foo-solutions

此文件定义命令\studentmode,然后输入全部foo-solutions.tex。编译foo.tex生成foo.pdf

foo.pdf 的屏幕截图

最后,我用 bash 脚本一次生成了这两个 pdfwrite-files.sh

#!/bin/bash

pdflatex foo-solutions.tex
pdflatex foo-solutions.tex

pdflatex foo
pdflatex foo

该脚本对两个文件进行两次编译,以确保所有引用都得到正确处理。

这个工作流程运行得相当好。然而,也有一些麻烦:

  1. 我必须跟踪三个文件而不是一个(foo-solutions.texfoo.texwrite-files.sh)。
  2. 当我撰写新的评估时bar.tex,我将foo-solutions.texfoo.tex和复制到新目录,并用 替换的write-files.sh实例foobar真的让我烦恼。
  3. 我的许多同事不习惯运行 Bash 脚本。因此,当我与他们分享我的文档时,他们在生成评估和解决方案时都遇到了麻烦。

如果能有一个解决方案,让我仅使用一个乳胶文件就能生成foo-solutions.pdf,那就太好了。foo.pdf

这可能吗?

笔记。我目前的工作流程受到以下启发:这个答案我也有类似的问题

答案1

除了您的第一个文件(您将其命名为foo-solutions.tex,但对于这个 Makefile 您应该将其命名为foo.tex)之外,您还可以使用以下 Makefile:

TEX   = pdflatex
# if you want to use specific FLAGS for compilation
FLAGS =

FILE = $(wildcard *.tex)

STDVER = $(FILE:%.tex=%-students)
SOLVER = $(FILE:%.tex=%-solutions)
STDOPT = studentmode

STDPDF = $(STDVER).pdf
SOLPDF = $(SOLVER).pdf

all: $(STDPDF) $(SOLPDF)

$(STDPDF): $(FILE)
    $(TEX) $(FLAGS) -jobname $(STDVER) "\def\$(STDOPT){}\input{$(FILE)}"
    $(TEX) $(FLAGS) -jobname $(STDVER) "\def\$(STDOPT){}\input{$(FILE)}"
    $(TEX) $(FLAGS) -jobname $(STDVER) "\def\$(STDOPT){}\input{$(FILE)}"
$(SOLPDF): $(FILE)
    $(TEX) $(FLAGS) -jobname $(SOLVER) $(FILE)
    $(TEX) $(FLAGS) -jobname $(SOLVER) $(FILE)
    $(TEX) $(FLAGS) -jobname $(SOLVER) $(FILE)

.PHONY: clean clean_sol clean_std
clean: clean_sol clean_std
clean_sol:
    -rm -f $(SOLVER).*
clean_std:
    -rm -f $(STDVER).*

将其放在与 .tex 文件相同的目录中,名为Makefile。此目录中应该只有一个 .tex 文件。如果有更多文件,请将行更改FILE = $(wildcard *.tex)FILE = <your-tex-files-name>.tex。它会生成两个单独的 pdf,一个名为<your-tex-files-name>-students.pdf,一个名为<your-tex-files-name>-solutions.pdf。使用 ,从 shell 调用它make

这是一个相当基本的 Makefile。它还可以进行一些改进,但应该够用了。

如果要删除创建的pdf和辅助文件,请make clean从shell调用。

答案2

1)使用 bash 脚本,您可以轻松避免有两个.tex 文件并简化您的代码。

这可以是你的foo.tex

\begin{document}

\begin{questions}
  \question What is the first sentence of \emph{Moby Dick}?
  \begin{solution}
    \emph{Call me Ishmael.}
  \end{solution}
\end{questions}

\end{document}

以及生成 foo-exam.pdf 和 foo-solutions.pdf 的脚本:

#!/bin/bash

pdflatex -jobname foo-exam "\documentclass{exam}\input foo"
pdflatex -jobname foo-exam "\documentclass{exam}\input foo"

pdflatex -jobname foo-solutions "\documentclass{exam}\printanswers\input foo"
pdflatex -jobname foo-solutions "\documentclass{exam}\printanswers\input foo"

2)您还可以通过使用参数调用脚本(例如),只使用一个脚本进行所有评估create-exam.sh foo

#!/bin/bash

if [ "$1" != "" ] && [ -f "${1}".tex ]; then

  pdflatex -jobname ${1}-exam "\documentclass{exam}\input ${1}"
  pdflatex -jobname ${1}-exam "\documentclass{exam}\input ${1}"

  pdflatex -jobname ${1}-solutions "\documentclass{exam}\printanswers\input ${1}"
  pdflatex -jobname ${1}-solutions "\documentclass{exam}\printanswers\input ${1}"

else
  echo "Syntax is:"
  echo "  create-exam name (where name.tex is the file to compile)"
fi

3)使用该参数,如果您将脚本安装到同事的 PATH 中一次,它将适用于所有评估。

可能存在不使用脚本的解决方案\immediate\write18{shell command},但需要在 Latex 中激活这个不安全的选项并转义该命令中的字符,这非常困难。如果绝对需要避免使用脚本,我会选择 Makefile 解决方案。

答案3

另一种选择是每次运行 TeX 时询问是否包含答案。这样您只需要 TeX 文件,不需要其他任何东西。不过回答这个问题可能会很烦人。

\documentclass{exam}
\def\TestIncludeAnswersTrue{true}
\def\TestIncludeAnswersFalse{false}
\def\askanswers{
  \typein[\IncludeAnswers]{Include answers?
  (\TestIncludeAnswersTrue/\TestIncludeAnswersFalse)}
  \ifx\TestIncludeAnswersTrue\IncludeAnswers
    \printanswers
  \else
    \ifx\TestIncludeAnswersFalse\IncludeAnswers
    \else
      \typeout{Please answer with '\TestIncludeAnswersTrue' or
      '\TestIncludeAnswersFalse'}
      \askanswers
    \fi
  \fi
}
\askanswers


\begin{document}

\begin{questions}
  \question What is the first sentence of \emph{Moby Dick}?
  \begin{solution}
    \emph{Call me Ishmael.}
  \end{solution}
\end{questions}

\end{document}

答案4

这里发布的解决方案效果很好,但我认为我终于找到了一个使用符号链接和的优雅解决方案latexmk

包裹currfile可以检测正在由 latex 编译的文件的名称。包xstring具有一个函数\IfSubStr,该函数根据给定字符串是否是另一个给定字符串的子字符串来执行代码。

因此,如果我们插入以下行

\IfSubStr*{\currfilename}{solutions}{ \printanswers }{ \noprintanswers }

在我们的序言中,如果文件名包含子字符串,考试类将打印解决方案solutions

考虑解决方案文档~/myexam/exam-solutions.tex

\documentclass{exam}

\usepackage{currfile}
\usepackage{xstring}

\IfSubStr*{\currfilename}{solutions}{ \printanswers }{ \noprintanswers }

\begin{document}

\begin{questions}

\question What is the first sentence of \emph{Moby Dick}?
  \begin{solution}
    \emph{Call me Ishmael.}
  \end{solution}

\end{questions}

\end{document}

发出将创建链接到的ln -s ~/myexam/exam-solutions.tex ~/myexam/exam.tex符号链接。从运行将自动生成裸考试和解决方案。exam.texexam-solutions.texlatexmk~/myexam/

相关内容