Iglesia booleana


33

Booleanos de la iglesia

Una iglesia booleana es una función que devuelve xverdadero y yfalso donde xes el primer argumento de la función y yes el segundo argumento de la función. Se pueden componer funciones adicionales a partir de estas funciones que representan las operaciones lógicas and not or xory implies.

Reto

Construir los booleanos Iglesia y and not or xory impliesPuertas de la iglesia en un idioma de su elección. and ory xordebe tomar dos funciones (que representan booleanos de la Iglesia) y devolver una función (que representa otro booleano de la Iglesia). Del mismo modo, notdebe invertir la función que toma y la impliespuerta debe realizar booleana implica lógica donde el primer argumento es impliesel segundo.

Tanteo

La longitud total de todo el código necesario para hacer Iglesia truey falseen su idioma y el and not or xore impliesIglesia puertas excluyendo el nombre de la función. (por ejemplo, false=lambda x,y:yen Python serían 13 bytes). Puede reutilizar estos nombres más adelante en su código con ellos contando 1 byte hacia el total de bytes de esa puerta.

Pseudocódigo Ejemplos:

Las funciones que cree deberían poder llamarse más adelante en su código de esta manera.

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

2
¿Tenemos que tratar las entradas de función (o los sustitutos más cercanos) como funciones de recuadro negro, o podemos inspeccionar el código dentro? ¿Y deben los valores de retorno de las operaciones lógicas ser las mismas funciones que se definieron previamente como los booleanos de la Iglesia, o pueden ser otra cosa que haga lo mismo?
Cadena no relacionada

1
@ JonathanAllan Lo edité para que fuera correcto. El aviso es como debería ser ahora.
Ryan Schaefer

2
¿Podemos tomar listas como argumentos (por ejemplo true([x, y]), and([true, true])([x, y]))?
ar4093

2
@RyanSchaefer Creo que debería reconsiderar permitir que los argumentos estén en una lista ordenada, ya que uno podría simplemente envolver los argumentos al comienzo de las soluciones. No creo que requerir eso haga algo para mejorar este desafío (de hecho, creo que limita el potencial de golf interesante). Por supuesto, esta es solo mi opinión, y está bien si no está de acuerdo.
FryAmTheEggman

1
La puntuación es bastante confusa. ¿No sería mejor dejar que las personas envíen funciones anónimas, pero si las usan en otras partes tienen que asignarlas, como de costumbre
Jo King

Respuestas:


14

Cálculo binario de Lambda , 13.875 12.875 bytes (103 bits)

Binary Lambda Calculus Language (BLC) de John Tromp es básicamente un formato de serialización eficiente para el cálculo lambda. Es una gran opción para esta tarea, ya que la notación de la Iglesia es incluso la forma "idiomática" de trabajar con booleanos en BLC.

Utilicé las siguientes funciones lambda para los combinadores, algunos de los cuales copié y jugué golf de la respuesta de Haskell: que se encontraron mediante una búsqueda exhaustiva con un límite de prueba de 20 reducciones β para cada caso. Hay una buena posibilidad de que estos sean lo más cortos posible.

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

Estos se traducen en las siguientes secuencias de código BLC (binario):

 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

Las funciones anteriores son en total 111 bits de largo (13.875 bytes) 103 bits de largo (12.875 bytes). No necesitan estar alineados con los límites de bytes para ser utilizados dentro de un programa, por lo que tiene sentido contar bytes fraccionarios.

No hay reutilización de código entre los combinadores, porque no hay variables / referencias / nombres en BLC: todo tuvo que copiarse. Aún así, la eficiencia de la codificación hace una representación bastante concisa.


1
No sé blc, pero ¿ And: (\a \b a b a)funcionará?
tsh

Si, funciona. De hecho, utilicé esta fórmula para mis secuencias de código. Simplemente olvidé actualizar la función lambda correspondiente (ahora corregida). La función equivalente trabaja para O: \a \b a a b. Sin embargo, es más largo que el que usé en BLC.
Pavel Potoček

25

Haskell , 50 - 6 = 44 bytes

-1 byte gracias a Khuldraeseth na'Barya, y -1 byte gracias a Christian Sievers.

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

Pruébalo en línea!


2
Nota al margen: se puede definir Showcasos de consty const ide imprimir los booleanos iglesia directamente. Pruébalo en línea! .
nimi


44
¿Por qué nadie lo usa f=n t?
Christian Sievers

3
Puede guardar un byte utilizando en t=purelugar de t=const.
Joseph Sible: reinstala a Monica el

