Booléens d'église

33

Booléens d'église

Un booléen d'église est une fonction qui retourne xpour vrai et ypour faux où xest le premier argument de la fonction et yle second argument de la fonction. D' autres fonctions peuvent être composées de ces fonctions qui représentent les and not or xoret impliesopérations logiques.

Défi

Construire les booléens Eglise et and not or xoret impliesportes Eglise dans une langue de votre choix. and oret xordoit assumer deux fonctions (représentant les booléens de l’Eglise) et rendre une fonction (représentant un autre booléen de l’Eglise). De même, notdevrait inverser la fonction qu'il prend et la impliesporte devrait effectuer booléen implique logique où le premier argument impliesle second.

Notation

La longueur totale de tout le code nécessaire pour faire Église trueet falsedans votre langue et and not or xoret impliesportes Eglise à l' exception du nom de la fonction. (par exemple, false=lambda x,y:yen Python, ce serait 13 octets). Vous pouvez réutiliser ces noms plus tard dans votre code, en comptant 1 octet pour le total en octets de cette porte.

Exemples de pseudo-codes:

Les fonctions que vous créez devraient pouvoir être appelées plus tard dans votre code, comme ceci.

true(x, y) -> x
false(x, y) -> y
and(true, true)(x, y) -> x
and(true, false)(x, y) -> y
# ... etc
Ryan Schaefer
la source
2
Devons-nous traiter les entrées de fonction (ou les substituts les plus proches) comme des fonctions de boîte noire, ou pouvons-nous inspecter le code à l'intérieur? Et les valeurs de retour des opérations logiques doivent-elles être les mêmes fonctions que celles définies précédemment par les booléens de l'Église, ou peuvent-elles être quelque chose d'autre qui fait la même chose?
Chaîne non
1
@ JonathanAllan Je l'ai édité, donc c'était correct. L'invite est comme il se doit maintenant.
Ryan Schaefer
2
Pouvons-nous prendre des listes comme arguments (par exemple true([x, y]), and([true, true])([x, y]))?
Ar4093
2
@RyanSchaefer Je pense que vous devriez reconsidérer la possibilité de placer les arguments dans une liste ordonnée, car on pourrait simplement envelopper les arguments au début des solutions. Je ne pense pas que cela exige quelque chose pour améliorer ce défi (en fait, je pense que cela limite un potentiel de golf intéressant). Bien sûr, ce n’est que mon opinion et c’est bien si vous n’êtes pas d’accord.
FryAmTheEggman
1
La notation est plutôt déroutante. Ne serait-il pas préférable de laisser les gens soumettre des fonctions anonymes, mais s'ils les utilisent ailleurs, ils doivent les assigner, comme d'habitude
Jo King

Réponses:

14

Lambda Calculus binaire , 13,875 12,875 octets (103 bits)

Le langage de calcul lambda binaire (BLC) de John Tromp est à la base un format de sérialisation efficace pour le calcul lambda. Cela convient parfaitement à cette tâche, car la notation de l'Église est même la façon "idiomatique" de travailler avec des booléens dans BLC.

J'ai utilisé les fonctions lambda suivantes pour les combinateurs, dont certaines ont été copiées et reproduites dans la réponse de Haskell:, qui ont été trouvées par une recherche exhaustive avec une limite de preuve de 20 β-réductions pour chaque cas. Il y a de fortes chances pour que celles-ci soient les plus courtes possibles.

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

Celles-ci traduisent les séquences de code BLC suivantes (binaires):

 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

Les fonctions ci-dessus ont une longueur totale de 111 bits (13,875 octets) et de 103 bits (12,875 octets). Ils n'ont pas besoin d'être alignés sur les limites d'octet pour être utilisés dans un programme, il est donc logique de compter des octets fractionnaires.

Il n'y a pas de réutilisation de code entre les combinateurs, car il n'y a pas de variables / références / noms dans BLC - tout devait être copié. Reste que l'efficacité de l'encodage donne une représentation assez succincte.

Pavel Potoček
la source
1
Je ne sais pas bc, mais ça va And: (\a \b a b a)marcher?
tsh
Oui cela fonctionne. J'ai effectivement utilisé cette formule pour mes séquences de code. J'ai juste oublié de mettre à jour la fonction lambda correspondante (maintenant corrigée). La fonction équivalente fonctionne pour ou: \a \b a a b. C'est plus long que celui que j'ai utilisé dans BLC cependant.
Pavel Potoček
25

