¡Golf todas las 16 puertas lógicas con 2 entradas y 1 salida!

63

Por ejemplo, la puerta A and Bes una puerta lógica con 2 entradas y 1 salida.

Hay exactamente 16 de ellos, porque:

  • cada puerta lógica toma dos entradas, que pueden ser verdaderas o falsas, lo que nos da 4 entradas posibles
  • de las 4 entradas posibles, cada una puede tener una salida de verdadero y falso
  • por lo tanto, hay 2 ^ 4 posibles puertas lógicas, que es 16.

Su tarea es escribir 16 programas / funciones que implementen todos ellos por separado.

Sus funciones / programas deben ser independientes .

Son válidos siempre que generen valores de verdadero / falso, lo que significa que puede implementar A or Ben Python como lambda a,b:a+b, incluso si 2se produce para A=Truey B=True.

La puntuación es el total de bytes utilizados para cada función / programa.

Lista de puertas lógicas

  1. 0,0,0,0 ( false)
  2. 0,0,0,1 ( and)
  3. 0,0,1,0 ( A and not B)
  4. 0,0,1,1 ( A)
  5. 0,1,0,0 ( not A and B)
  6. 0,1,0,1 ( B)
  7. 0,1,1,0 ( xor)
  8. 0,1,1,1 ( or)
  9. 1,0,0,0 ( nor)
  10. 1,0,0,1 ( xnor)
  11. 1,0,1,0 ( not B)
  12. 1,0,1,1 ( B implies A)
  13. 1,1,0,0 ( not A)
  14. 1,1,0,1 ( A implies B)
  15. 1,1,1,0 ( nand)
  16. 1,1,1,1 ( true)

Donde el primer número es la salida para A=false, B=false, el segundo número es la salida para A=false, B=true, el tercer número es la salida para A=true, B=false, el cuarto número es la salida para A=true, B=true.

Tabla de clasificación

Monja permeable
fuente
2
Sus funciones / programas pueden compartir código. ¿Qué significa esto? Además, ¿pueden los programas estar en diferentes idiomas?
Lynn
2
La explicación me parece confusa: "de las 4 entradas posibles que cada una puede tener y salida de verdad y falsedad". ¿No implica esto 8 (4 * 2) estados?
DavidC
44
Los nombres que falta son las compuertas AND-NOT (A AND NOT B y B AND NOT A).
Mego
14
Entonces sucedió de nuevo. Hay 18 respuestas, en su mayoría simples y correctas, luego, de la nada, la pregunta se volvió "confusa". Si no te gusta un desafío, continúa, toma otro, ¡no lo cierres!
edc65
44
@dorukayhan See: verdad vacía
Sp3000

Respuestas:

110

Dominó , 122,000 bytes o 72 fichas

El recuento de bytes es el tamaño del archivo guardado que es 0.122 MB.

La informática de Domino fue la inspiración. He probado todo esto hasta la simetría (¡y más allá!) A través de un juego de Steam de realidad virtual llamado Tabletop Simulator .

Detalles

  • I / O
    • Inicio : se incluye para mayor claridad (no se cuenta para el total) y es lo que "llama" o "ejecuta" la función. Debe "presionarse" después de que se ingrese la entrada [Amarillo] .
    • Entrada A : se incluye para mayor claridad (no se cuenta hacia el total) y se 'presiona' para indicar 1ay no se presiona de otra manera [Verde] .
    • Entrada B : se incluye para mayor claridad (no se cuenta hacia el total) y se 'presiona' para indicar 1ay no se presiona de otra manera [Azul] .
    • Salida : se cuenta en el total. Es el dominó el que declara el resultado de la puerta lógica [Negro] .
  • T / F
    • Un dominó de salida caído representa un resultado de Trueo1
    • Un dominó de salida permanente representa un resultado de Falseo0
  • Prensado
    • Para dar entrada o iniciar la cadena, genera la canica de metal
    • Establezca la fuerza de elevación en 100%
    • Levanta la canica por encima del dominó deseado
    • Deja caer la canica

ingrese la descripción de la imagen aquí

Puertas

  • falso, 1
    • ingrese la descripción de la imagen aquí
  • y 6 4
    • ingrese la descripción de la imagen aquí
  • A y no B, 4 3
    • ingrese la descripción de la imagen aquí
  • A, 1
    • ingrese la descripción de la imagen aquí
  • no A y B, 4 3
    • ingrese la descripción de la imagen aquí
  • B, 1
    • ingrese la descripción de la imagen aquí
  • xor, 15 11
    • ingrese la descripción de la imagen aquí
  • o 1
    • ingrese la descripción de la imagen aquí
  • ni 3 2
    • ingrese la descripción de la imagen aquí
  • xnor, 17 13
    • ingrese la descripción de la imagen aquí
  • no B, 2
    • ingrese la descripción de la imagen aquí
  • B implica A, 7 6
    • ingrese la descripción de la imagen aquí
  • no A, 2
    • ingrese la descripción de la imagen aquí
  • A implica B, 7 6
    • ingrese la descripción de la imagen aquí
  • nand, 16 15
    • ingrese la descripción de la imagen aquí
    • cierto 1
    • ingrese la descripción de la imagen aquí

TL; DR

Había estado esperando / queriendo un desafío amigable para el dominó y cuando vi esto, no pude dejarlo pasar. ¡El único problema era que aparentemente ya nadie posee fichas de dominó! Así que finalmente cedí y compré un Doce Dobles . Este conjunto tiene 91 mosaicos, lo que me dio la idea de tener una 'función call' / start domino en lugar del método normal (largo) 'time delay'. El crédito por el giro de 90 grados pertenece al canal de dominoesdouble07 .

Después de construirlos con dominó físico, se determinó en meta que las soluciones válidas deberían ser digitales. Así que recreé estas puertas en Tabletop Simulator . Lamentablemente, TS y la realidad no están de acuerdo en la física del dominó. Esto me obligó a agregar 11 fichas de dominó, pero también ahorré 8. En general, las fichas de dominó virtuales son aproximadamente x150 más efectivas en términos de creación y prueba ( Ctrl+ Z).

Actualizar

  • -9 [17-03-13] Acortadoxor xnor nand
  • [17-03-04] Enlace agregado al archivo del taller
  • +11 [17-03-03] Agregado digital xnoryxor
  • -8 [17-03-03] Digitalizó todas las puertas (excepto xory xnor). El bloqueo en Tabletop solo requiere 1 dominó, en lugar de 2.
  • [16-09-23] Imágenes reducidas
  • -11 [16-09-18] Casi corta xor por la mitad otra vez. Gracias a @DJMcMayhem por xnor y Joe por xor.
  • -31 [16-08-31] Actualizó algunas fotos y afeitó algunas fichas y cortó xor por la mitad
  • [16-08-28] Imágenes agregadas
Fruta no lineal
fuente
43
+1 Necesitamos más juegos de dominó en PPCG
Beta Decay
8
Relacionado.
Martin Ender
77
Guau. Esta es una de las respuestas más originales que he visto en este sitio.
DJMcMayhem
3
Parece que podrías quitarte un dominó si aprietas el xnor juntos y tienes 4 en la parte superior, en lugar de 5. Por otra parte, no lo he probado en absoluto.
DJMcMayhem
2
Gracias por tomarse el tiempo para hacer de esta una respuesta válida. Sin embargo, el enlace al archivo fuente es un poco difícil de encontrar. Normalmente, el enlace en el encabezado conduce al idioma en sí. Así que vincularía ese al juego de Steam y luego pondría el enlace al "archivo fuente" real en un enlace separado, claramente etiquetado en algún lugar del cuerpo de la respuesta.
Martin Ender
45

Hexagonía , 89 bytes.

Gracias a FryAmTheEggman por la inspiración necesaria para la solución XOR.

0000 !@
0001 ?.|@!
0010 #?#!)@
0011 ?!@
0100 +?|@!?
0101 ??!@
0110 ?<@!!<_\~(
0111 ?<<@!
1000 )\!#?@{
1001 (~?/@#!
1010 ??|@!)
1011 \#??!1@
1100 ?(~!@
1101 ?.|@!)
1110 ?$@#)!<
1111 1!@

Todos los programas se usan 0para falso y 1para verdadero.

Pruébalo en línea! Este no es un conjunto de pruebas, tendrá que copiar los diferentes programas y entradas usted mismo.

La solución anterior está dentro de los 2 bytes de la optimización (a menos que relajemos la interpretación verdadero / falso, supongo). He dejado un bruto barrido de búsqueda vigor durante cerca de dos días más de todos los programas que encaja en el lado de longitud 2, es decir, hasta 7 bytes (no bastantes Todos los programas - Hice algunas suposiciones sobre lo que las necesidades de cada programa válido y lo que hay programa válido podría tener). La búsqueda encontró soluciones para 15 de las 16 puertas posibles, y a menudo mucho más que solo una. Puede encontrar una lista de todas las soluciones alternativas en este pastebin donde también las he agrupado por comportamiento equivalente. Las que muestro arriba las he seleccionado porque son la solución más simple o la más interesante, y agregaré explicaciones para ellas mañana.

En cuanto a la 16ª puerta: XOR es la única puerta que aparentemente no se puede implementar en 7 bytes. Desafortunadamente, una búsqueda de fuerza bruta en programas más grandes no es factible con el código que tengo actualmente. Entonces XOR tuvo que ser escrito a mano. Lo más corto que he encontrado hasta ahora es el programa anterior de 10 bytes, que se basa en un intento fallido (pero muy cercano) de FryAmTheEggman. Es posible que exista una solución de 8 bytes o 9 bytes, pero aparte de eso, todas las soluciones deberían ser óptimas.

Explicaciones

Advertencia: muro de texto. En caso de que alguien esté interesado en cómo funcionan realmente estos programas de Hexagonía altamente comprimidos, he incluido explicaciones para cada uno de ellos a continuación. Intenté elegir la solución más simple para cada puerta en los casos en que existe más de un programa óptimo, para mantener las explicaciones razonablemente cortas. Sin embargo, algunos de ellos todavía aturden la mente, así que pensé que merecían un poco más de elaboración.

0000: Falso

No creo que necesitemos un diagrama para este:

 ! @
. . .
 . .

Como toda la cuadrícula de memoria se inicializa en ceros, !simplemente imprime un cero y @finaliza el programa.

Esta es también la única solución de 2 bytes.

0001: Y

 ? .
| @ !
 . .

Esto básicamente implementa cortocircuito . El siguiente diagrama gris muestra el comienzo del programa, donde se lee la primera entrada ?y el puntero de instrucción (IP) se ajusta a la esquina izquierda donde lo |refleja el espejo. Ahora la esquina actúa como condicional, por lo que hay dos rutas de ejecución diferentes según el valor de la primera entrada. El diagrama rojo muestra el flujo de control para A = 0y el diagrama verde para A = 1:

yo yo yo

Como puede ver, cuando Aestá 0, simplemente lo imprimimos y terminamos (recuerde que todos .son no-ops). Pero cuando Aes así 1, la IP atraviesa la primera fila de nuevo, leyendo Be imprimiendo eso.

En total hay dieciséis soluciones de 5 bytes para esta puerta. Catorce de ellos son esencialmente los mismos que los anteriores, ya sea usando en >lugar de |o reemplazando .con un comando que es efectivamente un no-op, o colocando ?en la segunda posición:

?.|@!    .?|@!    ?=|@!    =?|@!    ?_|@!    _?|@!    ?0|@!
?.>@!    .?>@!    ?=>@!    =?>@!    ?_>@!    _?>@!    ?0>@!

Y luego hay otras dos soluciones (que son equivalentes entre sí). Estos también implementan la misma lógica de cortocircuito, pero las rutas de ejecución son un poco más locas (y se dejan como ejercicio para el lector):

?<!@|
?<!@<

0010: A y no B

 # ?
# ! )
 @ .

Esto también implementa una forma de cortocircuito, pero debido al uso del #flujo de control es mucho más complicado. #es un conmutador de IP condicional. Hexagony realidad viene con seis direcciones IP marcadas 0a 5, que comienzan en las seis esquinas de la rejilla, apuntando a lo largo de su borde hacia la derecha (y el programa siempre comienza con IP 0). Cuando #se encuentra a, el valor actual se toma módulo 6y el flujo de control continúa con la IP correspondiente. No estoy seguro de qué ataque de locura me hizo agregar esta función, pero ciertamente permite algunos programas sorprendentes (como este).

Distinguiremos tres casos. Cuando A = 0, el programa es bastante simple, porque el valor siempre es 0cuando #se encuentra de tal manera que no se produce el cambio de IP:

yo

#no hace nada, ?lee A(es decir, tampoco hace nada), #sigue sin hacer nada, !imprime 0, lo )incrementa (esto es importante, de lo contrario la IP no saltaría a la tercera línea), @finaliza el programa. Suficientemente simple. Ahora consideremos el caso (A, B) = (1, 0):

yo

La ruta roja todavía corresponde a IP 0, y he agregado la ruta verde para IP 1. Vemos que después de las ?lecturas A( 1esta vez), #cambia a la IP que comienza en la esquina superior derecha. Eso significa que ?puede leer B( 0). Ahora )incrementa eso a 1tal que la #esquina superior izquierda no hace nada y nos quedamos con IP 1. El !imprime 1y el IP se envuelve alrededor de la diagonal izquierda. #Todavía no hace nada y @finaliza el programa.

Finalmente, el caso realmente extraño donde ambas entradas son 1:

yo

Esta vez, la segunda entrada también es 1y la )incrementa a 2. Eso significa que #en la esquina superior izquierda causa otro cambio de IP a IP 2, indicar en azul. En ese camino, primero lo incrementamos aún más 3(aunque eso es irrelevante) y luego pasamos la ?tercera vez. Como ahora hemos alcanzado EOF (es decir, la entrada está agotada), ?devuelve 0, !imprime eso y @finaliza el programa.

Notablemente, esta es la única solución de 6 bytes para esta puerta.

0011: UNA

 ? !
@ . .
 . .

Esto es lo suficientemente simple como para que no necesitemos un diagrama: lo ?lee A, lo !imprime y @termina.

Esta es la única solución de 3 bytes para esta puerta. (En principio, también sería posible hacerlo ,;@, pero la búsqueda no incluyó ;, porque no creo que pueda guardar bytes !para esta tarea).

0100: B y no A

 + ?
| @ !
 ? .

Este es mucho más simple que su "hermano" 0010. El flujo de control es en realidad el mismo que hemos visto anteriormente para 0001(Y). Si A = 0, entonces el IP atraviesa la línea inferior, leyendo Be imprimiendo eso antes de terminar. Si A = 1luego, el IP atraviesa la primera línea nuevamente, también lee B, pero +agrega dos bordes de memoria no utilizados, por lo que todo lo que hace es restablecer el valor actual 0, para que !siempre se imprima 0.

Hay bastantes alternativas de 6 bytes para esto (42 en total). Primero, hay un montón de soluciones equivalentes a las anteriores. Nuevamente podemos elegir libremente entre |y >, y +podemos reemplazarlo con cualquier otro comando que nos dé un borde vacío:

"?|@!?    &?|@!?    '?|@!?    *?|@!?    +?|@!?    -?|@!?    ^?|@!?    {?|@!?    }?|@!?
"?>@!?    &?>@!?    '?>@!?    *?>@!?    +?>@!?    -?>@!?    ^?>@!?    {?>@!?    }?>@!?

Además, también podemos usar en ]lugar de ?. ]se mueve a la siguiente IP (es decir, selecciona la IP 1), de modo que esta rama reutiliza ?en su lugar la esquina superior derecha. Eso da otras 18 soluciones:

"?|@!]    &?|@!]    '?|@!]    *?|@!]    +?|@!]    -?|@!]    ^?|@!]    {?|@!]    }?|@!]
"?>@!]    &?>@!]    '?>@!]    *?>@!]    +?>@!]    -?>@!]    ^?>@!]    {?>@!]    }?>@!]

Y luego hay otras seis soluciones que funcionan de manera diferente con diferentes niveles de locura:

/[<@!?    ?(#!@]    ?(#>@!    ?/@#/!    [<<@!?    [@$\!?

0101: B

 ? ?
! @ .
 . .

Woohoo, otro simple: leer A, leer B, imprimir B, terminar. Sin embargo, en realidad hay alternativas a esto. Como Asolo es un carácter, también podemos leerlo con ,:

,?!@

Y también existe la opción de usar un solo ?y usar un espejo para ejecutarlo dos veces:

?|@!    ?>@!

0110: Xor

  ? < @
 ! ! < _
\ ~ ( . .
 . . . .
  . . .

Como dije anteriormente, esta era la única puerta que no cabía en la longitud lateral 2, por lo que esta es una solución escrita a mano por FryAmTheEggman y yo, y hay una buena posibilidad de que no sea óptima. Hay dos casos para distinguir. Si A = 0el flujo de control es bastante simple (porque en ese caso solo necesitamos imprimir B):

yo

Comenzamos en el camino rojo. ?lee A, <es una rama que desvía el cero a la izquierda. La IP se ajusta a la parte inferior, luego _es otro espejo, y cuando la IP llega a la esquina, se ajusta a la esquina superior izquierda y continúa en el camino azul. ?lo lee B, lo !imprime. Ahora lo (decrementa. Esto es importante porque garantiza que el valor no sea positivo (es 0o -1ahora). Eso hace que IP se ajuste a la esquina derecha, donde @termina el programa.

Cuando las A = 1cosas se ponen un poco más difíciles. En ese caso, queremos imprimir not B, lo que en sí mismo no es demasiado difícil, pero la ruta de ejecución es un poco extraña.

yo

Esta vez, <desvía la IP hacia la derecha y luego <actúa como un espejo. Entonces, la IP atraviesa la misma ruta en reversa, leyendo Bcuando se encuentra ?nuevamente. La IP se ajusta a la esquina derecha y continúa en el camino verde. Encuentra a continuación (~que es "decremento, se multiplica por -1", que permutas 0y 1y por lo tanto calcula not B. \es solo un espejo e !imprime el resultado deseado. Luego ?intenta devolver otro número pero devuelve cero. La IP ahora continúa en la esquina inferior izquierda del camino azul. (decrementos, <refleja,(disminuye nuevamente, de modo que el valor actual es negativo cuando la IP llega a la esquina. Se mueve a través de la diagonal inferior derecha y luego finalmente golpea @para terminar el programa.

0111: O

 ? <
< @ !
 . .

Más cortocircuito.

yo yo

El A = 0caso (el camino rojo) es un poco confuso aquí. El IP se desvía a la izquierda, se envuelve en la esquina inferior izquierda, se refleja inmediatamente en el <y vuelve a la ?lectura B. A continuación, envuelve a la esquina rigt, imprime Bcon !y termina.

El A = 1caso (el camino verde) es un poco más simple. La <rama desvía la IP hacia la derecha, por lo que simplemente imprimimos !, volvemos a la esquina superior izquierda y terminamos en @.

Solo hay otra solución de 5 bytes:

\>?@!

Funciona esencialmente igual, pero las rutas de ejecución reales son bastante diferentes y utiliza una esquina para ramificar en lugar de a <.

1000: Ni

 ) \
! # ?
 @ {

Este podría ser mi programa favorito encontrado en esta búsqueda. Lo mejor es que esta implementación norrealmente funciona para hasta 5 entradas. Tendré que entrar un poco en los detalles del modelo de memoria para explicarlo. Entonces, como una actualización rápida, el modelo de memoria de Hexagony es una cuadrícula hexagonal separada, donde cada borde tiene un valor entero (inicialmente todo cero). Hay un puntero de memoria (MP) que indica un borde y una dirección a lo largo de ese borde (de modo que hay dos bordes vecinos delante y detrás del borde actual, con vecinos significativos izquierdo y derecho). Aquí hay un diagrama de los bordes que usaremos, con el MP comenzando como se muestra en rojo:

yo

Primero consideremos el caso donde ambas entradas son 0:

yo

Comenzamos en la ruta gris, que simplemente incrementa el borde A para 1que #cambie a IP, 1que es la ruta azul, comenzando en la esquina superior derecha. \no hace nada allí y ?lee una entrada. Nos ajustamos a la esquina superior izquierda donde )incrementa esa entrada. Ahora, siempre que la entrada sea cero, esto dará como resultado a 1, por lo que eso #no hace nada. Entonces {se mueve la MP a la izquierda, es decir, en la primera iteración de A a B . Dado que este borde aún tiene su cero inicial, la IP vuelve a la esquina superior derecha y en un nuevo borde de memoria. Entonces, este bucle continuará mientras ?lea ceros, moviendo el MP alrededor del hexágono desde Ba C a D y así sucesivamente. No importa si ?devuelve un cero porque era una entrada o porque era EOF.

Después de seis iteraciones a través de este bucle, {vuelve a A . Esta vez, el borde ya contiene el valor 1desde la primera iteración, por lo que la IP se ajusta a la esquina izquierda y continúa en el camino verde. !simplemente imprime eso 1y @finaliza el programa.

Ahora, ¿qué pasa si alguna de las entradas es 1?

yo

Luego ?lee eso 1en algún momento y lo )incrementa a 2. Eso significa #que ahora cambiará las direcciones IP nuevamente y continuaremos en la esquina derecha del camino rojo. ?lee otra entrada (si hay una), que realmente no importa y se {mueve un poco más. Esto tiene que ser un borde no utilizado, por lo tanto, funciona para hasta 5 entradas. La IP se ajusta a la esquina superior derecha donde se refleja inmediatamente y se ajusta a la esquina izquierda. !imprime 0en el borde no utilizado y #vuelve a cambiar a IP 0. Esa IP todavía estaba esperando en el #, yendo hacia el suroeste (camino gris), por lo que inmediatamente golpea @y finaliza el programa.

En total, hay siete soluciones de 7 bytes para esta puerta. 5 de ellos funcionan igual que esto y simplemente usan otros comandos para moverse a un borde no utilizado (y pueden caminar alrededor de un hexágono diferente o en una dirección diferente):

)\!#?@"    )\!#?@'    )\!#?@^    )\!#?@{    )\!#?@}

Y hay otra clase de soluciones que solo funciona con dos entradas, pero cuyas rutas de ejecución son incluso más desordenadas:

?]!|<)@    ?]!|<1@

1001: Igualdad

 ( ~
? / @
 # !

Esto también hace un uso muy inteligente de la selección de IP condicional. Necesitamos distinguir nuevamente entre A = 0y A = 1. En el primer caso queremos imprimir not B, en el segundo queremos imprimir B. Porque A = 0también distinguimos los dos casos para B. Comencemos con A = B = 0:

yo

Comenzamos en el camino gris. (~se puede ignorar, la IP se ajusta a la esquina izquierda (todavía en el camino gris) y se lee Acon ?. (disminuye eso, por lo que obtenemos una -1envoltura de IP en la esquina inferior izquierda. Ahora, como dije antes, #toma el módulo de valor 6antes de elegir la IP, por lo que un valor de -1realmente sale de IP 5, que comienza en la esquina izquierda del camino rojo. ?lee B, (decrementa eso también para que permanezcamos en IP 5cuando golpeemos #nuevamente. ~niega -1para que la IP se ajuste a la esquina inferior derecha, imprima 1y finalice.

yo

Ahora, si Bes así 1, el valor actual será 0cuando lleguemos a #la segunda vez, así que volveremos a IP 0(ahora en la ruta verde). Eso golpea ?por tercera vez, cediendo 0, lo !imprime y @termina.

yo

Finalmente, el caso donde A = 1. Esta vez, el valor actual ya es cero cuando golpeamos #por primera vez, por lo que esto nunca cambia a IP 5en primer lugar. Simplemente continuamos inmediatamente en el camino verde. ?ahora no solo da un cero, sino que regresa B. !lo imprime y @termina de nuevo.

En total, hay tres soluciones de 7 bytes para esta puerta. Los otros dos funcionan de manera muy diferente (incluso el uno del otro), y hacen un uso aún más extraño #. En particular, leen uno o más valores con ,(leyendo un código de caracteres en lugar de un entero) y luego usan ese valor módulo 6 para elegir una IP. Es bastante loco.

),)#?@!

?~#,~!@

1010: No es b

 ? ?
| @ !
 ) .

Este es bastante simple. La ruta de ejecución es la rama horizontal que ya conocemos de andantes. ??lee Ay luego inmediatamente B. Después de reflexionar |y bifurcar, B = 0ejecutaremos la rama inferior, donde )incrementa el valor al 1cual se imprime !. En la rama superior (si B = 1), ?simplemente restablezca el borde en el 0que también se imprime !.

Hay ocho programas de 6 bytes para esta puerta. Cuatro de ellos son más o menos lo mismo, usando en >lugar de |o en 1lugar de )(o ambos):

??>@!)    ??>@!1    ??|@!)    ??|@!1