44
@ JosephSible Intenté eso inicialmente. Por desgracia, t=purese producirá un error al intentar aplicar a, o, x, o ipara ella. Declarar el tipo de tpara arreglar esto cuesta más bytes que simplemente usar t=const.
Nitrodon

9

Python 2 , (-3?)  101  95 bytes

¡David Beazley te come el corazón!

-6 gracias a Chas Brown (movió el texto repetido :al de unión>. <)

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

Pruébalo en línea!

Creo que podría deberse a 95 - 3que no reutilizo las funciones A, Xo I, pero uso una sola =para la asignación (en frente de lambda). Tal vez no pueda eliminar ninguno; tal vez incluso puedo eliminar 3.5?


@ Ryan Schaefer, ¿puedo eliminar tres o mi uso de execsignifica que no puedo? Puedo ver que va en cualquier dirección: no reutilizo A, X o yo, pero el código no funcionará sin ellos. (¡¿Tal vez incluso pueda eliminar 3.5 ?!)
Jonathan Allan


Gracias @Chas! El colon que se deslizó a través de la red :) Buen trabajo en el reemplazo de -1 BTW
Jonathan Allan

7

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

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)

Pruébalo en línea! El enlace incluye casos de prueba básicos. Editar: Guardado 6 9 bytes gracias a @tsh.


1
Parece que no se puede reclamar este -7 ya que t, f, nse utilizan.
tsh

1
@tsh Así no entiendo el sistema de puntuación; excluye explícitamente el nombre en la definición, aunque el nombre en el uso cuesta 1 byte.
Neil

@Neil usted no puede reclamar el descuento byte para los nombres de funciones que son llamadas por su código ( t, fy nen su caso).
Asgallant

2
@asgallant no. No hay bytes para el nombre y 1 byte cuando se usa más tarde. 'T fnaox i' no tiene bytes, entonces 1 byte cuando se usa más tarde. Quería mejorar la legibilidad, pero ahora me doy cuenta de que debería haberlo dejado completamente golfizado y es demasiado tarde para cambiarlo ahora
Ryan Schaefer

@RyanSchaefer, ¿dónde está esa regla? Nunca lo he visto así.
Asgallant

6

Python 2 , 133 - 6 = 127 94 bytes

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

Pruébalo en línea!

Robando descaradamente la idea furtiva detrás de la respuesta de Jonathan Allan ; Sin embargo, no se deducen bytes.


Iba a publicar una respuesta a mi propia pregunta, pero no estaba seguro de si esto estaba permitido y creo que esto va en contra del espíritu. Así que creo que solo te guiaré. En lugar de usar listas, ¿hay alguna forma de usar las funciones que se están ingresando y la forma específica en que devuelven sus entradas para acortar el código?
Ryan Schaefer

Apostaría que, aunque la respuesta es sí, sería mucho más largo en Python.
Cadena no relacionada

Estoy corregido
Cadena no relacionada

@ Mr.Xcoder tiene razón, tenía la cantidad incorrecta de bytes para la función de ejemplo. Sin embargo, se les permitiría eliminar 6 bytes para los nombres de las funciones.
Ryan Schaefer

@Señor. Xcoder: modificado según sus observaciones.
Chas Brown

4

J , 67 bytes - 7 = 60

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

Pruébalo en línea!

Vale la pena señalar:

Las funciones de orden superior funcionan de manera diferente en J que en un lenguaje funcional. Para crear un nuevo verbo a partir de 1 o 2 verbos existentes, debe usar un adverbio (en el caso de 1) o una conjunción (en el caso de 2).

Sintácticamente, los adverbios vienen después de un verbo, y las conjunciones van entre ellos. Por lo tanto, "no" es un verbo fque haces f n, y "y" verbos fy gf a g.


4

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

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

Pruébalo en línea!

sin golf: inspirado en 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]

Bastante seguro de que las nuevas líneas son necesarias para separar las definiciones de funciones. También hace referencia a tf yn en otras definiciones de funciones, por lo que no puede deducirlas, por lo que 61-4 = 57.
Jonathan Allan

@ JonathanAllan He releído las instrucciones de puntuación y estoy de acuerdo en que las nuevas líneas deberían contar, gracias. No estoy de acuerdo con su segunda parte: cuando reutilizo los nombres, los cuento como "1 byte hacia el total de bytes de esa puerta", que está implícito aquí cuando uso nombres de 1 byte. A medida que mi lectura de las instrucciones continúa, no hay mención de contarlas más como un byte hacia el total de la definición original también. Así que voy con N-7 bytes. Además, otro comentario del OP aclara: "No hay bytes para el nombre y 1 byte cuando se usa más tarde".
Romano

