上下文
在学习逻辑时,我发现自己创建了具有不同数量命题变量的真值表。有时我需要为包含 6 个命题变量的命题创建真值表,这会产生一张巨大的表格。我在这里展示的是一个最小的工作示例。
\documentclass{article}
\begin{document}
\begin{center}
\begin{tabular}{*{3}{|c}|}
\hline
$p$ & $q$ & $p \wedge q$ \\ \hline
0 & 0 & 0 \\ \hline
0 & 1 & 0 \\ \hline
1 & 0 & 0 \\ \hline
1 & 1 & 1 \\ \hline
\end{tabular}
\end{center}
\end{document}
如果包含 1 的单元格填充特定颜色,而包含 0 的单元格为空(见下文),我会发现此表更容易查看。
\documentclass{article}
\usepackage[table]{xcolor}
\begin{document}
\begin{center}
\begin{tabular}{*{3}{|c}|}
\hline
$p$ & $q$ & $p \wedge q$ \\ \hline
& & \\ \hline
& \cellcolor{gray!50!white} & \\ \hline
\cellcolor{gray!50!white} & & \\ \hline
\cellcolor{gray!50!white} & \cellcolor{gray!50!white} & \cellcolor{gray!50!white} \\ \hline
\end{tabular}
\end{center}
\end{document}
但是,这会使展示如此简单主题的表格代码变得混乱。理想情况下,\tabular
第一个表格中的环境代码应该生成所示的第二个表格。
当然,我可以为这两种单元格创建一个宏来实现这一点,但是
- 这也会使得
tabular
环境变得混乱。 - 这将使列的文本处理更加困难,因为所有列的大小并不相同。当我说“文本处理”时,我指的是对给定列进行排序之类的任务:当这些列的内容为 0 和 1 时,对列进行排序比每行的大小不同且其内容为拉丁字母字符时更容易。
- 排版表格所需的字符数并没有明显减少。
我从来没有做过这样的事情,所以我不知道在哪里搜索。
问题
我如何制作一个表格,其源代码显示 1 和 0,以便在输出中 0 和 1 被给定值替换(在这种情况下,\cellcolor
所有列中的 1 和 0 将分别被命令替换为空,而 0 则不被替换)?
一般而言,我希望这种情况发生在给定表中的某些特定列。也就是说,这种行为不能发生在所有列中。
答案1
您可以使用collcell
。它允许您将单元格的内容包装在宏中。这里使用的宏是一个简单的\ifnum
开关。
\documentclass{article}
\usepackage[table]{xcolor}
\usepackage{collcell}
\newcommand\ColorCell[1]{\ifnum#1=1\relax
\cellcolor{gray!50!white}%
\fi}
\newcolumntype{P}{>{\collectcell\ColorCell}c<{\endcollectcell}}%
\begin{document}
\begin{center}
\begin{tabular}{*{3}{|P}|}
\hline
\multicolumn{1}{|c|}{$p$} & \multicolumn{1}{c|}{$q$} & \multicolumn{1}{c|}{$p \wedge q$} \\ \hline
0& 0& 0 \\ \hline
0 & 1 & 0 \\ \hline
1 & 0 & 0\\ \hline
1 & 1 & 1 \\ \hline
\end{tabular}
\end{center}
\end{document}
答案2
你可以做得更好。;-)
你有一台计算机,所以让它为我们做计算。所以这里有一组宏,确实计算真值表并排版。并且collcell
没有必要。
限制是九个参数。抱歉,但我没有实现从排版公式到直接波兰表示法的转换,而这是进行计算所必需的。
第一个参数是变量的数量,第二个参数是我们要显示真值的公式或公式。第三个参数是波兰表示法的翻译,其中变量用 表示#1
,#2
等等。*
表示使用灰色和白色代替 1 和 0。
这些例子应该足够清楚了。
\documentclass{article}
\usepackage{xparse}
\usepackage[table]{xcolor}
\ExplSyntaxOn
\NewDocumentCommand{\truthtable}{smmm}
{% #2 = number of variables, #3 = formulas, #4 = formulas
\IfBooleanTF { #1 }
{
\cs_set_eq:NN \__morales_truthtable_cell:n \__morales_truthtable_color:e
}
{
\cs_set_eq:NN \__morales_truthtable_cell:n \use:n
}
\morales_truthtable_prepare:nnn { #2 } { #3 } { #4 }
\exp_args:NnV \begin{tabular} \l__morales_truthtable_preamble_tl
\hline
\l__morales_truthtable_header_tl \\
\hline
\l__morales_truthtable_body_tl
\end{tabular}
}
\NewExpandableDocumentCommand{\AND}{mm}
{
\int_min:nn { #1 } { #2 }
}
\NewExpandableDocumentCommand{\OR}{mm}
{
\int_max:nn { #1 } { #2 }
}
\NewExpandableDocumentCommand{\NOT}{m}
{
\int_abs:n { #1 - 1 }
}
\NewExpandableDocumentCommand{\IMP}{mm}
{
\OR{\NOT{#1}}{#2}
}
\NewExpandableDocumentCommand{\IFF}{mm}
{
\AND{\IMP{#1}{#2}}{\IMP{#2}{#1}}
}
\int_new:N \l__morales_truthtable_columns_int
\int_new:N \l__morales_truthtable_formula_int
\seq_new:N \l__morales_truthtable_values_seq
\tl_new:N \l__morales_truthtable_preamble_tl
\tl_new:N \l__morales_truthtable_header_tl
\tl_new:N \l__morales_truthtable_body_tl
\tl_new:N \l__morales_truthtable_temp_tl
\cs_new_protected:Nn \morales_truthtable_prepare:nnn
{
\int_set:Nn \l__morales_truthtable_columns_int { \clist_count:n { #3 } }
\tl_set:Nx \l__morales_truthtable_preamble_tl
{
@{}c@{}| *{ \l__morales_truthtable_columns_int } { c| }
}
\tl_set:Nn \l__morales_truthtable_header_tl { }
\clist_map_inline:nn { #2 }
{
\tl_put_right:Nn \l__morales_truthtable_header_tl { & \multicolumn{1}{c|}{$##1$} }
}
% now build the truth values
\seq_clear:N \l__morales_truthtable_values_seq
\int_step_inline:nnn { 1 } { \fp_eval:n { 2**(#1) } }
{
\tl_set:Nx \l__morales_truthtable_temp_tl { \int_to_bin:n { ##1 - 1 } }
\seq_put_right:Nx \l__morales_truthtable_values_seq
{
\prg_replicate:nn
{
#1 - \tl_count:N \l__morales_truthtable_temp_tl
}
{ 0 }
\tl_use:N \l__morales_truthtable_temp_tl
}
}
\tl_clear:N \l__morales_truthtable_body_tl
\int_zero:N \l__morales_truthtable_formula_int
\clist_map_inline:nn { #3 }
{
\int_incr:N \l__morales_truthtable_formula_int
\cs_set:cn
{
__morales_truthtable_formula_
\int_eval:n { \l__morales_truthtable_formula_int }
:\prg_replicate:nn { #1 } { n }
}
{ ##1 }
}
\seq_map_inline:Nn \l__morales_truthtable_values_seq
{
\int_step_inline:nn { \l__morales_truthtable_columns_int }
{
\tl_put_right:Nn \l__morales_truthtable_body_tl
{
&
\__morales_truthtable_cell:n
{
\use:c
{
__morales_truthtable_formula_ ####1
:\prg_replicate:nn { #1 } { n }
}
##1
}
}
}
\tl_put_right:Nn \l__morales_truthtable_body_tl { \\ \hline }
}
}
\cs_new:Nn \__morales_truthtable_color:n
{
\int_compare:nT { #1 > 0 } { \cellcolor{gray!40} }
}
\cs_generate_variant:Nn \__morales_truthtable_color:n { e }
\ExplSyntaxOff
\begin{document}
\truthtable{2}{p,q,p\land q,p\lor q}{#1,#2,\AND{#1}{#2},\OR{#1}{#2}}
\truthtable*{2}{p,q,p\land q,p\lor q}{#1,#2,\AND{#1}{#2},\OR{#1}{#2}}
\bigskip
\truthtable{3}{p,q,p\land q,r,(p\land q)\to r}{
#1,#2,\AND{#1}{#2},#3,\IMP{\AND{#1}{#2}}{#3}
}
\truthtable*{3}{p,q,p\land q,r,(p\land q)\to r}{
#1,#2,\AND{#1}{#2},#3,\IMP{\AND{#1}{#2}}{#3}
}
\bigskip
\truthtable{3}{% a tautology
A,B,C,((A\land B)\to C)\leftrightarrow(A\to(B\to C))
}{
#1,#2,#3,\IFF{\IMP{\AND{#1}{#2}}{#3}}{\IMP{#1}{\IMP{#2}{#3}}}
}
\end{document}
代码根据公式数量准备合适的表格前言。然后生成从到0
的数字2^n-1
,并用初始零填充。
对于每个公式,定义一个具有与所述变量一样多的参数的函数,并用给定的公式替换文本。此后,每个数字都用作每个宏的输入,并逐行生成。