Tablas de la verdad: la computadora de tu bisabuelo

13

Si recuerdas tus años de escuela, tal vez recuerdes haber aprendido sobre las Tablas de la verdad . Parecían aburridos, pero son la base de la lógica y (algunos argumentarían) toda la informática ...


Problema

Su misión, si elige aceptarla, es escribir un programa, función o widget de código que pueda generar una entrada de tabla de verdad.

Entrada

La entrada será una cadena (como la estructura de datos) que contiene la declaración lógica para hacer la tabla de verdad. Por ejemplo:

p ∧ q

Esto significa p and q(conjunción lógica) y generará:

 p  q  p ∧ q
 T  T    T
 T  F    F
 F  T    F
 F  F    F            

Observe el espaciado: el elemento de la columna está en el centro del encabezado

Caracteres

Puntuación a través de caracteres, no bytes Los caracteres de comparación lógica son especiales y no siempre se ven como son. Usa estos personajes:

Conjunción Lógica (Y): U + 2227

Disyunción lógica (OR): U + 2228

Negación lógica (NO) ~o ¬U + 7e y U + ac respectivamente


Bonos

Todos estos bonos son opcionales, pero eliminarán puntos de su puntaje. Elige cualquiera.

Negación Lógica

La negación lógica es un operador unario en las tablas de verdad. Es el equivalente de !en la mayoría de los lenguajes basados ​​en C. Hace false=> truey viceversa. Se anota con un ¬ o ~ (debe admitir ambos). Apoyar esto eliminará el 10% de su puntaje. Sin embargo, debe agregar una columna adicional para mostrar sus resultados: Por ejemplo:

~p ∧ q

dará salida:

p  ~p  q  ~p ∧ q
T  F   T     F
T  F   F     F
F  T   T     T
F  T   F     F

Impresión bonita

La notación de tabla normal es aburrida. ¡Hagámoslo bonito! El formato de impresión bonito es el siguiente, ya que p ∧ qes el siguiente:

+---+---+-------+
| p | q | p ∧ q |
+---+---+-------+
| T | T |   T   |
+---+---+-------+
| T | F |   F   |
+---+---+-------+
| F | T |   F   |
+---+---+-------+
| F | F |   F   |
+---+---+-------+

Detalles especiales para una bonita impresión:

  • Hay un espacio de 1 espacio en cada celda
  • Los valores de celda aún están centrados

Si imprime bien sus tablas, desde su código y luego multiplique por 0.6. Use esta función para este bono:

score = 0.6 * code

Ejemplos

p ∧ q:

p  q  p ∧ q
T  T    T
T  F    F
F  T    F
F  F    F

p ∨ q:

p  q  p ∨ q
T  T    T
T  F    T
F  T    T
F  F    F

~p ∧ q:

p  ~p  q  ~p ∧ q
T   F  T     F
T   F  F     F
F   T  T     T
F   T  F     F

~p ∨ q:

p  ~p  q  ~p ∧ q
T   F  T     T
T   F  F     F
F   T  T     T
F   T  F     T

Reglas

  • Se aplican lagunas estándar
  • Sin recursos externos
  • Si vas a romper las reglas, sé inteligente;)

El código más corto (en caracteres) gana. ¡Buena suerte!

AlcaldeMonty
fuente
44
De la descripción sonaba como si fueran expresiones booleanas arbitrarias. Pero todos los ejemplos (sin bonificación) tienen un solo operador. ¿Está esto restringido a un solo operador? Además, los nombres de los valores en los ejemplos son todos py q. A menos que siempre tengan estos nombres, es posible que desee mostrar algunas opciones diferentes en los ejemplos de prueba. ¿Son siempre una sola letra?
Reto Koradi
2
Dado que esto usa caracteres no ASCII, podría ser bueno especificar si la longitud del código se cuenta en caracteres o bytes. Si son bytes, sería útil saber cuántos bytes usan los caracteres unicode.
Reto Koradi
Simplifica :). score = 0.6 * (code - 15)=.6 * code - 9
mınxomaτ
@RetoKoradi cambiado. Puntuación por caracteres, no bytes
MayorMonty
@RetoKoradi Si lo que mi maestro de geometría me dice es correcto, nunca verás más p qy ren una tabla de verdad;)
MayorMonty

