Ein zyklisches Tag-System simulieren

14

Ein zyklisches Tag-System ist ein winziges, Turing-vollständiges Rechenmodell, das aus einem Alphabet mit zwei Symbolen (ich werde es verwenden {0,1}), einer endlichen, nicht leeren zyklischen Liste von Produktionen , die aus diesen beiden Symbolen bestehen, und einem unbegrenzten Wort besteht, aus dem auch besteht diese beiden Symbole.

Bei jedem Schritt:

  • Das erste Element im Wort wird entfernt
  • wenn es war, wird 0die aktuelle Produktion übersprungen
  • War es das, wird 1die aktuelle Produktion an das Ende des Wortes angehängt .
  • Die nächste Produktion wird aktiv. Wenn dies die letzte Produktion war, kehren Sie zur ersten zurück.

Das System hält an, wenn das Wort leer wird.

Ein Beispiel (aus Wikipedia):

Productions: (010, 000, 1111)
Initial word: 11001

Generation  Production   Word (before)            Word (after)
   0           010           11001             →     1001010       
   1           000            1001010          →      001010000
   2           1111            001010000       →       01010000
   3           010              01010000       →        1010000
   4           000               1010000       →         010000000
   5           1111               010000000    →          10000000
   6           010                 10000000    →           0000000010
   7           000                  0000000010 →            000000010
   8           1111                  000000010 →             00000010
   9           010                    00000010 →              0000010

Ihre Aufgabe besteht darin, ein Programm oder eine Funktion zu schreiben, die Folgendes übernimmt:

  • eine Liste der Produktionen,
  • das Anfangswort und
  • eine Generation,

und druckt oder gibt das Wort bei dieser Generation zurück.

Beispielsweise,

cyclic_tag(
      prod=[[0,1,0],[0,0,0],[1,1,1,1]], 
      word=[1,1,0,0,1], 
      gen=4) => [1,0,1,0,0,0,0]

Implementierungsdetails:

  • Das Alphabet spielt keine Rolle. Sie können 0und 1, Trueund False, Tund NIL, Aund B, oder sogar 1und 0, oder was auch immer Sie sich vorstellen, solange Sie konsequent sind. Alle Eingaben und Ausgaben müssen dasselbe Alphabet verwenden, und Sie müssen angeben, wofür 0und wofür Sie verwenden 1.

  • Die Länge des Wortes muss theoretisch unbegrenzt sein. Das heißt, Sie können eine maximale Wortlänge möglicherweise nicht fest codieren. Wenn ich Ihr Programm auf einem idealen Computer mit unendlich viel Arbeitsspeicher ausführe, muss Ihr Programm theoretisch in der Lage sein, darauf zuzugreifen. (Sie können die Grenzen Ihres Interpreters / Compilers ignorieren.)

  • Wenn das angegebene System anhält, bevor die angegebene Generation erreicht ist, müssen Sie das leere Wort zurückgeben oder ausdrucken.

  • Die leere Produktion ist vorhanden, und Sie müssen damit umgehen können. Wenn Sie ein vollständiges Programm schreiben, muss Ihre E / A auch damit umgehen können.

Bearbeiten : Ich hatte ursprünglich vorgesehen, dass die Generierung 0das Eingangswort selbst und die Generierung 1das Ergebnis des ersten Schritts ist. Das heißt, ich hatte vorgehabt, dass Sie die vorherige Spalte zurückgeben. Da ich dies jedoch nicht klar genug dargelegt habe, werde ich beide Optionen akzeptieren . Für jede Generation können Sie den Wert entweder in der Vorher- oder in der Nachher- Spalte zurückgeben. Sie müssen angeben , dass Sie die folgen nach Spalte, wenn Sie so tun. Sie müssen auch konsistent sein, in welcher Spalte Sie sich entscheiden.

Ich werde ab sofort den kleinsten Code pro Woche vergeben (27.10.2014).

Marinus
quelle
Sind Sie sicher, dass Ihre Ausgabe im Beispiel korrekt ist? Basierend auf dem anderen Beispiel, das Sie gegeben haben, denke ich, dass es Gen 5 ist ...
FryAmTheEggman
Können wir die Eingabe in einer anderen Reihenfolge vornehmen?
Martin Ender
1
@FryAmTheEggman: Es ist richtig, ich meinte die 'Vorher'-Spalte. Wenn mehr Leute diesen Fehler gemacht haben, werde ich meine Frage ändern, um entweder zu akzeptieren. Ich gebe zu, ich war nicht sehr klar.
Marinus
@ Martinbüttner: solange du die bestellung angibst ist es egal.
Marinus

Antworten:

4

GolfScript (17 bis 19 Byte je nach Eingabeformat und akzeptiertem Ausgabeformat)