Haskell , 50 - 6 = 44 octets

-1 octet grâce à Khuldraeseth na'Barya et -1 octet à Christian Sievers.

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

Essayez-le en ligne!

Nitrodon
la source
2
Note côté: vous pouvez définir des Showinstances pour constet const idet imprimer directement l'église booléens. Essayez-le en ligne! .
nimi
apeut être raccourci.
Khuldraeseth na'Barya
4
Pourquoi personne n'utilise f=n t?
Christian Sievers
3
Vous pouvez enregistrer un octet en utilisant à la t=pureplace de t=const.
Joseph Sible-Rétablir Monica
4
@JosephSible J'ai essayé cela au départ. Malheureusement, t=pureprovoquera une erreur lorsque je tente d'appliquer a, o, xou ià elle. Déclarer le type de trésoudre ce problème coûte plus d'octets que simplement utiliser t=const.
Nitrodon
9

Python 2 , (-3?)  101  95 octets

David Beazley dévore votre coeur!

-6 grâce à Chas Brown (déplacé le répété :dans le texte de jointure>. <)

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

Essayez-le en ligne!

Je pense que c'est peut-être 95 - 3parce que je ne réutilise pas les fonctions A, Xou I, mais j'en utilise une seule =pour l'affectation (devant lambda). Peut-être que je ne peux pas en enlever peut-être que je parviens même à supprimer 3.5?

Jonathan Allan
la source
@Ryan Schaefer puis-je supprimer trois ou est-ce que mon utilisation execsignifie que je ne peux pas? Je peux voir aller dans les deux sens - je ne réutilise pas A, X ou moi, mais le code ne fonctionnera pas sans eux. (Peut-être que je pourrai même enlever 3,5?!)
Jonathan Allan
Merci @Chas! Le colon qui a glissé à travers le filet :) Bon travail pour remplacer -1 BTW
Jonathan Allan
7

JavaScript (Node.js) , 92 86 83 - 7 = 76 octets

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)

Essayez-le en ligne! Le lien inclut des cas de test de base. Edit: 6 9 9 octets enregistrés grâce à @tsh.

Neil
la source
1
Semble vous ne pouvez pas demander ce que -7 depuis t, f, nsont utilisés.
tsh
1
@tsh Ce n'est pas comme ça que je comprends le système de notation; il exclut explicitement le nom dans la définition, bien que le nom utilisé dans l'utilisation coûte 1 octet.
Neil
@Neil vous ne pouvez pas demander la remise d'octets pour les noms de fonctions qui sont appelés par votre code ( t, fet ndans votre cas).
asgallant
2
@asgallant no. Il n'y a pas d'octets pour le nom et 1 octet quand il sera utilisé plus tard. 'T fnaox i' ne contient pas d'octets, puis 1 octet lorsqu'il est utilisé ultérieurement. Je voulais améliorer la lisibilité, mais je me rends compte maintenant que j'aurais dû le laisser entièrement joué et qu'il est trop tard pour le changer maintenant
Ryan Schaefer
@RyanSchaefer où est cette règle? Je ne l'ai jamais vu faire comme ça.
asgallant
6

Python 2 , 133 - 6 = 127 94 octets

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:')

Essayez-le en ligne!

Volant sans vergogne l'idée sournoise derrière la réponse de Jonathan Allan ; pas d'octets déduits cependant.

Chas Brown
la source
J'allais répondre à ma propre question mais je ne savais pas si cela était autorisé et je pense que cela va à l’encontre de son esprit. Je pense donc que je vais simplement vous guider à la place. Au lieu d'utiliser des listes, pouvez-vous utiliser les fonctions saisies elles-mêmes et la manière spécifique avec laquelle elles renvoient leurs entrées pour raccourcir le code?
Ryan Schaefer
Je parierais que même si la réponse est oui, ce serait beaucoup plus long en Python.
Unrelated String
Je suis corrigé
Non liée String
@ Mr.Xcoder vous avez raison, j'avais le mauvais nombre d'octets pour la fonction exemple. Ils seraient toutefois autorisés à supprimer 6 octets pour les noms des fonctions.
Ryan Schaefer
@M. Xcoder: Modifié selon vos observations.
Chas Brown
4

