Logique numérique basée sur la grille (mosaïques Duodyadic)

33

Les mosaïques Duodyadic sont des types de blocs de fonction carrés qui prennent deux entrées, une de leur côté supérieur et une de leur côté gauche, et ont deux sorties, une de leur côté droit et une de leur côté inférieur. Chacune de leurs sorties est une fonction distincte de leurs deux entrées.

Par exemple, si #représente une mosaïque générique, la sortie droite Rest une fonction fdes entrées Tet L, et la sortie du bas Best une autre fonction gde Tet L:

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

(Les tuiles sont appelées "duo" puisqu'il y a deux fonctions et "dyadiques" puisque les deux fonctions ont deux arguments .)

Les tuiles peuvent ensuite être composées ensemble sur une grille, les sorties d'une tuile allant directement aux entrées des tuiles qu'elle voisine. Ici par exemple, la sortie droite de gauche #va dans l'entrée gauche de droite #:

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

Vous pouvez imaginer qu'avec un ensemble de mosaïques duodyadiques, chacune avec une fonctionnalité spécifique, des compositions complexes (et potentiellement utiles) pourraient être créées.

Dans ce défi, nous ne nous intéresserons qu'au jeu traditionnel de dix mosaïques duodyadiques basées sur la logique , dans lesquelles toutes les entrées et sorties sont des nombres binaires à un bit (zéros ou uns). Nous utiliserons un caractère ASCII distinct pour désigner chaque type de mosaïque.

Les caractères de mosaïque et leurs relations d'entrée-sortie sont les suivants:
( Test pour l'entrée supérieure, Lpour l'entrée gauche, Rpour la sortie droite, Bpour la sortie inférieure.)

  1. Zéro: 0ou (espace) → R = 0,B = 0
  2. Un: 1R = 1,B = 1
  3. Croix: +R = L,B = T
  4. Miroir: \R = T,B = L
  5. Haut seulement: UR = T,B = T
  6. Gauche seulement: )R = L,B = L
  7. Non: !R = not L,B = not T
  8. Et: &R = L and T,B = L and T
  9. Ou: |R = L or T,B = L or T
  10. Xor: ^R = L xor T,B = L xor T

Défi

Ecrivez un programme ou une fonction prenant une grille rectangulaire de caractères 0 1+\U)!&|^qui représente un "circuit" réalisé à l'aide des dix mosaïques duodyadiques à base logique. Vous devez également prendre en compte deux chaînes de 0'et 1'; un sera la colonne de gauche et un la première ligne. Votre programme / fonction doit imprimer / retourner la ligne de sortie inférieure et la colonne de sortie droite (également dans 0's et 1' s).

Par exemple, dans cette grille

+++
+++

toutes les entrées passent directement à travers la grille vers les sorties

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

donc une entrée de 010/ 01aurait la sortie 010/ 01:

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

Le résultat exact de votre programme serait [bottom output row]\n[right output column]ou [bottom output row]/[right output column]:

010
01

ou

010/01

Si vous avez écrit une fonction, vous pouvez renvoyer les deux chaînes dans un tuple ou une liste (ou encore les imprimer).

Détails

  • Prenez les trois entrées comme des chaînes de manière raisonnable (de préférence dans la grille de commande, la ligne du haut, la colonne de gauche): ligne de commande, fichier texte, sdtin, fonction arg.
  • Vous pouvez supposer que la longueur des lignes et des colonnes en entrée correspondra aux dimensions de la grille et ne contiendra que 0les s et 1'.
  • Votre grille doit utiliser les caractères appropriés ( 0 1+\U)!&|^). N'oubliez pas cela 0et signifie la même chose.

Cas de test

(Lire I / O sous la forme top/ leftbottom/ right.)

Nand:

&!

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

Tous les uns:

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

Toute entrée doit avoir pour résultat 1111/ 1111.

Xor from Nand: (notez la colonne d'espaces finaux)

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

00000/ 0000000000/ 00000
00000/ 1000000010/ 00000
10000/ 00000→ → 00010/ 00000
10000/ 1000000000/00000

Zig zag:

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

Le premier bit de l'entrée de gauche devient le dernier bit de la sortie de droite. Tout le reste est 0.

000000000000/ 000000000000000/ 000
000000000000/ 100000000000000/001

Propagation:

)))
UUU
U+U
U+U
UUU

