Gitterbasierte digitale Logik (duodyadische Kacheln)

33

Duodyadische Kacheln sind Arten von quadratischen Funktionsblöcken , die zwei Eingänge (einen von oben und einen von links) und zwei Ausgänge (einen von rechts und einen von unten) haben. Jeder ihrer Ausgänge ist eine separate Funktion für beide Eingänge.

Wenn beispielsweise #eine generische Kachel dargestellt wird, ist die rechte Ausgabe Reine Funktion fder Eingaben Tund Lund die untere Ausgabe Beine weitere Funktion gvon Tund L:

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

(Die Kacheln werden als "Duo" bezeichnet, da es zwei Funktionen gibt, und als "dyadisch", da beide Funktionen zwei Argumente haben .)

Kacheln können dann in einem Raster zusammengesetzt werden, wobei die Ausgaben einer Kachel direkt in die Eingaben der benachbarten Kacheln fließen. Hier geht zum Beispiel die rechte Ausgabe der linken #in die linke Eingabe der rechten #:

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

Sie können sich vorstellen, dass mit einer Reihe von duodyadischen Kacheln mit jeweils spezifischen Funktionen komplexe (und möglicherweise nützliche) Kompositionen erstellt werden könnten.

In dieser Herausforderung werden wir uns nur mit dem traditionellen Satz von zehn logikbasierten duodyadischen Kacheln befassen, bei denen alle Ein- und Ausgänge Einzelbit-Binärzahlen (Nullen oder Einsen) sind. Wir verwenden ein separates ASCII-Zeichen, um jeden Kacheltyp zu kennzeichnen.

Die Kachelzeichen und ihre Eingabe-Ausgabe-Beziehungen lauten wie folgt:
( Tgilt für die obere Eingabe, Lfür die linke Eingabe, Rfür die rechte Ausgabe, Bfür die untere Ausgabe.)

  1. Null: 0oder (Leerzeichen) → R = 0,B = 0
  2. Eins: 1R = 1,B = 1
  3. Kreuz: +R = L,B = T
  4. Spiegel: \R = T,B = L
  5. Nur oben: UR = T,B = T
  6. Nur links: )R = L,B = L
  7. Nicht: !R = not L,B = not T
  8. Und: &R = L and T,B = L and T
  9. Oder: |R = L or T,B = L or T
  10. Xor: ^R = L xor T,B = L xor T

Herausforderung

Schreiben Sie ein Programm oder eine Funktion, die ein rechteckiges Raster der Zeichen enthält 0 1+\U)!&|^, das eine "Schaltung" darstellt, die mit den zehn duodyadischen Kacheln auf Logikbasis erstellt wurde. Sie müssen auch zwei Folgen von 0's und 1' s aufnehmen; Eine wird die linke Eingabespalte sein und eine wird die obere Eingabezeile sein. Ihr Programm / Ihre Funktion muss die unterste Ausgabezeile und die rechte Ausgabespalte (auch in 0's und 1' s) drucken / zurückgeben .

Zum Beispiel in diesem Raster

+++
+++

Alle Eingänge fließen direkt über das Netz zu den Ausgängen

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

Ein Eingang von 010/ 01hätte also einen Ausgang von 010/ 01:

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

Die genaue Ausgabe Ihres Programms wäre [bottom output row]\n[right output column]oder [bottom output row]/[right output column]:

010
01

oder

010/01

Wenn Sie eine Funktion geschrieben haben, können Sie die beiden Zeichenfolgen in einem Tupel oder einer Liste zurückgeben (oder sie trotzdem drucken).

Einzelheiten

  • Nehmen Sie die drei Eingaben in einer angemessenen Weise als Zeichenfolge (vorzugsweise in der Reihenfolge Tabelle, obere Zeile, linke Spalte): Befehlszeile, Textdatei, SDTIN, Funktion arg.
  • Sie können davon ausgehen, dass die Länge der Eingabezeilen und -spalten mit den Rastermaßen übereinstimmt und nur 0's und 1' s enthält.
  • Ihr Raster muss die richtigen Zeichen enthalten ( 0 1+\U)!&|^). Denken Sie daran 0und meinen Sie dasselbe.

