% truthtable.sty %% Copyright 2021 D. Flück % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status “author-maintained”. % % The Current Maintainer of this work is D. Flück. % % This work consists of the file truthtable.sty. \NeedsTeXFormat{LaTeX2e}[1994/06/01] \ProvidesPackage{truthtable}[2023/09/16 0.1.0 Package for generating truth tables automatically using LuaTeX] \ProcessOptions\relax \@ifpackageloaded{luacode}{ \PackageWarningNoLine{truthtable}{Package luacode was already loaded} }{ \RequirePackage{luacode} } \begin{luacode*} function Impl(a,b) return (not a or b); end function Equiv(a,b) return ((a and b) or ((not a) and (not b))); end function Xor(a,b) return ((a or b) and (not (a and b))); end function Nand(a,b) return (not (a and b)); end function ComputeRows(header) return 2^header end function Split(s, delimiter) local result = {}; for match in (s..delimiter):gmatch("(.-)"..delimiter) do table.insert(result, match); end return result; end function EvaluateFormula(formula) local parsedFormula = "function res() return( " .. string.gsub(string.gsub(string.gsub(string.gsub(string.gsub(string.gsub(string.gsub(string.gsub(string.gsub(string.gsub(formula, " ", ""),">>","Impl"),"__","Equiv"),"<>","Equiv"),"%^","Xor"),"!&","Nand"),"!","not "),"&" ," and "),"|"," or "),";",",") .. " ) end"; chunk = load(parsedFormula); chunk(); local result = res(); return result; end function toBits(num) local t = "" -- will contain the bits while num>0 do local rest = math.fmod(num,2) if (rest == 1) then t = "1" .. t else t = "0" .. t end num=(num-rest)/2 end return t; end function printTruthValue(expr, dTrue, dFalse) local returnVal = "" if (expr) then returnVal = dTrue; else returnVal = dFalse; end return returnVal; end function parse(commaSepVariables, commaSepDisplayVariables, commaSepResultRows, commaSepResultDisplayRows, displayTrue, displayFalse, order) print("\n\ntruthtable v0.1.0\n") local vrbls = Split(commaSepVariables, ","); local numberOfColumns = #(vrbls); local rows = ComputeRows(numberOfColumns); local dVrbls = Split(commaSepDisplayVariables, ","); local resRows = Split(commaSepResultRows, ","); local dResRows = Split(commaSepResultDisplayRows, ","); local dHeader = string.gsub(commaSepDisplayVariables, ",", " & ") .. " & " .. string.gsub(commaSepResultDisplayRows, ",", " & ") .. [[ \\ \hline]]; if (#(dVrbls) ~= #(vrbls)) then print("Error: The number of variables does not match the number of display variables."); return end if (#(dResRows) ~= #(resRows)) then print("Error: The number of statements does not match the number of display statements."); return end tex.print(dHeader); local startVal; local endVal; local stepVal; if order == "asc" then startVal = 0; endVal = rows - 1; stepVal = 1; else startVal = rows - 1; endVal = 0; stepVal = -1; end for i = startVal,endVal,stepVal do local bitString = toBits(i); while #bitString < numberOfColumns do bitString = "0" .. bitString end local wVrbls = commaSepVariables; local wCommaSepRows = commaSepResultRows for ii = 1,numberOfColumns do wVrbls = string.gsub(wVrbls, vrbls[ii], (string.sub(bitString,ii,ii) == "1" ) and "+" or "-" ) wCommaSepRows = string.gsub(wCommaSepRows, vrbls[ii], (string.sub(bitString,ii,ii) == "1" ) and "+" or "-" ) end local aWVrbls = Split(string.gsub(string.gsub(wVrbls, "+", "true"),"-", "false"), ","); local aWCommaSepRows = Split(string.gsub(string.gsub(wCommaSepRows, "+", "true"),"-", "false"), ","); local row = ""; for c = 1,#(aWVrbls) do row = row .. printTruthValue(EvaluateFormula(aWVrbls[c]), displayTrue, displayFalse) .. " & "; end for c = 1,#(aWCommaSepRows) do row = row .. printTruthValue(EvaluateFormula(aWCommaSepRows[c]), displayTrue, displayFalse) .. " & "; end row = string.sub(row, 1, #row - 2) .. [[\\]]; tex.print(row); end end \end{luacode*} \newcommand{\truthtable}[6]{ \luadirect{parse("#1", "\luaescapestring{#2}", "\luaescapestring{#3}", "\luaescapestring{#4}", "\luaescapestring{#5}","\luaescapestring{#6}", "\luaescapestring{desc}")} } \newcommand{\truthtableasc}[6]{ \luadirect{parse("#1", "\luaescapestring{#2}", "\luaescapestring{#3}", "\luaescapestring{#4}", "\luaescapestring{#5}","\luaescapestring{#6}", "\luaescapestring{asc}")} } \endinput