制作依赖于后续环境的标题

制作依赖于后续环境的标题

我想排版一份测试和评分方案。我有以下代码:

\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}

如下图所示:

enter image description here

我想要的是一种自动生成标题的方法,标题给出每个问题的部分数和点数,以及每个部分可用的点数。

enter image description here

所有标题(X parts, Y points)都应使用问题后面提供的信息自动生成。

因此,如果我将“D 部分”(价值 10 分)添加到问题 1,则第一个蓝色标题将自动更新为(4 parts, 60 points)

“ques” 不能嵌套在“part”中,就像图片中一样,因为Problem2 没有“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 的输出:

enter image description here

代码如下:

\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}

顺便说一句,第二个问题不包含任何部分,所以我认为这里唯一合理的标题是打印可用的点数,而不提及部分数。这就是我的解决方案所做的。或者,您可以打印问题在问题中。

相关内容