Leí "1 byte más tarde" para indicar que el uso dentro de otra función cuesta un byte. Esto se alinea con cómo otros han puntuado también.
Jonathan Allan

@ JonathanAllan Estoy menos interesado en la exégesis y más en el golf de código 😀
Roman

4

Baja carga , 56 52 bytes

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

Pruébalo en línea! (incluye un traje de prueba y texto que identifica partes del programa)

Esto es sorprendentemente bueno para un esolang de muy bajo nivel. (Los números de iglesia, los booleanos de la iglesia, etc. se usan muy comúnmente en Underload por esta razón; el lenguaje no tiene números y booleanos integrados, y esta es una de las formas más fáciles de simularlos. Dicho esto, también es común codificar booleanos como los números de la Iglesia 0 y 1.)

Para cualquiera que esté confundido: Underload le permite definir funciones reutilizables, pero no le permite nombrarlas de la manera normal, simplemente flotan en la pila de argumentos (por lo tanto, si define cinco funciones y luego desea llamar a la primera) usted definió, necesita escribir una nueva función que tome cinco argumentos y llame al quinto de ellos, luego llámela con suficientes argumentos para que busque argumentos de repuesto para usar). Llamarlos los destruye de manera predeterminada, pero puede modificar la llamada para que no sea destructiva (en casos simples, solo necesita agregar dos puntos a la llamada, aunque los casos complejos son más comunes porque necesita asegurarse de que las copias en la pila no se interponga en su camino), por lo que el soporte de funciones de Underload tiene todos los requisitos que necesitaríamos de la pregunta.

Explicación

cierto

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

Este es bastante sencillo; nos deshacemos del argumento que no queremos y el argumento que queremos simplemente permanece allí, sirviendo como valor de retorno.

falso

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

Este es aún más sencillo.

no

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

Esta es la diversión: notno llama a su argumento en absoluto, solo usa una composición de función. Este es un truco común en Underload, en el que no inspeccionas tus datos en absoluto, solo cambias su funcionamiento al pre y post componer cosas con ellos. En este caso, modificamos la función para intercambiar sus argumentos antes de ejecutar, lo que claramente niega un número de Iglesia.

y

:((!)~^)*
 (     )   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 pregunta permite definir funciones en términos de otras funciones. Definimos "y" siguiente porque cuanto más recientemente se ha definido "no", más fácil es usarlo. (Esto no resta de nuestro puntaje, porque no estamos nombrando "no" en absoluto, pero ahorra bytes al escribir la definición nuevamente. Esta es la única vez que una función se refiere a otra, porque se refiere a cualquier función pero la definición más reciente costaría demasiados bytes).

La definición aquí es and x y = (not x) false y. En otras palabras, si not x, entonces volvemos false; de lo contrario, volvemos y.

o

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

@Nitrodon señaló en los comentarios que or x y = x x ynormalmente es más corto que or x y = x true y, y que resulta ser correcto en Underload también. Sería una implementación ingenua de eso (:~^), pero podemos aprovechar un byte adicional al notar que no importa si ejecutamos el primer argumento original o la copia del mismo, el resultado es el mismo de cualquier manera.

Underload en realidad no admite curry en el sentido habitual, ¡pero definiciones como esta hacen que parezca que sí! (El truco es que los argumentos no consumidos simplemente se quedan, por lo que la función que llama los interpretará como sus propios argumentos).

implica

(~(!)~^(~)~*)
(           )  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 definición utilizada aquí es implies x y = not (y false x). Si y es verdadero, esto se simplifica a not false, es decir true. Si y es falso, esto se simplifica a not x, lo que nos da la tabla de verdad que queremos.

En este caso, lo estamos utilizando notnuevamente, esta vez reescribiendo su código en lugar de hacer referencia a él. Simplemente se escribe directamente (~)~*sin paréntesis, por lo que se llama en lugar de definirse.

xor

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

Esta vez, estamos evaluando solo uno de nuestros dos argumentos, y usándolo para determinar qué componer en el segundo argumento. Underload te permite jugar rápido y suelto con arity, por lo que estamos usando el primer argumento para elegir entre dos funciones de dos argumentos y dos retornos; el intercambio de argumentos que los devuelve a ambos pero en el orden opuesto, y la función de identidad que los devuelve a ambos en el mismo orden.

Cuando el primer argumento es verdadero, por lo tanto, producimos una versión editada del segundo argumento que intercambia sus argumentos antes de ejecutar, es decir, precompone con "argumentos de intercambio", es decir not. Entonces, un primer argumento verdadero significa que devolvemos notel segundo argumento. Por otro lado, un primer argumento falso significa que componimos con la función de identidad, es decir, no hacemos nada. El resultado es una implementación de xor.


