Truth Tables: Your great-grandfather's computer
JavaScript (ES6), 141

Simple function, no bonus, 141 chars. (140 uft8, 1 unicode wide)

Complex function handling ~ or ¬, 254 chars (253 utf, 1 unicode wide), score 229

Could save 6 bytes using alert instead of console.log, but alert is particularly unfit to display tables.

Test running the snippet below in an EcmaScript 6 compliant browser (tested with Firefox. Won't work in Chrome as Chrome does not support .... Also, the bonus version use an extension of split that is Firefox specific).



/* TEST: redirect console.log into the snippet body */ console.log=x=&gt;O.innerHTML+=x+'\n'

// Simple
F=s=&gt;{[a,o,b]=[...s],z='  ',r=a+z+b+z+a+` ${o} ${b}
`;for(w='FT',n=4;n--;r+=w[c]+z+w[e]+z+z+w[o&lt;'∧'?c|e:c&amp;e]+`
`)c=n&amp;1,e=n&gt;&gt;1;console.log(r)}

// Simple, more readable
f=s=&gt;{
   [a,o,b]=[...s]
   r=a+'  '+b+'  '+a+` ${o} ${b}\n`
   for(w='FT',n=4; n--; )
   {
     c = n&amp;1, e = n&gt;&gt;1, x=o&lt;'∧' ? c|e : c&amp;e
     r += w[c]+'  '+w[e]+'    '+w[x]+'\n'
   }
   console.log(r)
}

// 10% Bonus
B=s=&gt;{[a,o,b]=s.split(/([∧∨])/),t=a&gt;'z',u=b&gt;'z',z='  ',r=(t?a[1]+z:'')+a+z+(u?b[1]+z:'')+b+z+a+` ${o} ${b}
`;for(s=v=&gt;'FT'[v]+z,n=4;n--;r+=s(c)+(t?s(d)+' ':'')+s(e)+(u?s(f)+' ':'')+(t?'   ':z)+s(o&lt;'∧'?d|f:d&amp;f)+`
`)c=n&amp;1,d=c^t,e=n&gt;&gt;1,f=e^u;console.log(r)}

Test1 = ['q∨p','q∧p']
Test2 = Test1.concat([
  '~q∨p','q∨~p','~q∨~p','~q∧p','q∧~p','~q∧~p',
  '¬q∨p','q∨¬p','¬q∨¬p','¬q∧p','q∧¬p','¬q∧¬p'
])


console.log('SIMPLE')
Test1.forEach(t=&gt;F(t));

console.log('BONUS')
Test2.forEach(t=&gt;B(t));
&lt;pre id=O&gt;&lt;/pre&gt;