Простий логічний калькулятор воріт


9

Якщо ви вирішите прийняти це, ваша місія полягає в тому, щоб побудувати простий оцінювач істини для наступних логічних операторів:

----------------------------------------------------------------------------------
  Logical Name          |  Gate Name   |  Symbol  |  Symbol Name  |  Truth Table
----------------------------------------------------------------------------------
  Identity              |  is          |          |  (none)       |  10
  Negation              |  not         |    ~     |  tilde        |  01
  Conjunction           |  and         |    &     |  ampersand    |  1000
  Disjunction           |  or          |    |     |  pipe         |  1110
  Negative Conjunction  |  nand        |    ^     |  caret        |  0111
  Joint Denial          |  nor         |    v     |  "vee"        |  0001
  Exclusive Disjunction |  xor         |    x     |  "ecks"       |  0110
  Equivalence           |  equals/xnor |    =     |  equals       |  1001
  Implication           |  implies     |    >     |  greater than |  1011

Таблиці істини в такому порядку:

  1. 1 1
  2. 1 0
  3. 0 1
  4. 0 0

Введення буде простим рядком 0, 1 та символом. Ви можете прийняти введення як параметр або прочитати його від користувача на stdin. Ось кілька зразків пар введення / виводу:

Input: 1
Output: 1

Input: ~1
Output: 0

Input: 0|1
Output: 1

Input: 1>0
Output: 0

Одинарний оператор (заперечення) завжди з'явиться перед булевим значенням, тоді як двійкові оператори завжди з'являться між двома булевими значеннями. Ви можете припустити, що всі дані будуть дійсними. Струни - це звичайні рядки ASCII.

Якщо ви віддаєте перевагу, ви можете використовувати T і F, а не 1 і 0. -6 для підрахунку символів, якщо ви підтримуєте обидва.

Це є : найкоротший код на будь-якій мові виграє!


3
Я вважаю ^, що назва символу повинна говорити про карету .
FireFly

3
@FireFly Ха-ха, ти маєш рацію. Занадто близько до обіду! Дякую.
астері

Відповіді:


6

APL (45 - 6 = 39)

⍎(1+9≠L)⌷¨↓⍉Z⍪⍉⍪'10∧∨⍲⍱≠≤*'[L←'TF&|^vx>'⍳Z←⍞]

Підтримується Tі Fяк вхід, але завжди виводить 0або 1.

Пояснення:

  • Z←⍞: прочитати рядок і зберегти його Z
  • L←'TF&|^vx>'⍳Z: отримайте індекс 'TF&|^vx>'для кожного символу в Z, даючи, 9якщо символ не знаходиться в 'TF&|^vx>'.
  • '10∧∨⍲⍱≠≤*'[... ]: знайдіть відповідний символ у '10∧∨⍲⍱≠≤*'. (Так стають символи, які не були у першому списку *).
  • ↓⍉Z⍪⍉⍪: зробіть це в матрицю, покладіть на неї original ( Z) і розділіть його на список рядків, де перший символ є оригіналом, а другий - його перекладом, якщо такий є.
  • (1+9≠L)⌷¨: для кожного з цих рядків отримайте перший символ, якщо не було перекладу (якщо L=9в цьому місці) та другий символ, якщо він був.
  • Приклад: якби вхід був T|0, ми вже мали би 1∨0відповідне вираз APL
  • : eval

Зауважте: ~і =вже робите правильно, щоб їх не потрібно було нічого замінювати.


Дуже хороший! Це підхід перекладу на APL-і-eval, правда? Я обдумував підхід на основі герунду в J, але не знаю, як хитро розділити операнди. : \
FireFly

Чому маніпулювання матрицею, коли ви можете просто додати правила перекладу для символів без змін, як-от ⍎'1010~∧∨⍲⍱≠=≤'['10TF~&|^vx=>'⍳⍞]? (Оцінка 33-6 = 27)
TwiNight

8

С - 165 127

Це було весело! Звичайна таблиця пошуку, спираючись на фіксований зсув для пошуку.

main(){
  char*s="100011001110110v& x = |^> /~",
       t[6]="0/xxx",
      *u= strchr((gets(t+2),t),0)-3;
  putchar(strchr(s,u[1])[*u*2+u[2]-159]);
}

З якої - то причини getsне отримує неявно оголошується, тому , коли я витягував включаються мені довелося змінити , gets(t+2)щоб (gets(t+2),t)(або аналогічно в інших місцях, вартістю більше).


Пояснення

Перш за все, оскільки у таблицях істинності для операторів є безліч символів, що перекриваються, ми хочемо зберігати таблиці пошуку таким чином, щоб ми могли перекриватись. Ось як я вирішив зберігати їх:

