Церковні булеани


33

Церковні буліни

Церква булева функція , яка повертає xдля істинно і yдля помилкових , де xце перший аргумент функції і yє другим аргументом функції. З цих функцій можуть бути складені подальші функції, які представляють and not or xorі impliesлогічні операції.

Виклик

Побудувати булеву Церква і and not or xorта impliesцерковні ворота на мові за вашим вибором. and orі xorповинен взяти на себе дві функції (представляючи церковні булеви) та повернути функцію (представляючи інший церковний булев). Аналогічно, notслід перевернути функцію, яку він займає, і impliesворота повинні виконувати булеві, має на увазі логіку, де перший аргумент impliesдругий.

Оцінка балів

Загальна довжина всього коду потрібно , щоб Церква trueі falseна вашій мові і тому and not or xorі impliesЦерква ворота виключаючи ім'я функції. (наприклад, false=lambda x,y:yу Python було б 13 байт). Ви можете повторно використовувати ці імена пізніше у своєму коді, рахуючи 1 байт до загального байту цього ворота.

Приклади псевдокоду:

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

true(x, y) -> x
false(x, y) -> y
and(true, true)(x, y) -> x
and(true, false)(x, y) -> y
# ... etc

2
Чи потрібно трактувати входи функцій (або найближчі замінники) як функції чорного поля, чи ми можемо перевірити код всередині? І чи повинні повернені значення логічних операцій бути такими ж функціями, які були визначені раніше, як церковні булеви, чи вони можуть бути чимось іншим, що робить те саме?
Непов’язана струна

1
@JonathanAllan Я редагував це так, щоб це було правильно. Підказка така, як і зараз.
Райан Шефер

2
Чи можемо ми взяти списки як аргументи (наприклад true([x, y]), and([true, true])([x, y]))?
ar4093

2
@RyanSchaefer Я думаю, вам слід переглянути, щоб аргументи знаходилися в упорядкованому списку, оскільки можна просто обговорити аргументи на початку рішення. Я не вважаю, що вимагати чогось зробити для покращення цієї проблеми (адже я думаю, що це обмежує цікавий потенціал для гольфу). Звичайно, це лише моя думка, і це добре, якщо ви не згодні.
FryAmTheEggman

1
Оцінка балів досить заплутана. Чи не було б краще дозволити людям надсилати анонімні функції, але якщо вони використовуватимуть їх в інших частинах, вони повинні призначити їх, як зазвичай
Джо Кінг,

Відповіді:


14

Двійковий обчислення лямбда , 13,875 12,875 байт (103 біта)

Бінарний мова обчислення лямбда (BLC) Джона Тромпа - це в основному ефективний формат серіалізації для обчислення лямбда. Це чудово підходить для цього завдання, оскільки позначення Церкви - це навіть "ідіоматичний" спосіб роботи з булевими в BLC.

Я використовував наступні лямбда-функції для комбінаторів, деякі з яких я скопіював і гольфував з відповіді Хаскелла:, які були знайдені вичерпним пошуком з обмеженням до 20 β-скорочень для кожного випадку. Є хороший шанс, що вони найкоротші.

True:  (\a \b a)
False: (\a \b b)
Not:   (\a \b \c a c b)
And:   (\a \b b a b)
Or:    (\a a a)
Xor:   (\a \b b (a (\c \d d) b) a)
Impl:  (\a \b a b (\c \d c))

Вони перекладаються на наступні (двійкові) послідовності коду BLC:

 bits |  name | BLC
------+-------+---------
    7 | True  | 0000 110
    6 | False | 0000 10
   19 | Not   | 0000 0001 0111 1010 110
   15 | And   | 0000 0101 1011 010
    8 | Or    | 0001 1010
   28 | Xor   | 0000 0101 1001 0111 0000 0101 0110
   20 | Impl  | 0000 0101 1101 0000 0110

Функції вище - загалом 111 біт (13,875 байт), 103 біти (12,875 байт). Їм не потрібно вирівнювати межі байтів, щоб використовуватись у програмі, тому має сенс рахувати дробові байти.

