Lógica digital basada en cuadrícula (mosaicos duodádicos)

33

Las teselas duodádicas son tipos de bloques de función cuadrados que toman dos entradas, una desde su lado superior y otra desde su lado izquierdo, y tienen dos salidas, una en su lado derecho y otra en su lado inferior. Cada una de sus salidas es una función separada de sus dos entradas.

Por ejemplo, si #representa un mosaico genérico, la salida derecha Res una función fde entradas Ty L, y la salida inferior Bes otra función gde Ty L:

 T
L#R         R = f(T, L)
 B          B = g(T, L)

(Los mosaicos se denominan "dúo" ya que hay dos funciones y "diádico" ya que ambas funciones tienen dos argumentos ).

Los mosaicos se pueden componer juntos en una cuadrícula, las salidas de un mosaico van directamente a las entradas de los mosaicos vecinos. Aquí, por ejemplo, la salida derecha de la izquierda #entra en la entrada izquierda de la derecha #:

 AB         D = f(f(A, C), B)
C##D        E = g(A, C)
 EF         F = g(f(A, C), B)

Puede imaginar que, dado un conjunto de mosaicos duodádicos, cada uno con una funcionalidad específica, se podrían hacer composiciones complejas (y potencialmente útiles).

En este desafío, solo nos ocuparemos del conjunto tradicional de diez mosaicos duodádicos basados ​​en lógica , donde todas las entradas y salidas son números binarios de un solo bit (ceros o unos). Usaremos un carácter ASCII separado para denotar cada tipo de mosaico.

Los caracteres de mosaico y sus relaciones de entrada-salida son los siguientes:
( Tes para la entrada superior, Lpara la entrada izquierda, Rpara la salida derecha, Bpara la salida inferior).

  1. Cero: 0o (espacio) → R = 0,B = 0
  2. Uno: 1R = 1,B = 1
  3. Cruz: +R = L,B = T
  4. Espejo: \R = T,B = L
  5. Solo superior: UR = T,B = T
  6. Solo izquierda: )R = L,B = L
  7. No: !R = not L,B = not T
  8. Y: &R = L and T,B = L and T
  9. O: |R = L or T,B = L or T
  10. Xor: ^R = L xor T,B = L xor T

Reto

Escriba un programa o función que tome en una cuadrícula rectangular de los caracteres 0 1+\U)!&|^que representa un "circuito" hecho usando los diez mosaicos duodádicos basados ​​en lógica. También necesita tomar dos cadenas de 0'sy 1' s; una será la columna de entrada izquierda y la otra será la fila de entrada superior. Su programa / función necesita imprimir / devolver la fila de salida inferior y la columna de salida derecha (también en 0'sy 1' s).

Por ejemplo, en esta cuadrícula

+++
+++

todas las entradas fluyen directamente a través de la cuadrícula a las salidas

 ABC
D+++D
E+++E
 ABC

entonces una entrada de 010/ 01tendría salida 010/ 01:

 010
0+++0
1+++1
 010

El resultado exacto de su programa sería [bottom output row]\n[right output column]o [bottom output row]/[right output column]:

010
01

o

010/01

Si escribió una función, podría devolver las dos cadenas en una tupla o lista (o aún imprimirlas).

Detalles

  • Tome las tres entradas como cadenas de cualquier manera razonable (preferiblemente en la cuadrícula de orden, fila superior, columna izquierda): línea de comando, archivo de texto, sdtin, función arg.
  • Puede suponer que las longitudes de fila y columna de entrada coincidirán con las dimensiones de la cuadrícula y solo contendrán 0'sy 1' s.
  • Su cuadrícula debe usar los caracteres adecuados ( 0 1+\U)!&|^). Recuerda eso 0y significa lo mismo.

Casos de prueba

(Lea E / S como top/ leftbottom/ right.)

Nand:

&!

00/ 001/ 1
00/ 101/ 1
10/ 001/ 1
10/ 111/0

