我想列出集合 {1, 2, 3, 4, 5} 的子集数量。我尝试使用forest
包。
\documentclass[border=3mm]{standalone}
\usepackage{amsmath}
\usepackage{forest}
\begin{document}
\begin{forest}
for tree={edge={->}}
[\{1;\,2;\,3;\,4;\,5\}[1[2[3[4[5]][5]][4[5]][5]][3[4[5]][5]][4[5]][5]][2[3[4[5]][5]][4[5]][5]][3[4[5]][5]][4[5]][5]]
\end{forest}
\end{document}
在这个图中,没有空集。有什么更好的列出方法吗?
答案1
这是我最终想出来的另一种方法。不使用纯 Ti钾Z,它将Forest与expl3函数结合起来,构建除根之外所有节点的内容。
subsets
启动样式。n elements=<integer>
应该用来指定根子集中元素的数量。然后,样式将构造根子集,添加后代并适当地填充它们。也就是说,
\begin{forest}
subsets,
[, n elements=3]
\end{forest}
将生成包含 3 个元素的根集树
和
\begin{forest}
subsets,
[, n elements=5]
\end{forest}
对于包含 5 的集合。
完整代码:
\documentclass[border=10pt]{standalone}
\usepackage{xparse,forest}
\ExplSyntaxOn
\clist_new:N \l_subsets_subset_clist
\cs_new_protected_nopar:Nn \subsets_construct_subset:nn
{
\clist_set:Nn \l_subsets_subset_clist { #2 }
\clist_clear:N \l_tmpa_clist
\clist_map_inline:nn { #1 }
{
\int_zero:N \l_tmpa_int
\clist_set_eq:NN \l_tmpa_clist \l_subsets_subset_clist
\clist_clear:N \l_subsets_subset_clist
\clist_map_inline:Nn \l_tmpa_clist
{
\int_incr:N \l_tmpa_int
\int_compare:nF { ##1 = \l_tmpa_int }
{
\clist_put_right:Nn \l_subsets_subset_clist { ####1 }
}
}
}
\clist_if_empty:NTF \l_subsets_subset_clist
{
\emptyset
}{
\{ \clist_use:Nn \l_subsets_subset_clist { , } \}
}
}
\NewDocumentCommand \constructsubset { m m }
{
\group_begin:
\subsets_construct_subset:nn { #1 } { #2 }
\group_end:
}
\ExplSyntaxOff
\forestset{
declare toks={subset chooser}{},
declare toks register={root set},
root set={},
n elements/.style={
tempcounta'=0,
if={>nn={0}{#1}}{content=\emptyset}{
until={
>Rn={tempcounta}{#1}%
}{
tempcounta'+=1,
if tempcounta=1{root set=1}{root set+={,}, root set+/.register=tempcounta},
},
delay={
tempcounta'=0,
while={>Rn<{tempcounta}{#1}}{
where n children=0{
tempcountb'=#1,
tempcountb-/.register=tempcounta,
repeat/.process={Rw{tempcountb}{##1}{append={[]}}},
}{},
tempcounta'+=1,
do dynamics,
},
},
},
},
subsets/.style={
before typesetting nodes={
where level=0{content=\{,content+/.register=root set,content+=\}}{
temptoksa/.option=n,
for nodewalk={until={>On={level}{0}}{parent}}{+temptoksa={,},+temptoksa/.option=n,},
subset chooser/.register=temptoksa,
TeX/.process={ORw2{subset chooser}{root set}{\xdef\tempa{\constructsubset{##1}{##2}}}},
content/.expanded=\tempa,
},
for tree={
math content,
edge+=<-,
},
},
},
}
\begin{document}
\begin{forest}
subsets,
[, n elements=3]
\end{forest}
\begin{forest}
subsets,
[, n elements=5]
\end{forest}
\end{document}
答案2
这里有两种方法可以做到这一点。第一种方法是根据 option 中的信息明确构造每个节点set
。第二种方法稍快一些,因为它通过将所有后续兄弟节点复制到根节点中来构造根节点的子节点。
--排版树在这里仍然是最耗时的。而且,为包含 9 个以上元素的集合排版树会耗尽我的 80000 个保存堆栈。:-(
\documentclass{standalone}
\usepackage{forest}
\forestset{
declare keylist={set}{},
subsets/.style={
delay={
split option={content}{;}{set+},
content={$\{##1\}$},
process set
},
},
process set/.style={
split option={set}{,}{process element}
},
process element/.style={
if={strequal("#1","")}{}{split={#1}{=}{process@element,gobble}}
},
process@element/.style={
set-=#1,
append/.process=Ow{set}{[#1,set={##1},process set]},
},
gobble/.style={},
}
\begin{document}
\begin{forest}
subsets
[1;2;3;4;5]
\end{forest}
\end{document}
第二种方式:
\documentclass{standalone}
\usepackage{forest}
\forestset{
subsets/.style={
delay={
tempkeylista={},
split option={content}{;}{setup subsets},
content={$\{##1\}$},
process keylist register=tempkeylista,
},
},
setup subsets/.style={
tempkeylista'/.process=Rw{tempkeylista}{do element=#1,delay={##1}}
},
do element/.style={
prepend={[#1,
tempkeylistb'={},
for following siblings={
tempkeylistb/.process=Ow{name}{append'=##1}
},
process keylist register=tempkeylistb
]},
},
}
\begin{document}
\begin{forest}
subsets
[1;2;3;4;5]
\end{forest}
\end{document}