Не існує повторного використання коду між комбінаторами, оскільки в BLC немає змінних / посилань / імен - все довелося скопіювати. Тим не менш, ефективність кодування зумовлює досить коротке уявлення.


1
Я не знаю БЛК, але And: (\a \b a b a)спрацює?
tsh

Так, це працює. Я фактично використовував цю формулу для своїх кодових послідовностей. Я просто забув оновити відповідну функцію лямбда (зараз виправлена). Еквівалентна функція працює для Or : \a \b a a b. Він довший, ніж той, який я використовував у BLC, хоча.
Павло Поточек

25

Haskell , 50 - 6 = 44 байти

-1 байт завдяки Khuldraeseth na'Barya, а -1 байт завдяки Крістіану Сіверсу.

t=const
f=n t
n=flip
a=n n f
o=($t)
x=(n>>=)
i=o.n

Спробуйте в Інтернеті!


2
Примітка сторони: ви можете визначити Showекземпляри для constі const idта друкувати церковні булеві безпосередньо. Спробуйте в Інтернеті! .
німі


4
Чому ніхто не використовує f=n t?
Крістіан Сіверс

3
Ви можете зберегти байт, використовуючи t=pureзамість t=const.
Джозеф Сибл-Відновити Моніку

4
@JosephSible Я спробував це спочатку. На жаль, t=pureпризведе до помилки при спробі застосувати a, o, xабо iдо нього. Оголошення типу tвиправити це коштує більше байтів, ніж просто використання t=const.
Нітродон

9

Python 2 , (-3?)  101  95 байт

Девід Бізлі з'їсть ваше серце!

-6 завдяки Шасу Брауну (перемістив повторне :в текст приєднання>. <)

exec'=lambda x,y=0:'.join('F y;T x;N x(F,T);A x(y,F);O x(T,y);X x(N(y),y);I O(y,N(x))'.split())

Спробуйте в Інтернеті!

Я думаю, це може бути 95 - 3тому, що я не використовую повторно функції A, Xабо I, але використовую сингл =для призначення (перед lambda). Можливо, я не можу видалити будь-якого; можливо, мені навіть вдасться зняти 3,5?


@Ryan Schaefer чи можу я видалити три, чи моє використання execозначає, що я не можу? Я бачу, що йде в будь-якому випадку - я не використовую A, X або I, але код не працює без них. (Можливо, мені навіть вдасться зняти 3.5 ?!)
Джонатан Аллан


Дякую @Chas! Товста кишка, яка прослизнула через мережу :) Гарна робота по заміні на -1 BTW
Джонатан Аллан

7

JavaScript (Node.js) , 92 86 83 - 7 = 76 байт

t=p=>q=>p
f=t(q=>q)
n=p=>p(f)(t)
a=p=>n(p)(f)
o=p=>p(t)
x=p=>p(n)(f())
i=p=>n(p)(t)

Спробуйте в Інтернеті! Посилання включає основні тестові випадки. Редагувати: Збережено 6 9 байт завдяки @tsh.


1
здається , ви не можете стверджувати це як -7 , так як t, f, nвикористовуються.
tsh

1
@tsh Це не так, як я розумію систему балів; це явно виключає ім'я у визначенні, хоча ім'я у використанні коштує 1 байт.
Ніл

@Neil ви не можете претендувати на байтовую знижку для імен функцій, які викликаються з допомогою коду ( t, fі nв вашому випадку).
asgallant

2
@asgallant ні. Це не байт для імені та 1 байт, коли воно буде використано пізніше. 'T fnaox i' не є байтами, а потім 1 байт при використанні пізніше. Я хотів покращити читабельність, але тепер я розумію, що я повинен був просто залишити його повністю в гольф, і зараз вже пізно змінити його
Райан Шефер

@RyanSchaefer, де це правило? Я ніколи не бачив, щоб це робилося так.
asgallant

6

Python 2 , 133 - 6 = 127 94 байт

