Booleany kościelne
Kościół logiczna jest funkcją, która wraca x
do prawdziwego i y
fałszywego gdzie x
jest pierwszy argument funkcji i y
jest drugi argument funkcji. Dalsze funkcje mogą składać się z tych funkcji, które reprezentują and
not
or
xor
i implies
logicznych operacji.
Wyzwanie
Skonstruowania wartości logicznych i kościelnych and
not
or
xor
oraz implies
Church Gates w języku wyboru. and
or
i xor
powinien przyjąć dwie funkcje (reprezentujące boolean Kościoła) i zwrócić funkcję (reprezentującą inny boolean Kościoła). Podobnie, not
powinno odwrócić funkcję, którą przyjmuje, a implies
bramka powinna wykonać wartość logiczną, co oznacza logikę, w której pierwszy argument implies
jest drugim.
Punktacja
Łączna długość całego kodu wymaganego do utworzenia Kościoła true
oraz false
w twoim języku oraz bramek and
not
or
xor
i implies
Kościoła z wyłączeniem nazwy funkcji. (na przykład false=lambda x,y:y
w Pythonie byłoby 13 bajtów). Możesz użyć tych nazw później w swoim kodzie, licząc 1 bajt w sumie bajtów tej bramki.
Przykłady pseudokodu:
Utworzone funkcje powinny mieć możliwość późniejszego wywołania w kodzie.
true(x, y) -> x
false(x, y) -> y
and(true, true)(x, y) -> x
and(true, false)(x, y) -> y
# ... etc
źródło
true([x, y])
,and([true, true])([x, y])
)?Odpowiedzi:
Binary Lambda Calculus ,
13,87512,875 bajtów (103 bity)Binary Lambda Calculus Language (BLC) Johna Trompa jest w zasadzie wydajnym formatem serializacji dla rachunku lambda. Doskonale pasuje do tego zadania, ponieważ notacja kościelna jest nawet „idiomatycznym” sposobem pracy z booleanami w BLC.
Użyłem następujących funkcji lambda dla kombinatorów,
z których niektóre skopiowałem i grałem w golfa z odpowiedzi Haskella:które zostały znalezione przez wyczerpujące poszukiwanie z limitem dowodu wynoszącym 20 β-redukcji dla każdego przypadku. Istnieje duża szansa, że są one możliwie najkrótsze.Przekładają się one na następujące (binarne) sekwencje kodu BLC:
Powyższe funkcje mają w sumie
111 bitów (13,875 bajtów),103 bity długości (12,875 bajtów). Nie trzeba ich wyrównywać do granic bajtów, aby mogły być używane w programie, dlatego warto liczyć ułamkowe bajty.Ponowne użycie kodu między kombinatorami jest niemożliwe, ponieważ w BLC nie ma żadnych zmiennych / referencji / nazw - wszystko trzeba było skopiować. Mimo to wydajność kodowania stanowi dość zwięzłą reprezentację.
źródło
And: (\a \b a b a)
zadziała?\a \b a a b
. Jest jednak dłuższy niż ten, którego użyłem w BLC.Haskell , 50–6 = 44 bajty
-1 bajt dzięki Khuldraeseth na'Barya, a -1 bajt dzięki Christian Sievers.
Wypróbuj online!
źródło
Show
przypadki dlaconst
iconst id
i bezpośrednio wydrukować wartości logicznych kościelnych. Wypróbuj online! .a
można skrócić.f=n t
?t=pure
zamiastt=const
.t=pure
spowoduje błąd przy próbie zastosowaniaa
,o
,x
, lubi
do niego. Zadeklarowanie typut
naprawienia tego kosztuje więcej bajtów niż zwykłe użyciet=const
.Python 2 , (-3?)
10195 bajtówDavid Beazley zjedz swoje serce!
-6 dzięki Chasowi Brownowi (przeniesiono powtórzony
:
do tekstu łączenia>. <)Wypróbuj online!
Myślę, że może tak być,
95 - 3
ponieważ nie używam ponownie funkcjiA
,X
lubI
, ale używam jednego=
do przypisania (przedlambda
). Może nie mogę usunąć żadnego; może nawet uda mi się usunąć 3.5?źródło
exec
oznacza, że nie mogę? Widzę, że tak czy inaczej - nie używam ponownie A, X ani ja, ale kod nie działa bez nich. (Może uda mi się nawet usunąć 3.5 ?!)JavaScript (Node.js) ,
928683 - 7 = 76 bajtówWypróbuj online! Link zawiera podstawowe przypadki testowe. Edycja: Zapisano
69 bajtów dzięki @tsh.źródło
t
,f
,n
are used.t
,f
, andn
in your case).Python 2 ,
133 - 6 = 12794 bajtyWypróbuj online!
Bezwstydnie kradnie podstępny pomysł stojący za odpowiedzią Jonathana Allana ; nie odjęto jednak bajtów.
źródło
J, 67 bytes - 7 = 60
Try it online!
Worth noting:
Higher order functions work differently in J than in a functional language. To create a new verb from 1 or 2 existing verbs, you need to use either an adverb (in the case of 1) or a conjunction (in the case of 2).
Syntactically, adverbs come after a verb, and conjunctions go between them. Thus to "not" a verb
f
you dof n
, and to "and" verbsf
andg
, youf a g
.źródło
Wolfram Language (Mathematica), 61-7=54 bytes
Try it online!
un-golfed: inspired by Wikipedia,
źródło
Underload,
5652 bytesTry it online! (includes a testsuite and text identifying parts of the program)
This scores surprisingly well for a very low-level esolang. (Church numerals, Church booleans, etc. are very commonly used in Underload for this reason; the language doesn't have numbers and booleans built in, and this is one of the easier ways to simulate them. That said, it's also common to encode booleans as the Church numerals 0 and 1.)
For anyone who's confused: Underload lets you define reusable functions, but doesn't let you name them in the normal way, they just sort of float around on the argument stack (so if you define five functions and then want to call the first one you defined, you need to write a new function that takes five arguments and calls the fifth of them, then call it with insufficiently many arguments so that it looks for spare arguments to use). Calling them destroys them by default but you can modify the call to make it non-destructive (in simple cases, you just need to add a colon to the call, although the complex cases are more common because you need to make sure that the copies on the stack don't get in your way), so Underload's function support has all the requirements we'd need from the question.
Explanation
true
This one's fairly straightforward; we get rid of the argument we don't want and the argument we do want just stays there, serving as the return value.
false
This one's even more straightforward.
not
This one's fun:
not
doesn't call its argument at all, it just uses a function composition. This is a common trick in Underload, in which you don't inspect your data at all, you just change how it functions by pre- and post-composing things with it. In this case, we modify the function to swap its arguments before running, which clearly negates a Church numeral.and
Pytanie pozwala zdefiniować funkcje w kategoriach innych funkcji. Definiujemy „i” dalej, ponieważ im niedawno „nie” zostało zdefiniowane, tym łatwiej jest z niego korzystać. (Nie odejmuje się to od naszego wyniku, ponieważ w ogóle nie nazywamy „nie”, ale oszczędza bajty po ponownym zapisaniu definicji. Jest to jedyny raz, gdy jedna funkcja odnosi się do innej, ponieważ odnosi się do dowolnej funkcji ale ostatnio zdefiniowany kosztowałby zbyt wiele bajtów).
Oto definicja
and x y = (not x) false y
. Innymi słowy, jeślinot x
, to wrócimyfalse
; w przeciwnym razie wracamyy
.lub
@Nitrodon wskazał w komentarzach, które
or x y = x x y
są zwykle krótsze niżor x y = x true y
, i okazuje się, że jest to poprawne również w przypadku niedociążenia. Naiwna implementacja tego byłaby(:~^)
, ale możemy oderwać się od dodatkowego bajtu, zauważając, że nie ma znaczenia, czy uruchomimy oryginalny pierwszy argument, czy jego kopię, wynik jest taki sam w obu przypadkach.Niedociążenie nie obsługuje curry w zwykłym znaczeniu tego słowa, ale takie definicje sprawiają, że wygląda tak! (Sztuczka polega na tym, że niewykorzystane argumenty po prostu się trzymają, więc wywołana funkcja zinterpretuje je jako własne argumenty.)
implikuje
Stosowana tutaj definicja to
implies x y = not (y false x)
. Jeśli y jest prawdziwe, upraszcza tonot false
, tjtrue
. Jeśli y jest fałszywe, upraszcza tonot x
, dając nam tabelę prawdy, której chcemy.W tym przypadku używamy
not
ponownie, tym razem przepisując kod zamiast odwoływać się do niego. Jest napisany bezpośrednio, jak(~)~*
bez nawiasów wokół, więc jest wywoływany, a nie definiowany.Xor
Tym razem oceniamy tylko jeden z naszych dwóch argumentów i używamy go do ustalenia, co skomponować na drugim argumencie. Niedociążenie pozwala ci grać szybko i luźno z arity, więc używamy pierwszego argumentu, aby wybierać między dwiema dwuargumentowymi funkcjami z dwoma zwrotami; zamiana argumentów, która zwraca je obie, ale w odwrotnej kolejności, oraz funkcja tożsamości, która zwraca je obie w tej samej kolejności.
Gdy pierwszy argument jest prawdziwy, tworzymy zredagowaną wersję drugiego argumentu, który zamienia swoje argumenty przed uruchomieniem, tj. Wstępnie składa się z „argumentami zamiany”, tj
not
. Tak więc prawdziwy pierwszy argument oznacza, że zwracamynot
drugi argument. Z drugiej strony fałszywy pierwszy argument oznacza, że komponujemy z funkcją tożsamości, tzn. Nie robimy nic. Rezultatem jest wdrożeniexor
.źródło
or x y = x x y
oszczędza niektóre bajtyor x y = x true y
.Rubin, 82 - 4 = 78 bytes
Wypróbuj online!
źródło
Java 8, wynik:
360358319271233 (240–7) bajtówTo było trudniejsze do osiągnięcia, niż myślałem, kiedy go zaczynałem. ZwłaszczaEDIT: Ok, not re-using functions but just duplicating the same approach is a lot cheaper in terms of byte-count for Java.. And I get the full -7 bonus for not using any of the functions as well.implies
. W każdym razie to działa .. Prawdopodobnie można tu grać w golfa.Wypróbuj online.
Wyjaśnienie:
źródło
C++17,
207−49=158195 − 58 = 137 bytesThe linebreaks are unnecessary (other than the first two).
Try it online!
Unit-tested with assertions such as:
UPDATED: formerly I'd had
but Roman's answer pointed the way to the shorter version. Notice that now
not_(std::plus<>)
is ill-formed, where formerly it was equivalent tostd::plus<>
; but sincestd::plus<>
doesn't "represent a Church boolean," I think either behavior is okay by the rules.źródło
Forth (gforth),
133bytes - 7 =126122Try it online!
-4 bytes thanks to Quuxplusone
Initially I significantly overthought this, considering things like macros and literals, but then I realized that if I define things in terms of true and false (like I should have done in the first place), it gets much simpler.
Code explanation
źródło
execute
three times. Defining the shorthand: j execute ;
would save you 4 bytes.SKI-calculus + C combinator, 36 bytes
I don't actually know of any interpreter that allows you to define additional combinators in terms of previous ones, so I had to test this using http://ski.aditsu.net/ by pasting in the desired combinators e.g.
CCKK(SK)pq
outputsq
, showing thatK
does not implySK
.źródło
Julia 1.0, 36 bytes
I don't know if that counts, I'm actually just overloading the native
Bool
type to be callable, so I get most of the logic gates for free. Unfortunately, Julia doesn't have animplies
gate, so I had to write my own function.Try it online!
źródło
Perl 6,
120106102101 bytes-1 byte thanks to Jo King
Try it online!
źródło
C++17,
202−49=153193 − 58 = 135 bytesInspired by the comment-discussion of what counts as a 2-ary function anyway, here's a curried version of my previous C++17 solution. It's actually shorter because we can use the same macro to define
not_
as to define all the other functions!Try it online!
This one is tested with assertions like
Notice that
or_
is defined as effectivelyWe could define
or_
more "concisely" asbut that would cost us because we wouldn't get to use the
D
macro anymore.źródło
True
andFalse
instead oftrue_
andfalse_
? And similar for the other operators. That will save 12 bytes.APL (dzaima/APL), 47 bytesSBCS
Based on Jonah's J solution.
true
andfalse
are infix functions,not
is a suffix operator, and the rest are infix operators.As per OP, this counts everything from and including
←
to the end of each line, and counts each call a previous definition as a single byte.Try it online!
true and false are the left and right identity functions.
not
simply swaps the arguments of its operand function.The rest implement the decision tree:
and
uses the righthand function⍹
to select the result of the lefthand function⍶
if true, else the result of thefalse
function.or
uses the lefthand function⍶
to select thetrue
if true, else the result of the righthand function⍹
.xor
uses the righthand function⍹
to select the the negated result of the lefthand function⍶not
if true, else the result of the lefthand function.implies
uses the lefthand function⍶
to select the result of the righthand function⍹
if true, else the result of thetrue
function.źródło
Stax, 34 bytes
Run and debug it at staxlang.xyz!
Pushes a bunch of blocks to the stack. Each block expects its last argument atop the stack, followed in reverse order by the rest.
Unpacked (41 bytes):
Each pair of
{ }
is a block. I used the two registers X and Y to holdtrue
andnot
so I could access 'em easily later. Unfortunately,false
couldn't simply be a no-op, as that would leave the stack cluttered and mess up a single XOR case.Test suite, commented
źródło
Befunge-98,
1057765 bytesPlaying further with the notion of "function" in languages without functions... here's a Befunge-98 version of Church booleans!
In this constrained dialect of Befunge-98, a program consists of a series of "lines" or "functions," each of which begins with a
>
(Go Right) instruction in column x=0. Each "function" can be identified with its line number (y-coordinate). Functions can take input via Befunge's stack, as usual.Line 0 is special, because (0,0) is the starting IP. To make a program that executes line L, just place instructions on line 0 that, when executed, fly the instruction pointer to (x=L, y=0).
The magic happens on line 1. Line 1, when executed, pops a number
L
from the stack and jumps to line numberL
. (This line had previously been> >>0{{2u2}2}$-073*-\x
, which can "absolute jump" to any line; but I just realized that since I know this line is pegged to line 1, we can "relative jump"L-1
lines in a heck of a lot less code.)Line 2 represents Church
FALSE
. When executed, it pops two numberst
andf
from the stack and then flies to line numberf
.Line 3 represents Church
TRUE
. When executed, it pops two numberst
andf
from the stack and then flies to line numbert
.Line 6, representing Church
XOR
, is innovative. When executed, it pops two numbersa
andb
from the stack, and then flies to linea
with stack inputNOT EXEC b
. So, ifa
represents ChurchTRUE
, the result ofa NOT EXEC b
will beNOT b
; and ifa
represents ChurchFALSE
, the result ofa NOT EXEC b
will beEXEC b
.Here's the ungolfed version with test harness. On line 0, set up the stack with your input. For example,
338
meansIMPLIES TRUE TRUE
. Make sure the closingx
appears at exactly (x,y)=(0,15) or else nothing will work! Also make sure your stack setup begins withba
, so that the program will actually terminate with some output.Try it online!
Here's the version whose bytes I counted.
Notice that to define a function in this dialect you don't mention its name at all; its "name" is determined by its source location. To call a function, you do mention its "name"; for example,
XOR
(6
) is defined in terms ofNOT
andEXEC
(5
and1
). But all my "function names" already take only one byte to represent. So this solution gets no scoring adjustments.źródło