Respuestas:

6

JavaScript (ES6), 141

Función simple, sin bonificación, 141 caracteres. (140 uft8, 1 ancho unicode)

Manejo de funciones complejas ~ o ¬, 254 caracteres (253 utf, 1 unicode de ancho), puntaje 229

Podría ahorrar 6 bytes usando en alertlugar de console.log, peroalert es particularmente inadecuado para mostrar tablas.

Pruebe a ejecutar el fragmento a continuación en un navegador compatible con EcmaScript 6 (probado con Firefox. No funcionará en Chrome ya que Chrome no es compatible .... Además, la versión de bonificación utiliza una extensión splitespecífica de Firefox).

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

// Simple
F=s=>{[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<'∧'?c|e:c&e]+`
`)c=n&1,e=n>>1;console.log(r)}

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

// 10% Bonus
B=s=>{[a,o,b]=s.split(/([∧∨])/),t=a>'z',u=b>'z',z='  ',r=(t?a[1]+z:'')+a+z+(u?b[1]+z:'')+b+z+a+` ${o} ${b}
`;for(s=v=>'FT'[v]+z,n=4;n--;r+=s(c)+(t?s(d)+' ':'')+s(e)+(u?s(f)+' ':'')+(t?'   ':z)+s(o<'∧'?d|f:d&f)+`
`)c=n&1,d=c^t,e=n>>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=>F(t));

console.log('BONUS')
Test2.forEach(t=>B(t));
<pre id=O></pre>

edc65
fuente
1
+1, me encanta JavaScript y esta solución merece un voto positivo.
Arjun
JavaScript es mi idioma nativo, ¡pero no dejaré que eso me afecte! : D Buen trabajo!
MayorMonty
6

Plantilla MediaWiki - 2347 caracteres

