Die XOROR-Sequenz


23

Zelluläre Automaten sind wirklich faszinierend. Diejenigen, über die normalerweise gesprochen wird, sind die binären, dh diejenigen, die durch eine Zahl darstellbar sind. Diese wurden jedoch meiner Meinung nach zu Tode gebracht. Ternäre CAs sind interessanter, aber wir müssen alle ASCII-Werte berücksichtigen! Was für ein Spaß könnte das sein!

Anstatt für jeden Charakter einen Regelsatz zu bestimmen, verwende ich eine einfache Entscheidungsregel, über die ich gleich sprechen werde. Um die nächste Generation zu bestimmen, betrachten wir die drei "oberen" Zellen, ähnlich wie bei einem zellularen Automaten. Beachten Sie ein Beispiel:

QWERTY
X Y Z

Die "Spitze" von Yist WER, die Zellen oben und rechts, oben und oben und links zu sein. Y wird das Ergebnis der Funktion sein, die ich definieren werde. Dabei handelt es sich um eine Funktion für Zeichenfolgen mit drei Zeichen. Die „Spitze“ von Xist QW, oder eine Raumfüllung im inexistent / fehlende Zelle .

Nun zur spaßigen Funktion! Ich bezeichne diese Sequenz aus einem bestimmten Grund als XOROR-Sequenz. Sei Ader Zeichencode der oberen linken Zelle, Bder Zeichencode Cder oberen Zelle und der Zeichencode der oberen rechten Zelle. Dann ist die resultierende Zelle das Zeichen, dessen Zeichencode ist (A XOR B) OR C, das heißt (A^B)|C. (Wenn ein resultierender Wert größer als 126 ist, wird er auf gesetzt (CHARCODE % 127) + 32. Wenn ein Wert kleiner als 32 ist, wird nichts getan.) Hier ein Beispiel für den Startwert Hello, World!:

S: Hello, World!
0: mmmo/c_ z}~)e
   m = ( )^(H)|(e) = (32^72)|101 = 104|101 = 109 (m)
    m = (H)^(e)|(l) = (72^101)|108 = 45|108 = 109 (m)
    etc.
1: mmo/c_<   +wl
2: mo/c_<c< + |;
3: o/c_<c  ?+  g
4: oc_<c c??4+gg
5: 0_<c c  4+ o 
6: _<c ccc4??ooo
7:  c ccc4 ?o o 
8: ccccc4w? pooo
9: cccc4w h   o 
A: ccc4wc hh ooo
B: cc4wc4kh ooo 
C: c4wc4  #ooo o
D: wwc4w4#ooo oo
E: wc4wwc oo oo 
F: w4wwc4oo oo o
G: wwwc4   oo oo
H: wwc4w4 oo oo 
I: w4wwc4oooo oo
J: wwwc4  oo oo 
K: wwc4w4oo oo o
L: wc4wwo  oo oo
M: w4wwo8ooo oo 
N: wwwo8  o oo o
O: wwo8w8oooo oo

Und wir können noch eine Weile weitermachen. Diese Änderung der Zeichenfolge wird als XOROR-Sequenz bezeichnet.

Ziel Sie müssen ein Programm oder eine Funktion schreiben, die eine der folgenden Aufgaben ausführt:

  1. Wenn Sie eine Zeichenfolge sund eine Zahl angeben n >= 0, geben Sie die nth-Zeichenfolge in der XOROR-Sequenz mit seed aus s, wobei n = 0es sich um die erste Transformation der Zeichenfolge handelt.
  2. Wenn ein String angegeben wird s, wird ein unendlicher Stream der XOROR-Sequenz mit Seed ausgegeben (für Programme) oder generiert (für Funktionen / Generatoren) s. Sie können anhalten, wenn die Sequenz wiederholt wird, dies ist jedoch nicht erforderlich.

s besteht immer nur aus druckbaren ASCII-Zeichen, vom Leerzeichen bis zur Tilde plus Tabulatoren (keine Zeilenumbrüche)

Dies ist ein , also gewinnt das kürzeste Programm in Bytes.


Ich habe Probleme beim Parsen des Satzes "Also, welche Funktion auch immer ich für einen String mit drei Zeichen definieren möchte, Y wird." Könnte dies umformuliert werden: "Y wird das Ergebnis der Funktion sein, die ich definieren werde, eine Funktion für Zeichenfolgen mit drei Zeichen."
Hypotenuser