J , 67 octets - 7 = 60

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

Essayez-le en ligne!

À noter:

Les fonctions d'ordre supérieur fonctionnent différemment en J que dans un langage fonctionnel. Pour créer un nouveau verbe à partir de 1 ou 2 verbes existants, vous devez utiliser soit un adverbe (dans le cas de 1), soit une conjonction (dans le cas de 2).

Syntaxiquement, les adverbes viennent après un verbe et les conjonctions vont entre eux. Ainsi, pour "pas" un verbe que fvous faites f n, et pour "et" les verbes fet gvous f a g.

Jonas
la source
4

Wolfram Language (Mathematica) , 61-7 = 54 octets

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

Essayez-le en ligne!

non-golfé: inspiré par Wikipedia ,

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]
romain
la source
Je suis sûr que les nouvelles lignes sont nécessaires pour séparer les définitions de fonctions. De plus, vous faites référence à tf et n dans d’autres définitions de fonctions afin que vous ne puissiez pas déduire celles-ci, donc 61-4 = 57.
Jonathan Allan
@ JonathanAllan J'ai relu les instructions de notation et suis d'accord pour dire que les nouvelles lignes doivent compter, merci. Je ne suis pas d’accord avec votre deuxième partie: lorsque je réutilise les noms, je les considère effectivement comme "1 octet vers le total d'octets de cette porte", ce qui est implicite ici, dans le cas où j'utilise des noms à 1 octet. D'après mon interprétation des instructions, il n'est pas question de les compter ensuite comme un octet dans le total de la définition d'origine. Je vais donc avec N-7 octets. En outre, un autre commentaire de l'OP clarifie: "Il n'y a pas d'octet pour le nom et 1 octet quand il sera utilisé plus tard."
Roman
J'ai lu "1 octet plus tard" comme signifiant que l'utilisation dans une autre fonction coûte un octet. Cela correspond à la façon dont les autres ont également marqué.
Jonathan Allan
@JonathanAllan Je suis moins intéressé par l'exégèse et plus par le code de golf 😀
Roman
4

Sous-charge , 56 52 octets

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

Essayez-le en ligne! (comprend une suite de tests et un texte identifiant des parties du programme)

Cela marque étonnamment bien pour un esolang de très bas niveau. (Les chiffres, les booléens, etc. de l’Église, sont très couramment utilisés dans Underload pour cette raison; la langue n’a pas de chiffres et de booléens intégrés, et c’est l’un des moyens les plus faciles de les simuler. Cela dit, il est également commun à coder les booléens en chiffres 0 et 1)

Pour ceux qui sont confus: Underload vous permet de définir des fonctions réutilisables, mais ne vous permet pas de les nommer de la manière habituelle, ils flottent simplement sur la pile d'arguments (donc si vous définissez cinq fonctions et souhaitez ensuite appeler la première) vous avez défini, vous devez écrire une nouvelle fonction qui prend cinq arguments et appelle le cinquième d’entre eux, puis l’appeler avec un nombre insuffisant d’arguments pour qu’elle recherche les arguments de réserve à utiliser). Les appeler les détruit par défaut, mais vous pouvez modifier l'appel pour le rendre non destructif (dans les cas simples, il suffit d'ajouter deux points à l'appel, bien que les cas complexes soient plus courants, car vous devez vous assurer que les copies sur la pile ne vous gênez pas), le support de fonction de Underload a donc toutes les exigences de la question.

Explication

vrai

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

Celui-ci est assez simple; nous nous débarrassons de l'argument que nous ne voulons pas et l'argument que nous voulons ne fait que subsister, servant de valeur de retour.

faux

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

Celui-ci est encore plus simple.

ne pas

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

Celui-ci est amusant: notn'appelle pas son argument du tout, il utilise simplement une composition de fonction. C'est une astuce courante dans Underload, dans laquelle vous n'inspectez pas vos données, vous changez simplement la façon dont elles fonctionnent, en pré-et post-composant des éléments avec. Dans ce cas, nous modifions la fonction pour échanger ses arguments avant l'exécution, ce qui annule clairement un chiffre d'église.

et

:((!)~^)*
 (     )   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