MediaWiki tiene una función de plantilla integrada llamada {{#expr}}que puede manejar expresiones lógicas. ¡Este debe ser el desafío perfecto para las plantillas de MediaWiki! Sin embargo, características como variables, bucles y una sintaxis legible habrían ayudado un poco. Además, el hecho de que no haya un operador NOT para la función expr la hizo un poco más compleja.

{{#sub:{{#replace:{{#replace:{{{1}}}|~|}}|¬|}}|0|1}} {{#sub:{{{1}}}|{{#expr:{{#len:{{{1}}}}}-1}}|{{#len:{{{1}}}}}}} {{{1}}}<br>T T &nbsp;{{#if:{{#pos:{{#sub:{{#replace:{{{1}}}|~|¬}}|0|1}}|¬}}|&nbsp;|}} {{#replace:{{#replace:{{#expr:{{#replace:{{#replace:{{#replace:{{#replace:{{#replace:{{#replace:{{{1}}}|~|¬}}|{{#sub:{{#replace:{{#replace:{{{1}}}|~|}}|¬|}}|0|1}}|{{#if:{{#pos:{{#replace:{{{1}}}|~|¬}}|¬{{#sub:{{#replace:{{#replace:{{{1}}}|~|}}|¬|}}|0|1}}}}|0|1}}}}|{{#sub:{{{1}}}|{{#expr:{{#len:{{{1}}}}}-1}}|{{#len:{{{1}}}}}}}|{{#if:{{#pos:{{#replace:{{{1}}}|~|¬}}|¬{{#sub:{{{1}}}|{{#expr:{{#len:{{{1}}}}}-1}}|{{#len:{{{1}}}}}}}}}|0|1}}|0|1}}|¬|}}|∧|and}}|∨|or}}}}|1|T}}|0|F}}<br>T F &nbsp;{{#if:{{#pos:{{#sub:{{#replace:{{{1}}}|~|¬}}|0|1}}|¬}}|&nbsp;|}} {{#replace:{{#replace:{{#expr:{{#replace:{{#replace:{{#replace:{{#replace:{{#replace:{{#replace:{{{1}}}|~|¬}}|{{#sub:{{#replace:{{#replace:{{{1}}}|~|}}|¬|}}|0|1}}|{{#if:{{#pos:{{#replace:{{{1}}}|~|¬}}|¬{{#sub:{{#replace:{{#replace:{{{1}}}|~|}}|¬|}}|0|1}}}}|0|1}}}}|{{#sub:{{{1}}}|{{#expr:{{#len:{{{1}}}}}-1}}|{{#len:{{{1}}}}}}}|{{#if:{{#pos:{{#replace:{{{1}}}|~|¬}}|¬{{#sub:{{{1}}}|{{#expr:{{#len:{{{1}}}}}-1}}|{{#len:{{{1}}}}}}}}}|1|0}}|1|0}}|¬|}}|∧|and}}|∨|or}}}}|1|T}}|0|F}}<br>F T &nbsp;{{#if:{{#pos:{{#sub:{{#replace:{{{1}}}|~|¬}}|0|1}}|¬}}|&nbsp;|}} {{#replace:{{#replace:{{#expr:{{#replace:{{#replace:{{#replace:{{#replace:{{#replace:{{#replace:{{{1}}}|~|¬}}|{{#sub:{{#replace:{{#replace:{{{1}}}|~|}}|¬|}}|0|1}}|{{#if:{{#pos:{{#replace:{{{1}}}|~|¬}}|¬{{#sub:{{#replace:{{#replace:{{{1}}}|~|}}|¬|}}|0|1}}}}|1|0}}}}|{{#sub:{{{1}}}|{{#expr:{{#len:{{{1}}}}}-1}}|{{#len:{{{1}}}}}}}|{{#if:{{#pos:{{#replace:{{{1}}}|~|¬}}|¬{{#sub:{{{1}}}|{{#expr:{{#len:{{{1}}}}}-1}}|{{#len:{{{1}}}}}}}}}|0|1}}|0|1}}|¬|}}|∧|and}}|∨|or}}}}|1|T}}|0|F}}<br>F F &nbsp;{{#if:{{#pos:{{#sub:{{#replace:{{{1}}}|~|¬}}|0|1}}|¬}}|&nbsp;|}} {{#replace:{{#replace:{{#expr:{{#replace:{{#replace:{{#replace:{{#replace:{{#replace:{{#replace:{{{1}}}|~|¬}}|{{#sub:{{#replace:{{#replace:{{{1}}}|~|}}|¬|}}|0|1}}|{{#if:{{#pos:{{#replace:{{{1}}}|~|¬}}|¬{{#sub:{{#replace:{{#replace:{{{1}}}|~|}}|¬|}}|0|1}}}}|1|0}}}}|{{#sub:{{{1}}}|{{#expr:{{#len:{{{1}}}}}-1}}|{{#len:{{{1}}}}}}}|{{#if:{{#pos:{{#replace:{{{1}}}|~|¬}}|¬{{#sub:{{{1}}}|{{#expr:{{#len:{{{1}}}}}-1}}|{{#len:{{{1}}}}}}}}}|1|0}}|1|0}}|¬|}}|∧|and}}|∨|or}}}}|1|T}}|0|F}}

Prueba:

{{TemplateName|¬X ∧ ~Y}}

{{TemplateName|p ∨ q}}

Resultado:

X Y ¬X ∧ ~Y
T T    F
T F    F
F T    F
F F    T

p q p ∨ q
T T   T
T F   T
F T   T
F F   F

Supongo que MediaWiki> = 1.18, donde las extensiones ParserFunctions vienen incluidas con el software.

León
fuente
2
Bienvenido a Programming Puzzles y Code Golf. Usar MediaWiki no es algo en lo que hubiera pensado; +1. Sin embargo, falta el comportamiento de columna adicional del operador ¬/ ~; si lo agrega, calificará para un 10%bono.
wizzwizz4
Me acabo de dar cuenta de que, a menos que pueda usar plantillas anidadas (¿podría extenderse demasiado las reglas?), Agregar correctamente esa columna aumentaría el recuento de caracteres ... :)
leo
En ese caso, probablemente deberías eliminar el soporte de negación, porque no obtienes ninguna bonificación por ello.
wizzwizz4
Sí, lo investigaré. Sin embargo, no creo que tenga un gran impacto en el ranking final ...: D
leo
1
@leo Esto es genial, y creo que usar plantillas anidadas estaría bien si solo agregas el recuento de caracteres de las dos, esa parece ser la práctica aceptada hoy en día.
Harry
4

Python: 288 caracteres (+10 de penalización porque no pude hacer que Unicode funcione: c)

Sin bonificaciones Esta es mi primera respuesta codegolf.

def f(i):
    i=i.split(" ")
    print i[0],i[2],
    for f in i[0:3]: print f,
    print ""
    for t in["TT","TF","FT","FF"]:
        p,q=t[0],t[1]
        y = t[0]+" "+t[1]
        if i[1]=="^": r=(False,True)[p==q]
        if i[1]=="v": r=(False,True)[p!=q]
        if r: y+="   T"
        else: y+="   F"
        print y

i es la entrada

EDITAR: se eliminaron algunos espacios y ahora utiliza argumentos de función como entrada.

DJgamer98
fuente
1
¡Bienvenido a PP&CG! Asegúrese de que su código siga las reglas, de acuerdo con la pregunta. Como especificación de la regla, su código debe ser una función, un programa completo o un bit de código. Esto implica que la entrada DEBE ser STDIN o argumentos de función (o equivalente) ¡Happy Coding!
MayorMonty
3

Dyalog APL , 58 48 caracteres

Requiere ⎕IO←0, que es el predeterminado en muchos sistemas. Toma una cuerda como argumento.

{('p q ',⍵)⍪'FT '[p,q,⍪⍎⍵]\⍨324⊤⍨9⍴≢p q←↓2 2⊤⌽⍳4}

Sin bonificaciones, pero en el lado positivo, cualquier operador trabaja.

⍳4 primeros cuatro índices (0 1 2 3)

 reversa (3 2 1 0)

2 2⊤ tabla booleana de dos bits

 dividido en una lista de dos elementos de listas (bits altos, bits bajos)

p q← almacenar como p y q

 contarlos (2) *

9⍴ remodelar cíclicamente a la longitud 9 (2 2 2 2 2 2 2 2 2)

324⊤⍨ codificar 324 de este modo, es decir, como binario de 12 bits (1 0 1 0 0 0 1 0 0)

\⍨ use eso para expandir (inserte un espacio para cada 0) ...

'FT '[... ] la cadena "FT", indexada por

⍎⍵ el argumento ejecutado (válido ya que p y q ahora tienen valores)

convertir eso en una matriz de columnas

q, anteponer una columna que consta de q (1 1 0 0)

q, anteponer una columna que consta de p (1 0 1 0)

(... )⍪ inserte una fila arriba, que consiste en

 el argumento

'p q ', antepuesto con la cadena "p q"


* Destaque este problema si ve como ≢y no como ̸≡.

Adán
fuente
2

Julia, 161 bytes

Sin bonificaciones

s->(S=split(s);P=println;p=S[1];q=S[3];a=[&,|][(S[2]=="∨")+1];c="  ";P(p,c,q,c,s);for t=["TT","TF","FT","FF"] P(t[1],c,t[2],c^2,"FT"[a(t[1]>'F',t[2]>'F')+1])end)

Sin golf:

function f(s::String)
    # Split the input on spaces
    S = split(s)

    # Separate out the pieces of the statement
    p = S[1]
    q = S[3]
    a = [&, |][(S[2] == "∨") + 1]

    # Print the header
    println(p, "  ", q, "  ", s)

    # Create the table entries in a loop
    for t = ["TT", "TF", "FT", "FF"]
        println(t[1], "  ", t[2], "    ", "FT"[a(t[1] > 'F', t[2] > 'F') + 1])
    end
end
Alex A.
fuente
1

Mathematica, 129 Bytes

Golfizado:

t=InputString[];s=Append[StringCases[t,LetterCharacter],t];Grid[Prepend[Map[If[#,"T","F"]&,BooleanTable[ToExpression[s]],{2}],s]]

Sin golf:

(*Take input*)
t=InputString[];
(* Find all occurrences of letters and append the final statement.*)
s=Append[StringCases[t,LetterCharacter],t];
(* Evaluate the list as expressions and create a boolean table of True/False values, then display as a table. *)
(* To satisfy the output conditions, we must convert each True/False to T/F *)
Grid[Prepend[Map[If[#,"T","F"]&,BooleanTable[ToExpression[s]],{2}],s]]

No soy un experto en Mathematica, pero esto me pareció bastante elegante en comparación con tener que hacer una comparación directa de personajes.

Tenía una solución que funcionaba para la negación, pero era más larga de lo que despegaría la reducción de puntaje.

Dependiendo de lo que califica para una impresión bonita, podría intentar ese bono. Siento que generar ASCII en Mathematica sería demasiado costoso para compensar la reducción de puntaje, pero si las dos características principales son un borde punteado y un relleno especificado dentro de las celdas, eso es solo un par de opciones en Grid.

Con una bonita impresión, 171 * 0.6 = 102.6 Bytes

t=InputString[];s=Append[StringCases[t,LetterCharacter],t];Grid[Prepend[Map[If[#,"T","F"]&,BooleanTable[ToExpression[s]],{2}],s],Spacings->1,Frame->All,FrameStyle->Dashed]
Xanderhall
fuente
1

Python3, 145 139 120 119 Bytes

Sin bonificación (con bonificación al final)

 def f(s):
 a,m,b=s.split(" ");print(a,b,s);F,T,c=0,1,"FT"
 for p in c:
  for q in c:print(p,q," ",c[eval(p+"+*"[m=="∧"]+q)>0])

Necesitar Python3 para soporte Unicode fuera de la caja.

Basado en el código Python de DJgamer98, descubrir que su mesa no está bien.

Edit1: división en variables distintas y omisión de la variable de cadena del operador

Edit2: (ab) usando F y T como variables y caracteres de cadena

Edit3: Ahorrando un espacio gracias a NoOneIsHere

Con Bonus, 215 * 0.6 = 129

def f(s):
 r="+---"*3+"----+"
 a,m,b=s.split(" ");F,T,c=0,1,"FT"
 print("%s\n| %s | %s | %s |\n%s"%(r,a,b,s,r));
 for p in c:
  for q in c: print("| %s | %s |   %s   |\n%s"%(p,q,c[eval(p+"+*"[m=="∧"]+q)>0],r));
Karl Napf
fuente
Bienvenido a PPCG! Puede guardar un byte eliminando el espacio después q in c:.
NoOneIsHere
Edit2: Eso no es abuso. ¡Mira aquí , donde uso el primer carácter del contenido del archivo como nombre de archivo!
Adám
1

C / C ++ 302 bytes

335 caracteres menos 10% para manejar la negación. Formateo incompleto pero envío antes de ver cuál es el impacto de la finalización.

Marcado como C / C ++ porque mi gcc y g ++ lo aceptan con -permisivo y me parece mucho más C que C ++.

#include <stdio.h>
void T(char*S) { int (*P)(char*,...)=printf;char*v[2]={"F","T"};for(int m=4;m--;){P("|");char*s=S;int x=m&1;X:P(" %s |",v[x]);if(*++s!=' '){x=x^1;goto X;}char*o=++s;s+=3;int y=(m>>1)&1;Y:P(" %s |",v[y]);if(*++s){y=y^1;goto Y;}int g;for(g=o-S+1;g--;)P(" ");P(*++o==39?v[x&y]:v[x|y]);for(g=s-o;g--;)P(" ");P("|\n");}}

Estoy seguro de que probablemente haya algunos ajustes que podrían aplicarse. De hecho, manejar los nots agrega más de lo que elimina el 10% de bonificación.

Esto supone que el formato de entrada es el indicado, es decir, 2 valores de entrada (p y q), con o sin el prefijo not y nada más, y todos los tokens delimitados por un solo espacio.

Sin golf:

void ungolfed(char* S)
{
   int (*P)(char*,...) = printf;         // useful lookup stuff
   char* v[2] = {"F","T"};

   for(int m = 4; m--;) {                // loop over all 2 bit bit patterns (truth table inputs)

      P("|");                            // start of line format
      char* s=S;                         // iterator to start of equation for each bit pattern

      int x = m&1;                       // input 1 (aka. p which I called x here to be awkward)
X:    P(" %s |",v[x]);                   // input 1 output and format

      if(*++s!=' ') {                    // if next character is not a space then input must be prefixed with the not character
         x=x^1;                          // so negate the input
         goto X;                         // and redo input 1 output
      }

      char* o = ++s;                     // remember where the operator is
      s+=3;                              // and skip it and following space

      int y = (m>>1)&1;                  // input 2 (aka. q which I called y obviously) processing as for input 1
Y:    P(" %s |",v[y]);

      if(*++s) {
         y=y^1;
         goto Y;
      }

      int g;

      for(g=o-S+1;g--;) P(" ");         // pre-result value padding

      P(*++o==39?v[x&y]:v[x|y]);      // result

      for(g=s-o;g--;) P(" ");           // post-result value padding and format
      P("|\n");
   }
}

y las pruebas:

int main()
{
   T("p \x22\x27 q");  // p & q
   puts("");

   T("p \x22\x28 q");  // p | q
   puts("");

   T("\x7ep \x22\x27 q");  // ~p & q
   puts("");

   T("\xacp \x22\x28 q");  // ~p | q
   puts("");

   T("p \x22\x28 \xacq");  // p | ~q
   puts("");

   return 0;
}
original.legin
fuente
0

Mathematica, 128 caracteres

TraditionalForm@Grid[({#}~Join~BooleanTable[#,Cases[b,_Symbol,{0,∞}]]&/@Cases[b=ToExpression@#,_,{0,∞}]/.{0<1->"T",0>1->"F"})]&

es el personaje de uso privado U+F3C7 representa \[Transpose].

Afortunadamente para nosotros los golfistas de Mathematica, y ya representamosAnd y Or, así que todo lo que tenemos que hacer es convertir la cadena de entrada en una expresión de Mathematica y podemos hacer operaciones lógicas simbólicas en ella.

Tenga en cuenta que esta solución también manejará Not( ¬), Implies( ), Equivalent( ), Xor( ), Nand( ), Xor( ) y Nor( ), pero no recibe la bonificación porque ~pes un error de sintaxis en Mathematica. Meh

ingrese la descripción de la imagen aquí

Explicación

b=ToExpression@#

Convierte la cadena de entrada en una expresión de Mathematica y la almacena b.

Cases[b=ToExpression@#,_,{0,∞}]

Esta es una lista de todas las subexpresiones posibles de la entrada. Cada uno recibirá su propia columna.

Cases[b,_Symbol,{0,∞}]

Esta es una lista de todas las variables que aparecen en la entrada.

BooleanTable[#,Cases[b,_Symbol,{0,∞}]]&

Función pura que toma una expresión de entrada #y devuelve una lista de valores de verdad para todas las combinaciones posibles de valores de verdad para las variables.

{#}~Join~BooleanTable[...]

Antecede la expresión misma a esta lista.

.../@Cases[b=ToExpression@#,_,{0,∞}]

Aplica esta función a cada subexpresión de la entrada.

.../.{0<1->"T",0>1->"F"}

Luego reemplace true ( 0<1) con "T" y false ( 0>1) con "F".

(...)

Intercambiar filas y columnas.

Grid[...]

Mostrar el resultado como a Grid.

TraditionalForm@Grid[...]

Convierta el Gridformato tradicional para que use los símbolos elegantes.

ngenisis
fuente