Testfälle

(Lese I / O als top/ leftbottom/ right.)

Nand:

&!

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

Alle:

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

Jede Eingabe sollte zu 1111/ führen 1111.

Xor from Nand: (Beachten Sie die Spalte mit den nachgestellten Leerzeichen)

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

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

Zick-Zack:

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

Das erste Bit des linken Eingangs wird zum letzten Bit des rechten Ausgangs. Alles andere ist 0.

000000000000/ 000000000000000/ 000
000000000000/ 100000000000000/001

Vermehrung:

)))
UUU
U+U
U+U
UUU

Das erste Bit des linken Eingangs geht an alle Ausgänge.

000/ 00000000/ 00000
000/ 10000111/11111

Hier ist ein Pastebin aller 1 × 1-Rastertestfälle.

Wertung

Die kürzeste Übermittlung in Bytes gewinnt.

Bonus: Welche coolen "Circuits" kannst du machen?

PS: Googeln Sie nicht mit "duodyadischen Kacheln". Ich habe sie gestern erfunden. D
Wenn Sie darüber diskutieren möchten, wie Sie diese Idee zu einer vollwertigen Programmiersprache erweitern können, besuchen Sie diesen Chatroom .

Calvins Hobbys
quelle
11
+1 für eine coole Herausforderung, aber auch, weil du duodyadische Kacheln erfunden hast, was WIRKLICH cool ist.
Alex A.
3
+1 Es ist wirklich völlig nutzlos, dies zu googeln: goo.gl/zuqfdW . Schöne Herausforderung!
BrainSteel
Ich bin bei ihnen. Ich interessiere mich viel mehr für Ihre Kacheln als Programmiersprache als für diese besondere Golfherausforderung. PS: Es gibt 16 mögliche Kacheln, also wäre es schön, Buchstaben / Namen für die anderen sechs Kacheln zu finden.
Sparr
Es wäre interessant, Blöcke zu haben, deren Ausgabe / Eingabe aus verschiedenen Richtungen erfolgt, da ansonsten kein Latch möglich ist, da alles nach unten verläuft.
Sp3000,
2
Sie können T / B in U (p) / D (own) ändern, sodass wir F / B analog zur Rubik's Cube-Notation haben. . . Tritriadische Würfel?
Soham Chowdhury

Antworten:

8

Pyth, 122

Ein bisschen wie ein Monster. Verwendet einfach Rekursion, nichts Besonderes wie dynamisches Programmieren.

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

Online-Demonstration .

Die Eingabe erfolgt folgendermaßen: Zuerst das Raster (kein Escapezeichen, keine zusätzlichen Symbole) und dann die beiden Eingabezeilen, z. B. (Zick-Zack)

+++\00000000
000\!!!!\000
00000000\+++
000000000000
100
Jakube
quelle
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}]&

Das ist ein privat genutztes Unicode-Zeichen, das Mathematica als hochgestelltes Zeichen verwendet T, dh es ist der Transpositionsoperator.

Hier ist eine besser lesbare Version:

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

Dies ist eine unbenannte Funktion, die die drei Zeichenfolgen für die Raster-, oberen und linken Eingaben verwendet und die unteren und rechten Ausgaben druckt.

Erläuterung

Lassen Sie uns dies Schritt für Schritt durchgehen (ich werde versuchen, keine Mathematica-Kenntnisse anzunehmen). Sie müssen den Code von vorne nach hinten lesen. Der grundlegende Algorithmus durchläuft nur die Zeilen, in denen jede Funktion berechnet und die Ergebnisse gespeichert werden, auf die fnachfolgende Kacheln zugreifen sollen.

Eingabeverarbeitung

Das ist das bisschen:

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

