Tabelas da verdade: o computador do seu bisavô


13

Se você se lembrar dos anos de escolaridade, lembre-se de aprender sobre as Tabelas da Verdade . Eles pareciam chatos, mas são a base da lógica e (alguns argumentariam) toda a computação ...


Problema

Sua missão, caso você aceite aceitá-la, é escrever um programa, função ou widget de código que possa gerar uma tabela verdade fornecida.

Entrada

A entrada será uma string (como estrutura de dados) contendo a instrução lógica na qual a Tabela da Verdade será inserida. Por exemplo:

p ∧ q

Isso significa p and q(conjunção lógica) e produzirá:

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

Observe o espaçamento: O item da coluna está no centro do cabeçalho

Personagens

Pontuação por caracteres, não bytes Os caracteres de comparação lógica são especiais e nem sempre são o que parecem. Use estes caracteres:

Conjunção lógica (AND): U + 2227

Disjunção lógica (OR): U + 2228

Negação lógica (NOT) ~ou ¬U + 7e e U + ac respectivamente


Bónus

Todos esses bônus são opcionais, mas eliminam pontos da sua pontuação. Escolha qualquer.

Negação Lógica

Negação lógica é um operador unário em tabelas verdadeiras. É o equivalente !na maioria dos idiomas baseados em C. Faz false=> truee vice-versa. É anotado com um ¬ ou ~ (você deve suportar ambos). Apoiar isso derrubará 10% da sua pontuação. Você deve, no entanto, adicionar uma coluna adicional para mostrar seus resultados: Por exemplo:

~p ∧ q

irá produzir:

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

Pretty Print

A notação de tabela normal é chata. Vamos torná-lo bonito! O formato de impressão bonito é o seguinte para p ∧ q:

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

Detalhes especiais para impressão bonita:

  • Há um preenchimento de 1 espaço em cada célula
  • Os valores das células ainda estão centralizados

Se você imprimir suas tabelas, use seu código e multiplique por 0,6. Use esta função para este bônus:

score = 0.6 * code

Exemplos

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

Regras

  • Aplicam-se brechas padrão
  • Nenhum recurso externo
  • Se você for violar as regras, seja inteligente;)

O código mais curto (em caracteres) vence. Boa sorte!


4
Pela descrição, parecia que essas eram expressões booleanas arbitrárias. Mas todos os exemplos (sem bônus) têm apenas um operador. Isso é restrito a um único operador? Além disso, os nomes dos valores nos exemplos são todos pe q. A menos que eles sempre tenham esses nomes, você pode mostrar algumas opções diferentes nos exemplos de teste. Eles são sempre uma única letra?
Reto Koradi

2
Como isso usa caracteres não ASCII, pode ser bom especificar se o comprimento do código é contado em caracteres ou bytes. Se forem bytes, seria útil saber quantos bytes os caracteres unicode usam.
Reto Koradi

Simplificar :). score = 0.6 * (code - 15)=.6 * code - 9
mınxomaτ

@RetoKoradi Alterado. Pontuação por caracteres, não bytes
MayorMonty

@RetoKoradi Se o que meu professor de geometria me diz é correto você nunca vai ver mais, em seguida, p qe rem uma tabela de verdade)
MayorMonty

Respostas:


6

JavaScript (ES6), 141

Função simples, sem bônus, 141 caracteres. (140 uft8, 1 unicode de largura)

Manuseio de funções complexas ~ ou ¬, 254 caracteres (253 utf, 1 unicode de largura), pontuação 229

Pode economizar 6 bytes usando em alertvez de console.log, mas alerté particularmente inadequado para exibir tabelas.