3
Alle os lassen es wie ein Zergrausch aussehen .
mbomb007

3
Beobachtung: Da XOR und OR die Anzahl der Bits beibehalten und alle ASCII-Werte 7 Bits sind, ist der einzige Fall, in dem ein CHARCODE größer als 126 ist, der 127. Daher können Sie ihn einfach durch ein Leerzeichen (32) ersetzen 127%127+32==32.
CAD97

2
Warum ist n=0nicht die ursprüngliche Zeichenfolge?
Neil

3
@FatalSleep Was Ihre erste Beschwerde betrifft, habe ich festgestellt, dass, wenn keine Zelle vorhanden ist, das Ergebnis ein Leerzeichen ist, also eher ein Leerzeichen (d^!)|(space). Was Ihre zweite Frage betrifft , führen Sie diese aus, (CHAR%127)+32 nachdem das XOROR ausgeführt wurde.
Conor O'Brien

Antworten:


4

MATL , 33 31 Bytes

Q:"32XKhKwh3YCPo2$1Z}Z~Z|127KYX

Dies funktioniert in Version 13.1.0 der Sprache / des Compilers, die der Herausforderung vorausgeht .

Die erste Eingabe ist die Zahl, die zweite die Zeichenfolge.

Probieren Sie es online!

Q           % take input (number) implicitly and add 1
:"          % repeat that many times
  32XK      %   push 32 (space). Copy to clipboard K.
  h         %   concatenate. Takes input (string) implicitly the first time
  Kwh       %   push space, swap, concatenate
  3YC       %   overlapping blocks of length 3 as columns of 2D array
  P         %   flip upside-down 
  o         %   convert to numbers
  2$1Z}     %   separate the three rows and push them
  Z~        %   bitwise XOR (note the rows are in reverse order)
  Z|        %   bitwise OR
  127KYX    %   replace 127 by space using regexprep, which converts to char
            % end loop
            % implicitly display

21

Mathematica, 133 Bytes

FromCharacterCode@Nest[BlockMap[If[#>126,#~Mod~127+32,#]&[BitXor[#,#2]~BitOr~#3]&@@#&,ArrayPad[#,1,32],3,1]&,ToCharacterCode@#,#2+1]&

Es wäre schön CellularAutomaton[], wenn eine Lösung funktionieren würde, aber ich kam immer wieder zu kurz. Jemand?

Bearbeiten: einige schöne Bilder (zum Vergrößern anklicken)

plotCA[str_, n_] := ArrayPlot[NestList[foo[str],n], ColorFunction -> "Rainbow"]

plotCA["Hello, World!", 60]:

60 Iterationen von "Hello, World!"

plotCA[bXORnotb, 100]:

100 Iterationen von Hamlet-Monolog

plotCA[raven, 100]:

100 Iterationen von Poe


1
Können Sie nicht einfach CellularAutomatonIhre Update-Funktion geben? (Die tatsächliche Regel Nummer mit 127 gültigen Staaten wäre verrückt.)
Martin Ender

@ MartinBüttner Du kannst, aber es ist ein mühsamer Versuch, das Verhalten an den Rändern zu berücksichtigen, um es mit der Spezifikation in Einklang zu bringen. BlockMap [] war nur kürzer.
Hypotenuser

7

Java, 193 185 Bytes

Weil Java.

-8 Bytes durch Umschalten in eine Schleife anstatt in eine anonyme Funktion

Gibt die n-te Iteration von XOROR auf s zurück.

(s,n)->{String o=s;for(;n-->=0;){o="";for(int i=0;i<s.length();i++){char c=(char)((i>1?s.charAt(i-1):' ')^s.charAt(i)|(i<s.length()-1?s.charAt(i+1):' '));o+=c>126?' ':c;}s=o;}return o;}

Lesbare Version:

static BiFunction<String, Integer, String> f = (s,n)->{
    String o=s;
    for(;n-->=0;) {
        o = "";
        for (int i=0;i<s.length();i++) {
            char c=(char)((i>1?s.charAt(i-1):' ')^s.charAt(i)|(i<s.length()-1?s.charAt(i+1):' '));
            o+=c>126?' ':c;
        }
        s=o;
    }
    return o;
};

public static void main(String[]a) {
    System.out.println(f.apply("Hello, World",1));
}

Ziemlich wörtliche Implementierung der Spezifikation mit einer rekursiven Schleife, um die Operation n-mal anzuwenden. Einige Bytes wurden jedoch mit meiner Beobachtung gespeichert, dass die CHARCODE> 126-Klausel immer nur mit CHARCODE == 127 auftreten wird, was zum Speichern führtSPACE anstelle von führt DEL.

Ich habe meinen Code über ein paar willkürlich ausgewählte Zeichenketten laufen lassen und diesen wunderbaren Zyklus gefunden:

oook$ok$ok$ok$
ook$ok$ok$ok$o
oo$ok$ok$ok$ok
oook$ok$ok$ok$

5
Diese Antwort sieht aus ok!
Conor O'Brien


5

CJam, 38 Bytes

lri){2S*\*3ew{)\:^|_'~>{i127%' +}&}%}*