La question permet de définir des fonctions en fonction d'autres fonctions. Nous définissons "et" ensuite parce que plus récemment "non" a été défini, plus il est facile de l’utiliser. (Cela ne soustrait pas de notre partition, parce que nous ne nommons pas du tout "non", mais cela économise des octets au lieu de réécrire la définition. C’est le seul moment où une fonction se réfère à une autre, car faisant référence à une fonction mais la dernière définition coûterait trop d'octets.)

La définition ici est and x y = (not x) false y. En d'autres termes, si not x, alors nous revenons false; sinon, nous revenons y.

ou

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

@Nitrodon a souligné dans les commentaires qu'il or x y = x x yest normalement plus court que or x y = x true y, et que cela s'avère également correct en sous-charge. Une mise en œuvre naïve de ce principe serait (:~^), mais nous pouvons utiliser un octet supplémentaire en notant que peu importe que nous utilisions le premier argument original ou sa copie, le résultat est le même dans les deux cas.

La sous-charge ne prend pas réellement en charge le currying au sens habituel du terme, mais des définitions comme celle-ci lui donnent l’impression! (Le truc, c’est que les arguments non consommés restent collés, donc la fonction que vous appelez les interprétera comme ses propres arguments.)

implique

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

La définition utilisée ici est implies x y = not (y false x). Si y est vrai, cela se simplifie not false, c'est- à -dire true. Si y est faux, cela se simplifie not x, nous donnant ainsi la table de vérité que nous voulons.

Dans ce cas, nous utilisons à notnouveau, cette fois en réécrivant son code plutôt que de le référencer. C'est juste écrit directement comme (~)~*sans parenthèses, donc il est appelé plutôt que défini.

xor

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

Cette fois-ci, nous n'évaluons qu'un seul de nos deux arguments et nous l'utilisons pour déterminer la composition du second argument. Underload vous permet de jouer rapidement et sans effort avec l'arité. Nous utilisons donc le premier argument pour choisir entre deux fonctions à deux arguments et deux retours; l'argument swap qui les renvoie tous les deux mais dans l'ordre inverse et la fonction d'identité qui les renvoie tous les deux dans le même ordre.

Lorsque le premier argument est vrai, nous produisons donc une version modifiée du deuxième argument qui permute ses arguments avant de s'exécuter, c'est-à-dire précompose avec "arguments de permutation", c'est-à-dire not. Donc, un vrai premier argument signifie que nous retournons notle deuxième argument. Par contre, un premier argument faux signifie que nous composons avec la fonction identité, c'est-à-dire que nous ne faisons rien. Le résultat est une implémentation de xor.

ais523
la source
or x y = x x yenregistre quelques octets or x y = x true y.
Nitrodon
La sous-charge est souvent contre-intuitive lorsqu'il s'agit de remplacer des littéraux par des variables réutilisées, mais dans ce cas, cette transformation permet d'économiser plus d'octets que prévu, au lieu de moins. Merci pour l'amélioration!
ais523
3

Java 8, score: 360 358 319 271 233 (240-7) octets

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

C’était plus compliqué à réaliser que je ne le pensais quand j’ai commencé .. Surtout le implies. Quoi qu'il en soit, cela fonctionne .. Peut probablement être joué au golf un peu ici et là. EDIT: Ok, ne pas réutiliser des fonctions mais simplement dupliquer la même approche revient beaucoup moins cher en termes de comptage d’octets pour Java.

Essayez-le en ligne.

Explication:

// 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);
Kevin Cruijssen
la source
2

C ++ 17, 207−49 = 158 195 - 58 = 137 octets

Les sauts de ligne sont inutiles (autres que les deux premiers).

#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_))

Essayez-le en ligne!

Unités testées avec des affirmations telles que:

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'));

MISE À JOUR: autrefois j'avais

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

mais la réponse de Roman a ouvert la voie à la version plus courte. Notez que maintenant not_(std::plus<>)est mal formé, où il était autrefois équivalent à std::plus<>; mais comme std::plus<>"ne représente pas un booléen de l'Église", je pense que l'un ou l'autre comportement est acceptable selon les règles.

Quuxplusone
la source
"Autre que le premier" ne devrait-il pas être mis à jour avec "autre que les deux premiers"?
LF
@LF: Absolument correct. Mis à jour. :)
Quuxplusone
2

