Dear Hans, I am sorry that I miss “context(func(set,u) and “1” or “0”) In your code. Correcting it, it works perfectly. By changing the logic function, we can draw truth tables upto 3 variables. After making a truth table, I draw Karnaugh Map of that table. I made a short MetaFun code for drawing Karnaugh map for the class material. In that code, it calculate the truth value using MetaFun function again. Recently, I read about “How to bring the data made by Lua into MetaFun.” So, my next try is to bring the truth value which is made in Lua. Then I omit the truth-value-calculation part from the MetaFun code. If there is a way to draw a diagonal in the \starttabulate ..., then we may use Lua code to do the job. In the wiki, there is an example of diagonal rule. https://wiki.contextgarden.net/TABLE#Diagonal_rules I tried it in \starttabulate … \stoptabulate, but it is not working. And the shape drawn using MetaFun is much better. Anyway, I’ll try it. Thank you again. Best wishes, Dalyoung PS: Here is my code which produces the truth table and its Karnaugh Map. The code for the truth table is cleaned up by Hans, but the MetaFun part will be changed. \startMPdefinitions numeric tVal[][],rlSkip[],rlNum[],uk, wd, ht; string val[],code[],subcode; uk := LineHeight; wd := 1.5uk; ht := uk+5pt; vardef funcOr(expr a,b) = if a + b = 0: out := 0; else: out := 1; fi; out enddef; vardef funcAnd(expr a,b) = if a + b > 1: out := 1; else: out := 0; fi; out enddef; vardef funcNot(expr a) = if a = 0: out:=1; else: out:=0 fi; out enddef; def KmapFrame(expr first,second) = val[0]:=first; val[1]:=second; for k=0,1: rlSkip[k] := length val[k]; rlNum[k] := 2*rlSkip[k]; if rlSkip[k] = 1: code[k] := "01"; else: code[k] :="00011110"; fi; endfor; label.top(textext("$" & first & "$"), (-.7wd,0)); label.top(textext("$" & second & "$"), (-.3wd,.5ht)); % drawing lines draw (-1.2wd,0) -- origin -- ((rlNum[1]+1)*wd,0); draw (0, 1.1ht) -- origin -- (0,-(rlNum[0]+.2)*ht); draw (-wd,ht) --origin; for i=0 upto rlNum[0]-1: subcode := substring (i*rlSkip[0],(i+1)*rlSkip[0]) of code[0]; label.top(textext(subcode), ((-.7wd, -(i+1)*ht))); endfor; for i=0 upto rlNum[1]-1: subcode := substring (i*rlSkip[1],(i+1)*rlSkip[1]) of code[1]; label.top(textext(subcode), ((i+1)*wd,.3ht)); endfor; setbounds currentpicture to boundingbox currentpicture enlarged 2mm; draw boundingbox currentpicture; enddef; \stopMPdefinitions \startbuffer[Kmap_xyz] KmapFrame("x", "yz"); vardef logicFunc(expr a,b,c) = result := funcAnd(funcNot(b), funcOr(a,c)); result enddef; for i=0,1: for j=0 upto rlNum[1]-1: b := scantokens(substring (j*rlSkip[1],j*rlSkip[1]+1) of code[1]); c := scantokens(substring (j*rlSkip[1]+1,j*rlSkip[1]+2) of code[1]); tVal[i][j] := logicFunc(i,b,c); label.top(tVal[i][j], ((j+1)*wd,-(i+1)*ht)); endfor; endfor; draw unitsquare xyscaled (1wd,2ht) shifted (1.5wd,-2.1ht) withpen pencircle scaled 2pt withcolor .625blue ; draw unitsquare xyscaled (1.8wd,1ht) shifted (.6wd,-2.1ht) withpen pencircle scaled 2pt withcolor .625red ; \stopbuffer \starttext \startluacode function document.MakeHead(p,a) if not a then local t = p p = string.rep("|mcw(1cm)",#p-1) .. "|mcw(2cm)|" a = t end context.starttabulate { p } context.FL() for i=1,#a do context.NC() context(a[i]) end context.NC() context.NR() context.LL() end function document.MakeFooter() context.HL() context.stoptabulate() end local tf = { true, false } function document.truthTable(a,func) document.MakeHead(a) for i,s in ipairs(tf) do for j,t in ipairs(tf) do for k,u in ipairs(tf) do context.NC() context(s and "1" or "0") context.NC() context(t and "1" or "0") context.NC() if #a == 3 then break end context(u and "1" or "0") context.NC() context(func(s,t,u) and "1" or "0") context.NC() context.AR() end if #a == 3 then context(func(s,t) and "1" or "0") context.NC() context.AR() end end end document.MakeFooter() end \stopluacode \startluacode --statistics.starttiming() local function logicF(p,q,r) return (p or r) and (not q) end document.truthTable({ "x", "y","z","f(x,y,x)"},logicF) \stopluacode \processMPbuffer[Kmap_xyz] \stoptext