18 Bytes:

~.@*<{\1,or(@*+}/`

Nimmt Eingaben in das Formular auf [1 1 0 0 1] [[0 1 0] [0 0 0] [1 1 1 1]] 4und gibt Ausgaben in das Formular aus [1 0 1 0 0 0 0]. (Könnte 17 Bytes ohne das letzte sein, `wenn die Ausgabe 1010000akzeptabel ist).

Online-Demo

19 Bytes:

~.@*<{\0`or(1&@*+}/

Nimmt Eingaben in das Formular auf "11001" ["010" "000" "1111"] 4.

Online-Demo

Präparation

~        # Evaluate input: stack: word productions gen
.@*<     # Produce a list of the right number of productions with suitable repetition
{        # For each of those productions:
  \      #   Bring the word to the top
  0`or   #   Ensure that we don't get an error if the word is empty
  (1&    #   Pop the first char from the word and evaluate it
  @*     #   Repeat the production that many times
  +      #   Concatenate 0 or 1 copies of the production to the rest of the word
}/       # Endforeach

Kredit Martin Büttner ‚s CJam Lösung für die Idee , die Liste der Produktionen durch Wiederholung und Abschneiden zu erzeugen.

Peter Taylor
quelle
Sie sind an die von Ihnen angegebene CJam-Lösung gebunden, daher habe ich diese Antwort ausgewählt. Wenn Sie ein weiteres Byte abschneiden, werde ich es mir noch einmal überlegen :)
Marinus
@marinus, akzeptierst du die 17-Byte-Version, auf die ich mich im Text meiner Antwort beziehe?
Peter Taylor
Hatte das nicht gesehen, aber es sieht gültig aus. Sie sollten es vielleicht etwas deutlicher markieren.
Marinus
5

Haskell, 55 53 51

(t:w)%p|t=w++p|0<1=w
x%_=x
e w=(!!).scanl(%)w.cycle

dies verwendet Trueas 1und Falseas 0. Beispiellauf:

*Main> let t=True ; f=False
*Main> e [t,f,t] [[f,f,f],[t,t,t]] 4
[False,False,False,False,False]
stolzer haskeller
quelle
3

CJam, 31 30 28 27 24 18 Bytes