Dos usan un solo ?que se usa dos veces debido a un espejo. La negación entonces sucede como lo hicimos xorcon cualquiera (~o ~).

?>!)~@    ?>!~(@

Y finalmente, dos soluciones usan un conmutador de IP condicional, porque ¿por qué usar la forma simple si la enrevesada también funciona?

??#)!@    ??#1!@

1011: B implica A

 \ #
? ? !
 1 @

Esto utiliza una conmutación de IP bastante elaborada. Comenzaré con el A = 1caso esta vez, porque es más simple:

ingrese la descripción de la imagen aquí

Comenzamos en el camino gris, que lee Acon ?y luego golpea el #. Dado Aque 1esto cambia a IP 1(ruta verde). El !imprime de inmediato que, la IP se ajusta a la parte superior izquierda, lee B(innecesariamente) y termina.

Cuando las A = 0cosas se ponen un poco más interesantes. Primero consideremos A = B = 0:

ingrese la descripción de la imagen aquí

Esta vez, #no hace nada y permanecemos en IP 0(ruta roja desde ese punto en adelante). ?lo lee By lo 1convierte en a 1. Después de pasar a la esquina superior izquierda, golpeamos #nuevamente, así que terminamos en el camino verde después de todo, e imprimimos 1como antes, antes de terminar.

Finalmente, aquí está (A, B) = (0, 1)el caso falso:

ingrese la descripción de la imagen aquí

Tenga en cuenta que he eliminado la ruta gris inicial para mayor claridad, pero el programa comienza de la misma manera y terminamos en la ruta roja como antes. Entonces esta vez ?vuelve el segundo 1. Ahora nos encontramos con el 1. En este punto, es importante comprender qué hacen realmente los dígitos en Hexagony (hasta ahora solo los hemos usado en ceros): cuando se encuentra un dígito, el valor actual se multiplica por 10 y luego se agrega el dígito. Esto normalmente se usa para escribir números decimales textualmente en el código fuente, pero significa que en B = 1realidad está asignado al valor 11. Entonces, cuando golpeamos #, esto se toma un módulo 6para dar 5y, por lo tanto, cambiamos a IP 5(en lugar de 1como antes) y continuamos en el camino azul. Golpear?una tercera vez devuelve un cero, por lo !que imprime eso, y después de otras dos ?, la IP se ajusta a la parte inferior derecha donde termina el programa.

Hay cuatro soluciones de 7 bytes para esto y todas funcionan de manera diferente:

#)/!?@$    <!?_@#1    \#??!1@    |/)#?@!

1100: No un

 ? (
~ ! @
 . .

Solo una lineal simple: leer Acon ?, negar con (~, imprimir con !, terminar con @.

Hay una solución alternativa, y eso es negar con ~):

?~)!@

1101: A implica B

 ? .
| @ !
 ) .

Esto es mucho más simple que la implicación opuesta de la que acabamos de hablar. Es nuevamente uno de esos programas de rama horizontal, como el de and. Si Aes así 0, simplemente se incrementa 1en la rama inferior y se imprime. De lo contrario, la rama superior se ejecuta nuevamente donde ?lee By luego !imprime eso.

Aquí hay un montón de alternativas (66 soluciones en total), principalmente debido a la libre elección de no-operaciones efectivas. Para empezar, podemos variar la solución anterior de la misma manera que podríamos andy también podemos elegir entre )y 1:

?.|@!)    .?|@!)    ?=|@!)    =?|@!)    ?_|@!)    _?|@!)    ?0|@!)
?.|@!1    .?|@!1    ?=|@!1    =?|@!1    ?_|@!1    _?|@!1    ?0|@!1
?.>@!)    .?>@!)    ?=>@!)    =?>@!)    ?_>@!)    _?>@!)    ?0>@!)
?.>@!1    .?>@!1    ?=>@!1    =?>@!1    ?_>@!1    _?>@!1    ?0>@!1

Y luego hay una versión diferente que usa la selección de IP condicional, donde el primer comando se puede elegir casi arbitrariamente, y también hay una opción entre )y 1para algunas de esas opciones:

"?#1!@    &?#1!@    '?#1!@    )?#1!@    *?#1!@    +?#1!@    -?#1!@    .?#1!@    
0?#1!@    1?#1!@    2?#1!@    3?#1!@    4?#1!@    5?#1!@    6?#1!@    7?#1!@    
8?#1!@    9?#1!@    =?#1!@    ^?#1!@    _?#1!@    {?#1!@    }?#1!@

"?#)!@    &?#)!@    '?#)!@              *?#)!@    +?#)!@    -?#)!@    
0?#)!@              2?#)!@              4?#)!@              6?#)!@    
8?#)!@                        ^?#)!@    _?#)!@    {?#)!@    }?#)!@

1110: Nand

 ? $
@ # )
 ! <

El último complicado. Si todavía estás leyendo, casi lo logras. :) Veamos A = 0primero:

ingrese la descripción de la imagen aquí

?lee Ay luego golpeamos $. Este es un comando de salto (como el de Befunge #) que omite la siguiente instrucción para que no terminemos en el @. En cambio, la IP continúa en #. Sin embargo, como Aes 0, esto no hace nada. )lo incrementa para 1que la IP continúe en la ruta inferior donde 1se imprime. El <desvío de la IP hacia la derecha donde se ajusta a la esquina izquierda y el programa termina.

Luego, cuando la entrada es (A, B) = (1, 0), obtenemos esta situación:

ingrese la descripción de la imagen aquí

Es esencialmente lo mismo que antes, excepto que en el #cambio a IP 1(ruta verde), pero dado Bque 0cambiamos a IP 0cuando golpeamos #por segunda vez (ahora ruta azul), donde se imprime 1como antes.

Finalmente, el A = B = 1caso:

ingrese la descripción de la imagen aquí

Esta vez, cuando somos #la segunda vez, el valor actual sigue siendo 1así que no volveremos a cambiar la IP. Lo <refleja y la tercera vez que golpeamos ?obtenemos un cero. Por lo tanto, la IP se ajusta a la parte inferior izquierda donde !imprime el cero y finaliza el programa.

Hay nueve soluciones de 7 bytes en total para esto. La primera alternativa simplemente usa en 1lugar de ):

?$@#1!<

Luego, hay dos soluciones que te ayudarán con la cantidad de conmutación de IP que está ocurriendo:

)?#_[!@    1?#_[!@

Esto realmente me dejó alucinado: la parte interesante es que la conmutación de IP se puede usar como un condicional diferido. Las reglas de cambio de IP del lenguaje son tales que la IP actual da otro paso antes de que ocurra el cambio. Si ese paso pasa por una esquina, entonces el valor actual decide en qué rama continuará la IP si alguna vez volvemos a ella. Exactamente esto sucede cuando la entrada es A = B = 1. Aunque todo esto es coherente con la forma en que diseñé el lenguaje, nunca fui consciente de esta implicación de la especificación, por lo que es bueno cuando mi lenguaje me enseña algunos trucos nuevos: D.

Luego hay una tercera solución cuya cantidad de conmutación de IP es aún peor (aunque no hace uso de ese efecto condicional diferido):

>?1]#!@

Y luego hay otro:

?$@#)!<

Y luego están estas cuatro soluciones equivalentes, que utilizan una conmutación de IP no condicional y en su lugar implementan toda la lógica a través de ramas y esquinas:

]<?<@!)    ]<?<@!1    ]|?<@!)    ]|?<@!1

1111: Cierto

 1 !
@ . .
 . .

Te has ganado algo simple para el final: establece el borde en 1, imprime con !, termina con @. :)

Por supuesto, hay una alternativa:

)!@

Como de costumbre, todos los diagramas de flujo de control creados con HexagonyColorer de Timwi y el diagrama de memoria con su EsotericIDE .

Martin Ender
fuente
99
Aaaaa y el premio tl; dr va a ... (bromeando obviamente, gran respuesta y muy bien escrito, +1)
Bassdrop Cumberwubwubwub
44
Esta es la razón por la que ya no estás activo en el chat.
Optimizador
Más tarde, pero ¿podría agregar un enlace a su código de fuerza bruta?
nedla2004
@ nedla2004 Por lo general, no los guardo, pero siempre es una versión modificada de este script .
Martin Ender
40

APL 22 20 18 bytes

Las entradas verdaderas y falsas son programas completos, y las otras 14 son funciones. (Gracias a Adám.)

0000 false              0 (complete program)
0001 p and q            ∧
0010 p and not q        >
0011 p                  ⊣
0100 not p and q        <
0101 q                  ⊢
0110 xor                ≠
0111 p or q             ∨
1000 not p and not q    ⍱
1001 eq                 =
1010 not q              ~⊢
1011 p or not q         ≥
1100 not p              ~⊣
1101 not p or q         ≤
1110 not p or not q     ⍲
1111 true               1 (complete program)

Pruébalo aquí

jimmy23013
fuente
1
+1 ¡Buen uso de atops! Puede guardar dos bytes haciendo 0000 y 1111 en trad-fns 0y 1.
Adám
Existe un consenso para permitir tfns, pero no para contar la primera línea. Esto corresponde a no contar el nombre de archivo en idiomas que usan archivos como contenedores de programas con nombre de programa = nombre de archivo.
Adám
Continuemos esta discusión en el chat .
Adám
10
Jalea: 19 bytes. Esto: 18 bytes. ¿No significa esto que superaste a Dennis ? +1 por eso.
NoOneIsHere
29

