Generate LaTeX Truth Table with Python Cheetah
Not really an answer to this question as it doesn't involve Cheetah. However if anyone searches for truth table, potentially they would like a truth table macro so I'll post this for that reason. The macro \truthtable{<prims>}{<exprs>}
(compile with LuaLaTeX
) takes two arguments:
- The first argument is a comma separated list of primitives (variables)
- The second argument is a semi-colon separated list of logical statements involving the operations of:
- Negation, entered as
-
- Conjunction, entered as
*
- Disjunction, entered as
+
- Implication, entered as
(stuff)->(stuff)
- Negation, entered as
For example, \truthtable{a,b,c,d}{-a;a*b*d;(a)->(b);a*(b+c);(a*(b+c))->(b)}
produces the following:
\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,d}{-a;a*b*d;(a)->(b);a*(b+c);(a*(b+c))->(b)}
\]
\end{document}
I am also interested in generating LaTeX code with Python
, so your posting gave me the hint to the framework to use. I just created a simple example:
from Cheetah.Template import Template
definition = """\\documentclass{article}
\\title{$paper.title}
\\author{$author.name}
\\begin{document}
\\maketitle
\\end{document}"""
class author:
"""A simple example author class"""
name = "Uwe Ziegenhagen"
def f(self):
return 'Hello World'
class paper:
"""A simple example paper class"""
title = "My First paper"
def f(self):
return 'hello world'
uwe = author()
mypaper = paper()
print Template(definition, searchList=[{'author' : uwe,'paper' : mypaper}])
For archiving purposes, for people less familiar with Cheetah framework, the above is just a regular Python script. The output of the script on the standard output (could be of course piped into a file) is the LaTeX code.
Template modules, like Cheetah, are overkill if you want to use Python for this type of work. I would use straight Python as follows:
template = """\\documentclass{{article}}
\\title{{ {title} }}
\\author{{ {author} }}
\\begin{{document}}
\\maketitle
\\end{{document}}"""
info = {"title": "My First Paper",
"author": "A. Author"}
print template.format(**info)