Boolesche Kirche
Ein Church-Boolescher Wert ist eine Funktion, die x
für wahr und y
für falsch zurückgibt, wobei x
das erste Argument für die Funktion und y
das zweite Argument für die Funktion ist. Aus diesen Funktionen können weitere Funktionen zusammengestellt werden, die die and
not
or
xor
und implies
logischen Operationen darstellen.
Herausforderung
Konstruieren Sie die Kirche booleans und and
not
or
xor
und implies
Kirche Tore in einer Sprache Ihrer Wahl. and
or
und xor
sollte zwei Funktionen übernehmen (die Boolesche Werte der Kirche darstellen) und eine Funktion zurückgeben (die einen anderen Booleschen Wert der Kirche darstellt). In gleicher Weise not
sollte die Funktion invertiert werden, und das implies
Gate sollte eine boolesche Logik ausführen, bei der das erste Argument implies
das zweite ist.
Wertung
Die Gesamtlänge der gesamten Code erforderlich ist, um Kirche zu machen true
und false
in Ihrer Sprache und die and
not
or
xor
und implies
Kirche Tore ohne die Namen der Funktion. (Zum Beispiel false=lambda x,y:y
in Python wären das 13 Bytes). Sie können diese Namen später in Ihrem Code wiederverwenden, indem Sie 1 Byte für die Bytesumme dieses Gatters zählen.
Pseudocode-Beispiele:
Die von Ihnen erstellten Funktionen sollten später in Ihrem Code so aufgerufen werden können.
true(x, y) -> x
false(x, y) -> y
and(true, true)(x, y) -> x
and(true, false)(x, y) -> y
# ... etc
quelle
true([x, y])
,and([true, true])([x, y])
)?Antworten:
Binäre Lambda-
Rechnung,13,875 -12,875 Byte (103 Bit)Binary Lambda Calculus Language (BLC) von John Tromp ist im Grunde ein effizientes Serialisierungsformat für Lambda-Kalkül. Es passt hervorragend zu dieser Aufgabe, da die Notation der Kirche sogar die "idiomatische" Art ist, mit Booleschen in BLC zu arbeiten.
Ich habe die folgenden Lambda-Funktionen für die Kombinatoren verwendet,
von denen ich einige aus der Haskell-Antwort kopiert und golfen habe:, diedurch eine erschöpfende Suche mit einer Beweisgrenze von 20 β-Reduktionen für jeden Fall gefunden wurden. Es besteht eine gute Chance, dass dies der kürzeste Weg ist.Diese übersetzen in die folgenden (binären) BLC-Codesequenzen:
Die obigen Funktionen sind insgesamt
111 Bits lang (13,875 Bytes) und103 Bits lang (12,875 Bytes). Sie müssen nicht an Byte-Grenzen ausgerichtet sein, um in einem Programm verwendet zu werden. Daher ist es sinnvoll, gebrochene Bytes zu zählen.Es gibt keine Wiederverwendung von Code zwischen den Kombinatoren, da es in BLC keine Variablen / Referenzen / Namen gibt - alles musste kopiert werden. Die Effizienz der Codierung sorgt jedoch für eine recht knappe Darstellung.
quelle
And: (\a \b a b a)
funktionieren?\a \b a a b
. Es ist jedoch länger als das, was ich in BLC verwendet habe.Haskell , 50 - 6 = 44 Bytes
-1 Byte dank Khuldraeseth na'Barya und -1 Byte dank Christian Sievers.
Probieren Sie es online!
quelle
Show
Instanzen fürconst
und definierenconst id
und die Booleschen Werte der Kirche direkt drucken. Probieren Sie es online! .a
kann gekürzt werden.f=n t
?t=pure
anstelle von verwendent=const
.t=pure
tritt ein Fehler auf, wenn ich versuche zu beantragena
,o
,x
, oder ,i
um es. Die Angabe der Art dert
Fehlerbehebung kostet mehr Byte als nur die Verwendungt=const
.Python 2 (-3?)
10195 BytesDavid Beazley frisst dein Herz raus!
-6 danke an Chas Brown (verschob die wiederholte
:
in den Join-Text>. <)Probieren Sie es online!
Ich denke , es könnte sein ,
95 - 3
weil ich die Funktionen nicht wiederverwendet werdenA
,X
oderI
, aber ich benutze eine einzige=
für die Zuweisung (vorlambda
). Vielleicht kann ich keine entfernen; vielleicht bekomme ich ja 3.5 zu entfernen?quelle
exec
nicht? Ich sehe, dass es in beide Richtungen geht - ich verwende A, X oder I nicht wieder, aber der Code funktioniert ohne sie nicht. (Vielleicht kann ich sogar 3.5 entfernen ?!)JavaScript (Node.js) ,
928683 - 7 = 76 ByteProbieren Sie es online! Link enthält grundlegende Testfälle. Bearbeiten:
69 Bytes dank @tsh gespeichert.quelle
t
,f
,n
verwendet.t
,f
, undn
in Ihrem Fall).Python 2 ,
133 - 6 = 12794 BytesProbieren Sie es online!
Schamlos die hinter Jonathan Allans Antwort verborgene Idee stehlen ; Es werden jedoch keine Bytes abgezogen.
quelle
J , 67 Bytes - 7 = 60
Probieren Sie es online!
Nichts wert:
Funktionen höherer Ordnung arbeiten in J anders als in einer funktionalen Sprache. Um ein neues Verb aus 1 oder 2 vorhandenen Verben zu erstellen, müssen Sie entweder ein Adverb (im Fall von 1) oder eine Konjunktion (im Fall von 2) verwenden.
Syntaktisch folgen Adverbien auf ein Verb, und Konjunktionen werden zwischen ihnen gesetzt. Also zu "nicht" einem Verb, das
f
du tustf n
, und zu "und" Verbenf
undg
dirf a g
.quelle
Wolfram Language (Mathematica) , 61-7 = 54 Bytes
Probieren Sie es online!
ungegolft: inspiriert von Wikipedia ,
quelle
Unterlast ,
5652 BytesProbieren Sie es online! (enthält eine Testsuite und einen Text, der Teile des Programms identifiziert)
Dies ist überraschend gut für einen sehr niedrigen Esolang. (Church-Zahlen, Church-Boolesche Werte usw. werden in Underload aus diesem Grund sehr häufig verwendet. In der Sprache sind keine Zahlen und Boolesche Werte integriert, und dies ist eine der einfacheren Möglichkeiten, sie zu simulieren. Dies gilt auch für Kodieren Sie Boolesche Werte mit den Ziffern 0 und 1.)
Für alle, die verwirrt sind: Unter Last können Sie wiederverwendbare Funktionen definieren, aber nicht wie gewohnt benennen. Sie schweben einfach auf dem Argumentenstapel herum (wenn Sie also fünf Funktionen definieren und dann die erste aufrufen möchten) Sie haben definiert, dass Sie eine neue Funktion schreiben müssen, die fünf Argumente akzeptiert und das fünfte von ihnen aufruft. Rufen Sie sie dann mit unzureichend vielen Argumenten auf, damit sie nach zu verwendenden Ersatzargumenten sucht. Wenn Sie sie aufrufen, werden sie standardmäßig zerstört, aber Sie können den Aufruf so ändern, dass er nicht destruktiv ist (in einfachen Fällen müssen Sie dem Aufruf nur einen Doppelpunkt hinzufügen, obwohl die komplexen Fälle häufiger vorkommen, da Sie sicherstellen müssen, dass die Kopien vorhanden sind auf dem Stack nicht stören), so dass die Funktionsunterstützung von Underload alle Anforderungen hat, die wir aus der Frage heraus benötigen würden.
Erläuterung
wahr
Das ist ziemlich einfach; Wir werden das Argument los, das wir nicht wollen, und das Argument, das wir wollen, bleibt einfach da und dient als Rückgabewert.
falsch
Das ist noch einfacher.
nicht
Das macht Spaß:
not
Nennt das Argument überhaupt nicht, sondern verwendet nur eine Funktionskomposition. Dies ist ein allgemeiner Trick in Underload, bei dem Sie Ihre Daten überhaupt nicht überprüfen, sondern lediglich die Funktionsweise ändern, indem Sie die Dinge vor und nach dem Komponieren damit bearbeiten. In diesem Fall ändern wir die Funktion, um ihre Argumente vor der Ausführung auszutauschen, wodurch eine Kirchennummer eindeutig negiert wird.und
Die Frage erlaubt die Definition von Funktionen in Bezug auf andere Funktionen. Wir definieren "und" als nächstes, weil es umso einfacher ist, es zu verwenden, je neuer "nicht" definiert wurde. (Dies subtrahiert nicht von unserer Punktzahl, da wir überhaupt nicht "nicht" benennen, sondern es werden Bytes gespart, wenn die Definition erneut geschrieben wird. Dies ist das einzige Mal, dass eine Funktion auf eine andere verweist, da sie sich auf eine Funktion bezieht aber die zuletzt definierte würde zu viele Bytes kosten.)
Die Definition hier ist
and x y = (not x) false y
. Mit anderen Worten, wennnot x
, dann kehren wir zurückfalse
. ansonsten kehren wir zurücky
.oder
@Nitrodon hat in den Kommentaren darauf hingewiesen, dass dies
or x y = x x y
normalerweise kürzer ist alsor x y = x true y
und dass es sich auch bei Unterlast als richtig herausstellt. Eine naive Umsetzung wäre das(:~^)
, aber wir können ein zusätzliches Byte herausholen, indem wir feststellen, dass es egal ist, ob wir das ursprüngliche erste Argument oder die Kopie davon ausführen, das Ergebnis ist in beiden Fällen dasselbe.Unterlast unterstützt eigentlich nicht das Curry im üblichen Sinne, aber Definitionen wie diese lassen es so aussehen wie es ist! (Der Trick besteht darin, dass nicht konsumierte Argumente einfach herumstehen und von der aufgerufenen Funktion als eigene Argumente interpretiert werden.)
impliziert
Die hier verwendete Definition ist
implies x y = not (y false x)
. Wenn y wahr ist, vereinfacht sich dies zunot false
, dhtrue
. Wenn y falsch ist, vereinfacht sich diesnot x
und gibt uns die gewünschte Wahrheitstabelle.In diesem Fall verwenden wir
not
dieses Mal erneut, indem wir den Code neu schreiben, anstatt ihn zu referenzieren. Es wird direkt geschrieben,(~)~*
ohne Klammern, es wird also eher aufgerufen als definiert.xor
Dieses Mal werten wir nur eines unserer beiden Argumente aus und verwenden es, um zu bestimmen, woraus das zweite Argument bestehen soll. Mit Unterlast können Sie schnell und locker mit Arity spielen. Daher verwenden wir das erste Argument, um zwischen zwei Funktionen mit zwei Argumenten und zwei Rückgabewerten zu wählen. das Argument swap, das beide in umgekehrter Reihenfolge zurückgibt, und die Identitätsfunktion, die beide in derselben Reihenfolge zurückgibt.
Wenn das erste Argument wahr ist, erzeugen wir daher eine bearbeitete Version des zweiten Arguments, die ihre Argumente vor dem Ausführen austauscht, dh mit "Swap-Argumenten" vorkomponiert, dh
not
. Ein wahres erstes Argument bedeutet also, dass wirnot
das zweite Argument zurückgeben. Andererseits bedeutet ein falsches erstes Argument, dass wir mit der Identitätsfunktion komponieren, dh nichts tun. Das Ergebnis ist eine Implementierung vonxor
.quelle
or x y = x x y
spart einige Bytes überor x y = x true y
.Ruby , 82 - 4 = 78 Bytes
Probieren Sie es online!
quelle
Java 8, Score:
360358319271233 (240-7) BytesDies war schwieriger zu erreichen, als ich dachte, als ich damit anfingBEARBEITEN: Ok, Funktionen nicht wiederzuverwenden, sondern nur den gleichen Ansatz zu duplizieren, ist in Bezug auf die Byteanzahl für Java viel billiger. Und ich bekomme den vollen Bonus von -7, wenn ich keine der Funktionen ebenfalls benutze.implies
. Wie auch immer, es funktioniert .. Kann wahrscheinlich ein bisschen hier und da golfen werden.Probieren Sie es online aus.
Erläuterung:
quelle
C ++ 17,
207-49 = 158195 - 58 = 137 BytesDie Zeilenumbrüche sind nicht erforderlich (außer den ersten beiden).
Probieren Sie es online!
Unit-getestet mit Behauptungen wie:
AKTUALISIERT: Früher hatte ich gehabt
aber die Antwort von Roman wies den Weg zur kürzeren Version. Beachten Sie, dass jetzt
not_(std::plus<>)
schlecht geformt ist, wo es früher äquivalent warstd::plus<>
; aber dastd::plus<>
es keinen "Church Boolean" darstellt, denke ich, dass beide Verhaltensweisen den Regeln entsprechen.quelle
Forth (gforth) ,
133Bytes - 7 =126122Probieren Sie es online!
-4 Bytes dank Quuxplusone
Anfangs habe ich dies deutlich überlegt, unter Berücksichtigung von Makros und Literalen, aber dann wurde mir klar, dass es viel einfacher wird, wenn ich Dinge in Bezug auf wahr und falsch definiere (wie ich es eigentlich hätte tun sollen).
Code Erklärung
quelle
execute
dreimal. Wenn Sie die Kurzschrift definieren: j execute ;
, sparen Sie 4 Bytes.SKI-Kalkül + C-Kombinator, 36 Bytes
Ich kenne eigentlich keinen Interpreter, mit dem Sie zusätzliche Kombinatoren in Bezug auf vorherige definieren können. Deshalb musste ich dies mit http://ski.aditsu.net/ testen, indem ich die gewünschten Kombinatoren, z. B.
CCKK(SK)pq
Ausgabenq
, einfügte , um dies zu zeigenK
impliziert nichtSK
.quelle
Julia 1.0 , 36 Bytes
Ich weiß nicht, ob das zählt, ich überlade eigentlich nur den nativen
Bool
Typ, um aufrufbar zu sein, also bekomme ich die meisten Logikgatter kostenlos.implies
Da Julia leider kein Tor hat, musste ich meine eigene Funktion schreiben.Probieren Sie es online!
quelle
Perl 6 ,
120106102101 Bytes-1 Byte danke an Jo King
Probieren Sie es online!
quelle
C ++ 17,
202-49 = 153193 - 58 = 135 BytesInspiriert von der Kommentardiskussion darüber, was ohnehin als 2-stellige Funktion gilt, hier ein Curry Version meiner vorherigen C ++ 17-Lösung. Es ist tatsächlich kürzer, weil wir das gleiche Makro zum Definieren verwenden können
not_
, um alle anderen Funktionen zu definieren!Probieren Sie es online!
Dieser wird mit Behauptungen wie getestet
Beachte das
or_
als effektiv definiert istWir könnten definieren
or_
"prägnanter" definieren alsaber das würde uns kosten, weil wir das
D
Makro nicht mehr benutzen würden .quelle
True
undFalse
anstelle vontrue_
und, da C ++ zwischen Groß- und Kleinschreibung unterscheidetfalse_
? Ähnliches gilt für die anderen Betreiber. Das spart 12 Bytes.APL (dzaima / APL) , 47 Byte SBCS
Beyogen auf Jonahs J-Lösung .
true
undfalse
sind Infix-Funktionen,not
sind Suffix-Operatoren und der Rest sind Infix-Operatoren.Gemäß OP zählt dies alles von und
←
bis zum Ende jeder Zeile und zählt jeden Aufruf einer vorherigen Definition als ein einzelnes Byte.Probieren Sie es online!
wahr und falsch sind die linken und rechten Identitätsfunktionen.
not
tauscht einfach die Argumente seiner Operandenfunktion aus.Der Rest implementiert den Entscheidungsbaum:
and
Verwendet die rechte Funktion⍹
, um das Ergebnis der linken Funktion auszuwählen,⍶
wenn true, andernfalls das Ergebnis derfalse
Funktion.or
Verwendet die Funktion⍶
für die linke Hand , um "true
wenn wahr" auszuwählen , andernfalls das Ergebnis der Funktion für die rechte Hand⍹
.xor
Verwendet die rechte Funktion⍹
, um das negierte Ergebnis der linken Funktion auszuwählen,⍶not
wenn true, sonst das Ergebnis der linken Funktion.implies
Verwendet die Funktion⍶
für die linke Hand , um das Ergebnis der Funktion für die rechte Hand auszuwählen,⍹
wenn dies wahr ist, andernfalls das Ergebnis dertrue
Funktion.quelle
Stax , 34 Bytes
Führen Sie es aus und debuggen Sie es unter staxlang.xyz!
Schiebt eine Reihe von Blöcken auf den Stapel. Jeder Block erwartet sein letztes Argument auf dem Stapel, gefolgt von dem Rest in umgekehrter Reihenfolge.
Entpackt (41 Bytes):
Jedes Paar
{ }
ist ein Block. Ich benutzte die zwei Register X und Y, um sie zu haltentrue
undnot
so konnte ich später leicht auf sie zugreifen. Unglücklicherweise,false
konnte es nicht einfach ein No-Op sein, da dies den Stapel überladen und einen einzelnen XOR-Fall durcheinander bringen würde.Testsuite, kommentiert
quelle
Befunge-98 ,
1057765 BytesWeiter spielen mit dem Begriff "Funktion" in Sprachen ohne Funktionen ... hier ist eine Befunge-98-Version von Church Booleans!
In diesem eingeschränkten Dialekt von Befunge-98 besteht ein Programm aus einer Reihe von "Zeilen" oder "Funktionen", von denen jede mit einer
>
(Go Right) -Anweisung in Spalte x = 0 beginnt . Jede "Funktion" kann mit ihrer Zeilennummer (y-Koordinate) identifiziert werden. Funktionen können über Befunges Stack eingegeben werden wie gewohnt .Zeile 0 ist etwas Besonderes, da (0,0) die Start-IP ist. Um ein Programm zu erstellen, das Zeile L ausführt, platzieren Sie einfach Anweisungen in Zeile 0, die, wenn sie ausgeführt werden, den Anweisungszeiger auf (x = L, y = 0) bewegen.
Die Magie geschieht in Zeile 1. Zeile 1 gibt bei der Ausführung eine Zahl aus
L
vom Stapel und springt zur ZeilennummerL
. (Diese Zeile war zuvor eine> >>0{{2u2}2}$-073*-\x
, die zu jeder Zeile "absolut springen" kann. Da ich jedoch weiß, dass diese Zeile an Zeile 1 gebunden ist, können wirL-1
Zeilen in einer Menge weniger Code "relativ springen" .)Zeile 2 steht für Kirche
FALSE
. Bei der Ausführung werden zwei Zahlent
undf
vom Stapel abgerufen und dann zur Zeilennummer geflogenf
.Zeile 3 steht für Kirche
TRUE
. Wenn er ausgeführt wird , erscheint es zwei Zahlent
undf
aus dem Stapel und dann fliegt nach Zeilennummert
.Linie 6, die die Kirche repräsentiert
XOR
, ist innovativ. Wenn es ausgeführt wird, werden zwei Zahlena
undb
vom Stapel abgerufen und dann zur Zeilea
mit der Stapeleingabe geflogenNOT EXEC b
. Wenn alsoa
die Kirche repräsentiertTRUE
, ist das Ergebnis desa NOT EXEC b
WillensNOT b
; und wenna
repräsentiert KircheFALSE
, ist das Ergebnis desa NOT EXEC b
WillensEXEC b
.Hier ist die ungolfed Version mit Testgeschirr. Richten Sie in Zeile 0 den Stack mit Ihrer Eingabe ein. Zum Beispiel
338
bedeutetIMPLIES TRUE TRUE
. Stellen Sie den Verschluss sicherx
genau (x, y) = (0,15) ist, sonst funktioniert nichts! Stellen Sie außerdem sicher, dass Ihre Stapelkonfiguration mit beginntba
, damit das Programm tatsächlich mit einer Ausgabe beendet wird.Probieren Sie es online!
Hier ist die Version, deren Bytes ich gezählt habe.
Beachten Sie, dass Sie zum Definieren einer Funktion in diesem Dialekt den Namen überhaupt nicht erwähnen. Sein "Name" wird durch seinen Ursprungsort bestimmt. Um eine Funktion aufzurufen, geben Sie ihren "Namen" an. Zum Beispiel wird
XOR
(6
) durchNOT
undEXEC
(5
und1
) definiert. Aber alle meine "Funktionsnamen" benötigen bereits nur ein Byte, um dargestellt zu werden. Diese Lösung erhält also keine Bewertungsanpassungen.quelle