Todos unos:

1111
1\+\
1+\+
1\+\

Cualquier entrada debe resultar en 1111/ 1111.

Xor de Nand: (observe la columna de espacios finales)

\)+\ 
U&!& 
+! ! 
\&!& 
   ! 

00000/ 0000000000/ 00000
00000/ 1000000010/ 00000
10000/ 0000000010/ 00000
10000/ 1000000000/00000

Zig zag:

+++\00000000
000\!!!!\000
00000000\+++

El primer bit de la entrada izquierda se convierte en el último bit de la salida derecha. Todo lo demás es 0.

000000000000/ 000000000000000/ 000
000000000000/ 100000000000000/001

Propagación:

)))
UUU
U+U
U+U
UUU

El primer bit de la entrada izquierda va a todas las salidas.

000/ 00000000/ 00000
000/ 10000111/11111

Aquí hay un pastebin de todos los casos de prueba de cuadrícula 1 × 1.

Tanteo

La presentación más corta en bytes gana.

Bonus: ¿Qué "circuitos" geniales puedes hacer?

PD: No te molestes en buscar en Google "baldosas duodádicas". Los inventé ayer; D
Si quieres discutir expandir esta idea a un lenguaje de programación completo, ven a esta sala de chat .

Pasatiempos de Calvin
fuente
11
+1 para un desafío genial, pero también porque inventaste fichas duodádicas, que es REALMENTE genial.
Alex A.
3
+1 Realmente es completamente inútil para googlear esto: goo.gl/zuqfdW . Buen desafío!
BrainSteel
Estoy con ellos Estoy mucho más interesado en sus mosaicos como lenguaje de programación que en este desafío de golf en particular. PD: Hay 16 fichas posibles, por lo que sería genial tener letras / nombres para las otras seis.
Sparr
Sería interesante tener bloques que emitan / ingresen desde diferentes direcciones, porque de lo contrario no puede hacer un enganche ya que todo fluye en una dirección hacia abajo-derecha.
Sp3000
2
Puede cambiar T / B a U (p) / D (propio), para que podamos tener F / B de forma análoga a la notación Cubo de Rubik, y luego. . . cubos tritriadic?
Soham Chowdhury

Respuestas:

8

Pyth, 122

Como un monstruo. Utiliza simplemente recursividad, nada lujoso como la programación dinámica.

D:NGHR@Cm+d[1HG&GH|GHxGH0),[GH!G)[HG!H)x"+\\!1U)&|^"N#aYw)M:@@YGH?hgGtHHv@eYG?egtGHGv@ePYHjkm+0egtleYklePYjkm+0hgbtlePYleY

Demostración en línea .

La entrada es de la siguiente manera: primero la cuadrícula (sin escape, sin símbolos adicionales) y luego las dos líneas de entrada, por ejemplo (Zig zag)

+++\00000000
000\!!!!\000
00000000\+++
000000000000
100
Jakube
fuente
8

Mathematica, 331 276 270 267 264 262 252 250 bytes

