La secuencia XOROR

23

Los autómatas celulares son realmente fascinantes. Los que generalmente se mencionan son los binarios, es decir, los representables por un número. Sin embargo, esos, en mi opinión, se han hecho a la muerte. Las AC ternarias son más interesantes, ¡pero tenemos que considerar todas las ASCII! ¡Qué divertido podría ser eso!

En lugar de decidir un conjunto de reglas para cada personaje, usaré una regla de decisión simple de la que hablaré pronto. Para decidir la próxima generación, observamos las tres células "superiores", de forma muy similar a un autómata celular. Observa un ejemplo:

QWERTY
X Y Z

La "parte superior" de Yes WER, siendo las celdas arriba y derecha, arriba y arriba y izquierda. Y será el resultado de la función que estoy a punto de definir, que es una función en cadenas de tres caracteres. La "parte superior" de Xes QW, o un espacio que llena la celda inexistente / faltante .

Ahora, para la función divertida ! Llamo a esta secuencia la secuencia XOROR por una razón. Sea Ael código de char de la celda superior izquierda, el código de char de Bla celda anterior y el código de char de la celda Csuperior derecha. Entonces, la célula resultante es el personaje cuyo charCode es (A XOR B) OR C, es decir, (A^B)|C. (Si un valor resultante es mayor que 126, entonces se establece en (CHARCODE % 127) + 32. No se hace nada si un valor es menor que 32.) Aquí hay un ejemplo de la semilla 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

Y podemos continuar por un tiempo más adelante. Esta modificación de la cadena se llama secuencia XOROR.

Objetivo Debe escribir un programa o función que realice una de las siguientes tareas:

  1. Dada una cadena sy un número n >= 0, ngenera la th cadena en la secuencia XOROR con semilla s, n = 0siendo la primera transformación de la cadena.
  2. Dada una cadena s, genera (para programas) o genera (para funciones / generadores) un flujo infinito de la secuencia XOROR con semilla s. Puede optar por detenerse si la secuencia se repite, pero esto no es necesario.

s siempre consistirá en caracteres ASCII imprimibles, desde espacio hasta tilde más pestañas (sin líneas nuevas).

Este es un , por lo que gana el programa más corto en bytes.

Conor O'Brien
fuente
Tengo problemas para analizar la oración "Entonces, cualquier función que esté a punto de definir en una cadena de tres caracteres, Y se convertirá". ¿Podría reescribirse esto: "Y será el resultado de la función que estoy a punto de definir, una función en cadenas de tres caracteres"?
hYPotenuser
3
Todos los os hacen que parezca una fiebre zerg .
mbomb007
3
Observación: Dado que XOR y OR conservan el número de bits y todo ASCII es de 7 bits, el único caso en el que un CHARCODE es> 126 es si es 127. Por lo tanto, puede reemplazarlo con un espacio (32) desde entonces 127%127+32==32.
CAD97
2
¿Por qué n=0no es la cadena original?
Neil
3
@FatalSleep En cuanto a su primera queja, dije que, si no hay una celda presente, el resultado es un espacio, por lo que preferiría ser (d^!)|(space). En cuanto a su segunda pregunta, se realiza (CHAR%127)+32 después de que se realiza el XOROR.
Conor O'Brien

Respuestas:

4

MATL , 33 31 bytes

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

Esto funciona en la versión 13.1.0 del lenguaje / compilador, que es anterior al desafío.

La primera entrada es el número, la segunda es la cadena.

Pruébalo en línea!

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
Luis Mendo
fuente
21

Mathematica, 133 bytes

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

Sería bueno hacer que una CellularAutomaton[]solución funcionara, pero me quedé corto. ¿Nadie?

Editar: algunas fotos bonitas (haga clic para ampliar)

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

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

60 iteraciones de "¡Hola, mundo!"

plotCA[bXORnotb, 100]:

100 iteraciones del soliloquio de Hamlet

plotCA[raven, 100]:

100 iteraciones de Poe

hYPotenuser
fuente
1
¿No puedes simplemente dar CellularAutomatontu función de actualización? (El número real de la regla con 127 estados válidos sería una locura)
Martin Ender
@ MartinBüttner Puede, pero es un lastre tratar de dar cuenta del comportamiento en los bordes, para que cumpla con la especificación. BlockMap [] fue solo más corto.
hYPotenuser
7