Forth (gforth) , 133 octets - 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 ;

Essayez-le en ligne!

-4 octets grâce à Quuxplusone

Au départ, j’ai beaucoup réfléchi à cela, en considérant des choses comme les macros et les littéraux, mais j’ai réalisé que si je définissais les choses en termes de vrai et de faux (comme j’aurais dû le faire au départ), cela deviendrait beaucoup plus simple.

Explication du code

\ 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
reffu
la source
1
Vous répétez le mot long executetrois fois. Définir le raccourci vous : j execute ;ferait économiser 4 octets.
Quuxplusone
1

Combinateur SKI-calcul + C, 36 octets

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

Je ne sais pas en fait d'un interprète qui vous permet de définir combinators supplémentaires en termes de précédents, donc je devais tester cela en utilisant http://ski.aditsu.net/ en collant des combinateurs souhaités CCKK(SK)pqsorties q, montrant que Kn'implique pas SK.

Neil
la source
1

Julia 1.0 , 36 octets

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

Je ne sais pas si cela compte, je surcharge en fait le Booltype natif pour pouvoir être appelé, alors je reçois gratuitement la plupart des portes logiques. Malheureusement, Julia n'a pas de impliesporte et j'ai donc dû écrire ma propre fonction.

Essayez-le en ligne!

utilisateur3263164
la source
Je pense que vous devez toujours inclure les opérateurs surchargés dans votre soumission ... mais la notation ne les compte pas, car ce ne sont que des noms? Donc, ce serait +6 octets des nouvelles lignes? Je ne sais pas trop comment fonctionne la notation avec ce défi
Jo King Le
Je ne suis pas tout à fait sûr de savoir comment cela fonctionne non plus, mais le fait d'inclure un code qui ne fait littéralement rien ne me semble pas sensé.
user3263164
Même si le code est déjà déclaré, vous devez quand même l'inclure, sinon toute soumission de langue de golf sur deux sera de zéro octet. Tu n'as rien à faire
Jo King
1

Perl 6 , 120 106 102 101 octets

-1 octet grâce à Jo King

my (\t,\f,&n,&a,&o,&i,&x)={@_[0]},{@_[1]},|<f,t &^v,f t,&^v &^v,t n(&^v),&v>>>.&{"&\{\&^u($_)}".EVAL}

Essayez-le en ligne!

Nwellnhof
la source
1

C ++ 17, 202−49 = 153 193 - 58 = 135 octets

Inspiré par la discussion de commentaires sur ce qui compte de toute façon comme une fonction à deux niveaux, voici une version amusante de ma précédente solution C ++ 17. En réalité, il est plus court car nous pouvons utiliser la même macro not_pour définir toutes les autres fonctions!

#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_))

Essayez-le en ligne!

Celui-ci est testé avec des affirmations comme

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

Avis qui or_est défini de manière efficace

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

Nous pourrions définir or_plus "concise" comme

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

mais cela nous coûterait parce que nous ne pourrions plus utiliser la Dmacro.

Quuxplusone
la source
C ++ étant sensible à la casse, pourquoi ne pas utiliser Trueet Falseau lieu de true_et false_? Et similaire pour les autres opérateurs. Cela permettra d'économiser 12 octets.
G. Sliepen
@ G.Sliepen: l'algorithme de scoring de l'OP prend déjà en compte le fait que les identifiants ont en réalité une longueur de caractère. Citation: "La longueur totale de tout le code nécessaire pour rendre Church vraie et fausse dans votre langue et le and not or xor et implique des portes d'église excluant le nom de la fonction. (Par exemple, false = lambda x, y: y en python 13 octets). Vous pouvez réutiliser ces noms plus tard dans votre code en comptant 1 octet pour le total en octets de cette porte. "
Quuxplusone
Ah, j'ai raté ça.
G. Sliepen
0

APL (dzaima / APL) , 47 octets SBCS

Basé sur la solution J de Jonah .

trueet falsesont des fonctions infixes, notest un opérateur de suffixe et le reste sont des opérateurs infixes.

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

Selon l'OP, cela compte tout, de la fin à la fin de chaque ligne, et compte chaque appel d'une définition précédente sous la forme d'un octet unique.

Essayez-le en ligne!

true et false sont les fonctions d'identité gauche et droite.

not échange simplement les arguments de sa fonction opérande.