Print@@@{#[[2;;,-1,2]],#[[-1,2;;,1]]}&@MapIndexed[h=Characters;({r@#2,b@#2}=<|##|>&@@Thread[h@"0 1+\\)U!&|^"->{0,0,1,i={##},{#2,#},##,1-i,1##,Max@i,(#-#2)^2}]&[r[#2-{1,0}],b[#2-{0,1}]]@#{1,1})&,Join[h@{"0"<>#3},h@StringSplit[#2<>"
"<>#,"
"]],{2}]&

El es un carácter Unicode de uso privado que Mathematica usa como superíndice T, es decir, es el operador de transposición.

Aquí hay una versión más legible:

Print @@@ {#[[2 ;;, -1, 2]], #[[-1, 2 ;;, 1]]} &@
  MapIndexed[h = Characters;
   (
     {r@#2, b@#2} = <|##|> & @@ Thread[
            h@"0 1+\\)U!&|^" -> {
              0,
              0,
              1,
              i = {##},
              {#2, #},
              ##,
              1 - i,
              1 ##,
              Max@i,
              (# - #2)^2
              }] & [
          r[#2 - {1, 0}],
          b[#2 - {0, 1}]
          ] @ # {1, 1}
     ) &,
   Join[
    h@{"0" <> #3},
    h@StringSplit[#2 <> "\n" <> #, "\n"]\[Transpose]
   ],
   {2}] &

Esta es una función sin nombre que toma las tres cadenas para las entradas de cuadrícula, superior e izquierda e imprime las salidas inferior y derecha.

Explicación

Veamos este paso a paso (intentaré no asumir ningún conocimiento de Mathematica). Es necesario leer el código de frente a frente. El algoritmo básico simplemente recorre las líneas que computan cada función y almacenan los resultados fpara que sean accedidos por mosaicos posteriores.

Procesamiento de entrada

Esa es esta parte:

Join[
  h@{"0" <> #3},
  h@StringSplit[#2 <> "\n" <> #, "\n"]\[Transpose]
]

Esto simplemente divide la cuadrícula en una lista anidada de caracteres (tenga en cuenta que definí hcomo un alias para Characteralgún lugar del código) y luego antepone una fila y una columna con las entradas. Esto funciona, porque 1y 0también son los nombres de los mosaicos de función constante, por lo que colocarlos en ellos tiene el mismo efecto que alimentar las entradas manualmente. Dado que estas son funciones, técnicamente tomarán su entrada desde fuera de la cuadrícula, pero dado que son funciones constantes, eso no importa. La esquina superior izquierda obtiene un, 0pero esto es bastante arbitrario ya que los resultados de ese mosaico nunca se utilizan.

También tenga en cuenta la transposición. Agregar columnas requiere más caracteres que agregar filas, por lo que transpongo la cuadrícula después de agregar la fila superior. Esto significa que las partes superior / inferior e izquierda / derecha se intercambian por la parte principal del programa, pero son completamente intercambiables, por lo que no importa. Solo necesito asegurarme de devolver los resultados en el orden correcto.

Resolviendo la cuadrícula

(Esta sección está un poco desactualizada. Se solucionará una vez que esté realmente seguro de que he terminado de jugar al golf).

A continuación, corremos MapIndexedsobre el nivel interno de esta lista anidada. Esto llama a la función anónima proporcionada como primer argumento para cada carácter en la cuadrícula, y también le da una lista con las dos coordenadas actuales. La cuadrícula se atraviesa en orden, por lo que podemos calcular con seguridad cada celda en función de las anteriores.

Utilizamos las variables r(ight) y b(ottom) como tablas de búsqueda para los resultados de cada celda. Nuestra función anónima tiene las coordenadas actuales #2, por lo que obtenemos las entradas a cualquier celda con

r[#2 - {1, 0}],
b[#2 - {0, 1}]

Tenga en cuenta que en la primera fila y columna esto accederá a valores indefinidos de ry b. Mathematica realmente no tiene un problema con eso y solo le devolverá sus coordenadas, pero descartamos este resultado de todos modos, ya que todos los mosaicos en esa fila / columna son funciones constantes.

Ahora esta cosa:

<|##|> & @@ Thread[
  h@"0 1+\\U)!&|^" -> {
     z = {0, 0}, z, o = 1 + z, {##}, ...
  }] &

Es una forma de golf de

<|"0" -> (z = {0, 0}), " " -> z, "1" -> (o = 1 + z), "+" -> {##}, ... |> &

Lo que a su vez es una función que, dadas las dos entradas de mosaico, devuelve una Asociación (lo llamaría un hashmap o una tabla en otros idiomas), que contiene todos los resultados de mosaico posibles para estas dos entradas. Para comprender cómo se implementan todas las funciones, debe saber que se puede acceder al primer argumento de dicha función #y al segundo con #2. Además, ##le ofrece una secuencia de ambos argumentos que se pueden usar para "salpicar" los argumentos.

  • 0: es sencillo, solo devolvemos una constante {0, 0}y también la asignamos zpara uso futuro (por ejemplo, en el mosaico de espacios).
  • 1: es esencialmente justo {1,1}, pero tener zesto se acorta a 1+z. También guardamos esto o, porque será útil para todos los mosaicos donde ambas salidas son idénticas.
  • +: Aquí hacemos uso de la secuencia. {##}es igual {#,#2}y pasa ambas entradas sin cambios.
  • \: Intercambiamos los dos argumentos, {#2,#}.
  • U: Ahora podemos hacer uso de o. o#2significa {1,1}*#2que solo ponemos el argumento superior en ambas salidas.
  • )Análogamente para el argumento de la izquierda: o#.
  • !: Bit a bit no es molesto en Mathematica, pero ya que sólo tenga 0y 1, simplemente puede restar las dos entradas de 1(por lo tanto la inversión de ellos) y pasarlas: 1-{##}.
  • &: Este es bastante ingenioso. Primero notamos que bit a bit y para 0y 1es idéntico a la multiplicación. Además, o##es lo mismo que o*#*#2.
  • |: De nuevo, usamos una función equivalente. Bitwise o es lo mismo que Maxen este caso, por lo que aplicamos Maxa los argumentos de entrada y multiplicamos el resultado en {1,1}.
  • ^: Lo más corto que he encontrado para xor es tomar la diferencia y cuadrarla (para asegurar la positividad), así que tenemos o(#-#2)^2.

Una vez que esta función se completa y devuelve la asociación completa, usamos el carácter de la celda actual para extraer el elemento que nos interesa y almacenarlo en ry b. Tenga en cuenta que este también es el valor de retorno de la función anónima utilizada MapIndexed, por lo que la asignación en realidad me dará una cuadrícula de todos los resultados.

Procesamiento de salida

MapIndexeddevuelve una cuadrícula 3D, donde la primera dimensión corresponde a la coordenada de la cuadrícula horizontal (recuerde la transposición anterior), la segunda dimensión corresponde a la coordenada de la cuadrícula vertical y la tercera indica si tenemos una salida inferior o izquierda. Tenga en cuenta que esto también contiene la fila y la columna de entrada de las que debemos deshacernos. Entonces accedemos a la salida inferior de la fila inferior con

#[[2;;,-1,2]]

y la salida derecha de la columna final con

#[[-1,2;;,1]]

Tenga en cuenta que 2;;es un rango del segundo al último elemento.

Por último, aplicamos Printa ambos (utilizando @@@como el azúcar sintáctico para el segundo nivel Apply), que solo imprime todos sus argumentos de forma consecutiva (y dado que se aplica a dos expresiones separadas, habrá una nueva línea entre el fondo y salida correcta).

Martin Ender
fuente
8

C, 332 309 272 270 266 259 247 225 bytes

#define C(x)*c-x?
i,k,T,L,m;f(c,t,l)char*c,*t,*l;{while(L=l[i]){for(k=0;T=t[k];c++)L=C(49)C(43)C(92)C(85)C(41)C(33)C(38)C('|')C(94)T=48:(T^=L-48):(T|=L):(T&=L):(T^=1,L^1):(T=L):T:(m=T,T=L,m):L:(T=49),t[k++]=T;c++;l[i++]=L;}}

Ver resultados en línea aquí!

Esto define una función void f(char*, char*, char*), que debe tomar el tablero como su primera entrada, luego la fila superior de entrada y luego la fila izquierda de entrada.

Esto es lo que solía probar:

#include "stdio.h"
int main() {
    char buf[1024],top[33],left[33];
    /* Copy and paste an example circuit as the first input,
       and put a 'Q' immediately after it. 
       Note that the Q is never touched by the function f, and is used
       solely as a delimiter for input. */
    scanf("%[^Q]Q ",buf);
    /* Then enter your top inputs */
    scanf("%[01]%*[^01]", top);
    /* Then your left ones */
    scanf("%[01]", left);
    /* OUTPUT: Bottom\nRight */
    f(buf, top, left);
    return 0;
}

Por lo tanto, al ingresar el multiplicador de 2 bits de Sp3000:

UUUU))))
UU++)))&
UUU+)  U
UU++&))U
U++&+)^U
U)&\&)UU
   U+^UU
   \&UUUQ
11110000
00000000

Obtenemos:

00001001
11111111

En otra nota, con el medio sumador de Sp3000 en mente, me gustaría ver un sumador completo ... ¡ Uno de ustedes lo hizo! No creo que el sistema sea un lenguaje de programación, pero ha sido muy interesante. ¡Sin embargo, este parece ser un excelente objetivo para metagolf!

Una breve explicación:

Aquí está el código desvelado y comentado:

/* We define the first half of the ?: conditional operator because, well,
   it appears over and over again. */
#define C(x)*c-x?
/* i,k are counting variables
   T,L are *current* top and left inputs */
i,k,T,L,m;
f(c,t,l)char*c,*t,*l;{
    /* The outer loop iterates from top to bottom over l and c */
    while(L=l[i]){
        /* Inner loop iterates from left to right over t and c */
        for(k=0;T=t[k];c++)
            /* This line looks awful, but it's just a bunch of character
            comparisons, and sets T and L to the output of the current c */
            L=C(49)C(43)C(92)C(85)C(41)C(33)C(38)C('|')C(94)T=48:(T^=L-48):(T|=L):(T&=L):(T^=1,L^1):(T=L):T:(m=T,T=L,m):L:(T=49),
            /* Write our output to our input, it will be used for the next row */
            t[k++]=T;
        c++; /*Absorbs the newline at the end of every row */
        /* Keep track of our right-most outputs, 
        and store them in the handy string passed to the function. */
        l[i++]=L;
    }
    /* Bottom output is now stored entirely in t, as is right output in l */        
}

Repetimos c, de izquierda a derecha (luego de arriba a abajo), reescribiendo las tentradas cada vez y sacando una salida de la derecha que se inserta en la lcadena. Podemos imaginar esto como reemplazar la fila superior de ccon 1'sy 0' s iterativamente, y hacer un seguimiento de los bits que se expulsan a la derecha.

Aquí hay una secuencia más visual, fila por fila:

 111                                  
1&+^  =>  110 ->0  =>     ->0  =>     0 Thus, "01" has been written to l,
1+&+     1+&+         110 ->1         1
                                  110   And "110" is stored currently in t.

Obviamente, esto se vuelve más complicado con diferentes símbolos y tamaños, pero la idea central es válida. Esto funciona solo porque los datos nunca fluyen hacia arriba o hacia la izquierda.

BrainSteel
fuente
¡Mucho potencial para jugar al golf! Comience cambiando el encabezado de fa f(c,t,l)char*c,*t,*l(no le importa una mierda el tipo de retorno).
FUZxxl
@FUZxxl Alguien mencionó esto en el chat, pero no pude hacerlo funcionar. ¿Es este comportamiento estándar? LLVM arroja al menos 2 errores con esa línea.
BrainSteel
Lo siento. Que debería haber sido f(c,t,l)char*c,*t,*l;. No compile en modo C11, ya que la regla int implícita que nos permite eliminar el tipo de retorno se ha eliminado en esa revisión.
FUZxxl
@FUZxxl Parece que también falla en C99. De hecho, cada modo en el que he configurado el compilador ha rechazado ese código.
BrainSteel
¿Agregaste el punto y coma justo después *l? Se compila en modo C99 en mi máquina.
FUZxxl
7

Python 2, 316 bytes

Esta función construye 10 funciones lambda de mosaico, luego itera a través de la cuadrícula, actualizando los estados lógicos. Luego se imprimen los estados lógicos verticales y horizontales finales.

def b(d,j,g):
 h=enumerate;e=dict((s[0],eval('lambda T,L:('+s[1:]+')'))for s in' 0,0#00,0#11,1#+L,T#\\T,L#UT,T#)L,L#!1-L,1-T#&T&L,T&L#|T|L,T|L#^T^L,T^L'.split('#'));j=list(j+'\n');g=list(g)
 for y,k in h(d.split('\n')):
  L=g[y]
  for x,c in h(k):T=j[x];L,B=e[c](int(T),int(L));j[x]=`B`
  g[y]=`L`
 print''.join(j+g)

El código no protegido que incluye pruebas:

def logic(grid, top, left):
    loop = enumerate;
    func = dict((s[0], eval('lambda T,L:('+s[1:]+')')) for s in ' 0,0#00,0#11,1#+L,T#\\T,L#UT,T#)L,L#!1-L,1-T#&T&L,T&L#|T|L,T|L#^T^L,T^L'.split('#'));
    top = list(top+'\n');
    left = list(left)
    for y,row in loop(grid.split('\n')):
        L = left[y]
        for x,cell in loop(row) :
            T = top[x];
            L, B = func[cell](int(T), int(L));
            top[x] = `B`
        left[y] = `L`
    print ''.join(top + left)

import re
testset = open('test.txt', 'rt').read().strip()
for test in testset.split('\n\n'):
    if test.endswith(':'):
        print '------------------\n'+test
    elif re.match('^[01/\n]+$', test, re.S):
        for run in test.split():
            top, left = run.split('/')
            print 'test', top, left
            logic(grid, top, left)
    else:
        grid = test

El test.txtarchivo (incluidas otras 2 pruebas de Sp3000):

Nand:

&!

00/0
00/1
10/0
10/1

All ones:

1111
1\+\
1+\+
1\+\

1001/1100

Xor from Nand (note the column of trailing spaces):

\)+\ 
U&!& 
+! ! 
\&!& 
   ! 

00000/00000
00000/10000
10000/00000
10000/10000

Half adder:

+))
U&+
U+^

000/000
000/100
100/000
100/100

Right shift:

\\\
\++
\++

001/110
010/101
101/100

La salida de prueba:

------------------
Nand:
test 00 0
01
1
test 00 1
01
1
test 10 0
01
1
test 10 1
11
0
------------------
All ones:
test 1001 1100
1111
1111
------------------
Xor from Nand (note the column of trailing spaces):
test 00000 00000
00000
00000
test 00000 10000
00010
00000
test 10000 00000
00010
00000
test 10000 10000
00000
00000
------------------
Half adder:
test 000 000
000
000
test 000 100
001
101
test 100 000
101
001
test 100 100
110
110
------------------
Right shift:
test 001 110
000
111
test 010 101
101
010
test 101 100
010
110
Caballero Lógico
fuente
7

Python 2, 384 338 325 bytes

def f(G,T,L):
 def g(x,y):
  if x>-1<y:l=g(x-1,y)[1];t=g(x,y-1)[0];r=l,t,1-l,0,0,1,t,l,l&t,l|t,l^t;i="+\\!0 1U)&|^".index(G[y*-~W+x]);return((t,l,1-t)+r[3:])[i],r[i]
  return(int((y<0)*T[x]or L[y]),)*2
 H=G.count("\n")+1;W=len(G)/H;return eval('"".join(map(str,[g(%s]for _ in range(%s)])),'*2%('_,H-1)[0','W','W-1,_)[1','H'))

En serio CH, si esto no es un juguete ya deberías comenzar a llamar a algunas fábricas de juguetes.

Más golf y mucho menos eficiente ahora, pero aún no ha alcanzado a CarpetPython. Entrada como f("1111\n1\\+\\\n1+\\+\n1\\+\\","0101","1010"), salida es una tupla de dos cadenas. Sin embargo, asegúrese de que el tablero no tenga una nueva línea final, lo que romperá las cosas.

Programa de prueba

def f(G,T,L):
 def g(x,y):
  if x>-1<y:l=g(x-1,y)[1];t=g(x,y-1)[0];r=l,t,1-l,0,0,1,t,l,l&t,l|t,l^t;i="+\\!0 1U)&|^".index(G[y*-~W+x]);return((t,l,1-t)+r[3:])[i],r[i]
  return(int((y<0)*T[x]or L[y]),)*2
 H=G.count("\n")+1;W=len(G)/H;return eval('"".join(map(str,[g(%s]for _ in range(%s)])),'*2%('_,H-1)[0','W','W-1,_)[1','H'))


import itertools

G = r"""
+))
U&+
U+^
""".strip("\n")

def test(T, L):
    print f(G, T, L)

def test_all():
    W = len(G[0])
    H = len(G)

    for T in itertools.product([0, 1], repeat=len(G.split("\n")[0])):
        T = "".join(map(str, T))

        for L in itertools.product([0, 1], repeat=len(G.split("\n"))):
            L = "".join(map(str, L))

            print "[T = %s; L = %s]" % (T, L)
            test(T, L)
            print ""

test("000", "000")
test("000", "100")
test("100", "000")
test("100", "100")

También puede probar todos los casos posibles con test_all().

Casos de prueba extra

Media víbora

Aquí hay un medio sumador que agrega los bits superiores izquierdos, generando <input bit> <carry> <sum>:

+))
U&+
U+^

