Таблиці правди: комп’ютер вашого прадіда


13

Якщо ви пам’ятаєте ще про шкільні роки, ви могли б пам’ятати, дізнавшись про таблиці правди . Вони здавалися нудними, але вони є основою для логіки і (дехто заперечує) всіх обчислень ...


Проблема

Ваша місія, якщо ви вирішите її прийняти, це написати програму, функцію або віджет коду, який може вивести таблицю істинності із заданим входом.

Вхідні дані

Введенням буде рядок (як структура даних), що містить логічний вислів для внесення таблиці Істини. Наприклад:

p ∧ q

Це означає p and q(логічна сполука) і виведе:

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

Помітьте пробіл: елемент стовпця знаходиться в центрі заголовка

Персонажі

Оцінка за допомогою символів, а не в байтах Символи порівняння логіки є особливими і не завжди такими, якими вони виглядають. Використовуйте ці символи:

Логічна сполука (AND): U + 2227

Логічна диз'юнкція (АБО): U + 2228

Логічне заперечення (НЕ) ~або ¬U + 7e і U + ac відповідно


Бонуси

Усі ці бонуси необов’язкові, але знищують бали. Виберіть будь-яку.

Логічне заперечення

Логічне заперечення є одинаковим оператором у таблицях істинності. Це еквівалент !більшості мов на базі С. Це робить false=> trueі навпаки. Він позначений символом a ¬ або ~ (ви повинні підтримувати обидва). Підтримка цього знищить 10% вашої оцінки. Однак ви повинні додати додатковий стовпець, щоб показати його результати: Наприклад:

~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 | q | p ∧ q |
+---+---+-------+
| T | T |   T   |
+---+---+-------+
| T | F |   F   |
+---+---+-------+
| F | T |   F   |
+---+---+-------+
| F | F |   F   |
+---+---+-------+

Особливі деталі для симпатичного друку:

  • У кожній комірці є 1 пробіл
  • Значення клітин все ще зосереджено

Якщо ви досить роздрукуєте свої таблиці з коду, а потім помножте на 0,6. Використовуйте цю функцію для цього бонусу:

score = 0.6 * code

Приклади

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

Правила

  • Застосовуються стандартні лазівки
  • Ніяких зовнішніх ресурсів
  • Якщо ви збираєтесь порушувати правила, будьте розумні;)

Виграє найкоротший код (у символах). Щасти!


4
З опису звучало так, що це були довільні булеві вирази. Але всі приклади (без бонусу) мають лише одного оператора. Чи обмежено це лише одним оператором? Також назви значень у прикладах - всі pі q. Якщо вони завжди мають ці назви, ви можете показати кілька варіантів у тестових прикладах. Чи завжди вони є однією буквою?
Рето Коради

2
Оскільки для цього використовуються символи, що не належать до ASCII, можливо, було б добре вказати, чи враховується довжина коду в символах чи байтах. Якщо це байти, було б корисно знати, скільки байтів використовують символи unicode.
Рето Коради

Спростіть :). score = 0.6 * (code - 15)=.6 * code - 9
mınxomaτ

@RetoKoradi Змінено. Оцінка за символами, а не за байтами
MayorMonty

@RetoKoradi Якщо то , що мій учитель геометрії каже мені правильно , ви ніколи не будете бачити більше p qі rв таблиці істинності;)
MayorMonty

Відповіді:


6

JavaScript (ES6), 141

Проста функція, без бонусу, 141 символів. (140 uft8, 1 ширина одного коду)

Комплексна робота з функціями ~ або ¬, 254 символів (253 утф, 1 унікод), оцінка 229

Не вдалося зберегти 6 байтів, використовуючи alertзамість них console.log, але alertособливо непридатні для відображення таблиць.