Dies teilt das Raster lediglich in eine verschachtelte Liste von Zeichen auf (beachten Sie, dass ich heinen Alias ​​für Characterirgendwo im Code definiert habe) und stellt dann eine Zeile und eine Spalte mit den Eingaben voran. Dies funktioniert, da 1und 0auch die Namen der Konstantenfunktionskacheln sind. Wenn Sie diese also auf die Kacheln setzen, hat dies den gleichen Effekt wie das manuelle Einspeisen der Eingaben. Da dies Funktionen sind, beziehen sie ihre Eingaben technisch von außerhalb des Gitters, aber da es sich um konstante Funktionen handelt, spielt dies keine Rolle. Die obere linke Ecke erhält ein, 0aber dies ist ziemlich willkürlich, da die Ergebnisse dieser Kachel niemals verwendet werden.

Beachten Sie auch die Umsetzung. Das Hinzufügen von Spalten erfordert mehr Zeichen als das Hinzufügen von Zeilen. Deshalb transponiere ich das Raster, nachdem ich die oberste Zeile hinzugefügt habe. Dies bedeutet, dass oben / unten und links / rechts für den Hauptteil des Programms vertauscht werden, aber sie sind vollständig austauschbar, so dass es keine Rolle spielt. Ich muss nur sicherstellen, dass die Ergebnisse in der richtigen Reihenfolge zurückgegeben werden.

Das Gitter lösen

(Dieser Abschnitt ist etwas veraltet. Wird behoben, sobald ich wirklich sicher bin, dass ich mit dem Golfen fertig bin.)

Als nächstes durchlaufen wir MapIndexeddie innere Ebene dieser verschachtelten Liste. Dies ruft die anonyme Funktion auf, die als erstes Argument für jedes Zeichen im Raster bereitgestellt wird, und gibt ihr auch eine Liste mit den aktuellen zwei Koordinaten. Das Gitter wird der Reihe nach durchlaufen, sodass wir jede Zelle auf der Grundlage der vorherigen Zellen sicher berechnen können.

Wir verwenden die Variablen r(ight) und b(ottom) als Nachschlagetabellen für die Ergebnisse jeder Zelle. Unsere anonyme Funktion enthält die aktuellen Koordinaten #2, sodass wir die Eingaben für jede Zelle mit erhalten

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

Beachten Sie, dass in der ersten Zeile und Spalte auf undefinierte Werte von rund zugegriffen wird b. Mathematica hat damit kein wirkliches Problem und gibt Ihnen stattdessen nur Ihre Koordinaten zurück, aber wir verwerfen dieses Ergebnis trotzdem, da alle Kacheln in dieser Zeile / Spalte konstante Funktionen sind.

Nun dieses Ding:

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

Ist eine Golf Form von

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