Pruebas:

000 / 000  ->  000 / 000
000 / 100  ->  001 / 101
100 / 000  ->  101 / 001
100 / 100  ->  110 / 110

La salida debe ser la misma incluso si se cambian los bits segundo / tercero de las entradas.

Giro a la derecha

Dado abc / def, esto produce fab / cde:

\\\
\++
\++

Pruebas:

001 / 110 -> 000 / 111
010 / 101 -> 101 / 010
101 / 100 -> 010 / 110

Clasificador de 3 bits

Ordena los primeros tres bits de la parte superior en los últimos tres bits de la parte inferior. La salida correcta es basura.

UUU)))
UU)U U
U&UU U
U+|&)U
\UU++|
 \)&UU
  \+|U
   UUU

Pruebas:

000000 / 00000000 -> 000000 / 00000000
001000 / 00000000 -> 000001 / 11111111
010000 / 00000000 -> 000001 / 00001111
011000 / 00000000 -> 000011 / 11111111
100000 / 00000000 -> 000001 / 00001111
101000 / 00000000 -> 000011 / 11111111
110000 / 00000000 -> 000011 / 00001111
111000 / 00000000 -> 000111 / 11111111

Multiplicador de 2 bits por 2 bits

Toma los bits 1º / 2º de la parte superior como el primer número y los bits 3º / 4º de la parte superior como el segundo número. Salidas a los últimos cuatro bits de fondo. La salida correcta es basura.