Teste es hier.

Erläuterung

l                e# Read string.
ri               e# Read n.
){               e# Run this block n+1 times...
  2S*\*          e#   Wrap in two spaces.
  3ew            e#   Get all (overlapping) substrings of length 3.
  {              e#   Map this block over all those substrings...
    )\           e#     Pull off the third character and put it below the other two.
    :^           e#     Take XOR of the other two.
    |            e#     OR with the third one.
    _'~>         e#     Duplicate and check if it's greater than '~'.
    {i127%' +}&  e#     If so, mod 127, add to space.
  }%
}*

Ich denke, Sie können ein paar Bytes einsparen, lri){2S*\*3ew{)\:^|}%127c' er}*weil die Zeichen Pre-Modulo-Operation 127 nie überschreitet
Luis Mendo

5

Haskell, 123 Bytes

import Data.Bits
f s=toEnum.a<$>zipWith3(((.|.).).xor)(32:s)s(tail s++[32])
a x|x>126=32|1<2=x
tail.iterate(f.map fromEnum)

Dies gibt einen unendlichen Strom der XOROR-Sequenz zurück. Anwendungsbeispiel (drucke die ersten 5 Elemente des Seeds "Hello, World!"):

*Main> mapM_ print $ take 5 $ (tail.iterate(f.map fromEnum)) "Hello, World!"
"mmmo/c_ z}~)e"
"mmo/c_<   +wl"
"mo/c_<c< + |;"
"o/c_<c  ?+  g"
"oc_<c c??4+gg"

Wie es funktioniert:

tail.iterate(f.map fromEnum)               -- repeat forever: convert to ASCII
                                           -- value and call f, discard the first
                                           -- element (the seed).

                                           -- one iteration is:
  zipWith3(   )(32:s) s (tail s++[32])     -- zip the elements from the three lists
                                           -- (space:s), s and tail of s ++ space,
                                           -- e.g. s = "Hello!":
                                           --   | Hello|
                                           --   |Hello!|
                                           --   |ello! |
                                           -- (shortest list cuts off)

         ((.|.).).xor                      -- the function to zip with is a
                                           -- point-free version of (x xor y) or z

toEnum.a<$>                                -- adjust every element >126 and convert
                                           -- back to characters

4

PHP, 186 Bytes (mit n) | 177 Bytes (unendlich)

Es stellte sich heraus, dass der Endlosdruck kürzer ist ...

// With n
function x($s,$n){while($n-->=0){for($i=0,$r='';$i<strlen($s);$i++){$b=ord($s[$i-1])or$b=32;$a=ord($s[$i+1])or$a=32;$t=($b^ord($s[$i]))|$a;$r.=chr($t>126?($t%127)+32:$t);}$s=$r;}echo$s;}

// Infinite
function i($s){while(true){for($i=0,$r='';$i<strlen($s);$i++){$b=ord($s[$i-1])or$b=32;$a=ord($s[$i+1])or$a=32;$t=($b^ord($s[$i]))|$a;$r.=chr($t>126?($t%127)+32:$t);}echo$s=$r;}}

Ungolfed mit n:

function x($s, $n) { // $s - string to process; $n - which string to output
  while ($n-- >= 0) {
    for ($i = 0, $r = ''; $i < strlen($s); $i++) {
      $b = ord($s[$i - 1]) or $b = 32;
      $a = ord($s[$i + 1]) or $a = 32;
      $t = ($b ^ ord($s[$i])) | $a;
      $r .= chr($t > 126 ? ($t % 127) + 32 : $t);
    }
  $s = $r;
  }
  echo $s;
}

