我想排版一份测试和评分方案。我有以下代码:
\documentclass{article}
\usepackage{ifthen}
\usepackage{amsmath,amsfonts,amsthm,amssymb}
\setcounter{secnumdepth}{0}
\newcommand{\probName}{}%
\newcounter{probCounter}%
\setcounter{probCounter}{1}
\newcounter{partCounter}%
\newenvironment{prob}[1][]%
{\setcounter{partCounter}{0}
\renewcommand{\probName}{#1}%
\section{{Problem \arabic{probCounter}}{: \probName}}%
}{
\stepcounter{probCounter}%
}
\newcommand{\partName}{}%
\renewenvironment{part}[1][]%
{\stepcounter{partCounter}%
\renewcommand{\partName}{#1}%
\subsection{{Part \Alph{partCounter}}{: \partName}}
}{}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newenvironment{ques}[1][]{
\ifthenelse{
\equal{#1}{}
}{}{
\ifthenelse{
\equal{#1}{1}
}{
\textbf{(#1 point)}
}{
\textbf{(#1 points)}
}}
}{}
\newenvironment{sol}[1][]{%
\begin{trivlist}%
\def\@tempa{#1}%
\ifx\@tempa\empty%
\item[]%
\else%
\item[\hskip\labelsep\relax #1]%
\fi%
{\bf Solution: \newline} }{%
\mbox{}\penalty10000\hfill\ensuremath{\Box} % \hmcpset@endmark%
\end{trivlist}%
}
\begin{document}
\begin{prob}[Prob 2 Title]
\begin{part}
\begin{ques}[10]
Q1
\end{ques}
\begin{sol}
Sol to Q1
\end{sol}
\end{part}
\begin{part}
\begin{ques}[20]
Q1
\end{ques}
\end{part}
\begin{part}
\begin{ques}[10]
Q1
\end{ques}
\begin{ques}[10]
Q2
\end{ques}
\end{part}
\end{prob}
\begin{prob}[Prob 2 Title]
\begin{ques}[20]
Q2 (parts are not the essential component in every problem, when it does not include the part, count it as 1)
\end{ques}
\begin{sol}
\begin{align}
step 1 \\
step 2 \\
e=mc^2
\end{align}
\end{sol}
\end{prob}
\end{document}
如下图所示:
我想要的是一种自动生成标题的方法,标题给出每个问题的部分数和点数,以及每个部分可用的点数。
所有标题(X parts, Y points)
都应使用问题后面提供的信息自动生成。
因此,如果我将“D 部分”(价值 10 分)添加到问题 1,则第一个蓝色标题将自动更新为(4 parts, 60 points)
。
“ques” 不能嵌套在“part”中,就像图片中一样,因为Problem
2 没有“Part A”。在这种情况下,标题仍然应该正确反映部分和点的数量。在这种情况下, (1 part, 20 points)
。
答案1
回答问题的新解决方案
您希望使用文档中稍后出现的信息为您的问题及其部分构建标题。显而易见的方法是使用\label
和\ref
,但由于您希望在后台执行此操作,因此需要动态生成标签名称。
用于交叉引用的动态标签
下面我定义了两个命令\dlabel
和 ,\dref
它们的功能分别类似于\label
和\ref
,不同之处在于它们使用动态名称作为标签,具体取决于计数器的当前值。语法为:
\dlabel{labelName}{counter}[value]
\dref{labelName}{counter}
这里的“计数器”是任何普通的乳胶计数器,“值”是存储用于交叉引用的内容(任何事物counter
可以在此处存储 sensible 。如果未提供任何值,则标签的值默认为(其版本)的值\arabic
。标签在辅助文件中存储为labelName-<counter value>
。
如果你想使用 返回的值,\dref
你不能只使用\dref
。相反,你需要使用一个特殊的计数器\theextractedReference
(这类似于数学使用\pgfmathresult
)。还有第三个宏 ,\Dref
其语法与 完全相同\dref
,用于设置extractedReference
计数器而不打印引用的值。
动态标签使用引用计数包以及一些扩展技巧。它们既可以工作,也可以不工作超链接并且应该对任何其他使用引用的包感到满意(我只检查了 hyperref)。
你的问题
一旦动态标签到位,做你想做的事情就不那么难了。你在你的问题中已经做了大部分工作。需要添加的只是在环境末尾使用添加动态标签的一些命令\dlabel
,然后在环境开始时你需要使用构建标题\Dref
。代码中还有一些注释。
以下是您的 MWE 的输出:
代码如下:
\documentclass{article}
\usepackage{xcolor}
\usepackage{ifthen}
\usepackage{amsmath,amsfonts,amsthm,amssymb}
\usepackage{etoolbox}
\usepackage{xparse}
\usepackage{refcount}
%% dynamic references based on counters
\makeatletter
%dynamic label: \dlabel{label name}{counter}[value]
\NewDocumentCommand\dlabel{mmo}{%
\IfNoValueTF{#3}{\def\dlabelval{\value{#2}}}{\def\dlabelval{#3}}%
\edef\mylabel{#1-\arabic{#2}}\edef\@currentlabel{\dlabelval}%
\expandafter\label{\mylabel}%
}
% dynamic reference: \dref{label name}{counter}
\newcommand\dref[2]{
\edef\myref{#1-\arabic{#2}}%
\expandafter\ref{\myref}%
}
% dynamic reference: \Dref{label name}{counter}
% - sets \theextractedReference equal to the reference value
\newcounter{extractedReference}
\newcommand\Dref[2]{%
\edef\myref{#1-\arabic{#2}}%
\expandafter\setcounterref{extractedReference}{\myref}%
}
%% problems
\setcounter{secnumdepth}{0}
\newcounter{problemNumber}% current problem number
\def\theproblemNumber{Problem~\arabic{problemNumber}}%
\newcounter{partNumber}% current part number
\def\thepartNumber{Part~\Alph{partNumber}}%
\newcounter{problemPoints}% points for problem: cumulative
\newcounter{partPoints}% points for part: cumulative
\newenvironment{problem}[1][]%
{\stepcounter{problemNumber}% increment problem number
\setcounter{problemPoints}{0}% reset points for problem
\setcounter{partNumber}{0}% reset parts for problem
% building the problem subheading: (# parts, # points)
\Dref{problemParts}{problemNumber}% set \theextractedReference = #parts
\let\problemHeading\relax% clear problem heading
\ifnum\theextractedReference>0% add number of parts to heading
\ifnum\theextractedReference=1%
\def\problemHeading{1 part}%
\else
\xdef\problemHeading{\theextractedReference\space parts}%
\fi
\fi
\Dref{problemPoints}{problemNumber}% set \theextractedReference = #points
\ifnum\theextractedReference>0% add number of points to heading
% add comma to heading as necessary
\ifx\problemHeading\relax\relax\else\appto\problemHeading{, }\fi
\ifnum\theextractedReference=1%
\appto\problemHeading{1 point}%
\else
\xappto\problemHeading{\theextractedReference\space points}%
\fi
\fi
\section{\theproblemNumber: #1% add header if not empty=\relax
\ifx\problemHeading\relax\relax\else\space(\problemHeading)\fi}%
}{% save number of parts and point for the problem
\dlabel{problemParts}{problemNumber}[\arabic{partNumber}]
\dlabel{problemPoints}{problemNumber}[\theproblemPoints]
}
\renewenvironment{part}%
{\stepcounter{partNumber}%
\setcounter{partPoints}{0}
\Dref{partPoints:\arabic{problemNumber}}{partNumber}% set \theextractedReference = #points %%% edited the partNumber counter
\let\partHeading\relax% clear heading
\ifnum\theextractedReference>0% add number of points to heading
\ifnum\theextractedReference=1%
\def\partHeading{1 point}%
\else
\def\partHeading{\theextractedReference\space points}%
\fi
\fi
\subsection{\thepartNumber: % add header if not empty=\relax
\ifx\partHeading\relax\relax\else Total \partHeading\fi}
}{% save number of points for part
\dlabel{partPoints:\arabic{problemNumber}}{partNumber}[\thepartPoints]} %%% edited the partNumber counter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% from OP
\newenvironment{question}[1][]{
\ifthenelse{
\equal{#1}{}
}{}{% increment point counters for parts and problems
\addtocounter{partPoints}{#1}
\addtocounter{problemPoints}{#1}
\ifthenelse{
\equal{#1}{1}
}{
\noindent\textbf{(#1 point)}
}{
\noindent\textbf{(#1 points)}
}}
}{}
\newenvironment{solution}[1][]{%
\begin{trivlist}%
\def\@tempa{#1}%
\ifx\@tempa\empty%
\item[]%
\else%
\item[\hskip\labelsep\relax #1]%
\fi%
\textbf{solution}: \newline
}{%
\mbox{}\penalty10000\hfill\ensuremath{\Box} % \hmcpset@endmark%
\end{trivlist}%
}
\makeatother
\begin{document}
\begin{problem}[First Title]
\begin{part}
\begin{question}[10]
Q1
\end{question}
\begin{solution}
Sol to Q1
\end{solution}
\end{part}
\begin{part}
\begin{question}[20]
Q1
\end{question}
\end{part}
\begin{part}
\begin{question}[10]
Q1
\end{question}
\begin{question}[10]
Q2
\end{question}
\end{part}
\end{problem}
\begin{problem}[Second title]
\begin{question}[20]
Q2 (parts are not the essential component in every problem, when it
does not include the part, count it as 1)
\end{question}
\begin{solution}
\begin{align}
step 1 \\
step 2 \\
e=mc^2
\end{align}
\end{solution}
\end{problem}
\end{document}
顺便说一句,第二个问题不包含任何部分,所以我认为这里唯一合理的标题是打印可用的点数,而不提及部分数。这就是我的解决方案所做的。或者,您可以打印问题在问题中。