Le premier bit de l'entrée de gauche va à toutes les sorties.

000/ 00000000/ 00000
000/ 10000111/11111

Voici une liste de tous les cas de test de grille 1 × 1.

Notation

La soumission la plus courte en octets l' emporte.

Bonus: Quels "circuits" cool pouvez-vous faire?

PS Ne vous embêtez pas sur Google "tuiles duodyadiques". Je les ai inventées hier; D
Si vous souhaitez discuter de l’extension de cette idée dans un langage de programmation à part entière, présentez-vous à cette salle de discussion .

Les passe-temps de Calvin
la source
11
+1 pour un défi intéressant, mais aussi parce que tu as inventé les tuiles duodyadiques, ce qui est vraiment cool.
Alex A.
3
+1 Il est vraiment complètement inutile de google ceci: goo.gl/zuqfdW . Beau défi!
BrainSteel
Je suis avec eux Je suis beaucoup plus intéressé par vos tuiles en tant que langage de programmation que par ce défi de golf particulier. PS: Il y a 16 tuiles possibles, donc trouver des lettres / noms pour les six autres serait bien.
Sparr
Il serait intéressant d’avoir des blocs qui produisent des entrées / sorties de différentes directions, car sinon vous ne pouvez pas faire de verrouillage, car tout se passe dans la bonne direction.
Sp3000
2
Vous pouvez changer T / B en U (p) / D (propre), afin que nous puissions avoir F / B d'une manière analogue à la notation de Rubik's Cube, et ensuite. . . cubes tritriadiques?
Soham Chowdhury

Réponses:

8

Pyth, 122

Une sorte de monstre. Utilise simplement la récursivité, rien de plus sophistiqué que la programmation dynamique.

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

Démonstration en ligne .

L’entrée est la suivante: d’abord la grille (pas d’échappement, pas de symboles supplémentaires), puis les deux lignes d’entrée, par exemple (Zig-zag)

+++\00000000
000\!!!!\000
00000000\+++
000000000000
100
Jakube
la source
8

Mathematica, 331 276 270 267 264 262 252 250 octets

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}]&

le s'agit d'un caractère Unicode à usage privé que Mathematica utilise en exposant T, c'est-à-dire qu'il s'agit de l'opérateur de transposition.

Voici une version plus lisible:

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}] &

C'est une fonction sans nom qui prend les trois chaînes pour les entrées grille, haut et gauche et imprime les sorties bas et droite.

Explication

