使用“xsim”,如何使用自定义模板分别打印两个练习类型及其解决方案

使用“xsim”,如何使用自定义模板分别打印两个练习类型及其解决方案

我正在尝试使用 xsim 来使用两种练习类型“练习”和“问题”。这两种练习类型都将用于在书的不同部分显示“练习”和“问题”,并在书的末尾分别显示它们的答案。@cgnieder 描述了如何使用练习类型“练习”来实现所需的目的这里。我采用了如下代码:

    \DeclareExerciseEnvironmentTemplate{exercise-temp}{%
    \par\noindent
    \textbf{\GetExerciseProperty{counter}}%
    \GetExercisePropertyT{subtitle}{ \textit{#1}} %
}{\par}

\newcommand\printsectionexercises{%
    \ForEachUsedExerciseByType{%
        \ifnum\ExercisePropertyGet{exercise}{##2}{chapter-value}=\value{chapter}
        \ifnum\ExercisePropertyGet{exercise}{##2}{section-value}=\value{section}
        \XSIMprint{exercise}{exercise}{##2}%
        \fi
        \fi
    }%
}

\newcommand\printexercisesolutions{%
    \def\currentchapter{}%
    \def\currentsection{}%
    \def\lastchapter{}%
    \def\lastsection{}%
    \ForEachUsedExerciseByType{%
        \let\lastchapter\currentchapter
        \let\lastsection\currentsection
        \edef\currentchapter{\ExercisePropertyGet{exercise}{##2}{chapter-value}}%
        \edef\currentsection{\ExercisePropertyGet{exercise}{##2}{section-value}}%
        \ifx\lastchapter\currentchapter\else
        \section*{Chapter \ExercisePropertyGet{exercise}{##2}{chapter}}
        \fi
        \ifx\lastsection\currentsection\else
        \subsection*{Exercise \ExercisePropertyGet{exercise}{##2}{section}}
        \fi
        \XSIMprint{solution}{exercise}{##2}%
    }%
}

\xsimsetup{
    exercise/template = exercise-temp ,
    solution/template = exercise-temp ,
    exercise/within = section ,
    exercise/the-counter = \arabic{exercise}. ,
    exercise/print = false
}

要打印“练习”,我使用

\subsection*{Exercise \thesection}
\printsectionexercises

为了给书末的所有练习提供“答案”,我使用

\printexercisesolutions

上述代码给出了所需的结果。

接下来,我尝试将上述代码用于其他 ExerciseType“问题”,如下所示:

    \DeclareExerciseEnvironmentTemplate{question-temp}{%
    \par\noindent
    \textbf{\GetExerciseProperty{counter}}%
    \GetExercisePropertyT{subtitle}{ \textit{#1}} %
}{\par}

\DeclareExerciseType{question}{
    exercise-env = question ,
    solution-env = answer ,
    exercise-name = \XSIMtranslate{Question} ,
    exercises-name = \XSIMtranslate{Questions} ,
    solution-name = \XSIMtranslate{Answer} ,
    solutions-name = \XSIMtranslate{Answers} ,
    exercise-template = question-temp ,
    solution-template = question-temp ,
    exercise-heading = \subsection* ,
    solution-heading = \subsection*
}

\newcommand{\printsectionquestions}{%
    \ForEachUsedExerciseByType{%
        \ifnum\ExercisePropertyGet{question}{##2}{chapter-value}=\value{chapter}
        \ifnum\ExercisePropertyGet{question}{##2}{section-value}=\value{section}
        \XSIMprint{question}{question}{##2}%
        \fi
        \fi
    }%
}

\newcommand{\printquestionsolutions}{%
    \def\currentchapter{}%
    \def\currentsection{}%
    \def\lastchapter{}%
    \def\lastsection{}%
    \ForEachUsedExerciseByType{%
        \let\lastchapter\currentchapter
        \let\lastsection\currentsection
        \edef\currentchapter{\ExercisePropertyGet{question}{##2}{chapter-value}}%
        \edef\currentsection{\ExercisePropertyGet{question}{##2}{section-value}}%
        \ifx\lastchapter\currentchapter\else
        \section*{Chapter \ExercisePropertyGet{question}{##2}{chapter}}
        \fi
        \ifx\lastsection\currentsection\else
        \subsection*{Question \ExercisePropertyGet{question}{##2}{section}}
        \fi
        \XSIMprint{answer}{question}{##2}%
    }%
}

\xsimsetup{
    exercise/template = question-temp ,
    solution/template = question-temp ,
    exercise/within = section ,
    exercise/the-counter = \arabic{question}. ,
    exercise/print = false
}

为了打印“问题”,我使用

\subsection*{Question \thesection}
\printsectionquestions

为了在最后打印出问题的“答案”,我使用

\printquestionsolutions

但是上述“问题”代码并没有给出与“练习”相应代码类似的结果。

问题:“问题”的编码结果与“练习”的编码结果有以下两点不同:

  1. 问题集的标题(例如,以下屏幕截图中的“问题 1.1”)出现在问题集下方,而它应该出现在上方:在此处输入图片描述
  2. 最后的答案集合只显示问题集的标题(如下图所示),但不显示相应的答案:在此处输入图片描述

如果有人能帮助解决上述问题,我将不胜感激。我是乳胶新手,所以请多多包涵。

ExerciseType 'Question' 的完整代码如下:

    \documentclass[fontsize=11pt]{book}
    
    \usepackage{xsim}
    
    %%For 'Questions'%%
    
    \DeclareExerciseEnvironmentTemplate{question-temp}{%
        \par\noindent
        \textbf{\GetExerciseProperty{counter}}%
        \GetExercisePropertyT{subtitle}{ \textit{#1}} %
    }{\par}
    
    \DeclareExerciseType{question}{
        exercise-env = question ,
        solution-env = answer ,
        exercise-name = \XSIMtranslate{Question} ,
        exercises-name = \XSIMtranslate{Questions} ,
        solution-name = \XSIMtranslate{Answer} ,
        solutions-name = \XSIMtranslate{Answers} ,
        exercise-template = question-temp ,
        solution-template = question-temp ,
        exercise-heading = \subsection* ,
        solution-heading = \subsection*
    }
    
    \newcommand{\printsectionquestions}{%
        \ForEachUsedExerciseByType{%
            \ifnum\ExercisePropertyGet{question}{##2}{chapter-value}=\value{chapter}
            \ifnum\ExercisePropertyGet{question}{##2}{section-value}=\value{section}
            \XSIMprint{question}{question}{##2}%
            \fi
            \fi
        }%
    }
    
    \newcommand{\printquestionsolutions}{%
        \def\currentchapter{}%
        \def\currentsection{}%
        \def\lastchapter{}%
        \def\lastsection{}%
        \ForEachUsedExerciseByType{%
            \let\lastchapter\currentchapter
            \let\lastsection\currentsection
            \edef\currentchapter{\ExercisePropertyGet{question}{##2}{chapter-value}}%
            \edef\currentsection{\ExercisePropertyGet{question}{##2}{section-value}}%
            \ifx\lastchapter\currentchapter\else
            \section*{Chapter \ExercisePropertyGet{question}{##2}{chapter}}
            \fi
            \ifx\lastsection\currentsection\else
            \subsection*{Question \ExercisePropertyGet{question}{##2}{section}}
            \fi
            \XSIMprint{answer}{question}{##2}%
        }%
    }
    
    \xsimsetup{
        exercise/template = question-temp ,
        solution/template = question-temp ,
        exercise/within = section ,
        exercise/the-counter = \arabic{question}. ,
        exercise/print = false
    }
    
    \begin{document}
    
    \mainmatter
    
    \chapter{Chapter on Cat}
    
    \section{Cat-1}
    
    SOME TEXT...
    
    \begin{question}
        Question 1 in Section 1.1 in Chapter 1
    \end{question}
    \begin{answer}
        Answer of Question 1 in Section 1.1 in Chapter 1
    \end{answer}
    
    \begin{question}
        Question 2 in Section 1.1 in Chapter 1
    \end{question}
    \begin{answer}
        Answer of Question 2 in Section 1.1 in Chapter 1
    \end{answer}
    
    \subsection*{Question \thesection}
        \printsectionquestions
    
    \section{Cat-2}
    
    SOME TEXT...
    
    \begin{question}
        Question 1 in Section 1.2 in Chapter 1
    \end{question}
    \begin{answer}
        Answer of Question 1 in Section 1.2 in Chapter 1
    \end{answer}
    
    \begin{question}
        Question 2 in Section 1.2 in Chapter 1
    \end{question}
    \begin{answer}
        Answer of Question 2 in Section 1.2 in Chapter 1
    \end{answer}
    
    \subsection*{Question \thesection}
    \printsectionquestions
    
    \chapter{Chapter on Dog}
    
    \section{Dog-1}
    
    SOME TEXT...
    
    \begin{question}
        Question 1 in Section 2.1 in Chapter 2
    \end{question}
    \begin{answer}
        Answer of Question 1 in Section 2.1 in Chapter 2
    \end{answer}
    
    \begin{question}
        Question 2 in Section 2.1 in Chapter 2
    \end{question}
    \begin{answer}
        Answer of Question 2 in Section 2.1 in Chapter 2
    \end{answer}
    
    \subsection*{Question \thesection}
    \printsectionquestions
    
    \section{Dog-2}
    
    SOME TEXT...
    
    \begin{question}
        Question 1 in Section 2.2 in Chapter 2
    \end{question}
    \begin{answer}
        Answer of Question 1 in Section 2.2 in Chapter 2
    \end{answer}
    
    \begin{question}
        Question 2 in Section 2.2 in Chapter 2
    \end{question}
    \begin{answer}
        Answer of Question 2 in Section 2.2 in Chapter 2
    \end{answer}
    
    \subsection*{Question \thesection}
    \printsectionquestions
    
    \chapter*{\underline{Answers to Questions}}
    
    \printquestionsolutions
    
    \end{document}

编辑: 最后,我想要在同一个文件中使用“锻炼”和“问题”实现如下效果:

在此处输入图片描述

答案1

提供的一些配置xsim可能会令人费解。

第一的exercise/print中所使用的选项\xsimsetup{exercise/print=false}是针对每个锻炼类型的。这意味着的一般形式exercise/print<env name>/print。因此,要针对锻炼类型设置question,您需要设置

\xsimsetup{
    question/template = question-temp ,
    answer/template = question-temp ,
    question/within = section ,
    question/the-counter = \arabic{question}. ,
    question/print = false
}

这解释了问题 1

  1. 问题集的标题(例如,以下屏幕截图中的“问题 1.1”)出现在问题集下方,而它应该出现在上方:

因为在原始设置下\xsimsetup{exercise/print=false},只有类型的练习exercise不会被打印,problem默认情况下,(新)类型的练习仍会打印。另请参阅包手册(v0.21,2022/02/12),

8.2. 环境选项和钩子

对于每种练习类型,两种环境都有以下选项,环境的名称是选项的模块名称(此处使用“练习”类型):

因此,问题 1 的实际发生情况是,problem环境被立即打印,并且\printsectionquestions什么都没有打印。

更令人费解的是, 的第一个强制参数\XSIMprint必须是“exercise”或“solution”之一。因此\XSIMprint{answer}{question}{##2}不会打印任何内容,也不会抛出任何错误。

这解释了问题2。

完整且更新的示例

\documentclass[fontsize=11pt]{book}

\usepackage{xsim}

%%For 'Questions'%%

\DeclareExerciseEnvironmentTemplate{question-temp}{%
    \par\noindent
    \textbf{\GetExerciseProperty{counter}}%
    \GetExercisePropertyT{subtitle}{ \textit{#1}} %
}{\par}

\DeclareExerciseType{question}{
    exercise-env = question ,
    solution-env = answer ,
    exercise-name = \XSIMtranslate{Question} ,
    exercises-name = \XSIMtranslate{Questions} ,
    solution-name = \XSIMtranslate{Answer} ,
    solutions-name = \XSIMtranslate{Answers} ,
    exercise-template = question-temp ,
    solution-template = question-temp ,
    exercise-heading = \subsection* ,
    solution-heading = \subsection*
}

\newcommand{\printsectionquestions}{%
  % ##1 type, ##2 id, ...
  \ForEachUsedExerciseByType{%
    \ifstrequal{question}{##1}{%
        \ifnum\ExercisePropertyGet{##1}{##2}{chapter-value}=\value{chapter}\relax
          \ifnum\ExercisePropertyGet{##1}{##2}{section-value}=\value{section}\relax
              \XSIMprint{exercise}{##1}{##2}%
          \fi
        \fi
    }{}%
  }%
}

\newcommand{\printquestionsolutions}{%
    \def\currentchapter{}%
    \def\currentsection{}%
    \def\lastchapter{}%
    \def\lastsection{}%
    \ForEachUsedExerciseByType{%
        \ifstrequal{question}{##1}{%
            \let\lastchapter\currentchapter
            \let\lastsection\currentsection
            \edef\currentchapter{\ExercisePropertyGet{##1}{##2}{chapter-value}}%
            \edef\currentsection{\ExercisePropertyGet{##1}{##2}{section-value}}%
            \ifx\lastchapter\currentchapter\else
                \section*{Chapter \ExercisePropertyGet{##1}{##2}{chapter}}
            \fi
            \ifx\lastsection\currentsection\else
                \subsection*{Question \ExercisePropertyGet{##1}{##2}{section}}
            \fi
            \XSIMprint{solution}{##1}{##2}%
        }{}%
    }%
}

\xsimsetup{
    question/template = question-temp ,
    answer/template = question-temp ,
    question/within = section ,
    question/the-counter = \arabic{question}. ,
    question/print = false
}

\begin{document}

\mainmatter

\chapter{Chapter on Cat}

\section{Cat-1}

SOME TEXT...

\begin{question}
    Question 1 in Section 1.1 in Chapter 1
\end{question}
\begin{answer}
    Answer of Question 1 in Section 1.1 in Chapter 1
\end{answer}

MORE TEXT...

\begin{question}
    Question 2 in Section 1.1 in Chapter 1
\end{question}
\begin{answer}
    Answer of Question 2 in Section 1.1 in Chapter 1
\end{answer}

\subsection*{Question \thesection}
    \printsectionquestions

\section{Cat-2}

SOME TEXT...

\begin{question}
    Question 1 in Section 1.2 in Chapter 1
\end{question}
\begin{answer}
    Answer of Question 1 in Section 1.2 in Chapter 1
\end{answer}

MORE TEXT...

\begin{question}
    Question 2 in Section 1.2 in Chapter 1
\end{question}
\begin{answer}
    Answer of Question 2 in Section 1.2 in Chapter 1
\end{answer}

\subsection*{Question \thesection}
\printsectionquestions

\chapter{Chapter on Dog}

\section{Dog-1}

SOME TEXT...

\begin{question}
    Question 1 in Section 2.1 in Chapter 2
\end{question}
\begin{answer}
    Answer of Question 1 in Section 2.1 in Chapter 2
\end{answer}

\begin{question}
    Question 2 in Section 2.1 in Chapter 2
\end{question}
\begin{answer}
    Answer of Question 2 in Section 2.1 in Chapter 2
\end{answer}

\subsection*{Question \thesection}
\printsectionquestions

\section{Dog-2}

SOME TEXT...

\begin{question}
    Question 1 in Section 2.2 in Chapter 2
\end{question}
\begin{answer}
    Answer of Question 1 in Section 2.2 in Chapter 2
\end{answer}

\begin{question}
    Question 2 in Section 2.2 in Chapter 2
\end{question}
\begin{answer}
    Answer of Question 2 in Section 2.2 in Chapter 2
\end{answer}

\subsection*{Question \thesection}
\printsectionquestions

\chapter*{\underline{Answers to Questions}}

\printquestionsolutions

\end{document}
关于猫的章节 狗篇 问题答案
关于猫的章节 狗篇 问题答案

更新:同时使用两种锻炼类型

除了概括\printSectionExerEnvsOfType和之外\printSoluEnvsOfType,还请注意\def\lastsection{}在里面添加的\ifx\lastchapter\currentchapter\else...\fi,在,即我前面例子中\printSoluEnvsOfType的广义形式。\printquestionsolutions

\documentclass[fontsize=11pt]{book}

\usepackage{xsim}

%%For 'Questions'%%

\DeclareExerciseEnvironmentTemplate{question-temp}{%
    \par\noindent
    \textbf{\GetExerciseProperty{counter}}%
    \GetExercisePropertyT{subtitle}{ \textit{#1}} %
}{\par}

\DeclareExerciseType{question}{
    exercise-env = question ,
    solution-env = answer ,
    exercise-name = \XSIMtranslate{Question} ,
    exercises-name = \XSIMtranslate{Questions} ,
    solution-name = \XSIMtranslate{Answer} ,
    solutions-name = \XSIMtranslate{Answers} ,
    exercise-template = question-temp ,
    solution-template = question-temp ,
    exercise-heading = \subsection* ,
    solution-heading = \subsection*
}

\newcommand{\printSectionExerEnvsOfType}[1]{%
  % ##1 type, ##2 id, ...
  \ForEachUsedExerciseByType{%
    \ifstrequal{#1}{##1}{%
        \ifnum\ExercisePropertyGet{##1}{##2}{chapter-value}=\value{chapter}\relax
          \ifnum\ExercisePropertyGet{##1}{##2}{section-value}=\value{section}\relax
%              \texttt{<##1><##2>}\par
              \XSIMprint{exercise}{##1}{##2}%
          \fi
        \fi
    }{}%
  }%
}

\newcommand{\printsectionexercises}{%
  \printSectionExerEnvsOfType{exercise}%
}

\newcommand{\printsectionquestions}{%
  \printSectionExerEnvsOfType{question}%
}

\newcommand{\printSoluEnvsOfType}[1]{%
    \def\currentchapter{}%
    \def\currentsection{}%
    \def\lastchapter{}%
    \def\lastsection{}%
    \ForEachUsedExerciseByType{%
        \ifstrequal{#1}{##1}{%
            \let\lastchapter\currentchapter
            \let\lastsection\currentsection
            \edef\currentchapter{\ExercisePropertyGet{##1}{##2}{chapter-value}}%
            \edef\currentsection{\ExercisePropertyGet{##1}{##2}{section-value}}%
            \ifx\lastchapter\currentchapter\else
                \section*{Chapter \ExercisePropertyGet{##1}{##2}{chapter}}
                \def\lastsection{}%
            \fi
            \ifx\lastsection\currentsection\else
                \subsection*{Question \ExercisePropertyGet{##1}{##2}{section}}
            \fi
            \XSIMprint{solution}{##1}{##2}%
        }{}%
    }%
}

\newcommand{\printexercisesolutions}{%
  \printSoluEnvsOfType{exercise}%
}

\newcommand{\printquestionsolutions}{%
  \printSoluEnvsOfType{question}%
}

\xsimsetup{
    % for exercise type 'exercise'
    exercise/template = question-temp ,
    solution/template = question-temp ,
    exercise/within = section ,
    exercise/the-counter = \arabic{exercise}. ,
    exercise/print = false,
    % for exercise type 'question'
    question/within = section ,
    question/the-counter = \arabic{question}. ,
    question/print = false,
}

\begin{document}

\mainmatter

\chapter{Chapter on Cat}

\section{Cat-1}

SOME TEXT...

\begin{exercise}
    Exercise 1 in Section 1.1 in Chapter 1
\end{exercise}
\begin{solution}
    Solution of Exercise 1 in Section 1.1 in Chapter 1
\end{solution}

MORE TEXT...

\begin{exercise}
    Exercise 2 in Section 1.1 in Chapter 1
\end{exercise}
\begin{solution}
    Solution of Exercise 2 in Section 1.1 in Chapter 1
\end{solution}

\subsection*{Exercise \thesection}
\printsectionexercises

\section{Cat-2}

SOME TEXT...

\begin{question}
    Question 1 in Section 1.2 in Chapter 1
\end{question}
\begin{answer}
    Answer of Question 1 in Section 1.2 in Chapter 1
\end{answer}

MORE TEXT...

\begin{question}
    Question 2 in Section 1.2 in Chapter 1
\end{question}
\begin{answer}
    Answer of Question 2 in Section 1.2 in Chapter 1
\end{answer}

\subsection*{Question \thesection}
\printsectionquestions

\chapter{Chapter on Dog}

\section{Dog-1}

SOME TEXT...

\begin{exercise}
    Exercise 1 in Section 2.1 in Chapter 2
\end{exercise}
\begin{solution}
    Solution of Exercise 1 in Section 2.1 in Chapter 2
\end{solution}

\begin{exercise}
    Exercise 2 in Section 2.1 in Chapter 2
\end{exercise}
\begin{solution}
    Solution of Exercise 2 in Section 2.1 in Chapter 2
\end{solution}

\subsection*{Exercise \thesection}
\printsectionexercises

\section{Dog-2}

SOME TEXT...

\begin{question}
    Question 1 in Section 2.2 in Chapter 2
\end{question}
\begin{answer}
    Answer of Question 1 in Section 2.2 in Chapter 2
\end{answer}

\begin{question}
    Question 2 in Section 2.2 in Chapter 2
\end{question}
\begin{answer}
    Answer of Question 2 in Section 2.2 in Chapter 2
\end{answer}

\subsection*{Question \thesection}
\printsectionquestions

\chapter*{\underline{Solutions to Exercises}}
\printexercisesolutions

\chapter*{\underline{Solutions to Questions}}
\printquestionsolutions

\end{document}
第 1 章 第 2 章
第 1 章 第 2 章
练习答案 问题解答
练习答案 问题解答

试图:更快,\printSectionExerEnvsOfType\printSoluEnvsOfType

新的循环宏\ForEachUsedExerciseByIDOfType{<type>}{<loop body>}比这两个宏都更快\ForEachUsedExerciseByID{<loop body>}\ForEachUsedExerciseByType{<loop body>}因为新的循环宏不会循环遍历(所有声明的)练习类型的内部列表。

\ExplSyntaxOn
% #1: type, #2: loop body
\NewDocumentCommand \ForEachUsedExerciseByIDOfType {m +m}
  {
    \tl_set_eq:NN \XSIMtmp \ExerciseType
    \xsim_foreach_exercise_id_of_type:nnn {used} {#1} {#2}
    \tl_set_eq:NN \ExerciseType \XSIMtmp
    \tl_clear:N \XSIMtmp
  }

\xsim_verbose:n
  { Defining~ loop~ macro~ \xsim_foreach_exercise_id_of_type:nnn } 
% #1: boolean property, #2: type, #3: loop body
\cs_new_protected:Npn \xsim_foreach_exercise_id_of_type:nnn #1#2#3
  {
    \cs_set:cn {__xsim_loop_item:nnnnnn} {#3}
    \xsim_foreach_exercise_id:n
      {
        % type, id, boolean property (i.e., used, printed)
        \__xsim_deliver_exercise_details:nnn {#2} {##1} {#1}
      }
  }
\ExplSyntaxOff

\newcommand{\printSectionExerEnvsOfType}[1]{%
  % ##1 type, ##2 id, ...
  \ForEachUsedExerciseByIDOfType{#1}{%
    \ifnum\ExercisePropertyGet{##1}{##2}{chapter-value}=\value{chapter}\relax
      \ifnum\ExercisePropertyGet{##1}{##2}{section-value}=\value{section}\relax
        \XSIMprint{exercise}{##1}{##2}%
      \fi
    \fi
  }%
}

\newcommand{\printSoluEnvsOfType}[1]{%
  \def\currentchapter{}%
  \def\currentsection{}%
  \def\lastchapter{}%
  \def\lastsection{}%
  \ForEachUsedExerciseByIDOfType{#1}{%
    \let\lastchapter\currentchapter
    \let\lastsection\currentsection
    \edef\currentchapter{\ExercisePropertyGet{##1}{##2}{chapter-value}}%
    \edef\currentsection{\ExercisePropertyGet{##1}{##2}{section-value}}%
    \ifx\lastchapter\currentchapter\else
      \section*{Chapter \ExercisePropertyGet{##1}{##2}{chapter}}
      \def\lastsection{}%
    \fi
    \ifx\lastsection\currentsection\else
      \subsection*{Question \ExercisePropertyGet{##1}{##2}{section}}
    \fi
    \XSIMprint{solution}{##1}{##2}%
  }%
}

相关内容