Ajedrez / jugador de ajedrez mediocre en final de juego, 70 piezas

Inspirado por esa respuesta de dominó, decidí que otro juego debería tener este honor.

Tenga en cuenta que tomé algunas reglas sobre cómo se mueven las piezas. Debido a que no tengo ganas de estudiar los movimientos óptimos para cada situación, las reglas para el movimiento de los blancos son simples: mantente fuera de control, captura la pieza de mayor rango que pueda ese turno, mientras pierdes la menor cantidad de material posible y detienes un peón de promover, en ese orden de prioridad. Si hay dos espacios a los que puede moverse, con igual preferencia, puede moverse a cualquiera de ellos (por lo tanto, en estos, si puede moverse a más de un cuadrado, son del mismo color). Tenga en cuenta que el blanco capturará con algo, incluso si se captura, si la pieza que está atacando tiene un valor mayor que el perdido. Los valores están aquí:pawn<knight=bishop<rook<queen

La entrada es si una torre está presente o no. Tenga en cuenta que las torres solo se etiquetan con los nombres A y B cuando es importante: si la puerta se comporta igual cuando se cambian las torres, no se etiquetan.

La salida es el color del rey blanco cuadrado termina en: Blanco = 1, negro = 0

Antes de las imágenes, quiero disculparme por las imágenes pobres. No soy muy bueno para sostener una cámara estable.

Falso 4:

Falso

Y 4:

ingrese la descripción de la imagen aquí

A y no B, 5 (creo que puedo reducir esto a tres, pero no tengo tablero en este momento):

ingrese la descripción de la imagen aquí

A, 4:

ingrese la descripción de la imagen aquí

No A y B, 5 (creo que puedo reducir esto a tres, pero no tengo tablero en este momento):

ingrese la descripción de la imagen aquí

B, 4:

ingrese la descripción de la imagen aquí

Xor, 5 (sé una forma de hacerlo 4, pero no tengo el tablero en este momento):

ingrese la descripción de la imagen aquí

O 4:

ingrese la descripción de la imagen aquí

Ni 4:

ingrese la descripción de la imagen aquí

Xnor, 5 (sé una forma de hacerlo 4, pero no tengo el tablero en este momento):

ingrese la descripción de la imagen aquí

No B, 4:

ingrese la descripción de la imagen aquí

B implica A, 5 (creo que puedo reducir esto a tres, pero no tengo tablero en este momento):

ingrese la descripción de la imagen aquí

No A, 4:

ingrese la descripción de la imagen aquí

A implica B, 5 (creo que puedo reducir esto a tres, pero no tengo tablero en este momento):

ingrese la descripción de la imagen aquí

Nand, 4:

ingrese la descripción de la imagen aquí

Verdadero 4:

ingrese la descripción de la imagen aquí

Limón Destructible
fuente
1
Wow, no tenía idea de que la programación en ajedrez era posible ... ¿Podría publicar un video / simulación de algunos de estos en acción?
Beta Decay
2
hmmm, actualmente no tengo acceso al tablero de ajedrez. Probablemente diría que la A implica que B / B implica que a / etc son más difíciles de entender debido al efecto de los peones en el movimiento de los reyes. Probablemente debería agregar una mejor explicación para esos dos
Destructible Lemon el
Me alegra inspirar: D Si estoy entendiendo correctamente, la ubicación del tablero y la pieza son equivalentes a un programa. Las torres son la entrada, así que puedo colocarlas en cualquier cuadrado siempre que sea del color correcto.
NonlinearFruit
No, la entrada de las torres es si están presentes o ausentes del tablero. Se etiquetan como ayb cuando no son puertas simétricas (cuando importa los diferentes ayb). También me di cuenta de cómo podía jugar golf en 2 piezas, pero no tengo el tablero en este momento. Pincel debe ser utilizado :)
Destructible Lemon
En tu caso "Y", si eliminas la torre correcta, ¿qué impide que el rey se mueva hacia abajo (a blanco)?
Nathan Merrill
27

Jalea , 19 bytes

0 0 0 0 ¤  1 byte  Empty niladic chain. Returns default argument 0.
0 0 0 1 &  1 byte  Bitwise AND.
0 0 1 0 >  1 byte  Greater than.
0 0 1 1    0 bytes Empty link. Returns left argument.
0 1 0 0 <  1 byte  Less than.
0 1 0 1 ị  1 byte  At-index (x,y -> [y][x]). Returns right argument.
0 1 1 0 ^  1 byte  Bitwise XOR.
0 1 1 1 |  1 byte  Bitwise OR.
1 0 0 0 |¬ 2 byte  Logical NOT of bitwise OR.
1 0 0 1 =  1 byte  Equals.
1 0 1 0 ¬} 2 bytes Logical NOT of right argument.
1 0 1 1 *  1 byte  Exponentiation.
1 1 0 0 ¬  1 byte  Logical NOT of left argument.
1 1 0 1 >¬ 2 bytes Logical NOT of greater than.
1 1 1 0 &¬ 2 bytes Logical NOT of bitwise AND.
1 1 1 1 !  1 byte  Factorial.

Pruébalo en línea!

Dennis
fuente
13
Me encanta el uso de Factorial para convertir 0 o 1 a 1.
Neil
¿Es Jelly UTF-8? En caso afirmativo, entonces ¤y ¬son 2 bytes, no 1.
Vi.
1
@Vi. Jelly admite UTF-8, pero también admite una página de códigos personalizada que codifica cada uno de los 256 caracteres que entiende como un solo byte cada uno. El enlace de bytes en el encabezado apunta a él.
Dennis
0 0 1 0 > 1 byte Greater than.¿No fallaría esto si la segunda entrada fuera negativa?
MD XF
@MFXF Podemos elegir qué verdad y qué valor falso apoyamos.
Dennis
24

Puertas lógicas NAND - 31 puertas

Como creador de la serie original de preguntas de la compuerta NAND , no podía dejar pasar la oportunidad de usar estas compuertas para resolver otro problema de compuerta lógica.

ingrese la descripción de la imagen aquí

En cada uno de estos diagramas, la entrada superior es A mientras que la entrada inferior es B.

Joe Z.
fuente
55
@xnor podría sentirse halagado al saber que su puerta lógica es la que requiere más puertas NAND para hacer D:
Joe Z.
¿Podría al menos usar Logisim para formatear su código?
mbomb007
1
@ mbomb007 Lo editaré más tarde. No tengo tanta experiencia con Logisim, por lo que podría llevar un tiempo.
Joe Z.
3
Pero me gusta más la escritura a mano.
Leaky Nun
1
Alternativamente, podría cambiar a ni gate y formatearlo usando redstone ...
jimmy23013
22

Etiqueta cíclica bit a bit, 118 bits = 14,75 bytes

Bitwise Cyclic Tag es quizás el lenguaje Turing-complete más simple jamás ideado. Hay una cinta de programa y una cinta de datos, ambas consistentes en una lista de bits. La cinta del programa se interpreta cíclicamente hasta que la cinta de datos esté vacía, de la siguiente manera:

  • 0: elimina el primer bit de la cinta de datos.
  • 1x: si el primer bit de la cinta de datos es 1, agregue el bit xa la cinta de datos.

Inicializamos la cinta de datos con un 1 seguido de los dos bits de entrada (el 1 es necesario porque no hay forma de crear un 1 si la cinta de datos consta completamente de 0), y usamos el bit de datos eliminado final como salida de la puerta .

  • 0,0,0,0 ( false):001
  • 0,0,0,1 ( and):1001001
  • 0,0,1,0 ( A and not B):0110100
  • 0,0,1,1 ( A):1001
  • 0,1,0,0 ( not A and B):0100
  • 0,1,0,1 ( B):0
  • 0,1,1,0 ( xor):0110110010
  • 0,1,1,1 ( or):0110
  • 1,0,0,0 ( nor):1101001000
  • 1,0,0,1 ( xnor):110101001100
  • 1,0,1,0 ( not B):1100100
  • 1,0,1,1 ( B implies A):110101101000
  • 1,1,0,0 ( not A):11010000
  • 1,1,0,1 ( A implies B):11010011001
  • 1,1,1,0 ( nand):10110100100010
  • 1,1,1,1 ( true):1100
Anders Kaseorg
fuente
¡Felicidades!
Leaky Nun
Es el arrastre 1en falserequiere?
CalculatorFeline
@CalculatorFeline Sí, necesitamos agregar un 0a la cinta para que pueda eliminarse en último lugar.
Anders Kaseorg
Ah Olvidé eso + envoltura. ¡Inteligente!
CalculatorFeline
20

Python 2, 137 bytes

[].sort
min
int.__rshift__
round
range
{}.get
cmp
max
lambda a,b:a<1>b
lambda a,b:a==b
lambda a,b:b<1
pow
{0:1,1:0}.get
{0:1}.get
lambda a,b:a+b<2
slice

Toma entradas como min(True,False)(o como min(1,0)). Aprovecha enormemente las salidas que solo necesitan tener el valor correcto de Truthy-Falsey. Siempre que sea posible, utiliza un incorporado para evitar un costoso lambda. Usé código para buscar complementos que funcionen.

Mi favorita es la {0:1}.getque pensé a mano. El diccionario {0:1}asigna la clave 0al valor 1. Su getmétodo toma una clave y un valor predeterminado, generando el valor que coincide con la clave, o el valor predeterminado si no existe dicha clave. Entonces, la única forma de generar un a 0es como {0:1}.get(1,0), con clave faltante 1y predeterminada 0. Se pueden obtener otras variantes con diferentes diccionarios, pero solo esta fue la más corta.

built_in_names = list(__builtins__) 

object_names = ["int","(0)","(1)"] + \
["True","False","0L","1L","0j","1j"] + \
["str", "''", "'0'","'1'","'a'"] + \
["list", "[]", "[0]", "[1]","['']","[[]]","[{}]"] + \
["set","set()","{0}","{1}","{''}"] + \
["dict","{}","{0:0}","{0:1}","{1:0}","{1:1}","{0:0,1:0}", "{0:0,1:1}","{0:1,1:0}","{0:1,1:1}"] + \
["id"]

object_method_names = [object_name+"."+method_name 
for object_name in object_names 
for method_name in dir(eval(object_name))]

additional_func_names = [
"lambda a,b:0",
"lambda a,b:1",
"lambda a,b:a",
"lambda a,b:b",
"lambda a,b:b<1",
"lambda a,b:a<1",
"lambda a,b:a+b",
"lambda a,b:a*b",
"lambda a,b:a==b",
"lambda a,b:a-b",
"lambda a,b:a<=b",
"lambda a,b:a>=b", 
"lambda a,b:a>b", 
"lambda a,b:a<b", 
"lambda a,b:a<1>b", 
"lambda a,b:a+b<2"]

func_names = built_in_names + object_method_names + additional_func_names

t=True
f=False

cases = [(f,f),(f,t),(t,f),(t,t)]

def signature(func):
    table = [bool(func(x,y)) for x,y in cases]
    table_string = ''.join([str(int(val)) for val in table])
    return table_string

d={}

for func_name in func_names:
    try:
        func = eval(func_name) 
        result = signature(func)
        if result not in d or len(func_name)<len(d[result]):
            d[result]=func_name
    except:
        pass

total_length = sum(len(func) for sig,func in d.items())

