我正在制作一个带有垂直线和编号的两部分分割算法。我更喜欢使用algorithm
包而不是使用algorithm2e
包,因为这个包既不提供命令\algstore
对\algrestore
,也不提供关于垂直线和数字的一些简单解决方案,当算法被分成两部分时。因此,基于问题的解决方案“如何在没有结束关键字的情况下在算法伪代码中正确创建垂直线缩进?“,我将这个算法分成两部分,使用它们algorithm
命令对。根据下图,它工作正常:
但是,当我使用长文本时,出现了两个问题(红线):
- 长文本超出了左边距,打断了三行垂直线的延续,如第 4 行所示;
- 从第二行下方的行开始垂直对齐中断为了和第一如果,分别根据第 2 行和第 3 行(与第 1 行和第 6 行比较)。
因此,我希望实现以下解决方案:
- 压缩两端对齐的长文本的宽度,但不会打断垂直线;
- 纠正第二行以下开始的行的垂直对齐错误为了和第一如果(蓝线为为了和如果参考)。
那么我该怎么做呢?
这里我放上图中的MWE代码。
\documentclass{article}
\usepackage{algorithm}
\usepackage{algpseudocode}
\usepackage{etoolbox}
\usepackage{lipsum}
\makeatletter
% start with some helper code
% This is the vertical rule that is inserted
\newcommand*{\algrule}[1][\algorithmicindent]{%
\makebox[#1][l]{%
\hspace*{.2em}% <------------- This is where the rule starts from
\vrule height .75\baselineskip depth .25\baselineskip
}
}
\newcount\ALG@printindent@tempcnta
\def\ALG@printindent{%
\ifnum \theALG@nested>0% is there anything to print
\ifx\ALG@text\ALG@x@notext% is this an end group without any text?
% do nothing
\else
\unskip
% draw a rule for each indent level
\ALG@printindent@tempcnta=1
\loop
\algrule[\csname ALG@ind@\the\ALG@printindent@tempcnta\endcsname]%
\advance \ALG@printindent@tempcnta 1
\ifnum \ALG@printindent@tempcnta<\numexpr\theALG@nested+1\relax
\repeat
\fi
\fi
}
% the following line injects our new indent handling code in place of the default spacing
\patchcmd{\ALG@doentity}{\noindent\hskip\ALG@tlm}{\ALG@printindent}{}{\errmessage{failed to patch}}
\patchcmd{\ALG@doentity}{\item[]\nointerlineskip}{}{}{} % no spurious vertical space
% end vertical rule patch for algorithmicx
\makeatother
\algrenewcommand\algorithmicrequire{\textbf{Input:}}
\algrenewcommand\algorithmicensure{\textbf{Output:}}
\begin{document}
% ---> Algorithm 01.
\begin{algorithm}
\caption{Arbitrary Algorithm}\label{IS2OSLS}
\begin{algorithmic}[1]
\Require A matrix $\mathbf{A}$ of size $m\times n$.
\Ensure Something.
\For{$i$ in $m$}
\For{$j$ in $n$}
\If{$i=j$}
\State Select a random action. \lipsum[1]
\Else
\If{$i=j+1$}
\State Stay silent
\Else
\State Break
\algstore{bkbreak}
\end{algorithmic}
\end{algorithm}
% ---> Algorithm 01: continuation.
\begin{algorithm}
\begin{algorithmic}
\algrestore{bkbreak}
\EndIf
\EndIf
\EndFor
\EndFor
\end{algorithmic}
\end{algorithm}
\end{document}
答案1
以下更新了答案如何在没有结束关键字的情况下在算法伪代码中正确创建垂直线缩进?。关键要素如下:
- 使用 a
\StatePar
输入一个\State
段落。这将添加 a\strut
以及段落的开始和结束,以便正确跳过基线。 - 环境
algorithmic
已更新为\offinterlineskip
。这消除了通常存在于垂直规则中的每个语句之间的间隙。 - 所有关键字和
\State
命令均已更新为使用,\strut
以便更好地呈现垂直间距(也归功于\offinterlineskip
)。
\documentclass{article}
\usepackage{algorithm}
\usepackage{algpseudocode}
\usepackage{etoolbox}
\usepackage{lipsum}
\makeatletter
% start with some helper code
% This is the vertical rule that is inserted
\newcommand*{\algrule}[1][\algorithmicindent]{%
\hspace*{.2em}% <------------- This is where the rule starts from
\vrule %height .75\baselineskip depth .25\baselineskip
\hspace*{\dimexpr#1-.2em-.4pt}%
}
\newcommand{\StatePar}[1]{%
\State\parbox[t]{\dimexpr\linewidth-\ALG@thistlm}{\strut #1\strut}%
}
\renewcommand{\ALG@beginalgorithmic}{\offinterlineskip}% Remove all interline skips
\newcount\ALG@printindent@tempcnta
\def\ALG@printindent{%
\ifnum \theALG@nested > 0% is there anything to print
\ifx\ALG@text\ALG@x@notext% is this an end group without any text?
% do nothing
\else
\unskip
% draw a rule for each indent level
\ALG@printindent@tempcnta=1
\loop
\algrule[\csname ALG@ind@\the\ALG@printindent@tempcnta\endcsname]%
\advance \ALG@printindent@tempcnta 1
\ifnum \ALG@printindent@tempcnta<\numexpr\theALG@nested+1\relax
\repeat
\fi
\fi
}
% the following line injects our new indent handling code in place of the default spacing
\patchcmd{\ALG@doentity}{\noindent\hskip\ALG@tlm}{\ALG@printindent}{}{\errmessage{failed to patch}}
% end vertical rule patch for algorithmicx
\makeatother
% Add \struts to keywords
\algrenewcommand\algorithmicend{\strut\textbf{end}}
\algrenewcommand\algorithmicdo{\strut\textbf{do}}
\algrenewcommand\algorithmicwhile{\strut\textbf{while}}
\algrenewcommand\algorithmicfor{\strut\textbf{for}}
\algrenewcommand\algorithmicforall{\strut\textbf{for all}}
\algrenewcommand\algorithmicloop{\strut\textbf{loop}}
\algrenewcommand\algorithmicrepeat{\strut\textbf{repeat}}
\algrenewcommand\algorithmicuntil{\strut\textbf{until}}
\algrenewcommand\algorithmicprocedure{\strut\textbf{procedure}}
\algrenewcommand\algorithmicfunction{\strut\textbf{function}}
\algrenewcommand\algorithmicif{\strut\textbf{if}}
\algrenewcommand\algorithmicthen{\strut\textbf{then}}
\algrenewcommand\algorithmicelse{\strut\textbf{else}}
\algrenewcommand\algorithmicrequire{\strut\textbf{Input:}}
\algrenewcommand\algorithmicensure{\strut\textbf{Output:}}
\let\oldState\State
\renewcommand{\State}{\oldState\strut}
\begin{document}
% ---> Algorithm 01.
\begin{algorithm}
\caption{Arbitrary Algorithm}
\begin{algorithmic}[1]
\Require A matrix $\mathbf{A}$ of size $m\times n$.
\Ensure Something.
\For{$i$ in $m$}
\For{$j$ in $n$}
\If{$i = j$}
\StatePar{Select a random action. \lipsum[1]}
\Else
\If{$i = j + 1$}
\State Stay silent
\Else
\State Break
\algstore{bkbreak}
\end{algorithmic}
\end{algorithm}
% ---> Algorithm 01: continuation.
\begin{algorithm}
\begin{algorithmic}
\algrestore{bkbreak}
\EndIf
\EndIf
\EndFor
\EndFor
\end{algorithmic}
\end{algorithm}
\end{document}