我想显示由 {} [] () 组成的所有有效括号字符串。这是预期的输出:
{[()]}
{[]()}
{[]}()
{([])}
{()[]}
{()}[]
{}[()]
{}[]()
{}([])
{}()[]
[{()}]
[{}()]
[{}]()
[({})]
[(){}]
[()]{}
[]{()}
[]{}()
[]({})
[](){}
({[]})
({}[])
({})[]
([{}])
([]{})
([]){}
(){[]}
(){}[]
()[{}]
()[]{}
这是我做的:
\{[()]\}\\
\{[]()\}\\
\{[]\}()\\
\{([])\}\\
\{()[]\}\\
\{()\}[]\\
\{\}[()]\\
\{\}[]()\\
\{\}([])\\
\{\}()[]\\
[\{()\}]\\
[\{\}()]\\
[\{\}]()\\
[(\{\})]\\
[()\{\}]\\
[()]\{\}\\
[]\{()\}\\
[]\{\}()\\
[](\{\})\\
[]()\{\}\\
(\{[]\})\\
(\{\}[])\\
(\{\})[]\\
([\{\}])\\
([]\{\})\\
([])\{\}\\
()\{[]\}\\
()\{\}[]\\
()[\{\}]\\
()[]\{\}\
但是,其中一些会导致错误。知道为什么会发生这种情况吗?最好的解决方法是什么?
编辑:抱歉,没有贴出 MWE 和完整示例。这是我的旧.tex
文件。注释掉的是导致错误的文件(!缺少数字,视为零。\protect):
\documentclass{article}
\begin{document}
Lots of Brackets:\\
\texttt{
\{[()]\}\\
\{[]()\}\\
\{[]\}()\\
\{([])\}\\
\{()[]\}\\
\{()\}[]\\
\{\}[()]\\
\{\}[]()\\
\{\}([])\\
\{\}()[]\\
%[\{()\}]\\
%[\{\}()]\\
%[\{\}]()\\
%[(\{\})]\\
%[()\{\}]\\
%[()]\{\}\\
%[]\{()\}\\
%[]\{\}()\\
%[](\{\})\\
%[]()\{\}\\
(\{[]\})\\
(\{\}[])\\
(\{\})[]\\
([\{\}])\\
([]\{\})\\
([])\{\}\\
()\{[]\}\\
()\{\}[]\\
()[\{\}]\\
()[]\{\}\\
}
\end{document}
感谢 David Carlisle 的回答,我现在知道了确切的问题。此.tex
文件运行正常:
\documentclass{article}
\begin{document}
Lots of Brackets:\\
\texttt{
\{[()]\}\\\relax
\{[]()\}\\\relax
\{[]\}()\\\relax
\{([])\}\\\relax
\{()[]\}\\\relax
\{()\}[]\\\relax
\{\}[()]\\\relax
\{\}[]()\\\relax
\{\}([])\\\relax
\{\}()[]\\\relax
[\{()\}]\\\relax
[\{\}()]\\\relax
[\{\}]()\\\relax
[(\{\})]\\\relax
[()\{\}]\\\relax
[()]\{\}\\\relax
[]\{()\}\\\relax
[]\{\}()\\\relax
[](\{\})\\\relax
[]()\{\}\\\relax
(\{[]\})\\\relax
(\{\}[])\\\relax
(\{\})[]\\\relax
([\{\}])\\\relax
([]\{\})\\\relax
([])\{\}\\\relax
()\{[]\}\\\relax
()\{\}[]\\\relax
()[\{\}]\\\relax
()[]\{\}\\\relax
}
\end{document}
但是,我最终将所有这些都放在了另一个文件中,并使用该listings
包和\lstinputlisting
命令直接从文件中插入文本。
答案1
如果您只想展示它们,我会使用以下verbatim
环境:
\documentclass[10pt]{article}
\usepackage{verbatim}
\begin{document}
\begin{verbatim}
{[()]}
{[]()}
{[]}()
{([])}
{()[]}
{()}[]
{}[()]
{}[]()
{}([])
{}()[]
[{()}]
[{}()]
[{}]()
[({})]
[(){}]
[()]{}
[]{()}
[]{}()
[]({})
[](){}
({[]})
({}[])
({})[]
([{}])
([]{})
([]){}
(){[]}
(){}[]
()[{}]
()[]{}
\end{verbatim}
\end{document}
答案2
请总是发布完整的文档而不仅仅是片段,并完整说明错误信息。
添加
\documentclass{article}
\begin{document}
你得到
! Missing number, treated as zero.
<to be read again>
\protect
l.14 [\{()\}]
\
这是由于建筑
\\
[\{...]
这与带有可选参数\\[\{...]
的命令相同,的可选参数是\\
\{...
\\
长度类似于\\[10pt]
因此\{
会产生错误,即它不是一个数字。
使用
\\\relax
将停止 LaTeX 寻找可选参数。
答案3
编辑(2017)
xint 1.09c (2013/10/09)
自 以来,即在最初发布几天后,答案就被破坏了,原因是 中的内部更改尝试使用抽象\xintApplyInline\macro{items}
扩展,原因我已忘记。的版本没有。在此处的代码中,宏无法以这种方式扩展。因此,我添加了一个以获取扩展并挽救代码。\macro
##1
1.09b
\xintApplyInline
\DefineAVANTAPRES
\empty
答案也因此被打破
xint 1.1 (2014/10/28)
,因为从那时起既没有xint
也没有xintfrac
加载xinttools
。因此需要答案\usepackage{xinttools}
。
也许你还想产生图案?
可以使用TeX
宏来实现这一点。由于技术原因(可以通过一些额外的工作来解决),下面的代码无法处理 \{
和\}
,而只能处理纯字符。
对于
N
开闭对,允许模式的数量除以 ,分别N!
为1
,2
,5
,14
, ,42
,132
,429
, ,1430
,4862
, ,16796
, ,对于 ,N=1
,2
, ... , 。这是通过运行下面的代码(第二种算法,可能更快)获得的(或者说,证实了……)。这些数字是许多组合问题中出现的10
加泰罗尼亚数 。参见(2N)!/(N!(N+1)!)
http://oeis.org/A000108。
首先用 声明(每个任意一个字符)的开闭对\DeclareStuff
。
然后命令\PrintStuff
作为参数给出一个列表开幕字符,它将显示完整的可能性列表保留开头字符的顺序。如果N
是此类字符的数量,则模式的真实总数必须乘以 以N!
考虑排列。例如,对于六对开头-结尾,可以找到132
模式,因此可能性的真实数量是132x720
。
\Stuff
模式的实际生成由具有完全可扩展递归结构的命令处理......
这是输出。您的案例对应于第二行,该行具有成对5
的模式3
,因此确实存在5x3! = 30
解决方案。成对的4
模式存在14x4!=336
解决方案;仅打印排列似乎是一个合理的选择(只是懒惰的人对自己的算法很满意,不想再增加一层来排列所有内容……)
更新:我在下面插入了另一种算法的输出和代码,该算法当然具有更有效的递归,并且也更容易解释。
以下是代码。它使用了包中的一些宏编程实用程序新工具。
\documentclass{article}
\usepackage{xinttools}% for some of its expandable and non expandable utilities to
% deal with lists.
\begin{document}
\makeatletter
% This is NON expandable
% can not be used with \{, \}. Only standard characters
\def\DeclareStuff #1%
{%
\toks@{}%
\xintAssignArray #1\to\DATA % attention fait un \edef
\count@ \@ne
\loop
\edef\tmp{\DATA{\count@+1}}%
\expandafter\let\csname FERMEUR\DATA\count@\endcsname\tmp
\toks@\expandafter\expandafter\expandafter
{\expandafter\the\expandafter\toks@
\romannumeral-`0\DATA{\count@}}%
\advance\count@\tw@
\ifnum\count@<\DATA{0} % \DATA{0} is twice the number of pairs
\repeat
\edef\LESOUVREURS {\the\toks@}% (The list of only the openers)
\xintApplyInline{\empty\DefineAVANTAPRES}{\LESOUVREURS}%
}%
\def\DefineAVANTAPRES #1%
{%
\expandafter\def\csname AVANT#1\endcsname ##1#1##2\relax {##1}%
\expandafter\def\csname APRES#1\endcsname ##1#1##2\relax {##2}%
}%
\def\AVANT #1#2{\csname AVANT#1\endcsname #2\relax }%
\def\APRES #1#2{\csname APRES#1\endcsname #2\relax }%
% THE WHOLE STUFF NEXT IS COMPLETELY EXPANDABLE
\def\Stuff #1{\expandafter\Stuffa\expandafter{\romannumeral-`0#1}}%
\def\Stuffa #1{\ifnum \xintNthElt{0}{#1}>1
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\xintApplyUnbraced {\Stuffb {#1}}{#1}}
{\expandafter{\expandafter#1\csname FERMEUR#1\endcsname}}%
}%
\def\Stuffb #1#2%
{%
\expandafter\Stuffc\expandafter
{\romannumeral-`0\AVANT #2{#1}}%
{\romannumeral-`0\APRES #2{#1}}#2%
}%
\def\Stuffc #1#2%
{%
\expandafter\Stuffd\expandafter{#2}{#1}%
}%
\def\Stuffd #1#2#3%
{%
\ifnum\xintLength {#1}>0 % APRES
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\ifnum\xintLength {#2}>0 % AVANT
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\expandafter\xintApplyUnbraced\expandafter
{\expandafter\Join\expandafter
{\romannumeral-`0\xintApply {\Autour #3}{\Stuff {#1}}}}{\Stuff {#2}}}%
{\xintApply {\Autour #3}{\Stuff {#1}}}}%
{\xintApply {\Apres #3}{\Stuff {#2}}}%
}%
\def\Apres #1{\expandafter\Apresa\csname FERMEUR#1\endcsname #1}%
\def\Apresa #1#2#3{ #3#2#1}% the space to stop the romannumeral, but here
% nothing is
\def\Autour #1{\expandafter\Autoura\csname FERMEUR#1\endcsname #1}%
\def\Autoura #1#2#3{ #2#3#1}%
\def\Join #1#2{\xintApply {\Joinb {#2}}{#1}}
\def\Joinb #1#2{ #1#2}% re-reverses order in joining.
% The list is printed in reverse order of its creation, perhaps
% then the pattern is easier to understand by a human
\def\PrintStuff #1{\noindent
\xintListWithSep{\hskip1ex plus 1ex minus.5ex }
{\xintRevWithBraces{\Stuff {#1}}}%
\begingroup\parfillskip\z@\par\endgroup\medskip}
\DeclareStuff {()[]<>-+?!aAbBcCdDeEfF}
\ttfamily
\PrintStuff {([}
\PrintStuff {([<}
\PrintStuff {([<-}
\PrintStuff {([<-?}
\PrintStuff {abcdef}
\thispagestyle{empty}
\end{document}
现在,以下是使用以下算法的输出:如果要遵守开启符的顺序,最后一对中不能包含任何内容。因此,只需少生成一对模式,然后将最后一对插入到任何合法位置,即倒数第二个开启符左侧的任何位置。
关于代码,我不会尝试解释;在某些时候,我需要从列表中生成abcd
某些类型的东西{-abcd}{a-bcd}{ab-cd}{abc-d}{abcd-}
;而不是为此编写一个宏(必须是可扩展的),而是以某种方式使用可用的工具xint
,这是一个技巧,最好编写正确的工具(因为这里的方法首先需要一些不可扩展的定义,这是可以避免的)。
与上一个代码相反,宏输出的模式列表\Stuff
具有精确的给定字符,而在上一个代码中,结束字符在打印时仍由宏表示(例如 \FERMEUR[ 是伪装的 ])。但是保留宏可能会有一些用处,因为它们的定义可以修改。要修改此处的代码,只需保留或删除几个\expandafter
' 即可。
但首先输出的顺序与以前的算法不同,但可能更容易让人理解当添加一对新的分隔符时会发生什么。
\documentclass{article}
\usepackage{xinttools}% for some of its expandable and non expandable utilities to
% deal with lists.
\begin{document}
\makeatletter
% This is NON expandable
% can not be used with \{, \}. Only standard characters
\def\DeclareStuff #1%
{%
\toks@{}%
\xintAssignArray #1\to\DATA % attention fait un \edef
\count@ \@ne
\loop
\edef\tmp{\DATA{\count@+1}}%
\expandafter\let\csname FERMEUR\DATA\count@\endcsname\tmp
\toks@\expandafter\expandafter\expandafter
{\expandafter\the\expandafter\toks@
\romannumeral-`0\DATA{\count@}}%
\advance\count@\tw@
\ifnum\count@<\DATA{0}
\repeat
\edef\LESOUVREURS {\the\toks@}%
%\xintApplyInline{\empty\DefineAVANTAPRES}{\LESOUVREURS}%
\xintApplyInline{\empty\DefineAVANTAPRES}{#1}% more AVANT-APRES
% \Stuff variant needs it also for closing characters
}%
\def\DefineAVANTAPRES #1%
{%
\expandafter\def\csname AVANT#1\endcsname ##1#1##2\relax {##1}%
\expandafter\def\csname APRES#1\endcsname ##1#1##2\relax {##2}%
% rajouté pour variante:
\expandafter\def\csname SPLITL#1\endcsname ##1#1##2\relax {{##1#1}{##2}}%
\expandafter\def\csname SPLITR#1\endcsname ##1#1##2\relax {{##1}{#1##2}}%
}%
\def\AVANT #1#2{\csname AVANT#1\endcsname #2\relax }%
\def\APRES #1#2{\csname APRES#1\endcsname #2\relax }%
\def\SPLITL #1#2{\csname SPLITL#1\endcsname #2\relax }%
\def\SPLITR #1#2{\csname SPLITR#1\endcsname #2\relax }%
% Completely Expandable macros:
\def\Stuff #1{\expandafter\Stuffa\expandafter{\romannumeral-`0#1}}%
\def\Stuffa #1{\expandafter\Stuffb\expandafter
{\romannumeral-`0\xintLength{#1}}{#1}}%
\def\Stuffb #1#2{\ifnum #1>1
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\expandafter\Stuffc\expandafter
{\romannumeral-`0\xintNthElt {1}{\xintReverseOrder {#2}}}%
{#2}}%
{\expandafter\expandafter\expandafter
{\expandafter\expandafter\expandafter
#2\csname FERMEUR#2\endcsname}}%
}%
\def\Stuffc #1#2% #1 = last character of #2
{%
\expandafter\Stuffd\expandafter #1\expandafter
{\romannumeral-`0\AVANT #1{#2}}%
}%
\def\Stuffd #1#2%
{%
\expandafter\Stuffe
\romannumeral-`0\xintNthElt {1}{\xintReverseOrder{#2}}%
{#2}#1%
}%
% ouh c'est compliqué
% SPLITL x transforme aabaubxahaoi en {aabaubx}{ahaoi} mais un seul x
% SPLITR x transforme aabaubxahaoi en {aabaub}{xahaoi} mais un seul x
\def\Stuffe #1#2% en #1, le marqueur ouvrant précédent, en #3 le dernier marqueur
{%
\expandafter\Stufff\expandafter
{\romannumeral-`0\xintApply {\SPLITL #1}{\Stuff {#2}}}%
}%
\def\Stufff #1#2%
{%
\xintApplyUnbraced {\Stuffg #2}{#1}%
}%
% compliqué
\def\Stuffg #1#2{\expandafter\expandafter\expandafter
\Stuffk
\expandafter\expandafter\expandafter
#1\csname FERMEUR#1\endcsname #2}%
\def\Stuffk #1#2#3#4%
{%
\xintApply {\Joinb {#3}}{\xintApply {\Insert #1#2}%
{\xintApply {\SPLITRrev {#4}}{#4}}{#4#1#2}}%
}%
\def\SPLITRrev #1#2{\SPLITR #2{#1}}% #1 is a "string", #2 a character
\def\Insert #1#2#3{\Inserta #1#2#3}%
\def\Inserta #1#2#3#4{ #3#1#2#4}%
\def\Joinb #1#2{ #1#2}%
%-------------------------------------------------------------------------------
% The list is printed in reverse order of its creation, perhaps
% then the pattern is easier to understand by a human
\def\PrintStuff #1{\noindent
\xintListWithSep{\hskip1ex plus 1ex minus.5ex }
{\xintRevWithBraces{\Stuff {#1}}}%
\begingroup\parfillskip\z@\par\endgroup\medskip}
\DeclareStuff {()[]<>-+?!aAbBcCdDeEfF}
\ttfamily
\PrintStuff {([}
\PrintStuff {([<}
\PrintStuff {([<-}
\PrintStuff {([<-?}
\PrintStuff {abcdef}
\thispagestyle{empty}
\end{document}