print total_length
print

for sig in sorted(d):
    print d[sig]
xnor
fuente
¿No puedes usar métodos de integración como int's __lt__o __eq__? Estos disminuirán aún más cuenta de bytes: int.__gt__en lugar de lambda a,b:b<1, int.__eq__en lugar de lambda a,b:a==by así sucesivamente
Gábor Fekete
@ GáborFekete Esos no existen en Python 2 porque ints descargan las comparaciones con cmp. No he probado esto para Python 3.
xnor
Oh, ahora veo!
Gábor Fekete
Ahorre 4 bytes utilizando la función notpara 0001, False- ideone
Jonathan Allan
1
@JonathanAllan Eso es inteligente, pero creo que notno cumple con los requisitos de una función porque no puedes hacerlo f=not;f(3,4). La cadena notfunciona porque los supuestos argumentos de la función se ven como una tupla, del mismo modo 3+que funcionaría 3+(4)aunque 3+no sea una función que pueda tomarse 4como entrada.
xnor
20

Go (juego), 33 piedras, 73 intersecciones

Si el dominó y el ajedrez son aceptables, entonces esto. No puede ser demasiado golfista en una tabla Go completa de 19x19. Entonces utilicé pequeñas tablas rectangulares. La entrada es si las piedras marcadas 1 y 2 están presentes. La salida es si el negro gana. Utiliza puntuación de área, 0.5 komi, superko situacional, sin suicidio. Todo negro para jugar. Algunos reciben múltiples soluciones.

Las blancas ganan (2, 1x5):

➊━━━➋

1 y 2 (3, 2x3):

➊◯➋
┗┷┛

1 y no 2 (2, 1x5):

╺➊━➁╸

1 (2, 1x5):

╺➊➁━╸ 
╺➊━━➁
➀━➁━╸

No 1 y 2 (2, 1x5):

╺➋━➀╸

2 (2, 1x5):

╺➋➀━╸

1 xo 2 (2, 2x3):

➀┯➁
┗┷┛

1 o 2 (2, 1x5):

╺➊━➋╸
➀━━━➁

1 ni 2 (2, 1x4):

➊━━➋
╺➀➁╸

1 = 2 (2, 1x7):

╺━➀━➁━╸

No 2 (2, 1x3):

➀➁╸

1 o no 2 (2, 1x4):

➀➁━╸
➀━➁╸
╺➊➁╸
➋➊━╸
➋━➊╸

No 1 (2, 1x3)

➁➀╸

No 1 o 2 (2, 1x4):

➁➀━╸

1 y 2 (2, 1x3):

➊━➋

El negro gana (2, 1x3):

➊➋╸
➀━➁
➊━➁

Esta página me ayudó un poco: http://www.mathpuzzle.com/go.html

Tal vez alguien podría encontrar una solución de 2 piedras para 1 y 2 en un tablero 1x9 ...

jimmy23013
fuente
1
¿Cuáles son tus reglas para el suicidio? ¿No permitido? ¿Y qué sucede cuando un lado llena todo el tablero? ¿Eso se considera suicidio?
Martin Ender
@MartinEnder No permitido. Y sí, eso se considera suicidio.
jimmy23013
La solución 1x7 parecía incorrecta. Estoy tratando de arreglarlo ...
jimmy23013
15

Javascript ES6, 124 bytes

a=>0
Math.min
parseInt
a=>a
a=>b=>a<b
a=>b=>b
a=>b=>a^b
Math.max
a=>b=>~a&~b
a=>b=>a==b
a=>b=>~b
Math.pow
a=>~a
a=>b=>a<=b
a=>b=>~a|~b
a=>1

En serio odio las lambdas en este momento.

Mama Fun Roll
fuente
1
Si se me permite escribir algunos programas y algunas funciones ... Creo que se podría cambiar a=>b=>0a a=>0y decir la gramática llamándolo es (a=>0)(a,b), sólo para esos 4 entradas.
jimmy23013
Oh si, gracias!
Mama Fun Roll
2
Math.minen lugar de a=>b=>a&b. Math.maxen lugar de a=>b=>a|b. Math.powen lugar de a=>b=>a>=b.
Conor O'Brien
1
Además, como NaN es falsey, puedes hacerlo en parseIntlugar de hacerlo a=>b=>a>b.
Conor O'Brien
1
@algmyr !NaN=> true, !!NaN=>false
Mama Fun Roll
14

Retina , 62 39 bytes

23 bytes gracias a @MartinEnder !

0000 false              1 byte : 2
0001 p and q            2 bytes: 11
0010 p and not q        2 bytes: 10
0011 p                  2 bytes: ^1
0100 not p and q        2 bytes: 01
0101 q                  2 bytes: 1$
0110 xor                5 bytes: 01|10
0111 p or q             1 byte : 1
1000 not p and not q    2 bytes: 00
1001 xnor               5 bytes: (.)\1
1010 not q              2 bytes: 0$
1011 p or not q         5 bytes: ^1|0$
1100 not p              2 bytes: ^0
1101 not p or q         5 bytes: ^0|1$
1110 not p or not q     1 byte : 0
1111 true               0 bytes: 

Toma entrada como PQ.

Emite un número entero entre 0a 3. 0es falsey, otros son sinceros.

Explicación

Todos son solo expresiones regulares .

Por ejemplo, 01|10solo coincide 01o 10.

En 0000, 2nunca estará en la entrada, por lo que nunca coincide.

En 1111, coincide con la cadena vacía, que hay 4.

Monja permeable
fuente
^1|0$solo debe coincidir con cadenas de 1 carácter. ¿Que está pasando aqui?
CalculatorFeline
@CalculatorFeline Coincide [ 1al comienzo de la entrada] O [ 0al final de la entrada]. También me tomó un minuto entenderlo ...
ETHproductions
Precedencia, chicos ...
Leaky Nun
Supongo que ^1|0$es más difícil de leer que 1.|.0. Parece hacer que la lectura sea más difícil
l4m2
10

Pila de gatos , 67 + 64 = 131 bytes

Tenga en cuenta que el +64 es de aplicar las -nmbanderas a cada programa. -nindica E / S numéricas y -mrefleja el código fuente en el último carácter; no todas las presentaciones necesitan estas marcas técnicamente, pero por coherencia y simplicidad, las califico de la misma manera.

-2 -2 -3 -3     !I                0 0 0 0     <I!+
-4 -4 -4  1     |!T*I             0 0 0 1     [>I=I_
-4 -4  3 -2     *I*_              0 0 1 0     :I*=I:
-2 -2  3  3     T*I               0 0 1 1     [<!>X
-2  1 -2 -2     _*T*I             0 1 0 0     *|!TI:
-2  1 -3  1     !-|_I             0 1 0 1     <!I!>X
-2  3  3 -2     ^T*I              0 1 1 0     ^:]<_I
-2  3  3  3     -_T*I             0 1 1 1     *I<-I!
 2 -3 -3 -3     -*|_I             1 0 0 0     ^{!:}I_
 2 -3 -3  2     _|*I              1 0 0 1     _|[<I!:
 1 -2  1 -2     :]I*:             1 0 1 0     _!:|]X
 1 -2  1  1     *I\<X             1 0 1 1     *>I>!I
 2  2 -3 -3     -*I               1 1 0 0     I^:!
 2  2 -3  2     _*I_              1 1 0 1     |I|^:!
 1  2  2 -1     |!:^I             1 1 1 0     -I*<*I
 1  1  1  1     *<X               1 1 1 1     +I+

()en Stack Cats verifica si un elemento es positivo o no positivo (es decir, 0 o negativo), por lo que lo estamos usando para verdad / falsedad respectivamente. La segunda columna es solo de interés y enumera las mejores puertas con 0/ 1s como salidas (con un puntaje total de 90).

La entrada es bits separados por delimitador a través de STDIN. Pruébalo en línea!


Stack Cats es un lenguaje esotérico reversible, donde los programas tienen simetría reflexiva. Dado un fragmento f(p >[[(!-)/. Ej. ), La imagen especular (p \(-!)]]<. Ej. ) Calcula el inverso f^-1. Como tal, los programas de longitud uniforme no hacen nada (o se atascan en un bucle infinito), y los únicos programas no triviales tienen una longitud impar, calculando f g f^-1dónde gestá el operador central.

Dado que la mitad del código fuente siempre es redundante, se puede omitir, y ejecutar el código con el -mindicador indica que el código fuente debe reflejarse en el último carácter para recuperar el código fuente real. Por ejemplo, el programa *<Xes en realidad *<X>*simétrico.

Jugar al golf en Stack Cats es muy poco intuitivo, por lo que los programas anteriores tuvieron que ser encontrados por la fuerza bruta. La mayoría de ellos son sorprendentemente complejos, pero explicaré algunos y agregaré a esta respuesta cuando tenga tiempo. Por ahora, algunas explicaciones y soluciones alternativas para las versiones 0/ 1se pueden encontrar en el repositorio de Github aquí .

Sp3000
fuente
1
Note that the +64 is from applying the -nm flags to each program.3 * 16 = 48 o 2 * 16 = 32, de cualquier forma 64 es hai
cat
@cat Las banderas cuestan 4 por programa, ya que también debes contar el espacio.
FryAmTheEggman
@cat meta meta relevante: meta.codegolf.stackexchange.com/questions/273/…
Martin Ender
Ha pasado más de un año. ¿Ya tienes tiempo?
CalculatorFeline
8

Haskell, 78 76 75 bytes

  1. _#_=2<1
  2. &&
  3. >
  4. pure
  5. <
  6. _#b=b
  7. /=
  8. ||
  9. (not.).max
  10. ==
  11. _#b=not b
  12. >=
  13. a#_=not a
  14. <=
  15. (not.).min
  16. _#_=1<2

Editar: -1 byte gracias a @cole.

nimi
fuente
Estaba a punto de comentar "amigo, ¡ _#_no es un operador estándar!" Y luego me di cuenta ... Bien hecho.
MathematicalOrchid
4 podría serpure
cole
@cole: Gracias. Wow, purese introdujo Preludeen 2015, por lo que estaba disponible en el momento de este desafío.
nimi
6

Brachylog , 36 34 bytes

0000 false              \     Backtrack (always false)
0001 p and q            1.    Unify input and output with 1
0010 p and not q        >.    Input > Output
0011 p                  1     Unify input with 1
0100 not p and q        <.    Input < Output
0101 q                  ,1.   Unify output with 1
0110 xor                '.    Input and output cannot unify
0111 p or q             1;1.  Unify input with 1 or unify output with 1
1000 not p and not q    0.    Unify input and output with 0
1001 eq                 .     Unify input with output
1010 not q              ,0.   Unify output with 0
1011 p or not q         >=.   Input >= Output
1100 not p              0     Unify input with 0
1101 not p or q         <=.   Input <= Output
1110 not p or not q     0;0.  Unify input with 0 or unify output with 0
1111 true                     Empty program (always true)

Esto se espera 0como valor falso y 1como valor verdadero. Devoluciones trueo false. p es Inputy q es Output.

Fatalizar
fuente
¿Cómo ingresas la salida?
Leaky Nun
1
@LeakyNun Al igual que la entrada. El predicado principal que consulta tiene dos argumentos, llamados Inputy Outputpor convención, pero puede establecer valores en ambos o devolver valores de ambos.
Fatalize
1
Esta es la herramienta adecuada para el trabajo: P
Conor O'Brien
6

Prólogo, 147 145 bytes