Java, 193185 bytes

Porque Java

-8 bytes cambiando al bucle en lugar de recurrir para convertirlo en una función anónima

Devuelve la enésima iteración de XOROR en s.

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

Versión legible:

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

Prácticamente una implementación literal de la especificación, con un bucle recursivo para aplicar la operación n veces. Sin embargo, algunos bytes se guardaron con mi observación de que la cláusula CHARCODE> 126 solo sucederá con CHARCODE == 127, lo que resulta en guardar en SPACElugar de DEL.

Ejecuté mi código en algunas cadenas elegidas arbitrariamente y encontré este maravilloso ciclo:

oook$ok$ok$ok$
ook$ok$ok$ok$o
oo$ok$ok$ok$ok
oook$ok$ok$ok$
CAD97
fuente
55
Esta respuesta se ve ok!
Conor O'Brien
3
esolangs.org/wiki/ook !
The Vee
5

CJam, 38 bytes

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

Pruébalo aquí.

Explicación

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.
  }%
}*
Martin Ender
fuente
Creo que puede guardar unos pocos bytes lri){2S*\*3ew{)\:^|}%127c' er}*porque la operación previa al módulo de caracteres nunca excede 127
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)

Esto devuelve un flujo infinito de la secuencia XOROR. Ejemplo de uso (imprima los primeros 5 elementos de la semilla "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"

Cómo funciona:

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
nimi
fuente
4

PHP, 186 bytes (con n) | 177 bytes (infinito)

Resultó que la impresión infinita es más corta ...

// 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 con 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;
}

Infinito sin golf:

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;
  }
}
daavko
fuente
1
Todavía se puede jugar mucho al golf. Por ejemplo, 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);}tiene 141 bytes de longitud (-36 bytes).
Blackhole
2

C ++

Enésima secuencia (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;}}

Sin golf

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

Enésima secuencia usando la sintaxis del puntero en lugar de la sintaxis de la matriz para hacer esto aún más confuso: (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;}}

Sin golf

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

Función de depuración (por diversión)

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;
    }
}
FatalSleep
fuente
1
Estoy bastante seguro de que los resultados dicen que debe generar el resultado, no simplemente devolverlo.
Mooing Duck
1
Escribí una versión C ++ desde cero, en comparación con la tuya y luego las fusioné
Mooing Duck
@MooingDuck Nice! Probablemente podría reducirlo aún más con int implícito por el compilador al pasar a C.
FatalSleep
por supuesto, adelante! Ya escribiste la mitad de ese código
Mooing Duck el
2

JAVA 240/280 Bytes

La versión popular de Java en el momento en que escribí esto afirmaba tener 185 bytes, pero hay dos puntos importantes de fraude. Primero, la medición es presumiblemente solo para la función, no para la fuente de trabajo completa. Tal vez no sea un problema. En segundo lugar, utiliza BiFunction sin importar ni un nombre completo. Agregar los bits necesarios para ejecutarlo tal como está (luego minimizarlo de manera justa) lo llevó a 348 bytes. Agregar solo el nombre completo de la clase BiFunction lo lleva a 248 bytes.

Por el contrario, creo que el mío es de 240 bytes cuando se juega con las mismas reglas (sin clase, sin salida real, solo la carne). La clase ejecutable completa es de 280 bytes, y se ve así (sin minificar):

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

O, minificado:

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];}
vrmxm
fuente
2

Perl, 47 bytes

Incluye +2 para -lp

Ejecutar con la entrada en STDIN, p. Ej. perl -lp xoror.pl <<< "Hello, World!" | head -26

xoror.pl:

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

Esto funciona como está, pero reemplaza el \x7fpor el valor binario correspondiente para obtener la puntuación dada

Ton Hospel
fuente
1

Swift: 273 personajes

¡Vaya, Swift es peor que Java! (¡Todas esas API con nombres largos!: 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)}}

Sin golf:

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

Gracias a @ CAD97 por mencionar que (A ^ B) | C solo puede ser mayor que 126 cuando es 127.

También me di cuenta de que no necesitas paréntesis alrededor de A ^ B | C porque XORing se realiza antes de ORing, por lo que me ahorró algunos bytes.


fuente