or x y = x x yguarda algunos bytes or x y = x true y.
Nitrodon

La subcarga a menudo es contraintuitiva cuando se trata de reemplazar literales con variables reutilizadas, pero en este caso, esa transformación resulta en guardar más bytes de lo esperado, en lugar de menos. Gracias por la mejora!
ais523


3

Java 8, puntaje: 360 358 319 271 233 (240-7) bytes

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

Esto fue más difícil de lograr de lo que pensé cuando lo comencé ... Especialmente el implies. De todos modos, funciona ... Probablemente se puede jugar un poco de golf aquí y allá. EDITAR: Ok, no volver a usar las funciones, sino simplemente duplicar el mismo enfoque es mucho más barato en términos de conteo de bytes para Java ... Y obtengo el bono completo -7 por no usar ninguna de las funciones también.

Pruébalo en línea.

Explicación:

// 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 = 158195 - 58 = 137 bytes

Los saltos de línea son innecesarios (aparte de los dos primeros).

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

Pruébalo en línea!

Probado en unidad con afirmaciones como:

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

ACTUALIZADO: anteriormente había tenido

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

pero la respuesta de Roman señaló el camino a la versión más corta. Tenga en cuenta que ahora not_(std::plus<>)está mal formado, donde antes era equivalente a std::plus<>; pero como std::plus<>no "representa a una iglesia booleana", creo que cualquiera de los dos comportamientos está bien según las reglas.


¿No debería actualizarse "otro que el primero" a "otro que los dos primeros"?
LF

@LF: Absolutamente correcto. Actualizado. :)
Quuxplusone

2

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

Pruébalo en línea!

-4 bytes gracias a Quuxplusone

Inicialmente pensé demasiado en esto, considerando cosas como macros y literales, pero luego me di cuenta de que si definía las cosas en términos de verdadero y falso (como debería haber hecho en primer lugar), se vuelve mucho más simple.

Explicación del código

\ 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
Repites la palabra larga executetres veces. Definir la taquigrafía : j execute ;le ahorraría 4 bytes.
Quuxplusone

1

SKI-cálculo + C combinador, 36 bytes

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

En realidad, no conozco ningún intérprete que le permita definir combinadores adicionales en términos de los anteriores, así que tuve que probar esto usando http://ski.aditsu.net/ pegando los combinadores deseados, por ejemplo, las CCKK(SK)pqsalidasq , , mostrando que Kno implica SK.


1

Julia 1.0 , 36 bytes

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

No sé si eso cuenta, en realidad solo estoy sobrecargando al nativo Bool tipo para que se pueda llamar, por lo que obtengo la mayoría de las puertas lógicas de forma gratuita. Desafortunadamente, Julia no tiene una impliespuerta, así que tuve que escribir mi propia función.

Pruébalo en línea!


Creo que aún necesita incluir los operadores sobrecargados en su envío ... pero la puntuación no los cuenta, ya que son solo nombres. Entonces, ¿serían +6 bytes de las nuevas líneas? No estoy muy seguro de cómo funciona la puntuación con este desafío
Jo King

Tampoco estoy 100% seguro de cómo funciona, pero tener que incluir código que literalmente no hace nada no tiene ningún sentido para mí.
user3263164

Incluso si el código ya está declarado, aún debe incluirlo, de lo contrario, cualquier otro envío de idioma de golf sería cero bytes. Simplemente no tiene que asignarlo a nada
Jo King


1

C ++ 17, 202−49 = 153193 - 58 = 135 bytes

Inspirado por la discusión de comentarios sobre lo que cuenta como una función de 2 arios de todos modos, aquí hay una versión al curry de mi solución C ++ 17 anterior. En realidad es más corto porque podemos usar la misma macro para definir not_y definir todas las demás funciones.

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

Pruébalo en línea!

Este se prueba con afirmaciones como

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

Observe que or_se define como efectivamente

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

Podríamos definir or_más "concisamente" como

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

pero eso nos costaría porque ya no podríamos usar la Dmacro.


Dado que C ++ distingue entre mayúsculas y minúsculas, ¿qué tal usar Truey en Falselugar de true_y false_? Y similar para los otros operadores. Eso ahorrará 12 bytes.
G. Sliepen

@ G.Sliepen: el algoritmo de puntuación de OP ya tiene en cuenta que los identificadores tienen efectivamente una longitud de un carácter. Cita: "La longitud total de todo el código requerido para hacer que Church sea verdadero y falso en su idioma y el y no o xor e implica puertas de Church excluyendo el nombre de la función. (Por ejemplo, false = lambda x, y: y en Python serían 13 bytes). Puede reutilizar estos nombres más adelante en su código con ellos contando 1 byte hacia el total de bytes de esa puerta ".
Quuxplusone