Випробуйте запуск фрагмента нижче у веб-переглядачі, сумісному з EcmaScript 6 (протестовано з Firefox. Не працюватиме в Chrome, оскільки Chrome не підтримує .... Крім того, для бонусної версії використовується розширення, splitяке стосується 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, я люблю JavaScript, і це рішення заслуговує на надбавку.
Арджун

JavaScript - це моя рідна мова, але я не дозволяю, щоб це впливало на мене! : D Гарна робота!
МерМонти,

6

Шаблон MediaWiki - 2347 символів

MediaWiki має вбудовану функцію шаблону, яка називається, {{#expr}}що може обробляти логічні вирази. Це має бути ідеальним викликом для шаблонів MediaWiki! Однак такі функції, як змінні, цикли та читаний синтаксис, трохи допомогли б. Крім того, відсутність оператора NOT для функції expr зробила його трохи складнішим.

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

Тест:

{{TemplateName|¬X ∧ ~Y}}

{{TemplateName|p ∨ q}}

Результат:

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

Я припускаю MediaWiki> = 1.18, де розширення ParserFunctions поставляються в комплекті з програмним забезпеченням.


2
Ласкаво просимо до головоломки програмування та коду для гольфу. Використання MediaWiki - це не те, про що я б подумав; +1. Однак, додаткова поведінка стовпця ¬/ ~оператора відсутня; якщо ви додасте його, ви отримаєте право на 10%бонус.
wizzwizz4

Я щойно зрозумів, що, якщо я не можу використовувати вкладені шаблони (які, можливо, занадто далеко розтягують правила?), Правильно додавши, що стовпець насправді збільшить кількість символів ... :)
leo

У такому випадку вам, мабуть, слід видалити підтримку заперечення, оскільки ви не отримуєте жодних бонусів за це.
wizzwizz4

Так, поглянемо на це. Я не думаю, що це матиме великий вплив на остаточний рейтинг ...: D
лео

1
@leo Це чудово, і я думаю, що використовувати вкладені шаблони було б добре, якщо ви просто додасте кількість символів двох з них, що, здається, є прийнятою практикою в наш час.
Гаррі

4

Python - 288 символів (+10 штрафних причин, тому що я не міг змусити unicode працювати: c)

Без бонусів. Це моя перша відповідь на кодегольф.

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 є вхід.

РЕДАКТУВАННЯ: Видалено кілька пробілів, і тепер він використовує функцію аргументів як вхід.


1
Ласкаво просимо до PP&CG! Будь ласка, переконайтеся, що ваш код дотримується правил відповідно до питання. Як специфікація правила, ваш код повинен бути функцією, повноцінною програмою або бітом коду. Це означає, що введення ОБОВ'ЯЗКОВО має бути STDIN або аргументи функції (або еквівалент) Happy Coding!
МерМонті

3

Діалог APL , 58 48 символів

Вимагає ⎕IO←0, що для багатьох систем за замовчуванням. В якості аргументу бере рядок.

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

Ніяких бонусів, але з плюсу будь-який оператор працює.

⍳4 перші чотири індекси (0 1 2 3)

 реверс (3 2 1 0)

2 2⊤ двобітний булевий стіл

 розділити на двоелементний список списків (високі, бітні)

p q← зберігати як p і q

 розраховуйте їх (2) *

9⍴ циклічно переробити цю довжину до довжини 9 (2 2 2 2 2 2 2 2 2)

324⊤⍨ кодують 324 таким чином, тобто як 12-бітний двійковий (1 0 1 0 0 0 1 0 0)

\⍨ використовувати це для розширення (вставити пробіл для кожного 0) ...

'FT '[... ] рядок "FT", індексований

⍎⍵ виконаний аргумент (дійсний, оскільки тепер у p і q є значення)

зробити це в матрицю стовпців

q, додайте стовпець, що складається з q (1 1 0 0)

q, додайте стовпець, що складається з p (1 0 1 0)

(... )⍪ вставити рядок вище, що складається з

 аргумент

'p q ', заздалегідь введений рядком "p q"


* Будь-ласка, позначте цю проблему, якщо ви бачите як, ≢а не як ̸≡.


2

Юлія, 161 байт

Без бонусів.

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)

Безголівки:

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

Математика, 129 байт

Гольф:

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

Безголівки:

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

Не експерт з математики, але я вважав це досить елегантним порівняно з тим, що потрібно робити порівняння прямого характеру.

У мене було рішення, яке працювало на заперечення, але воно тривало довше, ніж зменшиться оцінка.

Залежно від того, що підходить для симпатичного друку, я можу спробувати цей бонус. Я відчуваю, що виведення в ASCII в Mathematica було б занадто дорогим, щоб зменшити кількість балів, щоб компенсувати, але якщо дві основні особливості - це пунктирна межа та вказана прокладка всередині комірок, це лише пара варіантів у Grid.

З гарною друком, 171 * 0,6 = 102,6 байт

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 Байт

Без бонусу (з бонусом наприкінці)

 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])

Потрібен Python3 для підтримки Unicode поза коробкою.

Спираючись на код DJgamer98 Python, з'ясувати його таблицю невірно.

Edit1: Розбиття на різні змінні та опускання змінної рядка оператора

Edit2: (ab), використовуючи F і T як змінні, так і рядкові символи

Edit3: Економія одного місця завдяки NoOneIsHere

З бонусом, 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));

Ласкаво просимо до PPCG! Ви можете зберегти байт, видаливши пробіл після q in c:.
NoOneIsHere

Edit2: Це не зловживання. Дивіться тут , де я використовую перший символ вмісту файлу як ім'я файлу!
Adám

1

C / C ++ 302 байти

335 символів менше 10% для обробки заперечення. Форматування неповне, але надсилаюсь, перш ніж я побачу, який вплив має завершення.

Позначений як C / C ++, оскільки мій gcc та g ++ сприймає його з -fmissmisive, і мені це виглядає набагато більше, ніж C + ніж 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");}}

Я впевнений, що, мабуть, є декілька налаштувань, які можна було б застосувати. Насправді обробка грошей додає більше 10% бонусу.

При цьому передбачається, що формат введення є таким, як зазначено, тобто 2 вхідні значення (p і q), з або без префікса і нічим іншим, і всі лексеми, розділені одним пробілом.

Безголівки:

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

і тести:

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

Математика, 128 символів

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

є символом приватного користування, що U+F3C7представляє \[Transpose].

На щастя для нас, гольфістів у Mathematica, і вже представляємо, Andі Orтому все, що нам потрібно зробити, це перетворити вхідний рядок у вираз Mathematica і ми можемо на ньому робити символічні логічні операції.

Зауважте, що це рішення також впорається Not ( ¬), Implies( ), Equivalent( ), Xor( ), Nand( ), Xor( ) і Nor( ), але він не отримує бонус, оскільки ~pє синтаксичною помилкою в Mathematica. Мех.

введіть тут опис зображення

Пояснення

b=ToExpression@#

Перетворює вхідний рядок у вираз Mathematica і зберігає його в b.

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

Це перелік усіх можливих підвиразів вхідних даних. Кожен отримає власну колонку.

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

Це перелік усіх змінних, які з'являються у вхідних даних.

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

Чиста функція, яка приймає вхідний вираз #і повертає список істинних значень для всіх можливих комбінацій значень правди для змінних.

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

Передбачає сам вираз до цього списку.

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

Застосовує цю функцію до кожного суб-вираження вводу.

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

Потім замініть true ( 0<1) на "T", а false ( 0>1) на "F".

(...)

Розміняйте рядки та стовпці.

Grid[...]

Показати результат як Grid.

TraditionalForm@Grid[...]

Перетворіть у Gridтрадиційну форму, щоб вона використовувала вигадливі символи.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.