exec"t!u;f!v;n!u(f,t);a!u(v,f);o!u(t,v);x!u(n(v),v);i!o(v,n(u))".replace('!','=lambda u,v=0:')

Спробуйте в Інтернеті!

Безсоромно крадуть підступну ідею за відповіддю Джонатана Аллана ; жодних байтів не відраховується.


Я збирався опублікувати відповідь на власне запитання, але не знав, чи це дозволено, і я думаю, що це проти духу. Тому я думаю, що я просто проведу вас разом. Замість того, щоб використовувати списки, чи все-таки ви можете використовувати функції, які самі вводяться, і певний спосіб, коли вони повертають свої дані, щоб скоротити код?
Райан Шефер

Я б зробив ставку, що хоча відповідь "так", у Python це буде значно довше.
Непов’язана струна

Я виправлений
Непов’язана струна

@ Mr.Xcoder, ви праві, у мене неправильна кількість байтів для прикладу функції. Їм було б дозволено видалити 6 байт, хоча для назв функцій.
Райан Шефер

@Містер. Xcoder: Змінено відповідно до ваших спостережень.
Час Браун

4

J , 67 байт - 7 = 60

t=.[
f=.]
n=.~
a=.2 :'u v]'
o=.2 :'[u v'
x=.2 :'u~v u'
i=.2 :'v u['

Спробуйте в Інтернеті!

Варто зазначити:

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

Синтаксично прислівники приходять після дієслова, а сполучники йдуть між ними. Таким чином, до "не" дієслова fви робите f n, а до "і" дієслова fі g, ви f a g.


4

Мова Вольфрама (Mathematica) , 61-7 = 54 байти

t=#&
f=#2&
a=#2~#~f&
o=t~#~#2&
n=f~#~t&
x=n@#~#2~#&
i=#2~#~t&

Спробуйте в Інтернеті!

без гольфу: натхненний Вікіпедією ,

t[x_, y_] := x
f[x_, y_] := y
and[x_, y_] := x[y, f]
or[x_, y_] := x[t, y]
not[x_] := x[f, t]
xor[x_, y_] := y[not[x], x]
imply[x_, y_] := x[y, t]

Досить впевнений, що нові рядки необхідні для розділення визначень функцій. Також ви посилаєте tf і n в інших визначеннях функцій, щоб ви не могли їх вирахувати, тому 61-4 = 57.
Джонатан Аллан

@JonathanAllan Я перечитав інструкції з підрахунку балів і погоджуюсь, що нові рядки повинні нараховуватись, дякую. Я не погоджуюся з вашою другою частиною: коли я повторно використовую імена, я дійсно вважаю їх "1 байтом до загального байту цього ворота", який тут мається на увазі, коли я використовую однобайтові імена. По мірі того, як я читаю інструкції, немає жодної згадки про подальше їх підрахунок як один байт до загальної кількості початкового визначення. Тож я йду з байтами N-7. Також в іншому коментарі ОП уточнюється: "Це не байти для імені та 1 байт, коли воно буде використано пізніше".
Роман

Я читаю "1 байт пізніше", щоб означати, що використання в іншій функції коштує байта. Це узгоджується з тим, як інші забили також.
Джонатан Аллан

@JonathanAllan Мене менше цікавить екзегеза та більше кодують гольф 😀
Роман

4

Низький навантаження , 56 52 байти

(~!)(!)((~)~*):((!)~^)*(:^)(~(!)~^(~)~*)(()~(~)~^~*)

Спробуйте в Інтернеті! (включає тестовий набір та текст, що ідентифікує частини програми)

Це дивно добре для дуже низького рівня езолангу. (Церковні цифри, церковні булеви тощо) дуже часто використовуються в програмі Underload з цієї причини; в мові немає вбудованих чисел і булів, і це один із найпростіших способів їх моделювання. Однак, це також є загальним для кодувати булеви як церковні цифри 0 і 1.)