Passons en revue cette étape par étape (j'essaierai de ne pas assumer les connaissances de Mathematica). Vous devez en quelque sorte lire le code à l'envers. L’algorithme de base balaye les lignes en calculant chaque fonction et en enregistrant les résultats dansf pour que les tuiles suivantes puissent y accéder.

Traitement d'entrée

C'est ce bit:

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

Cela divise simplement la grille en une liste imbriquée de caractères (remarque que j'ai définie hcomme un alias pour Characterquelque part dans le code), puis ajoute une ligne et une colonne avec les entrées. Cela fonctionne, parce que 1et 0sont aussi les noms des tuiles fonction constante, donc en fait de les mettre sur le a le même effet que l' alimentation des entrées manuellement. Comme ce sont des fonctions, ils vont techniquement prendre leur entrée en dehors de la grille, mais étant donné que ce sont des fonctions constantes, cela n'a pas d'importance. Le coin en haut à gauche devient un 0mais cela est assez arbitraire car les résultats de cette tuile ne sont jamais utilisés.

Notez également la transposition. L'ajout de colonnes prend plus de caractères que l'ajout de lignes. Je transpose donc la grille après avoir ajouté la ligne du haut. Cela signifie que haut / bas et gauche / droite sont échangés pour la partie principale du programme, mais ils sont complètement échangeables, donc peu importe. Je dois juste m'assurer de renvoyer les résultats dans le bon ordre.

Résoudre la grille

(Cette section est légèrement obsolète. Je vais y remédier une fois que je suis vraiment sûr d’avoir terminé le golf.)

Ensuite, nous parcourons MapIndexedle niveau interne de cette liste imbriquée. Ceci appelle la fonction anonyme fournie en tant que premier argument pour chaque caractère de la grille, également donnant une liste avec les deux coordonnées actuelles. La grille étant parcourue dans l’ordre, nous pouvons calculer en toute sécurité chaque cellule en fonction des cellules précédentes.

Nous utilisons les variables r(ight) et b(ottom) comme tables de recherche pour les résultats de chaque cellule. Notre fonction anonyme a les coordonnées actuelles dans #2, donc nous obtenons les entrées de toute cellule avec

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

Notez que dans la première ligne et la première colonne, cela permettra d'accéder aux valeurs non définies de ret b. Mathematica n’a pas vraiment de problème avec cela et vous redonne simplement vos coordonnées, mais nous écartons néanmoins ce résultat, car toutes les mosaïques de cette rangée / colonne sont des fonctions constantes.

Maintenant cette chose:

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

Est une forme de golf de

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

Ce qui à son tour est une fonction qui, étant donné les deux entrées de mosaïque, retourne une Association (on l'appelle une table de hachage ou une table dans d'autres langues), contenant tous les résultats de mosaïque possibles pour ces deux entrées. Pour comprendre comment toutes les fonctions sont implémentées, vous devez savoir que le premier argument d’une telle fonction est accessible avec #le second #2. En outre, ##vous donne une séquence des deux arguments qui peuvent être utilisés pour "splat" les arguments.

  • 0: est simple, nous retournons simplement une constante {0, 0}et l'assignons également zpour une utilisation future (par exemple, dans la vignette d'espace).
  • 1: est essentiellement juste {1,1}, mais avoir zcela est raccourci à 1+z. Nous enregistrons également cela o, car il sera utile pour toutes les mosaïques où les deux sorties sont identiques.
  • +: Nous utilisons ici la séquence. {##}est identique à {#,#2}et passe les deux entrées inchangées.
  • \: Nous échangeons les deux arguments, {#2,#}.
  • U: Maintenant, nous pouvons utiliser o. o#2signifie {1,1}*#2donc que nous venons de mettre l'argument supérieur dans les deux sorties.
  • ): Pour l'argument analogue gauche: o#.
  • !: Négation binaire est gênant dans Mathematica, mais étant donné que nous ne jamais avoir 0et 1, nous pouvons tout simplement soustraire les deux entrées de 1(ce qui les inverser) et les transmettre: 1-{##}.
  • &: Celui-ci est assez chouette. Nous remarquons d’abord que bitwise et pour 0et 1est identique à la multiplication. En outre, o##est le même que o*#*#2.
  • |: Encore une fois, nous utilisons une fonction équivalente. Bitwise ou est le même que Maxdans ce cas, nous appliquons Maxdonc aux arguments d'entrée et multiplions le résultat {1,1}.
  • ^: Le plus court que j'ai trouvé pour xor est de prendre la différence et de la corriger (pour assurer la positivité), donc nous avons o(#-#2)^2.

Une fois que cette fonction est terminée et renvoie l'association complète, nous utilisons le caractère de la cellule actuelle pour extraire l'élément qui nous intéresse et le stocker dans ret b. Notez que c’est aussi la valeur de retour de la fonction anonyme utilisée dansMapIndexed , de sorte que le mappage me donnera en réalité une grille de tous les résultats.

Traitement de sortie

MapIndexedretourne une grille 3D, où la première dimension correspond à la coordonnée de la grille horizontale (rappelez-vous la transposition précédente), la deuxième dimension correspond à la coordonnée de la grille verticale et la troisième indique si nous avons une sortie en bas ou à gauche. Notez que cela contient également la ligne et la colonne en entrée dont nous devons nous débarrasser. Nous avons donc accès à la sortie inférieure de la rangée du bas avec

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

et la sortie droite de la dernière colonne avec

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

Notez que 2;; s'agit d'une plage allant du deuxième au dernier élément.

Enfin, nous appliquons Printà tous les deux (en utilisant en @@@tant que sucre syntaxique pour le deuxième niveau Apply), qui affiche simplement tous ses arguments dos à dos (et puisqu'il est appliqué à deux expressions distinctes, il y aura une nouvelle ligne entre sortie droite).

Martin Ender
la source
8

C, 332 309 272 270 266 259 247 225 octets

#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;}}

Voir les résultats en ligne ici!

Cela définit une fonction void f(char*, char*, char*), qui doit prendre le tableau en tant que première entrée, puis la rangée d’entrée supérieure, puis la rangée d’entrée gauche.

Voici ce que j'ai utilisé pour le tester:

#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;
}

Ainsi, en entrant le multiplicateur à 2 bits de Sp3000:

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

On a:

00001001
11111111

Sur une autre note, avec le demi-additionneur de Sp3000 en tête, j'aimerais voir un additionneur complet ... L'un de vous l'a fait! Je ne pense pas que le système soit autonome en tant que langage de programmation, mais il a été très intéressant. Cela semble être une excellente cible pour le métagolf!

Une courte explication:

Voici le code dévoilé et commenté:

/* 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 */        
}

Nous itérons sur c, de gauche à droite (puis de haut en bas), réécrivant les tentrées à chaque fois et en poussant une sortie la plus à droite qui est poussé dans la lchaîne. On peut imaginer que cela remplace la rangée supérieure de cavec 1et0 ' de manière itérative, tout en gardant une trace des bits qui sont poussés vers la droite.

Voici une séquence plus visuelle, ligne par ligne:

 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.

Cela devient évidemment plus compliqué avec des symboles et des tailles différentes, mais l'idée centrale est la même. Cela ne fonctionne que parce que les données ne remontent jamais ni ne sortent.

BrainSteel
la source
Beaucoup de potentiel pour le golf! Commencez par changer l'en-tête de fen f(c,t,l)char*c,*t,*l(ne vous inquiétez pas du type de retour).
FUZxxl
@FUZxxl Quelqu'un en a parlé dans un chat, mais je n'ai pas réussi à le faire fonctionner. Ce comportement est-il standard? LLVM génère au moins 2 erreurs avec cette ligne.
BrainSteel
Désolé. Aurait dû être f(c,t,l)char*c,*t,*l;. Ne compilez pas en mode C11, car la règle int implicite permettant de supprimer le type de retour a été supprimée dans cette révision.
FUZxxl
@FUZxxl Cela semble également échouer en C99. En fait, chaque mode dans lequel j'ai activé le compilateur a rejeté ce code.
BrainSteel
Avez-vous ajouté le point-virgule juste après *l? Il compile en mode C99 sur ma machine.
FUZxxl
7

Python 2, 316 octets

Cette fonction crée 10 fonctions lambda en mosaïque, puis itère dans la grille en mettant à jour les états logiques. Les états logiques finaux vertical et horizontal sont ensuite imprimés.

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)

Le code non-golfé comprenant des tests:

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

Le test.txtfichier (y compris 2 autres tests réalisés par 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 sortie de test:

------------------
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
Logic Knight
la source
7

Python 2, 384 338 325 octets

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

Sérieusement, si ce n'est pas déjà un jouet, vous devriez commencer à faire sonner des usines de jouets.

Plus golfé et beaucoup moins efficace maintenant, mais je n’ai toujours pas rattrapé CarpetPython. Comme en entrée f("1111\n1\\+\\\n1+\\+\n1\\+\\","0101","1010"), la sortie est un tuple de deux chaînes. Assurez-vous que le tableau ne comporte pas de saut de ligne, ce qui risquerait de casser des choses.

Programme de test

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

Vous pouvez également tester tous les cas possibles avec test_all().

Cas de test supplémentaires

Demi additionneur

Voici un demi additionneur qui ajoute les bits en haut à gauche <input bit> <carry> <sum>:

+))
U&+
U+^

Tests:

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

La sortie doit être la même, même si les deuxième / troisième bits des entrées sont modifiés.

Décalage droit

Étant donné abc / def, cela génère fab / cde:

\\\
\++
\++

Tests:

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

Trieur 3 bits

Trie les trois premiers bits du haut dans les trois derniers bits du bas. La sortie droite est indésirable.

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

Tests:

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

Multiplicateur 2 bits par 2 bits

Prend les 1er / 2ème bits de top comme premier chiffre et les 3ème / 4ème bits de top comme deuxième nombre. Affiche les quatre derniers bits du bas. La sortie droite est indésirable.

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

Edit: Golfé une colonne et deux lignes.

Tests:

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
la source
1

R, 524 517

Probablement beaucoup de place pour réduire cela pour le moment, mais cela a été vraiment intéressant à faire. Il y a deux fonctions. La fonction d est le travailleur et f le comparateur.

La fonction d est appelée avec 3 chaînes, Gates, Top et Left. Les portes sont placées dans une matrice déterminée par la largeur.

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

Un peu formaté

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

Quelques tests

> 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
la source