Ungolfed unendlich:

function x($s) { // $s - string to process
  while (true) {
    for ($i = 0, $r = ''; $i < strlen($s); $i++) {
      $b = ord($s[$i - 1]) or $b = 32;
      $a = ord($s[$i + 1]) or $a = 32;
      $t = ($b ^ ord($s[$i])) | $a;
      $r .= chr($t > 126 ? ($t % 127) + 32 : $t);
    }
    echo $s = $r;
  }
}

1
Es kann noch viel golfen werden. Zum Beispiel function i($s){for(;;$i=0,print$s=$r)for($r='';$i<strlen($s);$r.=chr($t>126?32:$t))$t=((ord($s[$i-1])?:32)^ord($s[$i]))|(ord($s[++$i])?:32);}ist 141 Bytes lang (-36 Bytes).
Blackhole

2

C ++

N-te Sequenz (212)

void x(char*s,int l,int n){for (;n-->0;) {char*t=new char[l-1](),w;for(int i=0;i<l-1;i++)t[i]=((w=(((i-1>= 0)?s[i-1]:32)^s[i])|((i+1<l-1)?s[i+1]:32))>126)?((w%127)+32):w;for(int i=0;i<l-1;i++)s[i]=t[i];delete[]t;}}

Ungolfen

void x(char*s, int l, int n){
    for (;n-- > 0;) {
        char*t=new char[l-1](),w;
        for(int i = 0;i < l-1; i++)
            t[i] = ((w = (((i-1>= 0) ? s[i-1] : 32)^s[i]) | ((i+1 < l-1) ? s[i+1] : 32)) > 126) ? ((w % 127) + 32) : w;

        for(int i = 0; i < l-1; i++)
            s[i] = t[i];
        delete[]t;
    }
}

N-Sequenz, die Zeigersyntax anstelle von Array-Syntax verwendet, um dies noch verwirrender zu machen: (231)

void x(char*s,int l,int n){for(int x=0;x++<n;) {char*t=new char[l-1](),w;for(int i=0;i<l-1; i++)*(t+i)=((w=(((i-1>= 0)?*(s+i-1):32)^*(s+i))|((i+1<l-1)?*(s+i+1):32))>126)?((w%127)+32):w;for(int i=0;i<l-1;i++)*(s+i)=*(t+i);delete[]t;}}

Ungolfen

void x(char* s, int l, int n){
    for (;n-- > 0;) {
        char*t = new char[l-1](),w;
        for(int i = 0; i < l-1; i++)
            *(t+i) = ((w = (((i-1>= 0) ? *(s+i-1) : 32)^ *(s+i)) | ((i+1<l-1) ? *(s+i+1) : 32)) > 126) ? ((w%127)+32) : w;

        for(int i = 0;i < l-1; i++)
            s[i] = t[i];
        delete[]t;
    }
}

Debug-Funktion (zum Spaß)

void d(char* seed, int len, int nth) {
    for (int n = 0; n++ < nth;) {
        char* tout = new char[len - 1]();
        for (int i = 0; i < len - 1; i++) {
            char x, y, z;
            x = ((--i >= 0) ? seed[i] : 32);
            y = seed[++i];
            z = ((++i < len - 1) ? seed[i] : 32);
            char w = (x ^ y) | z;
            tout[--i] = (w > 126) ? ((w % 127) + 32) : w;

            cout << "[" << x << " " << y << " " << z << "] " << w << endl;
        }

        for (int i = 0; i < len - 1; i++)
            seed[i] = tout[i];
        delete[] tout;
        cout << endl;
    }
}

1
Ziemlich sicher, dass die Ergebnisse besagen, dass Sie das Ergebnis ausgeben und nicht einfach zurückgeben müssen.
Mooing Duck

1
Ich schrieb eine C ++ - Version von Grund auf neu, verglich sie mit Ihrer und führte sie dann zusammen und erhielt diese bei 158 Bytes: coliru.stacked-crooked.com/a/838c29e5d496d2a6
Mooing Duck

@MooingDuck Schön! Könnte wahrscheinlich weiter reduziert werden, wenn der Compiler implizite Int durchführt, indem er zu C wechselt.
FatalSleep