{_@*<{\_0a?(@*+}/}

Dies definiert einen Block (der einer Funktion am nächsten kommt), der davon ausgeht, dass sich die Eingabe wie folgt auf dem Stapel befindet

[1 1 0 0 1] [[0 1 0] [0 0 0] [1 1 1 1]] 9

Auf ähnliche Weise verbleibt ein Array von 0s und 1s auf dem Stapel.

Teste es hier. Fügen Sie die Eingabe in die erste Zeile und den Code in die dritte Zeile ein und fügen Sie ein ~an, um den Block tatsächlich auszuwerten. Z.B

[1 1 0 0 1] [[0 1 0] [0 0 0] [1 1 1 1]] 9
{_@*<{\_0a?(@*+}/}~

Wenn die Ausgabe nicht dieselbe Form wie die Eingabe haben muss

Erläuterung:

_@*<{\_0a?(@*+}/
_@               "Duplicate the generation and pull the productions to the top.";
  *<             "Repeat the productions N times and take the first N elements.";
    {         }/ "For each element in that list, run this block.";
     \           "Swap production and current word W.";
      _0a?       "W = (W != []) ? W : [0]. This is to ensure we can unshift an element.";
          (      "Unshift the first 0 or 1 from the word.";
           @     "Rotate the stack, pulling the production to the top.";
            *    "Repeat it 0 or 1 times.";
             +   "Append to the word.";

Der Endzustand des Wortes bleibt auf dem Stapel.

Vielen Dank an Peter Taylor, der mich dazu gebracht hat, das noch einmal zu überdenken.

Martin Ender
quelle
1
l~{_,g{('1=@(:Pa+@@P*+}*}*\;28 und noch verbesserungswürdig (vor allem der (:PTeil), aber Zeit für das Mittagessen
Optimizer
@Optimizer Ah, gute Idee. Vielen Dank. Und ja, das :Pnervt mich auch: D
Martin Ender
l~{_,g{(si@(:Pa+@@P*+}*}*\;: 27 und nach :P
eingehender
_,gkann auch durch _!!dieselben Bytes ersetzt werden.
Optimierer
@Optimizer könnte ich dann genauso gut nutzen _{...}{}?.
Martin Ender
2

Mathematica, 84 80 77 Zeichen

f[_,w_,_]=w;f[p_,{x_,y___},n_/;n>0]:=f[RotateLeft@p,Flatten@{y,p~Take~x},n-1]

Beispiel:

f[{{0, 1, 0}, {0, 0, 0}, {1, 1, 1, 1}}, {1, 1, 0, 0, 1}, 4]

{1, 0, 1, 0, 0, 0, 0}

Alephalpha
quelle
2

Pyth 22

Benötigt alle 3 Argumente als separate Eingaben.

#Vvw=z+tz*@Q%NlQshz)zq

Nimmt Argumente wie:

11001
["010","000","1111"]
4

Erläuterung:

                        : Implicit: z = input(); Q=eval(input())
#                       : Loop until an exception is thrown
 Vvw               )    : for N in range(eval(input()))
    =z                  : assign to z
      +tz               : the sum of the tail of z and
         *@Q%NlQ        : Q[N%len(Q)] times
                shz     : the numeric value of the first character in z
                    zq  : print z then throw exception

Python 2 - 61 67 91 105 124

c=lambda p,w,g:g*w and c(p[1:]+p[:1],w[1:]+w[0]*p[0],g-1)or w

Hübsche Joe-Basic-Antwort. Angenommen, die leere Produktion ist [[]].

Vielen Dank an @xnor für den Hinweis, dass Golfen um 2 Uhr morgens eine schlechte Entscheidung ist.

Zusätzlicher Dank geht an @xnor, dem ich anscheinend 50% meiner Punktzahl zu verdanken habe.

Stichprobe:

>>> c([[0,1,0],[0,0,0],[1,1,1,1]],[1,1,0,0,1],4)
[1, 0, 1, 0, 0, 0, 0]
FryAmTheEggman
quelle
1
Sicherlich ist es kürzer eine Lambda und nur Schreib zu verwenden g and wfür x? Außerdem denke ich, g*wsollte es funktionieren, um einen wahrheitsgemäßen Wert zu liefern, wenn beide gungleich Null und wnicht leer sind.
Xnor
Auch das Innere verstehe ich nicht if x else w. Wird nicht ximmer wahr sein, weil dieser Code nur ausgeführt wird if x, oder fehle ich etwas?
Xnor
@xnor Sicherlich sind Sie ganz richtig :)
FryAmTheEggman
1
Noch ein andorpnc=lambda p,w,g:g*w and c(p[1:]+p[:1],w[1:]+w[0]*p[0],g-1)or w
bisschen
@xnor Danke :) Auch jetzt, da Sie es zu einer Funktion von 3 Variablen gemacht haben, denke ich, dass ich es in Pyth übersetze ...
FryAmTheEggman
1

Javascript ES6 - 88 Bytes

f=(p,w,g,n)=>g?w.replace(/(.)(.*)/,(_,a,b)=>f(p,a*1?b+p[(n=n||0)%p.length]:b,g-1,n+1)):w

Sieht der Antwort von Fry, die gerade in meinem Browser aufgetaucht ist, unheimlich ähnlich. (Kein Kopieren, ich schwöre feierlich.)

Es scheint, dass er die Array-Route gegangen ist, während ich die String / Regex-Route gegangen bin.

Erweitert:

f = (p,w,g,n) =>
    g ?
        w.replace( /(.)(.*)/, (_,a,b) =>
            f( p, a*1 ? b + p[(n=n||0)%p.length] : b, g-1, n+1 )
        )
    :
        w

Beispielausgabe

f(['010','000','1111'],'11001',4)
"1010000"

Beobachten Sie jetzt, wie die Golfsprachen hereinkommen und uns beide massakrieren. : D

COTO
quelle
Ich habe meinen Beitrag tatsächlich gelöscht, weil ich für die beiden Beispiele unterschiedliche Antworten erhalten habe. Haben Sie das Beispiel ausprobiert, in dem er von Generation zu Generation geht? Im Vergleich zu dem vollständigen
Anrufbeispiel
Und keine Sorge, ich glaube, Sie haben mich nicht kopiert: P
FryAmTheEggman
@FryAmTheEggman: Mine generiert konsistent die "Vorher" -Spalte für die nummerierte Generation. Dies stimmt mit dem Beispiel im OP überein, und es scheint logisch, dass "Generation 0" den Eingang einfach zurückliefert, ohne ihn zu verarbeiten, was mit dieser Interpretation übereinstimmt. Im Übrigen habe ich den Haftungsausschluss "Kopie" hinzugefügt, da die Lösungen in mancher Hinsicht unheimlich ähnlich waren. Wir haben dieselben Argumentnamen verwendet, dieselbe rekursive Grundstruktur und sogar dasselbe vierte Phantomargument hinzugefügt n. Großartige Köpfe, was? : D
COTO
Ok, ich denke, wenn einer von uns sich irrt, irren wir uns beide! Vereinigt stehen wir.
FryAmTheEggman
@FryAmTheEggman: Sie haben sich in Bezug auf Mr. Peppe nicht geirrt. ;)
COTO