Dies ist wiederum eine Funktion, die angesichts der beiden Kacheleingaben eine Zuordnung zurückgibt (Sie würden es eine Hashmap oder eine Tabelle in anderen Sprachen nennen), die alle möglichen Kachelergebnisse für diese beiden Eingaben enthält. Um zu verstehen, wie alle Funktionen implementiert sind, müssen Sie wissen, dass auf das erste Argument einer solchen Funktion mit #und auf das zweite mit zugegriffen werden kann #2. Außerdem erhalten ##Sie eine Folge beider Argumente, mit denen Sie die Argumente "splattern" können.

  • 0: ist unkompliziert, wir geben nur eine Konstante zurück {0, 0}und weisen diese auch zfür die zukünftige Verwendung zu (z. B. in der Raumkachel).
  • 1: ist im Wesentlichen gerecht {1,1}, aber mit zdiesem wird verkürzt 1+z. Wir speichern dies auch in o, da es für alle Kacheln nützlich ist, bei denen beide Ausgaben identisch sind.
  • +: Hier nutzen wir die Sequenz. {##}ist dasselbe wie {#,#2}und leitet beide Eingänge unverändert weiter.
  • \: Wir tauschen die beiden Argumente aus {#2,#}.
  • U: Jetzt können wir nutzen o. o#2Das heißt {1,1}*#2, wir setzen einfach das oberste Argument in beide Ausgaben.
  • )In analoger Weise für das linke Argument: o#.
  • !: Bitwise ist ärgerlich in Mathematica nicht, aber da wir immer nur haben 0und 1beide Eingänge aus, können wir einfach abziehen 1( und dadurch invertiert sie) und geben sie an: 1-{##}.
  • &: Dieser ist ziemlich geschickt. Zuerst bemerken wir, dass bitweise und für 0und 1mit der Multiplikation identisch ist. Darüber hinaus o##ist das gleiche wie o*#*#2.
  • |: Auch hier verwenden wir eine äquivalente Funktion. Bitweise oder ist dasselbe wie Maxin diesem Fall, daher wenden wir Maxauf die Eingabeargumente an und multiplizieren das Ergebnis mit {1,1}.
  • ^: Das kürzeste, was ich für xor gefunden habe, ist, den Unterschied zu nehmen und ihn zu quadrieren (um die Positivität sicherzustellen), also haben wir es o(#-#2)^2.

Nachdem diese Funktion abgeschlossen ist und gibt den vollständigen Verband wir die aktuelle Zelle Zeichen verwenden , um das Element herausziehen wir daran interessiert sind , und speichern Sie es in rund b. Beachten Sie, dass dies auch der Rückgabewert der in verwendeten anonymen Funktion ist MapIndexed, sodass mir die Zuordnung tatsächlich ein Raster aller Ergebnisse gibt.

Ausgabeverarbeitung

MapIndexedgibt ein 3D-Gitter zurück, wobei die erste Dimension der horizontalen Gitterkoordinate entspricht (die frühere Transposition beachten), die zweite Dimension der vertikalen Gitterkoordinate entspricht und die dritte angibt, ob wir eine untere oder eine linke Ausgabe haben. Beachten Sie, dass dies auch die Eingabezeile und -spalte enthält, die wir entfernen müssen. Also greifen wir mit auf die unterste Ausgabe der untersten Zeile zu

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

und die rechte Ausgabe der letzten Spalte mit

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

Beachten Sie, dass dies 2;;ein Bereich vom zweiten bis zum letzten Element ist.

Zuletzt wenden wir Printbeide an (wobei @@@als syntaktischer Zucker für die zweite Ebene verwendet wird Apply), wobei nur alle Argumente hintereinander ausgegeben werden (und da dies auf zwei separate Ausdrücke angewendet wird, wird zwischen bottom und eine neue Zeile eingefügt rechte Ausgabe).

Martin Ender
quelle
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;}}

Hier können Sie die Ergebnisse online anzeigen!

Dies definiert eine Funktion void f(char*, char*, char*), die die Karte als erste Eingabe, dann die obere Eingabezeile und dann die linke Eingabezeile verwenden soll.

Folgendes habe ich zum Testen verwendet:

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

Durch Eingabe des 2-Bit-Multiplikators von Sp3000:

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

Wir bekommen:

00001001
11111111

Mit dem halben Addierer von Sp3000 möchte ich einen Volladdierer sehen ... Einer von euch hat es geschafft! Ich denke nicht, dass das System als Programmiersprache für sich allein steht, aber es war sehr interessant. Dies scheint jedoch ein hervorragendes Ziel für Metagolf zu sein!

Eine kurze Erklärung:

Hier ist der entschlüsselte, kommentierte Code:

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

Wir iterieren von clinks nach rechts (dann von oben nach unten), schreiben die tEingaben jedes Mal neu und geben eine Ausgabe ganz rechts aus, die in die lZeichenfolge eingefügt wird . Wir können uns das so vorstellen, dass wir die obere Reihe von iterativ cdurch 1's und 0' s ersetzen und die Bits verfolgen, die rechts herausgedrückt werden.

Hier ist eine visuellere Sequenz, Zeile für Zeile:

 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.

Dies wird offensichtlich mit unterschiedlichen Symbolen und Größen komplizierter, aber die zentrale Idee gilt. Dies funktioniert nur, weil die Daten niemals auf- oder abfließen.

BrainSteel
quelle
Viel Potenzial zum Golfen! Beginnen Sie, indem Sie den Header von fauf ändern f(c,t,l)char*c,*t,*l(machen Sie sich keine Gedanken über den Rückgabetyp).
FUZxxl,
@FUZxxl Jemand hat dies im Chat erwähnt, aber ich konnte es nicht zum Laufen bringen. Ist dieses Verhalten Standard? LLVM löst mit dieser Zeile mindestens 2 Fehler aus.
BrainSteel
Es tut uns leid. Hätte sein sollen f(c,t,l)char*c,*t,*l;. Kompilieren Sie nicht im C11-Modus, da die implizite int-Regel, die das Löschen des Rückgabetyps ermöglicht, in dieser Revision gelöscht wurde.
FUZxxl
@FUZxxl Es scheint auch in C99 zu scheitern. Tatsächlich hat jeder Modus, in dem ich den Compiler eingestellt habe, diesen Code abgelehnt.
BrainSteel
Haben Sie gleich danach das Semikolon hinzugefügt *l? Es wird auf meinem Computer im C99-Modus kompiliert.
FUZxxl
7

Python 2, 316 Bytes

Diese Funktion erstellt 10 Kachel-Lambda-Funktionen, durchläuft dann das Raster und aktualisiert die Logikzustände. Die endgültigen vertikalen und horizontalen Logikzustände werden dann gedruckt.

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)