Ganó 2 bytes gracias a @SQB

a(a,a).       % 0000 false
b(1,1).       % 0001 P and Q
c(1,0).       % 0010 P and not Q
d(1,_).       % 0011 P
e(0,1).       % 0100 not P and Q
f(_,1).       % 0101 Q
g(P,Q):-P\=Q. % 0110 P xor Q
h(1,_).       % 0111 P or Q
h(0,1).
i(0,0).       % 1000 not P and not Q
j(P,P).       % 1001 P == Q                 
k(_,0).       % 1010 not Q
m(P,Q):-P>=Q. % 1011 P or not Q
n(0,_).       % 1100 not P              
r(P,Q):-P=<Q. % 1101 not P or Q         
s(0,_).       % 1110 not P or not Q
s(1,0).
t(_,_).       % 1111 true

Consulte x(P,Q).con xser la letra adecuada Py Qestablecer en 0 o 1.
Devuelve trueo false.

Ejemplo de SWISH que incluye pruebas : ingrese runTest.para ejecutar.

Fatalizar
fuente
¿Es compatible a(2,2).con falso?
jimmy23013
@ jimmy23013 Creo que podría suponer que supongo que 2 es falso. No estoy seguro si eso es aceptable.
Fatalize
@ jimmy23013 En realidad, a(a,a).(o cualquier otra letra) también funciona y ano es una entrada aceptable para la verdad, así que eso es bueno. Gracias por la sugerencia.
Fatalize
6

NTFJ, 86 bytes

0000 false              ~
0001 p and q            |:|
0010 p and not q        :||:|
0011 p                  $
0100 not p and q        #{:||:|
0101 q                  #{$
0110 xor                :#{:#{:||#}:|||
0111 p or q             :|#{:||
1000 not p and not q    :|#{:||:|
1001 eq                 :#{:#{:||#}:|||:|
1010 not q              #{$:|
1011 p or not q         #{:||
1100 not p              $:|
1101 not p or q         :||
1110 not p or not q     |
1111 true               #

Pruébalo aquí! Pero lea a continuación primero.

La entrada está implícita en la pila. El resultado se deja en la pila. Agregue 16 bytes (uno *al final de cada uno) si lo desea 0x00o 0x01una salida que represente 0 y 1. Agregue 160 bytes adicionales si desea un 0o un 1impreso. (Poner ~~##~~~#{@antes de cada uno *)

El único operador binario de NTFJ es NAND, por lo que cada uno de estos está escrito en forma NAND.

Veamos cada uno de ellos.

0: falso

~

~representa un bit falso Suficientemente simple. Como la entrada está implícita en la parte inferior de la pila, esta se deja en la parte superior.

1: p y q

|:|

NTFJ opera en una pila. :es el comando para duplicar. Observe que p and qnot (p nand q)y eso not q = q nand q.

Command | Stack
        | p q
   |    | (p nand q)
   :    | (p nand q) (p nand q)
   |    | (p nand q) nand (p nand q)
        | => not (p nand q)
        | => p and q

(Nota, entonces, :|se puede decir que es negación y |:|se puede decir que es conjunción )

2: p y no q

:||:|

Observe que esto es solo una negación :|y una conjunción |:|.

Command | Stack
        | p q
  :|    | p (not q)
  |:|   | p and (not q)

3: p

$

$saca un elemento de la pila. Así que sí.

4: no p y q

#{:||:|

Esto es lo mismo que 2, excepto con #{al principio. #empuja 1 (el bit verdadero) y {gira la pila hacia la izquierda una vez. Suficientemente simple.

5: q

#{$

Girar a la izquierda una vez, soltar.

6: xor

:#{:#{:||#}:|||

Observar:

p xor q = (p and (not q)) or ((not p) and q)                ; by experimentation (trust me)
        = (not ((not p) nand q)) or (not (p nand (not q)))  ; by definition of nand
        = not (((not p) nand q) and (p nand (not q)))       ; by De Morgan's laws
        = ((not p) nand q) nand (p nand (not q))            ; by definition of nand

Sin embargo, no hay forma de duplicar la pila por completo. Por lo tanto, vamos a tener que llevar a cada uno de p, qa la parte superior y duplicarlo.

Command | Stack
        | p q
   :    | p q q
  #{    | q q p
   :    | q q p p
  #{    | q p p q
  :|    | q p p (not q)
   |    | q p (p nand (not q))
  #}    | (p nand (not q)) q p
  :|    | (p nand (not q)) q (not p)
   |    | (p nand (not q)) (q nand (not p))
   |    | (p nand (not q)) nand (q nand (not p))

Y así, tenemos nuestro xor.

7: p o q

:|#{:||

Negar la parte superior, llevar de abajo hacia arriba, negar eso y juntarlos. Básicamente, p or q = (not p) nand (not q).

8: no p y no q

:|#{:||:|

Esto es simplemente la negación de 7. Fácil.

9: eq

:#{:#{:||#}:|||:|

Esto es solo xnor , o no xor. Simple de nuevo.

10: no q

#{$:|

Negación de 5.

11: p o no q

#{:||

Negate p, nand. (not p) nand q = not ((not p) and q) = p or (not q) (by De Morgan's laws).

12: no p

$:|

Caer, detenerse y negar.

13: no p o q

:||

¡Las leyes de De Morgan para salvar el día, otra vez! El mismo proceso que 11, solo negando en qlugar de p.

14: no p o no q

|

Esto es solo una imitación nand.

15: cierto

#

# Es la parte verdadera.

Conor O'Brien
fuente
por qué ...> _>
Rɪᴋᴇʀ
idk exactamente cómo funciona esto, pero parece bastante genial +1
Downgoat
¿Por qué 5 no es solo un programa vacío y 10 solo :|?
Joffan
6

Minecraft, 89 bloques

En todas las siguientes fotos, los bloques azules son para la Entrada A y los bloques naranjas son para la Entrada B

16. VERDADERA puerta - 1 cuadras

ingrese la descripción de la imagen aquí

15. Puerta NAND - 1x2x3 = 6 bloques

ingrese la descripción de la imagen aquí

14. A => B - 1x2x3 = 6 bloquesingrese la descripción de la imagen aquí

13. NO A - 2 bloques ingrese la descripción de la imagen aquí

12. B => A - 1x2x3 = 6 bloquesingrese la descripción de la imagen aquí

11. NO B - 2 bloques ingrese la descripción de la imagen aquí

10. XNOR - 1x3x4 = 12 bloques ingrese la descripción de la imagen aquí

9. NOR - 1x2x3 = 6 bloquesingrese la descripción de la imagen aquí

8. O - 1 bloques ingrese la descripción de la imagen aquí

7. XOR - 1x3x4 = 12 bloques ingrese la descripción de la imagen aquí

6. B - 1 bloques ingrese la descripción de la imagen aquí

5.! A&B - 1x2x5 = 10 bloques ingrese la descripción de la imagen aquí

4. A - 1 bloques ingrese la descripción de la imagen aquí

3. A &! B - 1x2x5 = 10 bloques ingrese la descripción de la imagen aquí

2. Y - 2x2x3 = 12 bloques ingrese la descripción de la imagen aquí

1. FALSO- 1 bloques ingrese la descripción de la imagen aquí

Husnain Raza
fuente
2
En la penúltima imagen (Y), puede guardar 6 bloques colocando las antorchas en la parte superior de la parte posterior de los bloques, es decir, opuestas a las palancas. Cambie la antorcha en el medio por un pedazo de polvo y elimine el polvo en la parte superior, bajando a 1x2x3 = 6 bloques.
Luca H
5

Mathematica, 67 bytes

0>1&
And
#&&!#2&
#&
!#&&#2&
#2&
Xor
Or
Nor
Xnor
!#2&
#||!#2&
!#&
!#||#2&
Nand
1>0&

Cada uno de estos se evalúa como una función, por lo que puede usarlos como

#&&!#2&[True, False]
Xor[True, False]

Ah, si solo los enteros fueran verdadero / falso en Mathematica, esos cuatro más largos podrían haberse acortado considerablemente.

Martin Ender
fuente
Si los enteros no son veraz / falsey, ¿qué sucede cuando los pones en una declaración if?
Conor O'Brien
3
@ CᴏɴᴏʀO'Bʀɪᴇɴ permanece sin evaluar.
Martin Ender
5

MATL, 34 23 bytes

¡Espero haber recibido el pedido bien! Zero es falsey, non-zero es verdadero. Cada función toma dos entradas implícitas (aunque puede ignorar algunas entradas). La primera entrada es A y la segunda es B. Puede ingresar 0/ 1para verdadero / falso o T/ F.

Aquí hay un ejemplo de TryItOnline para el caso de prueba 3.

¡Ahorré 4 bytes usando *for and, y otros 4 usando >/ en <lugar de ~wY&/ w~Y&después de que vi la respuesta de Dennis!

1.  0,0,0,0 0 (ignores input, just returns a zero)
2.  0,0,0,1 * (and)
3.  0,0,1,0 < (not-A and B)
4.  0,0,1,1 D (A)
5.  0,1,0,0 > (not-B and A)
6.  0,1,0,1 xD (discard A, display B)
7.  0,1,1,0 Y~ (xor)
8.  0,1,1,1 + (or)
9.  1,0,0,0 +~ (not-or)
10. 1,0,0,1 = (A=B)
11. 1,0,1,0 x~ (not-B)
12. 1,0,1,1 <~ (not-B or A)
13. 1,1,0,0 ~ (not-A)
14. 1,1,0,1 ~+ (not-A or B)
15. 1,1,1,0 *~ (not(A and B))
16. 1,1,1,1 1 (just returns 1)
David
fuente
10
El número seis piensa que es gracioso.
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ El número 6 es el mejor, ¡también me gusta el número 12! xD!
David
¿No tienes la función "desigual"?
Leaky Nun
No (al menos no lo creo)
David
2
@David Creo que el número 7 puede ser reemplazado por-
Luis Mendo
5

cc, 37 bytes

dc("calculadora de escritorio") es un comando estándar de Unix, una calculadora postfix basada en pila. Carece de operaciones de bits, y los operadores de comparación solo se pueden usar para ejecutar macros (lo que no vale los bytes). La división entera compensa algo de eso.

Estos scripts esperan 0y 1valores en la pila, y dejan el resultado en la pila.

0,0,0,0 (false)              0
0,0,0,1 (and)                *         a*b
0,0,1,0                      -1+2/     (a-b+1)/2
0,0,1,1 (A)                  r         reverse a, b: a now on top
0,1,0,0                      -1-2/     (a-b-1)/2
0,1,0,1 (B)                            (0 bytes) do nothing: b on top
0,1,1,0 (xor)                -         a-b
0,1,1,1 (or)                 +         a+b                  
1,0,0,0 (nor)                +v1-      sqrt(a+b) -1
1,0,0,1 (xnor)               +1-       a+b-1
1,0,1,0 (not B)              1-        b-1
1,0,1,1 (if B then A)        -1+       a-b+1
1,1,0,0 (not A)              r1-       a-1
1,1,0,1 (if A then B)        -1-       a-b-1            
1,1,1,0 (nand)               *1-       a*b - 1
1,1,1,1 (true)               1
alexis
fuente
5

Laberinto , 85 bytes

Gracias a Sp3000 por guardar 2 bytes.

!@
??&!@
??~&!@
?!@
?~?&!@
??!@
??$!@
??|!@
??|#$!@
??$#$!@
?#?$!@
?#?$|!@
?#$!@
?#$?|!@
??&#$!@
1!@

Todos estos son programas completos, que leen dos enteros 0o 1de STDIN (usando cualquier separador que no sea un dígito), e imprimen el resultado como 0o 1en STDOUT.

Pruébalo en línea! (No es un conjunto de pruebas, por lo que deberá probar diferentes programas y entradas manualmente).

En cuanto a las explicaciones, todo esto es bastante sencillo. Todos los programas son lineales, y los comandos en uso hacen lo siguiente:

?   Read integer from STDIN and push.
!   Pop integer and write to STDOUT.
@   Terminate program.
&   Bitwise AND of top two stack items.
|   Bitwise OR of top two stack items.
$   Bitwise XOR of top two stack items.
~   Bitwise NOT of top stack item.
#   Push stack depth (which is always 1 when I use it in the above programs).
1   On an empty stack, this pushes 1.

Tenga en cuenta que lo que estoy usando #siempre se usa para combinarlo $, es decir, para calcular XOR 1, o en otras palabras, para la negación lógica. Solo en unos pocos casos pude usar ~en su lugar, porque el siguiente &descarta todos los bits no deseados del resultado -1o -2.

Martin Ender
fuente
5

Código de máquina IA-32, 63 bytes

Hexdump del código, con el desmontaje:

0000  33 c0     xor eax, eax;
      c3        ret;

0001  91        xchg eax, ecx;
      23 c2     and eax, edx;
      c3        ret;

0010  3b d1     cmp edx, ecx;
      d6        _emit 0xd6;
      c3        ret;

0011  91        xchg eax, ecx;
      c3        ret;

0100  3b ca     cmp ecx, edx;
      d6        _emit 0xd6;
      c3        ret;

0101  92        xchg eax, edx;
      c3        ret;

0110  91        xchg eax, ecx;
      33 c2     xor eax, edx;
      c3        ret;

0111  8d 04 11  lea eax, [ecx + edx];
      c3        ret;

1000  91        xchg eax, ecx; // code provided by l4m2
      09 d0     or eax, edx;
      48        dec eax;
      c3        ret;

1001  3b ca     cmp ecx, edx;
      0f 94 c0  sete al;
      c3        ret;

1010  92        xchg eax, edx;
      48        dec eax;
      c3        ret;

1011  39 d1     cmp ecx, edx; // code provided by l4m2
      d6        _emit 0xd6;
      40        inc aex;
      c3        ret;

1100  91        xchg eax, ecx;
      48        dec eax;
      c3        ret;

1101  3b d1     cmp edx, ecx; // code inspired by l4m2
      d6        _emit 0xd6;
      40        inc aex;
      c3        ret;

1110  8d 44 11 fe   lea eax, [ecx+edx-2] // code provided by l4m2
      c3        ret;

1111  91        xchg eax, ecx;
      40        inc eax;
      c3        ret;

El código es más larga que podría ser, ya que utiliza una convención estándar de codificación: entrada en ecxy edx, y la producción en al. Esto puede expresarse en C como

unsigned char __fastcall func(int, int);

Parece que MS Visual Studio no entiende el SALCcódigo de operación indocumentado , así que tuve que usar su código, en lugar de su nombre.

¡Gracias l4m2 por mejorar algunas de las muestras de código!

anatolyg
fuente
1
1110 8D4411FE LEA EAX, [ECX+EDX-2]
l4m2
5

C 34 bytes

#define g(n,a,b)((n-1)>>3-b-2*a)&1

Donde n es el número de función a usar, pero creo que sería rechazado, así que propongo este otro:

C 244 bytes (usando memoria)

typedef int z[2][2];
z a={0,0,0,0};
z b={0,0,0,1};
z c={0,0,1,0};
z d={0,0,1,1};
z e={0,1,0,0};
z f={0,1,0,1};
z g={0,1,1,0};
z h={0,1,1,1};
z i={1,0,0,0};
z j={1,0,0,1};
z k={1,0,1,0};
z l={1,0,1,1};
z m={1,1,0,0};
z n={1,1,0,1};
z o={1,1,1,0};
z p={1,1,1,1};

Utiliza doble matriz indexada. n[0][1]es(A implies B)(0,1)

138 bytes

Acabo de enterarme de Forth. Supongo que es compatible con Ansi Forth, ya que también se ejecuta en gforth.

: z create dup , 1+ does> @ -rot 3 swap - swap 2* - rshift 1 and ; 
0 
z a z b z c z d z e z f z g z h z i z j z k z l z m z n z o z p 
drop

La función z crea una nueva función con el nombre proporcionado y luego coloca el número de puerta lógica desde la parte superior de la pila a la nueva dirección de la función. Deja la siguiente función de puerta lógica (n + 1) en la pila para la próxima declaración.

puedes probarlo:
Y AB

0 0 b . cr 
0 1 b . cr
1 0 b . cr 
1 1 b . cr   

("." imprime la parte superior de la pila "cr" es el retorno del carro)

Emmanuel
fuente
Solo tiene que proporcionar fragmentos de código para cada función.
CalculatorFeline
4

C, 268 bytes

#define c(a,b)0      // 0000 
#define d(a,b)a&b    // 0001 
#define e(a,b)a>b    // 0010 
#define f(a,b)a      // 0011 
#define g(a,b)a<b    // 0100 
#define h(a,b)b      // 0101 
#define i(a,b)a^b    // 0110 
#define j(a,b)a|b    // 0111 
#define k(a,b)!b>a   // 1000 
#define l(a,b)a==b   // 1001 
#define m(a,b)!b     // 1010 
#define n(a,b)!b|a   // 1011 
#define o(a,b)!a     // 1100 
#define p(a,b)!a|b   // 1101 
#define q(a,b)!b|!a  // 1110 
#define r(a,b)1      // 1111 

Las macros parecen más cortas que las funciones.

anatolyg
fuente
4

Brian y Chuck , 183 bytes

Gracias a Sp3000 por guardar 4 bytes.

Algunos de los programas contienen un carácter no imprimible. En particular, cada uno \x01debe reemplazarse con el <SOH>carácter de control (0x01):

0000
?
#>.
0001
,-?,-?>?\x01
#}>.
0010
,-?,?>?\x01
#}>.
0011
,?\x01+?
#>.
0100
,?,-?>?\x01
#}>.
0101
,,?\x01+?
#>.
0110
,?>},?>?_\x01
#}+{>?_}>.
0111
,\x01?,?>?
#{>.
1000
,?,?>?\x01
#}>.
1001
,-?>},?>?_\x01
#}+{>>?_}>.
1010
,,-?\x01+?
#>.
1011
,\x01?,-?>?
#{>.
1100
,-?\x01+?
#>.
1101
,\x01-?,?>?
#{>.
1110
,\x01-?,-?>?
#{>.
1111
?
#>+.