UUUU))))
UU++)))&
UUU+)  U
UU++&))U
U++&+)^U
U)&\&)UU
   U+^UU
   \&UUU

Editar: Golfed una columna y dos filas.

Pruebas:

00000000 / 00000000 -> 00000000 / 00000000
00010000 / 00000000 -> 00000000 / 10000000
00100000 / 00000000 -> 00000000 / 00000000
00110000 / 00000000 -> 00000000 / 10000000
01000000 / 00000000 -> 00000000 / 00000000
01010000 / 00000000 -> 00000001 / 11111111
01100000 / 00000000 -> 00000010 / 00000000
01110000 / 00000000 -> 00000011 / 11111111
10000000 / 00000000 -> 00000000 / 00000000
10010000 / 00000000 -> 00000010 / 10000000
10100000 / 00000000 -> 00000100 / 00000000
10110000 / 00000000 -> 00000110 / 10000000
11000000 / 00000000 -> 00000000 / 00000000
11010000 / 00000000 -> 00000011 / 11111111
11100000 / 00000000 -> 00000110 / 00000000
11110000 / 00000000 -> 00001001 / 11111111
Sp3000
fuente
1

R, 524 517

Probablemente hay mucho espacio para reducir esto en este momento, pero esto ha sido realmente interesante de hacer. Hay dos funciones La función d es el trabajador yf es el comparador.