Для тих, хто плутається: Underload дозволяє визначати функції багаторазового використання, але не дозволяє вам називати їх звичайним чином, вони просто сортуються навколо стеку аргументів (тому, якщо ви визначите п'ять функцій, а потім хочете викликати першу Ви визначили, вам потрібно написати нову функцію, яка бере п'ять аргументів і викликає п'ятий з них, а потім називати її недостатньо багатьма аргументами, щоб вона шукала запасні аргументи для використання). Виклик їх знищує їх за замовчуванням, але ви можете змінити виклик, щоб зробити його неруйнівним (у простих випадках потрібно просто додати двокрапку до виклику, хоча складні випадки є більш поширеними, оскільки вам потрібно переконатися, що копії на стеку не заважає), тому підтримка функції Underload має всі вимоги, які нам знадобляться з питання.

Пояснення

правда

(~!)
(  )  Define function:
 ~      Swap arguments
  !     Delete new first argument (original second argument)

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

помилковий

(!)
( )   Define function:
 !      Delete first argument

Цей ще простіший.

ні

((~)~*)
(     )  Define function:
    ~*     Modify first argument by pre-composing it with:
 (~)         Swap arguments

Це одне задоволення: notвзагалі не називає свого аргументу, він просто використовує функціональну композицію. Це звичайний трюк в "Underload", в якому ви взагалі не перевіряєте свої дані, ви просто змінюєте їх функціонування, попередньо і після складання речей з ним. У цьому випадку ми змінюємо функцію, щоб заміняти її аргументами перед запуском, що явно заперечує число Церкви.

і

:((!)~^)*
 (     )   Define function:
     ~^      Execute its first argument with:
  (!)          false
               {and implicitly, our second argument}
        *  Edit the newly defined function by pre-composing it with:
:            {the most recently defined function}, without destroying it

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

Визначення тут таке and x y = (not x) false y. Іншими словами, якщо not x, тоді ми повертаємось false; інакше ми повертаємось y.

або

(:^)
(  )  Define function:
 :      Copy the first argument
  ^     Execute the copy, with arguments
          {implicitly, the original first argument}
          {and implicitly, our second argument}

@Nitrodon зазначив у коментарях, що or x y = x x yзазвичай коротше or x y = x true y, і це виявляється правильним і в Underload. Наївна реалізація цього була б (:~^), але ми можемо відібрати додатковий байт, зазначивши, що не має значення, чи будемо ми запускати оригінальний перший аргумент чи його копію, і результат є тим самим.

Навантаження насправді не підтримує currying у звичному розумінні, але такі визначення, як це, виглядають так, як це є! (Хитрість полягає в тому, що невикористані аргументи просто затримуються, тому функція, яку ви викликаєте, буде інтерпретувати їх як власні аргументи.)

мається на увазі

(~(!)~^(~)~*)
(           )  Define function:
 ~               Swap arguments
     ~^          Execute the new first (original second) argument, with argument:
  (!)              false
                   {and implicitly, our second argument}
       (~)~*     Run "not" on the result

Тут використовується визначення implies x y = not (y false x). Якщо у істинно, це спрощується not false, тобто true. Якщо y помилково, це спрощується not x, тим самим даючи нам таблицю правди, яку ми хочемо.

У цьому випадку ми notзнову використовуємо , цього разу переписуючи його код, а не посилаючись на нього. Він просто написаний безпосередньо як (~)~*без дужок навколо нього, тому його називають, а не визначають.

xor

(()~(~)~^~*)
(          )  Define function:
   ~   ~^       Execute the first argument, with arguments:
    (~)           "swap arguments"
 ()               identity function
         ~*     Precompose the second argument with {the result}

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

Коли перший аргумент є істинним, тому ми виробляємо відредаговану версію другого аргументу, яка міняє своїми аргументами перед запуском, тобто попередньо створює "аргументи swap", тобто not. Отже, справжній перший аргумент означає, що ми повертаємо notдругий аргумент. З іншого боку, помилковий перший аргумент означає, що ми складаємось із функцією тотожності, тобто нічого не робимо. Результатом є реалізація xor.


or x y = x x yекономить кілька байт or x y = x true y.
Nitrodon

Недостатнє завантаження часто контр-інтуїтивно зрозуміло, коли мова йде про заміну літералів повторно використаними змінними, але в цьому випадку це перетворення виявляється, щоб заощадити більше байтів, ніж очікувалося, а не менше. Дякуємо за покращення!
ais523


3

Java 8, оцінка: 360 358 319 271 233 (240-7) байт

interface J<O>{O f(O x,O y,J...j);}J t=(x,y,j)->x;J f=(x,y,j)->y;J n=(x,y,j)->j[0].f(y,x);J a=(x,y,j)->j[0].f(j[1].f(x,y),y);J o=(x,y,j)->j[0].f(x,j[1].f(x,y));J x=(x,y,j)->j[0].f(j[1].f(y,x),j[1].f(x,y));J i=(x,y,j)->j[0].f(j[1].f(x,y),x);

Це було складніше, ніж я думав, коли почав це. Особливо implies. У будь-якому випадку, це працює .. Можливо, можливо, тут і там трохи пограють в гольф. EDIT: Гаразд, не повторне використання функцій, а просто дублювання одного і того ж підходу набагато дешевше в плані підрахунку байтів для Java .. І я отримую повний бонус -7 за те, що не використовую жодну з функцій.

Спробуйте в Інтернеті.

Пояснення:

// Create an interface J to create lambdas with 2 Object and 0 or more amount of optional
// (varargs) J lambda-interfaces, which returns an Object:
interface J<O>{O f(O x,O y,J...j);}

// True: with parameters `x` and `y`, always return `x`
J t=(x,y,j)->x;
// False: with parameters `x` and `y`, always return `y`
J f=(x,y,j)->y;

// Not: with parameters `x`, `y`, and `j` (either `t` or `f`), return: j(y, x)
J n=(x,y,j)->j[0].f(y,x);

// And: with parameters `x`, `y`, and two times `j` (either `t` or `f`), return:
//      j1(j2(x,y), y);
J a=(x,y,j)->j[0].f(j[1].f(x,y),y);

// Or: with parameters `x`, `y`, and two times `j` (either `t` or `f`), return:
//     j1(x, j2(x,y))
J o=(x,y,j)->j[0].f(x,j[1].f(x,y));

// Xor: with parameters `x`, `y`, and two times `j` (either `t` or `f`), return:
//      j1(j2(y,x), j2(x,y))
J x=(x,y,j)->j[0].f(j[1].f(y,x),j[1].f(x,y));

// Implies: with parameters `x`, `y`, and two times `j` (either `t` or `f`), return:
//          j1(j2(x,y), x)
J i=(x,y,j)->j[0].f(j[1].f(x,y),x);

2

C ++ 17, 207−49 = 158 195 - 58 = 137 байт

Перерви в рядку не потрібні (крім перших двох).

#define A auto
#define D(v,p)A v=[](A x,A y){return p;};
D(true_,x)
D(false_,y)
A not_=[](A f){return f(false_,true_);};
D(and_,x(y,false_))
D(or_,x(true_,y))
D(xor_,x(not_(y),y))
D(implies,x(y,true_))

Спробуйте в Інтернеті!

Тестова одиниця з твердженнями, такими як:

static_assert('L' == true_('L', 'R'));
static_assert('R' == not_(true_)('L', 'R'));
static_assert('L' == and_(true_, true_)('L', 'R'));
static_assert('L' == or_(true_, true_)('L', 'R'));
static_assert('R' == xor_(true_, true_)('L', 'R'));
static_assert('L' == implies(true_, true_)('L', 'R'));

ОНОВЛЕНО: раніше я мав

A not_=[](A f){return[f](A x,A y){return f(y,x);};};

але відповідь Романа вказала шлях до коротшої версії. Зауважте, що зараз not_(std::plus<>)це неправильна форма, де раніше це було рівнозначно std::plus<>; але оскільки std::plus<>"не представляє собою церковно-булевий характер", я думаю, що будь-яка поведінка нормальна нормами.


Чи не слід "окрім першого" оновити до "іншого, ніж перші два"?
НЧ

@LF: Абсолютно правильно. Оновлено. :)
Quuxplusone

