I need to type truth tables for my computer architecture classes. Until now I was using a manually typed tabular
but today I've found this answer from Scott H. which provides a command called truthtable
to automatically typeset it.
A command like
\truthtable{a,b,c}{a+b;b*(-c);-(a+b)+(b*(-c))}
produces
Now I would like to change logical operators (\vee
, \wedge
and \neg
) and use +
(or), ยท
(and) and \overline
or \bar
for not.
The function which typesets operators is:
\cs_new_protected:Npn \__tt_build_header:
{
\seq_set_from_clist:NN \l__tt_header_seq \l__tt_vars_clist
\seq_concat:NNN \l__tt_header_seq \l__tt_header_seq \l__tt_exprs_seq
\tl_set:Nx \l_tmpa_tl {\seq_use:Nnnn \l__tt_header_seq {&}{&}{&}}
\tl_replace_all:Nnn \l_tmpa_tl {*} {\wedge}
\tl_replace_all:Nnn \l_tmpa_tl {+} {\vee}
\tl_replace_all:Nnn \l_tmpa_tl {->} {\to}
\tl_replace_all:Nnn \l_tmpa_tl {-} {\neg}
\tl_use:N \l_tmpa_tl
}
Although it's written in LaTeX3 and I don't understand it, it's easy to replace \wedge
with \cdot
and \vee
with +
. But I don't know if it's easy to replace \neg
to obtain a symbol (or expression) with an overline. As I imagine this alternative is difficult, a centred tilde ~
could be enough. Then I've tested with \sim
but the result is ugly, the symbol is far away from negated variable or expression. Could you help me with a better alternative?
The complete code (needs lualatex) is
\documentclass{article}
\usepackage{xparse}
\begingroup
\catcode`\%=12\relax
\gdef\patmatch{"(%b())->(%b())","!%1||%2"}
\endgroup
\def\setimpaux#1{%
\directlua{
local s, _ = string.gsub("\luatexluaescapestring{#1}",\patmatch)
tex.sprint(s)
}
}
\ExplSyntaxOn
\int_new:N \l__tt_num_rows_int
\int_new:N \l__tt_num_cols_int
\int_new:N \l__tt_num_vars_int
\clist_new:N \l__tt_vars_clist
\seq_new:N \l__tt_exprs_seq
\seq_new:N \l__tt_header_seq
\NewDocumentCommand {\truthtable}{ m m }
{
\truth_table:nn {#1}{#2}
}
\cs_new_protected:Npn \truth_table:nn #1#2
{
\clist_set:Nn \l__tt_vars_clist {#1}
\seq_set_split:Nnn \l__tt_exprs_seq {;} {#2}
\int_set:Nn \l__tt_num_vars_int {\clist_count:N \l__tt_vars_clist}
\int_set:Nn \l__tt_num_rows_int {\fp_to_int:n {2^{\l__tt_num_vars_int}-1}}
\int_set:Nn \l__tt_num_cols_int {\clist_count:N \l__tt_vars_clist +\seq_count:N \l__tt_exprs_seq}
\__tt_gen_bins:
\seq_map_function:NN \l__tt_exprs_seq \__tt_eval_bools:n
\__tt_build_table:
}
\cs_new_protected:Npn \__tt_build_header:
{
\seq_set_from_clist:NN \l__tt_header_seq \l__tt_vars_clist
\seq_concat:NNN \l__tt_header_seq \l__tt_header_seq \l__tt_exprs_seq
\tl_set:Nx \l_tmpa_tl {\seq_use:Nnnn \l__tt_header_seq {&}{&}{&}}
\tl_replace_all:Nnn \l_tmpa_tl {*} {\wedge}
\tl_replace_all:Nnn \l_tmpa_tl {+} {\vee}
\tl_replace_all:Nnn \l_tmpa_tl {->} {\to}
\tl_replace_all:Nnn \l_tmpa_tl {-} {\neg}
\tl_use:N \l_tmpa_tl
}
\cs_generate_variant:Nn \seq_use:Nnnn {cnnn}
\cs_new_protected:Npn \__tt_build_table:
{
\begin{array}{*{\int_use:N \l__tt_num_cols_int}{c}}
\__tt_build_header:\\\hline
\int_step_inline:nnnn {0}{1}{\l__tt_num_rows_int}
{
\seq_use:cnnn {l__tt_row_{##1}_seq}{&}{&}{&}\\
}
\end{array}
}
\cs_new_protected:Npn \__tt_set_imp:n #1
{
\tl_if_in:nnT {#1} {->}
{
\tl_set:Nx \l_tmpb_tl {\setimpaux{#1}}
\exp_args:NV \__tt_set_imp:n \l_tmpb_tl
}
}
\cs_generate_variant:Nn \__tt_set_imp:n {V}
\cs_generate_variant:Nn \tl_replace_all:Nnn {Nnx}
\cs_new_protected:Npn \__tt_eval_bools:n #1
{
\tl_set:Nn \l_tmpa_tl {#1}
\int_step_inline:nnnn {0}{1}{\l__tt_num_rows_int}
{
\int_set:Nn \l_tmpa_int {1}
\tl_set_eq:NN \l_tmpb_tl \l_tmpa_tl
\__tt_set_imp:V \l_tmpb_tl
\tl_replace_all:Nnn \l_tmpb_tl {*}{&&}
\tl_replace_all:Nnn \l_tmpb_tl {+}{||}
\tl_replace_all:Nnn \l_tmpb_tl {-}{!}
\clist_map_inline:Nn \l__tt_vars_clist
{
\tl_replace_all:Nnx \l_tmpb_tl {####1} {\seq_item:cn {l__tt_row_{##1}_seq} {\l_tmpa_int}}
\int_incr:N \l_tmpa_int
}
\seq_put_right:cx {l__tt_row_{##1}_seq} {\fp_eval:n \l_tmpb_tl}
}
}
\cs_generate_variant:Nn \seq_set_split:Nnn {cnx}
\cs_new_protected:Npn \__tt_gen_bins:
{
\int_step_inline:nnnn {0}{1}{\l__tt_num_rows_int}
{
\seq_clear_new:c {l__tt_row_{##1}_seq}
\seq_set_split:cnx {l__tt_row_{##1}_seq} {} {\int_to_binary:n {##1}}
\int_while_do:nn {\seq_count:c {l__tt_row_{##1}_seq} < \l__tt_num_vars_int}
{
\seq_put_left:cn {l__tt_row_{##1}_seq} {0}
}
}
}
\ExplSyntaxOff
\begin{document}
\[
\truthtable{a,b,c}{a+b;b*(-c);-(a+b)+(b*(-c))}
\]
\end{document}
Best Answer
The undesired spacing around
\sim
comes from the fact that\sim
is defined as a relational symbol using\mathrel
; from the kernel:You can supress this space treating
\sim
as an ordinary symbol using\mathord{\sim}
:the compete code:
An explanation of
\mathord
,\mathrel
,\mathbin
and similars can be found in TeX by Topic or in the TeXbook.