Teste a execução do snippet abaixo em um navegador compatível com EcmaScript 6 (testado com Firefox. Não funcionará no Chrome, pois o Chrome não suporta .... Além disso, a versão bônus usa uma extensão splitespecífica do 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>


1
+1, eu amo JavaScript e esta solução merece um voto positivo.
Arjun

JavaScript é minha língua nativa, mas não deixarei que isso me afete! : D Bom trabalho!
MayorMonty

6

Modelo do MediaWiki - 2347 caracteres

O MediaWiki possui uma função de modelo criada chamada {{#expr}}que pode lidar com expressões lógicas. Esse deve ser o desafio perfeito para os modelos do MediaWiki! Porém, recursos como variáveis, loops e uma sintaxe legível teriam ajudado um pouco. Além disso, o fato de não haver um operador NOT para a função expr a tornou um pouco mais complexa.

{{#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}}

Teste:

{{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

Estou assumindo o MediaWiki> = 1,18, onde as extensões ParserFunctions são fornecidas com o software.


2
Bem-vindo à programação de quebra-cabeças e código de golfe. Usar o MediaWiki não é algo em que eu pensaria; +1. No entanto, o comportamento da coluna extra do operador ¬/ ~está ausente; se você adicioná-lo, você se qualificará para um 10%bônus.
Wizzwizz4

Eu só percebi que, a menos que eu posso usar modelos aninhadas (que pode ser esticar as regras um pouco longe demais?), Acrescentando adequadamente essa coluna seria realmente aumentar o caráter contagem ... :)
leo

Nesse caso, você provavelmente deve remover o suporte à negação, porque não está recebendo nenhum bônus por isso.
Wizzwizz4

Sim, vai olhar para ele. Eu acho que isso não terá muito impacto no ranking final ...: D
leo

1
@leo Isso é ótimo, e eu acho que usar modelos aninhados seria bom se você apenas adicionar a contagem de caracteres dos dois, que parece ser a prática aceita atualmente.
Harry

4

Python - 288 caracteres (+10 de penalidade, não consegui fazer o unicode funcionar: c)

Sem bônus. Esta é a minha primeira resposta 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 é a entrada.

EDIT: Removidos alguns espaços e agora usa a função args como entrada.


1
Bem-vindo ao PP&CG! Certifique-se de que seu código segue as regras, de acordo com a pergunta. Como especificação de regra, seu código deve ser uma função, programa completo ou parte do código. Isso implica que a entrada DEVE ser STDIN ou argumentos de função (ou equivalente) Happy Coding!
MayorMonty

3

Dyalog APL , 58 48 caracteres

Requer ⎕IO←0, que é padrão em muitos sistemas. Aceita string como argumento.

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

Sem bônus, mas no lado positivo, qualquer operador trabalha.

⍳4 quatro primeiros índices (0 1 2 3)

 reverso (3 2 1 0)

2 2⊤ tabela booleana de dois bits

 dividido em lista de dois elementos de listas (bits altos, bits baixos)

p q← loja como p e q

 contabilize-os (2) *

9⍴ remodelar ciclicamente para o comprimento 9 (2 2 2 2 2 2 2 2 2)

324⊤⍨ codificar 324 assim, ou seja, como binário de 12 bits (1 0 1 0 0 0 1 0 0)

\⍨ use isso para expandir (insira um espaço para cada 0) ...

'FT '[... ] a sequência "FT", indexada por

⍎⍵ o argumento executado (válido desde que p e q agora tenham valores)

transformá-lo em uma matriz de colunas

q, precede uma coluna que consiste em q (1 1 0 0)

q, precede uma coluna que consiste em p (1 0 1 0)

(... )⍪ insira uma linha acima, consistindo em

 o argumento

'p q ', anexado com a sequência "p q"


* Marque esta edição com estrela se você vê como ≢e não como ̸≡.


2

Julia, 161 bytes

Sem bônus.

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)

Ungolfed:

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

1

Mathematica, 129 bytes

Golfe:

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

Ungolfed:

(*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]]

Não sou especialista em Mathematica, mas achei isso bastante elegante em comparação a ter que fazer uma comparação direta de caracteres.

Eu tinha uma solução que funcionava para negação, mas era mais longa do que a redução de pontuação decolaria.

Dependendo do que se qualifica para uma impressão bonita, eu posso tentar esse bônus. Eu sinto que a saída em ASCII no Mathematica seria muito cara para a redução de pontuação compensar, mas se os dois principais recursos são uma borda pontilhada e preenchimento especificado dentro das células, são apenas algumas opções no Grid.

Com impressão bonita, 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]

1

Python3, 145 139 120 119 Bytes

Sem bônus (com bônus no 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])

Precisando de suporte ao Python3 para Unicode imediatamente.

Baseado no código Python do DJgamer98, descobrir sua tabela não está certo.

Edit1: Dividindo em variáveis ​​distintas e omitindo a variável de sequência do operador

Edit2: (ab) usando F e T como variáveis ​​e caracteres de sequência

Edit3: Salvando um espaço graças a NoOneIsHere

Com bônus, 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));

Bem-vindo ao PPCG! Você pode salvar um byte removendo o espaço depois q in c:.
NoOneIsHere

Edit2: Isso não é abuso. Veja aqui , onde eu uso o primeiro caractere do conteúdo do arquivo como nome do arquivo!
Adám

1

C / C ++ 302 bytes

335 caracteres menos 10% para lidar com negação. Formatação incompleta, mas envio antes que eu veja qual é o impacto da conclusão.

Marcado como C / C ++ porque meu gcc e g ++ o aceitam com -fpermissive e parece muito mais C do que C ++ para mim.

#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");}}

Tenho certeza de que provavelmente há alguns ajustes que poderiam ser aplicados. De fato, lidar com o nots adiciona mais do que o bônus de 10% remove.

Isso pressupõe que o formato de entrada seja o indicado, ou seja, 2 valores de entrada (p e q), com ou sem o prefixo not e nada mais, e todos os tokens delimitados por um único espaço.

Ungolfed:

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");
   }
}

e os testes:

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;
}

0

Mathematica, 128 caracteres

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

é o caractere de uso privado que U+F3C7representa \[Transpose].

Felizmente para nós, jogadores do Mathematica, e representamos Ande Or, portanto, tudo o que precisamos fazer é converter a string de entrada em uma expressão do Mathematica e podemos fazer operações lógicas simbólicas nela.

Observe que esta solução também manipula Not( ¬), Implies( ), Equivalent( ), Xor( ), Nand( ),Xor ( ) e Nor( ), mas não recebe o bônus porque ~pé um erro de sintaxe no Mathematica. Meh.

insira a descrição da imagem aqui

Explicação

b=ToExpression@#

Converte a sequência de entrada em uma expressão do Mathematica e a armazena b.

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

Esta é uma lista de todas as subexpressões possíveis da entrada. Cada um receberá sua própria coluna.

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

Esta é uma lista de todas as variáveis ​​que aparecem na entrada.

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

Função pura que pega uma expressão de entrada #e retorna uma lista de valores de verdade para todas as combinações possíveis de valores de verdade para as variáveis.

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

Anexa a própria expressão a esta lista.

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

Aplica essa função a cada subexpressão da entrada.

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

Em seguida, substitua true ( 0<1) por "T" e false ( 0>1) por "F".

(...)

Troque linhas e colunas.

Grid[...]

Exiba o resultado como a Grid.

TraditionalForm@Grid[...]

Converta a Gridforma tradicional para que ela use os símbolos extravagantes.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.