v    &    x    =    |    ^    >       ~     (operation)
1000 0001 0110 1001 0111 1110 1101 01 10    (truth table [order 00,01,10,11])
0    1    3    5    7    8    9    B  D     (offset in LUT below)

0123456789ABCDE   (offsets)
100011001110110   (values)

Далі ми хочемо зіставити символи оператора з цими зміщеннями. Ми робимо це, зберігаючи символи оператора в одному рядку при фіксованому зміщенні від даних LUT (а саме 16 символів пізніше, тобто безпосередньо після даних LUT). Процес пошуку - "знайти оператора в s, відняти 16, додати left*2+right(лівий / правий операнд). Для пошуку порожньої" операції ідентичності ", завдяки тому, як введений вхід, оператор у цьому випадку вирішить все t[1], що ініціалізується на- -в нашого випадку /. Таким чином, ми використовуємо в /якості ключа таблиці пошуку , щоб представити тотожну операцію. Коли ми обробляємо унарні ~операції « left» (для розрахунку пошуку згадувався раніше) завжди це ж / . /трапляється один менше0ASCII мудре, тобто коли ми компенсуємо цифри ASCII \будуть представляти -1. Похила в ключовій області таблиці пошуку (тобто другий-останній символ у s, тобто) розташована для компенсації цього.

Далі вгору, обробка вводу. Вхід має динамічну довжину, але було б простіше, якщо ми маємо конкретні статичні імена для лівого операнда, оператора та правого операнда, незалежно від введення. Якщо ми робимо вигляд, що ми могли прочитати вхід справа-наліво, це в основному відбудеться автоматично - правий операнд - це завжди найменший правий символ, оператор (за наявності) - другий праворуч, лівий операнд (якщо присутній ) третій праворуч. Для того, щоб мати можливість індексувати такий рядок, ми використовуємо strchrдля того, щоб знайти \0термінатор ( - 3щоб спростити індексацію). Це показує, чому t[0]і t[1]стати лівим операндом / оператором відповідно, коли вхід становить 1 або 2 символи.

Якщо взяти його разом, то результат буде putchar(strchr(s,u[1])[(u[0] - '0')*2 + (u[2] - '0') - 15]), але натомість деяке рефакторинг та постійне складання робить нас коротшими putchar(strchr(s,u[1])[u[0]*2+u[2]-159]).


Чи можете ви пояснити, як це працює?
Йоганнес Кун

Перекриття таблиці правди було блискучою ідеєю. Я б ніколи про це не думав. :)
asteri

Також читання справа наліво. Я знав, що введення та позиціонування змінної довжини становитимуть складність, і це чудовий спосіб її вирішити. По-справжньому відмінне зовнішнє мислення. Хочете приїхати працювати над моєю командою розвитку? Haha
asteri