La entrada y la salida usan valores de byte , por lo que la entrada debe ser de 0x00 o 0x01 bytes (sin separador) y la salida será uno de esos bytes. En realidad, esta es también la definición más sensata de verdad / falsedad para B&C porque el único comando de flujo de control ?considera los ceros como falsedad y todo lo demás como verdad.

Explicaciones

Primero una cartilla rápida de B&C:

  • Cada programa consta de dos instancias tipo Brainfuck, cada una escrita en su propia línea. Llamamos al primero Brian y al segundo Chuck . La ejecución comienza en Brian.
  • La cinta de cada programa es el código fuente del otro programa, y ​​el puntero de instrucción de cada programa es el cabezal de la cinta del otro programa.
  • Solo Brian puede usar el ,comando (byte de entrada) y solo Chuck puede usar el .comando (byte de salida).
  • El []bucle de Brainfuck no existe. En cambio, el único flujo de control que tiene es el ?que cambia el control a la otra instancia si el valor actual debajo del cabezal de la cinta no es cero.
  • Además de >y <, hay {y }que son esencialmente equivalentes a los fragmentos de Brainfuck [<]y [>], es decir, mueven el cabezal de la cinta a la siguiente posición cero en esa dirección. La principal diferencia es que {también se puede detener en el extremo izquierdo de la cinta, independientemente del valor que tenga.
  • Por conveniencia, cualquier _s en el código fuente se reemplaza con bytes nulos (ya que estos son muy útiles en programas no triviales para capturar {y }).

Tenga en cuenta que en todos los programas, la cinta de Chuck comienza con a #. Esto realmente podría ser cualquier cosa. ?funciona de tal manera que el cabezal de la cinta mueve una celda antes de comenzar la ejecución (de modo que la condición en sí no se ejecuta si es un comando válido). Entonces, nunca podemos usar la primera celda de Chuck para el código.

Hay cinco clases de programas, que explicaré en detalle más adelante. Por ahora los estoy enumerando aquí en orden de complejidad creciente.

0000, 1111: Funciones constantes

?
#>.
?
#>+.

Estos son muy simples. Cambiamos a Chuck incondicionalmente. Chuck mueve el cabezal de la cinta hacia la celda no utilizada hacia la derecha y lo imprime directamente o lo incrementa primero para imprimir 1.

0011, 0101, 1010, 1100: Funciones dependiendo de una sola entrada

,?\x01+?
#>.
,,?\x01+?
#>.
,,-?\x01+?
#>.
,-?\x01+?
#>.

Dependiendo de si comenzamos con ,o ,,estamos trabajando con Ao B. Veamos el primer ejemplo 0011(es decir A). Después de leer el valor, lo usamos ?como condicional en ese valor. Si A = 1, entonces esto cambia a Chuck, que mueve el cabezal de la cinta hacia la derecha e imprime el 1byte literalmente incrustado . De lo contrario, el control permanece en Brian. Aquí, el 1 byte es un no-op. Luego incrementamos bien la entrada +para asegurarnos de que no sea cero y luego cambiamos a Chuck con ?. Esta vez, se >mueve a una celda no utilizada a la derecha que luego se imprime como 0.

Para negar uno de los valores, simplemente lo decrementamos -. Esto se convierte 1en 0y 0en -1, que no es cero y, por lo tanto, es verdad en lo que ?respecta.

0001, 0010, 0100, 1000: Funciones binarias con un resultado Truthy

,-?,-?>?\x01
#}>.
,-?,?>?\x01
#}>.
,?,-?>?\x01
#}>.
,?,?>?\x01
#}>.

Esta es una extensión de la idea anterior para trabajar con dos entradas. Veamos el ejemplo de 1000(NOR). Nosotros (potencialmente) leemos ambas entradas con ,?. Si alguno de esos es 1, los ?cambios a Chuck. Mueve la cabeza de la cinta hasta el final con }(en la celda vacía después del código de Brian), mueve otra celda con >(todavía cero) y la imprime con ..

Sin embargo, si ambas entradas son cero, entonces el control todavía está con Brian. >luego mueve la cabeza de la cinta al }tal que este comando no se ejecuta cuando cambiamos a Chuck con ?. Ahora todo lo que hace Chuck es >.que solo se mueve a la 1celda e imprime eso.

Podemos obtener fácilmente las otras tres funciones negando una o ambas entradas según sea necesario.

0111, 1011, 1101, 1110: Funciones binarias con tres resultados Truthy

,\x01?,?>?
#{>.
,\x01?,-?>?
#{>.
,\x01-?,?>?
#{>.
,\x01-?,-?>?
#{>.