La función d se llama con 3 cadenas, puertas, superior e izquierda. Las puertas se colocan en una matriz determinada por el ancho.

I=strtoi;S=strsplit;m=matrix;f=function(L,T,G){O=I(c(0,1,L,T,!L,!T,L&T,L|T,xor(L,T)));X=which(S(' 01+\\U)!&|^','')[[1]]==G);M=m(c(1,1,1,2,1,1,3,2,2,4,3,4,5,4,3,6,4,4,7,3,3,8,5,6,9,7,7,10,8,8,11,9,9),nrow=3);return(c(O[M[2,X]],O[M[3,X]]))};d=function(G,U,L){W=nchar(U);H=nchar(L);U=c(list(I(S(U,'')[[1]])),rep(NA,H));L=c(list(I(S(L,'')[[1]])),rep(NA,W));G=m((S(G,'')[[1]]),nrow=W);for(i in 1:H)for(n in 1:W){X=f(L[[n]][i],U[[i]][n],G[n,i]);L[[n+1]][i]=X[1];U[[i+1]][n]=X[2]};cat(U[[H+1]],' / ',L[[W+1]],sep='',fill=T)}

Formateado un poco

I=strtoi;S=strsplit;m=matrix;
f=function(L,T,G){
    O=I(c(0,1,L,T,!L,!T,L&T,L|T,xor(L,T)));
    X=which(S(' 01+\\U)!&|^','')[[1]]==G);
    M=m(c(1,1,1,2,1,1,3,2,2,4,3,4,5,4,3,6,4,4,7,3,3,8,5,6,9,7,7,10,8,8,11,9,9),nrow=3);
    return(c(O[M[2,X]],O[M[3,X]]))
};
d=function(G,U,L){
    W=nchar(U);H=nchar(L);
    U=c(list(I(S(U,'')[[1]])),rep(NA,H));
    L=c(list(I(S(L,'')[[1]])),rep(NA,W));
    G=m((S(G,'')[[1]]),nrow=W);
    for(i in 1:H)
        for(n in 1:W){
            X=f(L[[n]][i],U[[i]][n],G[n,i]);
            L[[n+1]][i]=X[1];
            U[[i+1]][n]=X[2]
        };
    cat(U[[H+1]],' / ',L[[W+1]],sep='',fill=T)
}

Algunas pruebas

> d('&!','00','0')
01 / 1
> d('&!','00','1')
01 / 1
> d('&!','10','0')
01 / 1
> d('&!','10','1')
11 / 0
> d('\\)+\\ U&!& +! ! \\&!&    ! ','00000','00000')
00000 / 00000
> d('\\)+\\ U&!& +! ! \\&!&    ! ','00000','10000')
00010 / 00000
> d('\\)+\\ U&!& +! ! \\&!&    ! ','10000','00000')
00010 / 00000
> d('\\)+\\ U&!& +! ! \\&!&    ! ','10000','10000')
00000 / 00000
> d('+++\\00000000000\\!!!!\\00000000000\\+++','000000000000','100')
000000000000 / 001
> d('+++\\00000000000\\!!!!\\00000000000\\+++','000000000000','000')
000000000000 / 000
> d('+))U&+U+^','000','000')
000 / 000
> d('+))U&+U+^','000','100')
001 / 101
> d('+))U&+U+^','100','000')
101 / 001
> d('+))U&+U+^','100','100')
110 / 110
MickyT
fuente