我在写证明时使用了这个真值表。
不幸的是,我犯了一个小错误;第一次,我放错了一个额外的ʹ
符号,结果输出完全错误。我花了很长时间才明白为什么之后的一切似乎都不像我所知道的那样。
这让我很疑惑。是否有可能构建某种宏,使我能够根据给定的输入生成准确的真值表?换句话说:我希望它能像这样工作:
\truthtable{A, B, ( A \oplus B )', (A) \oplus (B')}
相比于必须手动绘制整个图形,可能会出错。您如何开始在 LaTeX 中编写这样的程序?
以下是上表的完整手动 MWE:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\documentclass[border=10pt]{standalone}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%hdashline
\usepackage{array}
\usepackage{arydshln}
\setlength\dashlinedash{0.2pt}
\setlength\dashlinegap{1.5pt}
\setlength\arrayrulewidth{0.3pt}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{table}[htbp!]
\centering
\caption{}
\label{tab}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{tabular}{@{}cccc@{}}
\toprule%%–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
$A$ & $B$ & $(A \oplus B)'$ & $(A) \oplus (B')$ \\
\midrule%%–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
0 & 0 & 1 & 1 \\ \hdashline%%··········································
0 & 1 & 0 & 0 \\ \hdashline%%··········································
1 & 0 & 0 & 0 \\ \hdashline%%··········································
1 & 1 & 1 & 1 \\ \bottomrule%––––––––––––––––––––––––––––––––––––––––––
\end{tabular}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{table}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
答案1
这是快速编写的。它不会操纵火星探测器,实际上它只是一行代码。如果您使代码可复制,我会在需要时添加所有表格选项。(事实上,我没有做任何努力使输出“漂亮”,也没有抑制空格或空行。)也可以使用循环来创建所有行。我在输出中添加了解释。
\documentclass{article}
\usepackage{pgf}
\newcounter{step}
\newcommand{\myrow}[2]{ #1 & #2 &
\pgfmathparse{not(int(mod(#1+#2,2)))}\pgfmathresult &
\pgfmathparse{int(mod(#1+not(#2),2))}\pgfmathresult\\
}
\setcounter{step}{0}
\def\tabcontent{\stepcounter{step}\ifnum\value{step}<5
\pgfmathtruncatemacro{\myA}{(\value{step}-1)/2}%
\pgfmathtruncatemacro{\myB}{mod(\value{step}-1,2)}%
\edef\temp{\noexpand\myrow{\myA}{\myB}}\temp%
\tabcontent\fi}
\begin{document}
In the first example (Table~\ref{tab:First}), explicit macros
\verb|\myrow{A}{B}| are used for each row. The \verb|\myrow| macro takes two
arguments, which are $A$ and $B$ in your application.
\begin{table}[!h]
\centering
\begin{tabular}{c@{}cccc@{}}
~$A$~ & ~$B$~ & $(A \oplus B)'$ & $(A) \oplus (B')$ \\
\hline
\myrow{0}{0}
\myrow{0}{1}
\myrow{1}{0}
\myrow{1}{1}
\end{tabular}
\caption{First example.}
\label{tab:First}
\end{table}
The important point is that the other entries of the remaining columns can be
computed with \texttt{pgf} via \verb|\pgfmathparse{not(int(mod(#1+#2,2)))}| and
\verb|\pgfmathparse{int(mod(#1+not(#2),2))}|, respectively. I strongly suspect
that other packages like \texttt{xint} allow you to do similar things. However,
I am most familiar with \texttt{pgf}.
In the second example (Table~\ref{tab:Second}), a loop produces the content
of the table. Since the \& character is notoriously nasty, this loop is realized
as a recursive macro. Alternatives to this recursion include the \verb|\gappto|
macro that comes with the \texttt{etoolbox} package.
\begin{table}[!h]
\centering
\begin{tabular}{c@{}cccc@{}}
~$A$~ & ~$B$~ & $(A \oplus B)'$ & $(A) \oplus (B')$ \\
\hline
\tabcontent
\end{tabular}
\caption{Second example.}
\label{tab:Second}
\end{table}
\end{document}
答案2
答案并不简短,代码比我想象的要长。代码可能看起来有点麻烦,但我没有以任何方式对其进行优化。我只是想展示一种解决方案,其中解释输入并生成真值表,例如(A\oplus B)'
A XOR B,结果被否定。代码不接受所有可能的输入。例如,只能有一个逻辑运算符:\land
,\lor
和\oplus
。所以(A\land B) \land \neg (A\land B)
不是有效输入。可以有多个运算符,如\neg
和'
。
应该可以扩展代码来克服这个限制。
\documentclass{scrartcl}
\usepackage{xparse}
\usepackage{array}
\usepackage{booktabs}
\ExplSyntaxOn
\tl_new:N \l__truthtable_op_tmp_tl
\tl_new:N \l__truthtable_logical_tmp_tl
\tl_new:N \l__truthtable_expression_tmp_tl
\seq_new:N \l__truthtable_logical_tmp_seq
\tl_new:N \l__truthtable_expression_left_tl
\tl_new:N \l__truthtable_expression_right_tl
\tl_new:N \l__truthtable_expression_out_tl
\seq_new:N \l__truthtable_op_seq
\seq_new:N \l__truthtable_vara_logical_seq
\seq_new:N \l__truthtable_varb_logical_seq
\seq_new:N \l__truthtable_op_logical_seq
\seq_new:N \l__truthtable_expression_seq
\seq_new:N \l__truthtable_expression_split_seq
\int_new:N \l__truthtable_expression_int
\int_new:N \g__truthtable_tmp_int
\bool_new:N \l__truthtable_vara_bool
\bool_new:N \l__truthtable_varb_bool
\bool_new:N \l__truthtable_result_bool
\NewDocumentCommand{\truthtable}{ m m m }
{
\group_begin:
\seq_set_from_clist:Nn \l__truthtable_expression_seq {#3}
\int_set:Nn \l__truthtable_expression_int { \seq_count:N \l__truthtable_expression_seq }
\seq_map_function:NN \l__truthtable_expression_seq \truthtable_parse:n
\truthtable_truthtable:NNnn \l__truthtable_expression_seq \l__truthtable_expression_int {#1} {#2}
\group_end:
}
\cs_new_protected:Npn \truthtable_truthtable_begin:N #1
{
\tabular{ *{ \int_eval:n { #1 + 2 } }{ >{$}c<{$} } }
\toprule
}
\cs_new_protected:Npn \truthtable_truthtable_end:
{
\\ \bottomrule
\endtabular
}
\cs_new_protected:Npn \truthtable_truthtable:NNnn #1 #2 #3 #4
{
\truthtable_truthtable_begin:N #2
\truthtable_truthtable_header:NNnn #1 #2 {#3} {#4}
\truthtable_truthtable_content:N #2
\truthtable_truthtable_end:
}
\cs_new_protected:Npn \truthtable_truthtable_header:NNnn #1 #2 #3 #4
{
#3 & #4
\int_compare:nNnF {#2} = { 0 }
{ & \seq_use:Nn #1 { & } }
\\ \midrule
}
\cs_new_protected:Npn \truthtable_truthtable_content:N #1
{
\int_gzero:N \g__truthtable_tmp_int
\int_step_inline:nnn { 0 } { 1 }
{
\int_step_inline:nnn { 0 } { 1 }
{
##1 & ####1
\truthtable_evaluate:Nnn #1 {##1} {####1}
\__truthtable_newline:N \g__truthtable_tmp_int
}
}
}
\cs_new_protected:Npn \__truthtable_newline:N #1
{
\int_gincr:N #1
\int_compare:nNnF {#1} = { 4 }
{ \\ }
}
\cs_new_protected:Npn \truthtable_parse:n #1
{
\tl_map_function:nN {#1} \__truthtable_get_operator:n
\__truthtable_split_at_operator:n {#1}
\truthtable_if_odd:VTF \l__truthtable_expression_left_tl
{ \truthtable_odd:NN \l__truthtable_expression_left_tl \l__truthtable_expression_right_tl }
{ \truthtable_even:NN \l__truthtable_expression_left_tl \l__truthtable_expression_right_tl }
}
\cs_new_protected:Npn \__truthtable_get_operator:n #1
{
\str_case:nnT {#1}
{
{ \oplus } { \seq_put_right:Nn \l__truthtable_op_seq { xor } }
{ \lor } { \seq_put_right:Nn \l__truthtable_op_seq { or } }
{ \land } { \seq_put_right:Nn \l__truthtable_op_seq { and } }
}
{ \tl_map_break:n { \tl_set:Nn \l__truthtable_op_tmp_tl {#1} } }
}
\cs_new_protected:Npn \__truthtable_split_at_operator:n #1
{
\exp_args:NNV
\seq_set_split:Nnn \l__truthtable_expression_split_seq \l__truthtable_op_tmp_tl {#1}
\tl_set:Nx \l__truthtable_expression_left_tl { \seq_item:Nn \l__truthtable_expression_split_seq { 1 } }
\tl_set:Nx \l__truthtable_expression_right_tl { \seq_item:Nn \l__truthtable_expression_split_seq { 2 } }
}
\cs_new_protected:Npn \truthtable_odd:NN #1 #2
{
\tl_clear:N \l__truthtable_expression_out_tl
\tl_reverse:N #2
\truthtable_odd_aux:NNn #1 \l__truthtable_expression_tmp_tl { ( }
\truthtable_odd_aux:NNn #2 \l__truthtable_expression_tmp_tl { ) }
\tl_reverse:N #2
\truthtable_get_logicals:NN \l__truthtable_expression_out_tl \l__truthtable_op_logical_seq
\truthtable_get_logicals:NN #1 \l__truthtable_vara_logical_seq
\truthtable_get_logicals:NN #2 \l__truthtable_varb_logical_seq
}
\cs_new_protected:Npn \truthtable_odd_aux:NNn #1 #2 #3
{
\tl_set_eq:NN #2 #1
\tl_map_inline:Nn #1
{
\str_if_eq:nnTF {##1} {#3}
{
\tl_set:Nx #2 { \tl_tail:N #2 }
\tl_map_break:
}
{
\tl_put_right:Nx \l__truthtable_expression_out_tl { \tl_head:N #2 }
\tl_set:Nx #2 { \tl_tail:N #2 }
}
}
\tl_set_eq:NN #1 #2
}
\cs_new_protected:Npn \truthtable_even:NN #1 #2
{
\truthtable_get_logicals:NN #1 \l__truthtable_vara_logical_seq
\truthtable_get_logicals:NN #2 \l__truthtable_varb_logical_seq
\seq_put_right:Nn \l__truthtable_op_logical_seq { }
}
\cs_new_protected:Npn \truthtable_get_logicals:NN #1 #2
{
\tl_clear:N \l__truthtable_logical_tmp_tl
\tl_map_inline:Nn #1
{
\str_case:nn {##1}
{
{ ' } { \truthtable_add_to_tl:Nnn \l__truthtable_logical_tmp_tl { not } { , } }
{ \neg } { \truthtable_add_to_tl:Nnn \l__truthtable_logical_tmp_tl { not } { , } }
}
}
\seq_put_right:NV #2 \l__truthtable_logical_tmp_tl
}
\cs_new_protected:Npn \truthtable_add_to_tl:Nnn #1 #2 #3
{
\tl_if_empty:NTF #1
{ \tl_set:Nn #1 { #2} }
{ \tl_put_right:Nn #1 {#3#2} }
}
\cs_new_protected:Npn \truthtable_evaluate:Nnn #1 #2 #3
{
\int_step_inline:nnn { 1 } {#1}
{
&
\truthtable_set_bool:Nn \l__truthtable_vara_bool {#2}
\truthtable_set_bool:Nn \l__truthtable_varb_bool {#3}
\truthtable_eval_logical:NNn \l__truthtable_vara_logical_seq \l__truthtable_vara_bool {##1}
\truthtable_eval_logical:NNn \l__truthtable_varb_logical_seq \l__truthtable_varb_bool {##1}
\truthtable_eval_operator:NNn \l__truthtable_vara_bool \l__truthtable_varb_bool {##1}
\truthtable_print_result:NNn \l__truthtable_op_logical_seq \l__truthtable_result_bool {##1}
}
}
\cs_new_protected:Npn \truthtable_eval_operator:NNn #1 #2 #3
{
\str_case_e:nn { \seq_item:Nn \l__truthtable_op_seq {#3} }
{
{ xor } { \truthtable_xor:NN #1 #2 }
{ or } { \truthtable_or:NN #1 #2 }
{ and } { \truthtable_and:NN #1 #2 }
}
}
\cs_new_protected:Npn \truthtable_eval_logical:NNn #1 #2 #3
{
\exp_args:NNx
\seq_set_from_clist:Nn \l__truthtable_logical_tmp_seq { \seq_item:Nn #1 {#3} }
\seq_map_inline:Nn \l__truthtable_logical_tmp_seq
{
\str_case:nn {##1}
{
{ not } { \truthtable_not:N #2 }
}
}
}
\cs_new_protected:Npn \truthtable_print_result:NNn #1 #2 #3
{
\truthtable_eval_logical:NNn #1 #2 {#3}
\bool_if:NTF #2
{ 1 }
{ 0 }
}
\cs_new_protected:Npn \truthtable_set_bool:Nn #1 #2
{
\int_case:nn {#2}
{
{ 0 } { \bool_gset_false:N #1 }
{ 1 } { \bool_gset_true:N #1 }
}
}
\cs_new_protected:Npn \truthtable_xor:NN #1 #2
{
\bool_xor:nnTF {#1} {#2}
{ \bool_set_true:N \l__truthtable_result_bool }
{ \bool_set_false:N \l__truthtable_result_bool }
}
\cs_new_protected:Npn \truthtable_not:N #1
{
\bool_set_inverse:N #1
}
\cs_new_protected:Npn \truthtable_or:NN #1 #2
{
\bool_lazy_or:nnTF {#1} {#2}
{ \bool_set_true:N \l__truthtable_result_bool }
{ \bool_set_false:N \l__truthtable_result_bool }
}
\cs_new_protected:Npn \truthtable_and:NN #1 #2
{
\bool_lazy_and:nnTF {#1} {#2}
{ \bool_set_true:N \l__truthtable_result_bool }
{ \bool_set_false:N \l__truthtable_result_bool }
}
\prg_new_conditional:Npnn \truthtable_if_odd:n #1 { T, F, TF }
{
\regex_count:nnN { \( } {#1} \l_tmpa_int
\regex_count:nnN { \) } {#1} \l_tmpb_int
\int_if_odd:nTF { \l_tmpa_int + \l_tmpb_int }
{ \prg_return_true: }
{ \prg_return_false: }
}
\prg_generate_conditional_variant:Nnn \truthtable_if_odd:n { V } { TF }
\ExplSyntaxOff
\begin{document}
\truthtable{A}{B}
{
(A\oplus B)',
(A)\oplus(B'),
A\oplus B,
A\oplus B',
\neg((A)\oplus (B)'),
A\lor B,
A\lor B',
A\land B
}
\end{document}
给予