Una modificación menor de la idea anterior para negar el resultado (es decir, imprimir 0cuando hayamos pasado por todo Brian y de 1otro modo). Veamos 0111(OR) como un ejemplo. Tenga en cuenta que el 1byte incrustado no funciona, por lo que esto todavía comienza con ,?,?. Si alguna de las entradas es, 1cambiamos a Chuck, que mueve la cabeza de la cinta al comienzo con {. >.mueve la cabeza de la cinta a ese 1byte e imprime.

Si ambas entradas son cero, entonces permanecemos con Brian, mueve el cabezal de la cinta {para omitirlo y luego cambia a Chuck. Cuando ejecuta >.esta vez, pasa a la celda vacía después del código de Brian e imprime el 0.

Nuevamente, obtenemos fácilmente las otras funciones al negar una o ambas entradas.

0110, 1001: Funciones binarias con dos resultados verdaderos

,?>},?>?_\x01
#}+{>?_}>.
,-?>},?>?_\x01
#}+{>>?_}>.

Este es un poco más complicado. Las funciones anteriores eran razonablemente simples porque pueden estar en cortocircuito : el valor de la primera entrada puede decidir la salida, y si no es así, miramos la otra entrada. Para estas dos funciones, siempre necesitamos mirar ambas entradas.

La idea básica es usar la primera entrada para decidir si la segunda entrada elige entre 0y 1o entre 1y 0. Tomemos 0110(XOR) como ejemplo:

Considere A = 0. En este caso, queremos que salga Bcomo está. ,lee A, ?no hace nada. >se mueve a la siguiente celda (distinta de cero) para que }nos lleve al _Chuck. Aquí, leemos Bcon ,y utilizar ?de nuevo. Si Bfue 0así, todavía estamos en Brian. >se salta el }Chuck y ?cambia para que se >.imprima 0en el código fuente de Brian. Si B, 1por otro lado, Chuck ejecuta el }que ya se mueve en el _código de Brian, >.entonces imprime el 1byte en su lugar.

Si A = 1, entonces cambiamos a Chuck de inmediato, quién ejecutará }+{>?. Lo que esto hace es moverse al _código fuente de Brian, convertirlo en un 1también con +, luego volver al inicio {y omitir el de Brian ?moviendo una celda a la derecha >antes de devolverle el control. Esta vez, después de que Brian leyó B, si B = 0, y Chuck usa >.la celda al lado de Brian ?será en 1lugar de 0. Además, cuando B = 1, Chuck }salta sobre lo que solía ser un hueco y se mueve hasta el final de la cinta, por lo que >.imprime un cero. De esta manera estamos imprimiendo not B.

Para implementar la equivalencia, simplemente negamos Aantes de usarla como condición. Tenga en cuenta que debido a esto también necesitamos agregar otro >a Chuck para omitir eso -también al regresar al inicio.

Martin Ender
fuente
4

ClojureScript, 88 84 76 74 bytes

nily falseson falsas, todos los demás valores son verdaderos. Los booleanos obligan a 0/1 para la aritmética y las desigualdades. Las funciones pueden tomar el número incorrecto de argumentos.

0000   nil?            ; previously: (fn[]nil)
0001   and
0010   <
0011   true?           ; previously: (fn[x]x)
0100   >
0101   (fn[x y]y)
0110   not=
0111   or
1000   #(= 0(+ % %2))
1001   =
1010   #(not %2)
1011   <=
1100   not
1101   >=
1110   #(= 0(* % %2))
1111   /               ; previously: (fn[]4), inc
MattPutnam
fuente
¿No es 0falso?
Leaky Nun
2
No en ClojureScript.
MattPutnam
@LeakyNun No en la mayoría de los LISP o lenguajes de programación funcionales, que Clojure definitivamente es
cat
@cat ¡ en la mayoría de los lenguajes de programación funcionales! Python, por ejemplo, evalúa not not(0)a False, que es el valor de falsey.
Erik the Outgolfer
3
@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Er ... Python no es puramente funcional ni el tipo de lenguaje funcional del que estoy hablando. Python es imprescindible, en su mayoría, y con algunos aspectos funcionales más pequeños (mal ejecutados). Erlang, Haskell (creo), Common LISP, Clojure, Raqueta, Esquema, Factor, Standard ML, CAML Objetivo, etc 0 es sólo otro valor y es como resultado Truthy, y el símbolo de falso ( #f, f, false, etc.) es falso. Todos los demás valores son verdaderos en la mayoría de los lenguajes funcionales.
gato
4

Brainfuck , 184 178 174 bytes

La entrada / salida usa U + 0000 y U + 0001.

0000 .
0001 ,[,[->+<]]>.
0010 ,[,-[+>+<]]>.
0011 ,.
0100 ,-[,[->+<]]>.
0101 ,,.
0110 ,>,[-<->]<[>>+<]>.
0111 ,-[,-[+>-<]]>+.
1000 ,-[,-[+>+<]]>.
1001 ,>,[-<->]<[>>-<]>+.
1010 ,,-[+>+<]>.
1011 ,-[,[->-<]]>+.
1100 ,-[+>+<]>.
1101 ,[,-[+>-<]]>+.
1110 ,[,[->-<]]>+.
1111 +.
Monja permeable
fuente
Su lectura de una segunda entrada condicional parece cara. Por ejemplo 0001, ¿no podría simplemente hacerlo ,[,>]<.(dado un intérprete que le permite ir a la izquierda de la celda inicial)?
Martin Ender
@ MartinEnder Pensé que no copiaría la respuesta de Dennis aquí.
Leaky Nun
4

Brain-Flak , 418 , 316 bytes

Pruébalo en línea!

Deje que las entradas sean los dos números superiores en la pila al comienzo del programa (cero para falso uno para verdadero) y la salida sea la parte superior de la pila al final del programa (cero para falso más para verdadero).

falso, 4 bytes (Cortesía de Leaky Nun )

(<>)

y 36 bytes

(({}{}[(())()])){{}{}(((<{}>)))}{}{}

A y no B, 40 bytes

((({}){}{}[(())()])){{}{}(((<{}>)))}{}{}

A, 6 bytes

({}<>)

no A y B, 38 bytes

((({}){}{}[(())])){{}{}(((<{}>)))}{}{}

B, 2 bytes

{}

xor, 34 bytes

(({}{}[(())])){{}{}(((<{}>)))}{}{}

o 6 bytes

({}{})

ni 34 bytes

(({}{}<(())>)){{}{}(((<{}>)))}{}{}

xnor, 10 bytes

({}{}[()])

no B, 34 bytes

{}(({}<(())>)){{}{}(((<{}>)))}{}{}

B implica A, 14 bytes

(({}){}{}[()])

no A, 34 bytes

(({}<{}(())>)){{}{}(((<{}>)))}{}{}

A implica B, 16 bytes

(({}){}{}[()()])

nand, 12 bytes

({}{}[()()])

verdadero, 6 bytes

<>(())

Explicación

Como la mayoría de estos son muy similares, no voy a explicar exactamente cómo funciona cada uno de ellos. Sin embargo, hago todo lo posible para aclarar cómo funcionan los dieciséis.

En primer lugar, están las puertas que devuelven tres del mismo valor (es decir, 2, 3, 5, 8, 9, 12, 14 y 15). Todos estos siguen el mismo patrón. Primero, convierte la entrada en un número de dos bits con a como los dos y B como los. Esto se hace con este fragmento (({}){}{}). Luego resta el valor de la entrada de dos bits que desea aislar ({}[value]). (En el código real, la resta y la conversión se realizan en un solo paso para guardar bytes). Esto se puede combinar con un no, si es necesario: (({}<(())>)){{}{}(((<{}>)))}{}{}.

Siguiente: y, ni, o, xor y xnor. Estos funcionan de manera similar a los anteriores. De hecho, algunos de estos se incluyen anteriormente, sin embargo, este método es más corto. El truco que utilicé aquí es que cada uno corresponde a una suma de A B. por ejemplo, xor se evalúa como verdadero si A + B = 1 y falso de lo contrario. Primero agrega AB y resta la cantidad relevante. Expresado como ({}{}[0,1,2 or 3]). Entonces, si es necesario, realice una no

A continuación: A, B, no A y no B. Estos se explican por sí mismos. Comenzamos eliminando el valor innecesario y luego lo negamos o terminamos.

Por último, están los dos simplones: verdadero y falso. Para estos, empujamos el valor correcto al off stack. El <>nilad devuelve cero para que podamos guardar dos bytes usando el interruptor como el valor cero.

No es la solución más eficiente que existe (quizás la más eficiente en Brain-Flak), pero me divertí mucho escribiendo esto y te imploro que intentes acortarlo.

Asistente de trigo
fuente
(<>)es suficiente para false; también, (<{}{}>)es de 8 bytes
Leaky Nun
Wow, tenía una definición mucho más estricta del desafío. Gracias. Reduciré esto en gran medida
Wheat Wizard
¿Qué quieres decir?
Leaky Nun
Pensé que tenía que eliminar las entradas existentes y colocar el resultado en su lugar. (<>)dejará las entradas y pondrá el cero en la otra pila.
Wheat Wizard
1
¿No es <>suficiente falsedebido a ceros implícitos? Además, creo que apuede ser el programa vacío. truepuede ser <>[][](no guarda bytes, pero se ve genial: P).
CalculatorFeline
4

ProgFk , 18.5 17.5 bytes

Como las instrucciones de ProgFk se especifican en nibbles, el siguiente código se proporciona en hexadecimal, una puerta lógica por línea y con espacios entre los bytes.

3
E1
DE 2D
<empty>
DE 1
1
E3
E2
E2 D
E3 D
1D
DE 2
D
DE 1D
E1 D
4

Explicación

ProgFk es un esolang basado en cinta (similar a Brainfuck) donde cada celda es un bit y las instrucciones se dan como mordiscos (4 bytes). Las instrucciones operan en la celda señalada por el puntero de instrucciones. La entrada se proporciona en la primera y segunda celdas (siendo Ay Bsiendo la primera y la segunda celdas respectivamente), y el puntero de instrucción comienza en la primera celda. La salida se almacena en la primera celda.

Cada instrucción utilizada se explica a continuación.

1   Increment the instruction pointer.
2   Decrement the instruction pointer.
3   Set the current bit to 0.
4   Set the current bit to 1.
D   Perform a NOT on the current bit.
E   The next instruction is an extended instruction.

Extended instructions:
1   Set the current bit to the current bit AND the next bit.
2   Set the current bit to the current bit OR the next bit.
3   Set the current bit to the current bit XOR the next bit.
6   Swap the current bit and the next bit.

¡Ahorré un byte gracias a @LeakyNun!

Cobre
fuente
4

En realidad, 24 bytes

Estos programas toman la entrada como A\nB(con la \nrepresentación de una nueva línea), que deja a B en la parte superior de la pila, con A debajo. Falseestá representado por 0y Trueestá representado por cualquier número entero positivo.

é0  (false: clear stack, push 0)
*   (and: multiply)
<   (A and not B: less-than)
X   (A: discard B)
>   (B and not A: greater-than)
@X  (B: discard A)
^   (A xor B: xor)
|   (A or B: or)
|Y  (A nor B: or, boolean negate)
=   (A xnor B: equals)
@XY (not B: discard A, boolean negate B)
≤   (if B then A: less-than-or-equal)
XY  (not A: discard B, boolean negate)
≥   (if A then B: greater-than-or-equal)
*Y  (A nand B: multiply, boolean negate)
é1  (true: clear stack, push 1)

Gracias a Leaky Nun por 3 bytes

Mego
fuente