Ah, me perdí eso.
G. Sliepen

0

APL (dzaima / APL) , 47 bytes SBCS

Basado en la solución J de Jonah .

truey falseson funciones de infijo, notes un operador de sufijo y el resto son operadores de infijo.

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

Según OP, esto cuenta todo, incluso hasta el final de cada línea, y cuenta cada llamada de una definición previa como un solo byte.

Pruébalo en línea!

verdadero y falso son las funciones de identidad izquierda y derecha.

not simplemente intercambia los argumentos de su función operando.

El resto implementa el árbol de decisión:

andusa la función derecha para seleccionar el resultado de la función izquierda si es verdadero, de lo contrario, el resultado de la falsefunción.

orusa la función de la izquierda para seleccionar truesi es verdadero, de lo contrario, el resultado de la función de la derecha .

xorusa la función derecha para seleccionar el resultado negado de la función izquierda ⍶notsi es verdadero, de lo contrario, el resultado de la función izquierda.

impliesusa la función izquierda para seleccionar el resultado de la función derecha si es verdadero, de lo contrario, el resultado de la truefunción.


0

Stax , 34 bytes

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

¡Ejecútelo y depúrelo en staxlang.xyz!

Empuja un montón de bloques a la pila. Cada bloque espera su último argumento sobre la pila, seguido en orden inverso por el resto.

Desempaquetado (41 bytes):

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

Cada par de { }es un bloque. Usé los dos registros X e Y para mantenerlos truey notasí podría acceder a ellos fácilmente más tarde. Desafortunadamente, falseno podría ser simplemente un no-op, ya que eso dejaría la pila desordenada y arruinaría un solo caso XOR.

Conjunto de pruebas, comentado

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 bytes

Jugando aún más con la noción de "función" en idiomas sin funciones ... ¡aquí hay una versión Befunge-98 de los booleanos de la Iglesia!

En este dialecto restringido de Befunge-98, un programa consiste en una serie de "líneas" o "funciones", cada una de las cuales comienza con un > instrucción (Ir a la derecha) en la columna x = 0. Cada "función" se puede identificar con su número de línea (coordenada y). Las funciones pueden recibir información a través de la pila de Befunge , como de costumbre.

La línea 0 es especial, porque (0,0) es la IP inicial. Para hacer un programa que ejecute la línea L, simplemente coloque las instrucciones en la línea 0 que, cuando se ejecute, vuele el puntero de instrucción a (x = L, y = 0).

La magia ocurre en la línea 1. La línea 1, cuando se ejecuta, saca un número Lde la pila y salta al número de línea L. (Esta línea había sido anteriormente > >>0{{2u2}2}$-073*-\x, lo que puede "saltar de forma absoluta" a cualquier línea; pero me di cuenta de que, dado que sé que esta línea está vinculada a la línea 1, podemos "saltar de forma relativa"L-1 líneas de en muchísimo menos código).

La línea 2 representa a la Iglesia FALSE. Cuando se ejecuta, aparece dos números ty fde la pila y luego vuela al número de línea f.

La línea 3 representa a la Iglesia TRUE. Cuando se ejecuta, aparece dos números ty fde la pila y luego vuela al número de línea t.

La línea 6, que representa a Church XOR, es innovadora. Cuando se ejecuta, muestra dos números ay bde la pila, y luego vuela a la línea acon la entrada de la pila NOT EXEC b. Entonces, si arepresenta a la Iglesia TRUE, el resultado de a NOT EXEC bserá NOT b; y si arepresenta a la Iglesia FALSE, el resultado de a NOT EXEC bserá EXEC b.


Aquí está la versión sin golf con arnés de prueba. En la línea 0, configure la pila con su entrada. Por ejemplo, 338significa IMPLIES TRUE TRUE. ¡Asegúrese de que el cierre xaparezca exactamente en (x, y) = (0,15) o de lo contrario nada funcionará! También asegúrese de que su configuración de pila comience ba, de modo que el programa realmente termine con alguna salida.

Pruébalo en línea!

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

Aquí está la versión cuyos bytes conté.

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

Observe que para definir una función en este dialecto no menciona su nombre en absoluto; su "nombre" está determinado por su ubicación de origen. Para llamar a una función, mencionas su "nombre"; por ejemplo, XOR( 6) se define en términos de NOTy EXEC( 5y 1). Pero todos mis "nombres de funciones" ya solo toman un byte para representar. Entonces esta solución no obtiene ajustes de puntuación.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.