Der ungolfed Code inklusive 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

Die test.txtDatei (einschließlich 2 anderer Tests von 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

Die Testausgabe:

------------------
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
Logik-Ritter
quelle
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'))

Ernsthaft CH, wenn dies noch kein Spielzeug ist, solltest du anfangen, einige Spielzeugfabriken anzurufen.

Golfer und viel weniger effizient, aber CarpetPython noch nicht eingeholt. Input wie f("1111\n1\\+\\\n1+\\+\n1\\+\\","0101","1010")Output ist ein Tupel von zwei Strings. Stellen Sie jedoch sicher, dass auf dem Board kein Zeilenumbruch vorhanden ist, der zu Problemen führen kann.

Testprogramm

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

Sie können auch alle möglichen Fälle mit testen test_all().

Zusätzliche Testfälle

Halbaddierer

Hier ist ein Halbaddierer, der die oberen linken Bits addiert und Folgendes ausgibt <input bit> <carry> <sum>:

+))
U&+
U+^

Tests:

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

Die Ausgabe sollte identisch sein, auch wenn das zweite / dritte Bit der Eingänge geändert wird.

Rechte Shifttaste

Vorausgesetzt abc / def, dies gibt Folgendes aus fab / cde:

\\\
\++
\++

Tests:

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

3-Bit-Sortierer

Sortiert die ersten drei Bits von oben in die letzten drei Bits von unten. Richtige Ausgabe ist Junk.

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

2 Bit mal 2 Bit Multiplikator

Nimmt das 1./2. Bit von oben als erste Zahl und das 3./4. Bit von oben als zweite Zahl. Ausgabe bis zu den letzten vier Bits von unten. Richtige Ausgabe ist Junk.

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

Bearbeiten: Golfed aus einer Spalte und zwei Zeilen.

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
quelle
1

R 524 517

Wahrscheinlich viel Platz, um dies im Moment zu reduzieren, aber das war wirklich interessant zu tun. Es gibt zwei Funktionen. Funktion d ist der Arbeiter und f ist der Vergleicher.

Die Funktion d wird mit 3 Strings aufgerufen, Gates, Top und Left. Die Gates werden in eine durch die Breite bestimmte Matrix gelegt.

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

Ein bisschen formatiert

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

Einige 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
quelle