Les autres mettent en œuvre l'arbre de décision:

andutilise la fonction righthand pour sélectionner le résultat de la fonction lefthand si true, sinon le résultat de la falsefonction.

orutilise la fonction lefthand pour sélectionner le truesi vrai, sinon le résultat de la fonction righthand .

xorutilise la fonction de droite pour sélectionner le résultat négatif de la fonction de gauche ⍶notsi true, sinon le résultat de la fonction de gauche.

impliesutilise la fonction de gauche pour sélectionner le résultat de la fonction de droite si vrai, sinon le résultat de la truefonction.

Adam
la source
0

Stax , 34 octets

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

Exécutez-le et déboguez-le sur staxlang.xyz!

Pousse un tas de blocs à la pile. Chaque bloc attend son dernier argument au sommet de la pile, suivi du reste par ordre inverse.

Décompressé (41 octets):

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

Chaque paire de { }est un bloc. J'ai utilisé les deux registres X et Y à la main trueet notque je puisse accéder à « em facilement par la suite. Malheureusement, falsecela ne pourrait tout simplement pas être un non-fonctionnement, car cela laisserait la pile de disques encombrée et gâcherait un seul cas XOR.

Suite de tests, commentée

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)
Khuldraeseth na'Barya
la source
0

Befunge-98 , 105 77 65 octets

Pour aller plus loin avec la notion de "fonction" dans des langues sans fonctions ... voici une version Befunge-98 de Church Booleans!

Dans ce dialecte contraint de Befunge-98, un programme consiste en une série de "lignes" ou de "fonctions", chacune d'entre elles commençant par une >instruction (Aller à droite) dans la colonne x = 0. Chaque "fonction" peut être identifiée par son numéro de ligne (coordonnée y). Les fonctions peuvent prendre des entrées via la pile de Befunge , comme d'habitude.

La ligne 0 est spéciale car (0,0) est l'IP de départ. Pour créer un programme qui exécute la ligne L, placez simplement les instructions sur la ligne 0 qui, lorsqu'elles sont exécutées, positionnent le pointeur sur (x = L, y = 0).

La magie se déroule sur la ligne 1. La ligne 1, lorsqu'elle est exécutée, Lextrait un numéro de la pile et passe au numéro de ligne L. (Cette ligne avait déjà été utilisée > >>0{{2u2}2}$-073*-\x, ce qui permet de "faire un saut absolu" vers n'importe quelle ligne; mais je viens de me rendre compte que puisque je sais que cette ligne est indexée sur la ligne 1, nous pouvons "faire un saut relatif" L-1dans beaucoup moins de code.)

La ligne 2 représente l'église FALSE. Lorsqu'il est exécuté, il apparaît deux numéros tet fde la pile, puis vole au numéro de ligne f.

La ligne 3 représente l'église TRUE. Lorsqu'il est exécuté, il apparaît deux numéros tet fde la pile, puis vole au numéro de ligne t.

Line 6, représentant Church XOR, est innovante. Lorsqu'il est exécuté, il apparaît deux nombres aet bde la pile, puis vole à la ligne ad'entrée de pile NOT EXEC b. Donc, si areprésente l'Eglise TRUE, le résultat de a NOT EXEC bsera NOT b; et si areprésente Eglise FALSE, le résultat de a NOT EXEC bsera EXEC b.


Voici la version non-golfée avec harnais de test. Sur la ligne 0, configurez la pile avec votre entrée. Par exemple, des 338moyens IMPLIES TRUE TRUE. Assurez-vous que la fermeture xapparaît exactement à (x, y) = (0,15), sinon rien ne fonctionnera! Assurez-vous également que votre configuration de pile commence par bapour que le programme se termine avec une sortie.

Essayez-le en ligne!

>  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",,,,,@

Voici la version dont j'ai compté les octets.

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

Notez que pour définir une fonction dans ce dialecte, vous ne mentionnez pas son nom du tout. son "nom" est déterminé par son emplacement source. Pour appeler une fonction, vous mentionnez son "nom"; Par exemple, XOR( 6) est défini en termes de NOTet EXEC( 5et 1). Mais tous mes "noms de fonction" ne prennent déjà qu'un octet à représenter. Donc, cette solution ne reçoit aucun ajustement de score.

Quuxplusone
la source