2

Четвертий (gforth) , 133 байт - 7 = 126 122

: j execute ;
: t drop ;
: f nip ;
: n ['] f ['] t rot j ;
: a dup j ;
: o over j ;
: x 2dup a n -rot o a ;
: m over n -rot a o ;

Спробуйте в Інтернеті!

-4 байти завдяки Quuxplusone

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

Пояснення коду

\ Helper function to save some bytes
: j        \ define a new word
  execute  \ execute the word at the provided address
;          \ end word definition

\ True
: t        \ define a new word
  drop     \ drop the second argument
;          \ end the word

\ False
: f        \ define a new word
  nip      \ drop the first argument
;          \ end the word

\ Not - The "hardest" one because we have to reference true and false directly
: n        \ define a new word
  ['] f    \ get address of false
  ['] t    \ get the address of true
  rot      \ stick the input boolean back on the top of the stack
  j        \ call the input boolean, which will select the boolean to return
;          \ end the word

\ And 
: a        \ define a new word
  dup      \ duplicate the 2nd input value
  j        \ call the 2nd input on the first and second input
;          \ end the word

\ Or
: o        \ define a new word
  over     \ duplicate the 1st input value
  j        \ call the 1st input on the first and second input
;          \ end the word

\ Xor
: x        \ define a new word
  2dup     \ duplicate both of the inputs
  a n      \ call and, then not the result (nand)
  -rot     \ move the result behind the copied inputs
  o a      \ call or on the original inputs, then call and on the two results
;          \ end the word

\ Implies
: m        \ define a new word
  over     \ duplicate the 1st input value
  n        \ call not on the 1st input value
  -rot     \ move results below inputs
  a o      \ call and on the two inputs, then call or on the two results
;          \ end the word

1
Ви повторюєте довге слово executeтричі. Визначення скорочення : j execute ;дозволить заощадити 4 байти.
Квомплусон

1

SKI-числення + комбінатор C, 36 байт

true=K
false=SK
not=C
and=CC(SK)
or=CIK
xor=C(CIC)I
implies=CCK

Я насправді не знаю жодного інтерпретатора, який дозволяє визначити додаткові комбінатори з точки зору попередніх, тому мені довелося перевірити це за допомогою http://ski.aditsu.net/ , вставивши в потрібні комбінатори, наприклад, CCKK(SK)pqвихідні дані q, показуючи, що Kне означає SK.


1

Джулія 1,0 , 36 байт

(b::Bool)(x,y)=b ? x : y;i(x,y)=!x|y

Я не знаю, чи вважається це, я фактично просто перевантажую рідний Boolтип, щоб його можна було викликати, тому я отримую більшість логічних воріт безкоштовно. На жаль, у Юлії немає impliesворіт, тому мені довелося написати власну функцію.

Спробуйте в Інтернеті!


Я думаю, вам все одно потрібно включити у ваше подання перевантажених операторів ... але оцінка не враховує їх, оскільки вони є лише іменами? Так це буде +6 байт з нових рядків? Я не надто впевнений, як діє підрахунок балів з цим викликом
Джо Кінг,

Я не на 100% впевнений, як це працює, але те, що включати код, який буквально нічого не робить, не має для мене сенсу.
користувач3263164

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


1

C ++ 17, 202−49 = 153 193 - 58 = 135 байт

Натхненний коментарем-обговоренням того, що так чи інакше вважається функцією 2-ary, ось викришена версія мого попереднього рішення C ++ 17. Це насправді коротше, тому що ми можемо використовувати той самий макрос not_для визначення всіх інших функцій!

#define D(v,p)auto v=[](auto x){return[=](auto y){return p;};};
D(true_,x)
D(false_,y)
D(not_,x(false_)(true_)(y))
D(and_,x(y)(false_))
D(or_,x(true_)(y))
D(xor_,x(not_(y))(y))
D(implies,x(y)(true_))

Спробуйте в Інтернеті!

Цей тестується з твердженнями на кшталт

static_assert('R' == and_(true_)(false_)('L')('R'));
static_assert('L' == or_(true_)(false_)('L')('R'));

Зауважте, що or_визначено як ефективне

auto or_=[](auto x){return[=](auto y){return x(true_)(y);};};

Ми могли б визначити or_більш "стисло" як

auto or_=[](auto x){return x(true_);};

але це коштуватиме нам, тому що ми більше не будемо використовувати Dмакрос.


Оскільки C ++ відрізняється від регістру, як щодо використання Trueта Falseзамість true_і false_? І аналогічно для інших операторів. Це заощадить 12 байт.
Г. Сліпен

@ G.Sliepen: Алгоритм оцінювання OP вже враховує, що ідентифікатори фактично є одним символом. Цитата: "Загальна довжина всього коду, необхідного для того, щоб Церква була правдивою та хибною у вашій мові, а не, чи xor, і передбачає церковні ворота, виключаючи ім'я функції. (Наприклад, false = lambda x, y: y у Python це буде 13 байт). Ви можете використати ці імена пізніше у своєму коді, рахуючи 1 байт до загального байту цього ворота. "
Quuxplusone

Ах, я пропустив це.
Г. Сліпен

0

APL (dzaima / APL) , 47 байт SBCS

На основі рішення J Іони .

trueі falseє функцією інфіксації, notє оператором суфікса, а решта - операторами інфіксації.

true←⊣
false←⊢
and←{⍺(⍶⍹false)⍵}
not←⍨
or←{⍺(true⍶⍹)⍵}
xor←{⍺(⍶not⍹⍶)⍵}
implies←{⍺(⍹⍶true)⍵}

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

Спробуйте в Інтернеті!

правда і хибність - ліва і права функції ідентичності.

not просто поміняє аргументи своєї операндної функції.

Решта реалізують дерево рішень:

andвикористовує праву функцію для вибору результату функції лівої руки, якщо це істинно, інакше результат falseфункції.

orвикористовує функцію лівої руки для вибору значення truetrue, інакше результат функції правої руки .

xorвикористовує функцію правої руки для вибору запереченого результату функції лівої руки, ⍶notякщо він є істинним, інакше результат функції лівої руки.

impliesвикористовує функцію лівої руки для вибору результату функції праворуч, якщо це істинно, інакше результат trueфункції.


0

Стакс , 34 байти

¿S£↓♣└²≡é♫Jíg░EèΩRΦ♂°┤rà╝¶πï╡^O|Θà

Запустіть і налагоджуйте його на staxlang.xyz!

Притискає купу блоків до стека. Кожен блок очікує свого останнього аргументу на вершині стека, за яким решта слід в зворотному порядку.

Розпаковано (41 байт):

{sd}Y{d}{y{d}a!}X{ya!}{b!}{cx!sa!}{sx!b!}

Кожна пара { }- це блок. Я використав два регістри X і Y для утримання, trueі notтому я міг легко отримати доступ до них пізніше. На жаль, falseне може бути просто бездіяльним, оскільки це залишить стек захаращеним і зіпсувати єдиний XOR-випадок.

Тестовий набір, коментується

false
{sd}    stack:   x y
 s      swap:    y x
  d     discard: y

true
{d}    stack:   x y
 d     discard: x

not
{y{d}a!}    stack:  p
 y{d}       push:   p f t
     a      rotate: f t p
      !     apply:  p(f,t)

and
{ya!}    stack:  p q
 y       push:   p q f
  a      rotate: q f p
   !     apply:  p(q,f)

or
{b!}    stack:  p q
 b      copies: p q p q
  !     apply:  p q(q,p)

xor
{cx!sa!}    stack:  p q
 c          copy:   p q q
  x!        not:    p q nq
    s       swap:   p nq q
     a      rotate: nq q p
      !     apply:  p(nq,q)

implies
{sx!b!}    stack:  p q
 s         swap:   q p
  x!       not:    q np
    b      copies: q np q np
     !     apply:  q np(np,q)

0

Befunge-98 , 105 77 65 байт

Граючи далі з поняттям "функція" мовами без функцій ... ось версія Befunge-98 церковних булей!

У цьому обмеженому діалекті Befunge-98 програма складається з серії "ліній" або "функцій", кожна з яких починається з >інструкції (Go Right) у стовпчику x = 0. Кожну "функцію" можна ідентифікувати за номером її рядка (y-координата). Функції можуть приймати вхід через стек Befunge , як зазвичай.

Рядок 0 є особливим, оскільки (0,0) є початковим IP. Щоб скласти програму, яка виконує рядок L, просто розмістіть інструкції на рядку 0, які, виконуючи їх, перетягують покажчик інструкцій на (x = L, y = 0).

Магія відбувається на рядку 1. Рядок 1, коли виконується, вискакує число Lзі стека та переходить на номер рядка L. (Цей рядок раніше був > >>0{{2u2}2}$-073*-\x, який може "абсолютний стрибок" до будь-якого рядка; але я просто зрозумів, що оскільки я знаю, що ця лінія прив’язана до рядка 1, ми можемо "відносно стрибати" L-1рядки в чорта набагато менше коду.)

Рядок 2 представляє Церкву FALSE. При виконанні він вискакує два числа tі fзі стека, а потім перелітає на номер рядка f.

Рядок 3 представляє Церкву TRUE. При виконанні він вискакує два числа tі fзі стека, а потім перелітає на номер рядка t.

Рядок 6, що представляє Церкву XOR, є інноваційним. Коли він виконаний, він вискакує два числа aта bзі стека, а потім летить у рядок aіз введенням стека NOT EXEC b. Отже, якщо aпредставляє Церкву TRUE, результат a NOT EXEC bволі буде NOT b; і якщо aпредставляє Церкву FALSE, результат a NOT EXEC bволі буде EXEC b.


Ось неперевершена версія з тестовим джгутом. У рядку 0 встановіть стек зі своїм входом. Наприклад, 338засоби IMPLIES TRUE TRUE. Переконайтесь, що закриття xвідображається рівно (x, y) = (0,15), інакше нічого не вийде! Також переконайтеся, що починається налаштування стека ba, щоб програма фактично закінчилася деяким результатом.

Спробуйте в Інтернеті!

>  ba 334  0f-1x
> >>1-0a-\x             Line 1: EXEC(x)(...) = goto x
> $^< <            <    Line 2: FALSE(t)(f)(...) = EXEC(f)(...)
> \$^                   Line 3: TRUE(t)(f)(...) = EXEC(t)(...)
> 3\^                   Line 4: OR(x)(y)(...) = EXEC(x)(TRUE)(y)(...)
> 3\2\^                 Line 5: NOT(x)(...) = EXEC(x)(FALSE)(TRUE)(...)
> 1\5\^                 Line 6: XOR(x)(y)(...) = EXEC(x)(NOT)(EXEC)(...)
> 2>24{\1u\1u\03-u}^    Line 7: AND(x)(y)(...) = EXEC(x)(y)(FALSE)(...)
> 3^                    Line 8: IMPLIES(x)(y)(...) = EXEC(x)(y)(TRUE)(...)

> "EURT",,,,@
> "ESLAF",,,,,@

Ось версія, чиї байти я порахував.

>>>1-0a-\x
>$^<< }u-30\<
>\$^
>3\^\
>3\2^
>1\5^
>2>24{\1u\1u^
>3^

Зауважте, що для визначення функції на цьому діалекті ви взагалі не згадуєте її ім'я; його "назва" визначається його джерелом розташування. Щоб викликати функцію, ви згадуєте її "ім'я"; наприклад, XOR( 6) визначається в термінах NOTі EXEC( 5і 1). Але всі мої "імена функцій" вже мають лише один байт для представлення. Таким чином, це рішення не отримує жодних коригувань.

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