Natürlich, mach 'das! Sie haben bereits die Hälfte dieses Codes geschrieben
Mooing Duck

2

JAVA 240/280 Bytes

Die populäre Java-Version zu der Zeit, als ich dies schrieb, gab an, 185 Bytes zu haben, aber es gibt zwei signifikante Fudge-Punkte. Erstens ist die Messung vermutlich nur für die Funktion, nicht für die gesamte Arbeitsquelle. Vielleicht kein solches Problem. Zweitens wird BiFunction ohne Import oder vollständig qualifizierten Namen verwendet. Das Hinzufügen der erforderlichen Bits, um es so wie es ist auszuführen (und es dann fair zu minimieren), brachte es auf 348 Bytes. Wenn Sie nur den vollständig qualifizierten Namen der BiFunction-Klasse hinzufügen, beträgt dieser 248 Byte.

Im Gegensatz dazu glaube ich, dass meine 240 Bytes sind, wenn nach den gleichen Regeln gespielt wird (keine Klasse, keine tatsächliche Ausgabe, nur das Fleisch). Die ausführbare Klasse ist 280 Byte groß und sieht wie folgt aus (nicht abgeschlossen):

class z{
  public static void main(String[] s){
    int L=s[0].length();
    for(int G=Integer.valueOf(s[1]);G-->0;){
      s[1]="";
      for(int N=0;N<L;N++){
        char C=(char)((N>0?s[0].charAt(N-1):' ')^(s[0].charAt(N))|(N<L-1?s[0].charAt(N+1):' '));
        s[1]+=C>126?' ':C;
      }
      System.out.println(s[1]);
      s[0] =s[1];
    }
  }
}

Oder verkleinert:

void m(String[] s){int L=s[0].length();for(int G=Integer.valueOf(s[1]);G-->0;){s[1]="";for(int N=0;N<L;N++){char C=(char)((N>0?s[0].charAt(N-1):' ')^(s[0].charAt(N))|(N<L-1?s[0].charAt(N+1):' '));s[1]+=C>126?' ':C;}s[0]=s[1];}return s[0];}

2

Perl, 47 Bytes

Beinhaltet +2 für -lp

Führen Sie mit der Eingabe auf STDIN, z perl -lp xoror.pl <<< "Hello, World!" | head -26

xoror.pl:

/./s;$_=$_.chop^" $_"|"$' ";y/\x7f/ /;print;redo

Dies funktioniert wie es ist, aber ersetzen Sie den \x7fdurch den entsprechenden Binärwert, um die angegebene Punktzahl zu erhalten


1

Swift: 273 Zeichen

Wow, Swift ist schlimmer als Java! (Alle diese APIs mit langen Namen!: P)

func c(s:String,n:Int=0-1){var a=[UInt8](s.utf8);for i in 0...(n>=0 ?n:Int.max-1){var z="";for i in 0..<a.count{let A=i-1<0 ?32:a[i-1],B=a[i],C=i+1<a.count ?a[i+1]:32;var r=A^B|C;r=r<32 ?32:r>126 ?32:r;z+=String(UnicodeScalar(r))};if n<0||i==n{print(z)};a=[UInt8](z.utf8)}}

Ungolfed:

func cellularAutoma(s: String,n: Int = -1)
{
    var array = [UInt8](s.utf8)
    for i in 0...(n >= 0 ? n : Int.max - 1)
    {
        var iteration = ""
        for i in 0..<array.count
        {
            let A = i - 1 < 0 ? 32 : array[i - 1], B = array[i], C = i + 1 < array.count ? array[i + 1] : 32
            var r = A ^ B | C
            r = r < 32 ? 32 : r > 126 ? 32 : r
            iteration += String(UnicodeScalar(r))
        }
        if n < 0 || i == n
        {
            print(iteration)
        }
        array=[UInt8](iteration.utf8)
    }
}

Vielen Dank an @ CAD97 für die Erwähnung, dass (A ^ B) | C nur größer als 126 sein kann, wenn es 127 ist.

Ich habe auch festgestellt, dass Sie keine Klammern um A ^ B | C benötigen, da das XOR-Verfahren vor dem OR-Verfahren durchgeführt wird, sodass ich ein paar Bytes gespart habe.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.