4
Я думаю, що більше відповідей повинні мати такі пояснення. Допомагає тим із нас, хто ще багато навчається! (І тим, хто все ще вчиться в значній
мірі

@agweber: Це добре чути, я трохи переживав своє пояснення. І так, напевно, всі тут перебувають у фазі "ще навчаються" .. ну, принаймні, я знаю, що я є.
FireFly

4

Tcl, 212 208-6 = 202

proc o n\ e {proc $n a\ b expr\ $e}
o > {$a<=$b}
o v {!($a|$b)}
o x {$a^$b}
o ^ {!($a&$b)}
namespace pat tcl::mathop 
lmap o\ b [lassign [split [string map {~0 1 ~1 0} $argv] {}] a] {set a [$o $a $b]}
puts $a

Безголівки:

# Defines an operator
proc operator {name expression} {
    proc $name {a b} "expr $expression"
}
operator > {$a<=$b}
operator v {!($a|$b)}
operator x {$a^$b}
operator ^ {!($a&$b)}
# Call the commands in ::tcl::mathop if the command is not in the global namespace
namespace path tcl::mathop
# lmap instead foreach
# assume that we only got 1 argument.
foreach {op b} [lassign [string map {{~ 0} 1 {~ 1} 0} [split $argv {}]] a] {
   set a [$op $a $b]
}
puts $a

Я думаю, що рядку foreach потрібне пояснення:

  • split $argv {} розбиває рядок введення (це насправді список, але код-гольф) на його символи.
  • string map {{~ 0} 1 {~ 1} 0} ...бере рядок і замінює ~ 0на 1і ~ 1на0
  • lassign ... a бере перший елемент списку і присвоює йому змінну a, повертає решту.
  • foreach {op b} ... {code}проходить список і щоразу займає 2 елементи: opіb
  • set a [$op $a $b]виконує команду у змінній op, зберігає результат уa

3

JavaScript - 107 105 символів

alert((x=eval(prompt().replace(/v/,'|~').replace(/\^/,'&~').replace(/x/,'^').replace(/=/,'==')))!=-1?x:0)

Ха-ха, приємно. Це зручно. Навіть не думав, eval()коли я це придумував. Просто дайте мені трохи повернутися додому і випробувати.
asteri

1
nand = &~і nor = |~?
Йоханнес Кун

@Johannes: Це на самому ділі не &~та |~, але NAND тільки зворотна І. Отже, інвертування одного з бітів також перетворює результат.
ProgramFOX

3

Befunge-98 - 104 101 98-6 72

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

#v~
2_vp5a00+*2%2\p10\%
0:<+1_v#-g5\g1
1_|#:\</2\-
.@>2%
 v   ~x^&=.>  |

Факт забави: змініть @на, a,$і натомість ви отримаєте вигадливий непомітний REPL (хоча, якщо ви це зробите, ви помітите, що ідентичність насправді "повторіть останню команду з lhs = 0 і rhs = input", що просто відбувається за замовчуванням для ідентичності ). REPL - не більше.

Ungolfed (більш рання версія):

v10001100111011v& x = |^>~
  $       1111111111222222
 1234567890123456789012345

 [read input]
> ~ :a- #v_   $ 21g " "- + 0g , @

v p11:   <
   ↑save chr

0 ←lup   [traverse LUT]
> 1+  :11g  \0g -! #v_
 v                  <
    lup chr acc
v>  :3` #v_  $"0"-\2*+

               v>   . , a,
 v       <
v> 9+9+ 21p $

Редагувати: надихнувшись рішенням @jpjacobs, я тепер покладаюся на положення символів у LUT для відображення таблиць правдивості. Наприклад, |знаходиться в положенні 1110 2 = 14, оскільки це відповідає таблиці істинності для |.


Це божевільно. Гаразд, кожне рішення у функціонуванні є божевільним.
Йоганнес Кун

2

J - 65 67-6 = 61

Більше не б. Прислівник. Не рахуючи присвоєння функції: 67 символів для TF-версії, 63 для не-TF-версії:

lgcTF =:".@({&('*+-+-<*01',.3 6#'.:')"1@n^:(9>n=:'&|~xv>^FT'&i.)@{.&.>&.;:)
lgc   =:".@({&('*+-+-<*',.3 4#'.:')"1@n^:(7>n=:'&|~xv>^'&i.)@{.&.>&.;:)

LgcTF обробляє і 0, і 1, а також T і F.

Підтримує весь синтаксис J з точки зору поїздів, дужок та оцінює суворо праворуч ліворуч (жодних інших правил пріоритету).

Усі символи, які не знаходяться у списку операторів + Z, не можна використовувати, інші діятимуть як у стандартному J (включаючи змінні).

Використання:

NB.Assign TF anyhow
T=:1 [ F=: 0
lgc 'T & F'
0
lgc ' T ~@& F' NB. negation after and = nand
NB. make a truth table
d=: 0 1
lgc 'd ~@|/ d'
1 0
0 0 
NB. and so on... 

1

Постскрипт 263

Ідею Firefly перекладено на Postscript.

{(0/xxx)dup 2 3 getinterval(%lineedit)(r)file exch 
readstring pop length 1 sub 3
getinterval(100011001110110v& x = |^> /~)dup
2 index 1 1 getinterval search pop exch pop exch pop 
length 3 2 roll{}forall exch pop exch 2 mul add 159 sub add 
1 getinterval =}loop

Відступ:

%!

{
    (0/xxx) dup 2 3 getinterval
    (%lineedit)(r)file exch % (0/xxx) file (xxx)
    readstring pop
    length % (0/xxx) len(x|xx|xxx)
    1 sub 3 getinterval % (0/x)|(/xx)|(xxx)
    (100011001110110v& x = |^> /~) dup
    2 index 1 1 getinterval search pop % (0/x)|(/xx)|(xxx) s post match pre
    exch pop exch pop % (xxx) s pre
    length 
    3 2 roll {} forall exch pop % s len(pre) u_0 u_2
    exch 2 mul add 159 sub add % s ind
    1 getinterval
    = flush
} loop

1

Befunge-93, 86 символів

Працює шляхом хешування другого символу вводу (пошук функції, яка була і компактною, і уникнення зіткнень, була певною роботою) для координати, і приймаючи перший і третій символи кожного модуля 2 як два найменш значущих біта координати x, потім отримання будь-якого значення в зазначеній позиції. Краща хеш-функція або більш компактний метод зберігання / адреси таблиць істинності - це лише два можливі способи зменшити довжину.

~~~\:8/\5%:++00p2%\2%2*+00gg,@
0 1







1001
0001
1101
1

0
0110



1110
1000


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