A sequência XOROR

23

Os autômatos celulares são realmente fascinantes. Os que geralmente são mencionados são os binários, ou seja, os representáveis ​​por um número. No entanto, esses, na minha opinião, foram mortos. As ACs ternárias são mais interessantes, mas temos todo o ASCII a considerar! Que divertido isso poderia ser!

Em vez de decidir um conjunto de regras para cada personagem, usarei uma regra de decisão simples da qual falarei em breve. Para decidir a próxima geração, analisamos as três células "superiores", como um autômato celular. Observe um exemplo:

QWERTY
X Y Z

O "topo" de Yé WER, sendo as células acima e à direita, acima e acima e à esquerda. Y será o resultado da função que estou prestes a definir, que é uma função em seqüências de três caracteres. O "top" de Xé QW, ou um enchimento espaço no / célula falta inexistente .

Agora, para a função divertida ! Eu chamo essa sequência de sequência XOROR por um motivo. Seja Ao código da célula no canto superior esquerdo, o código Bda célula acima e o código da célula no canto Csuperior direito. Em seguida, a célula resultante é o caractere cujo código é (A XOR B) OR C, ou seja (A^B)|C,. (Se um valor resultante for maior que 126, será definido como (CHARCODE % 127) + 32. Nada será feito se um valor for menor que 32.) Aqui está um exemplo da semente 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

E podemos continuar por um tempo adiante. Essa modificação da string é chamada de sequência XOROR.

Objetivo Você deve escrever um programa ou função que execute uma das seguintes tarefas:

  1. Dada uma sequência se um número n >= 0, nproduza a sequência th na sequência XOROR com seed s, n = 0sendo a primeira transformação da sequência.
  2. Dada uma sequência s, produza (para programas) ou gere (para funções / geradores) um fluxo infinito da sequência XOROR com semente s. Você pode optar por parar se a sequência se repetir, mas isso não é necessário.

s sempre consistirá apenas em caracteres ASCII imprimíveis, do espaço ao til e mais guias (sem novas linhas).

Este é um , portanto o programa mais curto em bytes vence.

Conor O'Brien
fonte
Estou tendo problemas para analisar a frase "Então, qualquer função que eu esteja prestes a definir em uma sequência de três caracteres, Y se tornará". Isso poderia ser reformulado: "Y será o resultado da função que estou prestes a definir, uma função em seqüências de três caracteres".
HYPotenuser #
3
Todos oeles fazem parecer uma corrida zerg .
mbomb007
3
Observação: Como XOR e OR preservam o número de bits e todo o ASCII é de 7 bits, o único caso quando um CHARCODE é> 126 é se for 127. Portanto, você pode substituí-lo por um espaço (32) desde então 127%127+32==32.
CAD16
2
Por que n=0não é a string original?
Neil
3
@FatalSleep Quanto à sua primeira reclamação, afirmei que, se nenhuma célula estiver presente, o resultado será um espaço, por isso seria melhor (d^!)|(space). Quanto à sua segunda pergunta, você executa (CHAR%127)+32 após a execução do XOROR.
Conor O'Brien

Respostas:

4

MATL , 33 31 bytes

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

Isso funciona na versão 13.1.0 do idioma / compilador, que antecede o desafio.

A primeira entrada é o número, a segunda é a string.

Experimente 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
Luis Mendo
fonte
21

Mathematica, 133 bytes

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

Seria bom fazer uma CellularAutomaton[]solução funcionar, mas eu continuava sendo breve. Alguém?

Editar: algumas fotos bonitas (clique para ampliar)

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

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

60 iterações de "Olá, Mundo!"

plotCA[bXORnotb, 100]:

100 iterações do solilóquio de Hamlet

plotCA[raven, 100]:

100 iterações de Poe

hYPotenuser
fonte
1
Você não pode simplesmente dar CellularAutomatonsua função de atualização? (A regra número real com 127 estados válidos seria insano.)
Martin Ender
@ MartinBüttner Você pode, mas é uma chatice tentar explicar o comportamento nas bordas, para que seja compatível com as especificações. BlockMap [] era apenas mais curto.
HYPotenuser #
7

Java, 193 185 bytes

Porque Java.

-8 bytes, alternando para loop em vez de recorrente para torná-lo uma função anônima

Retorna a n-ésima iteração de XOROR em 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;}

Versão legível:

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

Praticamente uma implementação literal da especificação, com um loop recursivo para aplicar a operação n vezes. Alguns bytes foram salvos, no entanto, com a minha observação de que a cláusula CHARCODE> 126 só acontecerá com CHARCODE == 127, o que resulta em economia ao SPACEinvés de em DEL.

Corri meu código por algumas seqüências escolhidas arbitrariamente e encontrei esse ciclo maravilhoso:

oook$ok$ok$ok$
ook$ok$ok$ok$o
oo$ok$ok$ok$ok
oook$ok$ok$ok$
CAD97
fonte
5
Esta resposta parece ok!
Conor O'Brien
3
esolangs.org/wiki/ook !
The Vee
5

CJam, 38 bytes

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

Teste aqui.

Explicação

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
fonte
Eu acho que você pode salvar alguns bytes lri){2S*\*3ew{)\:^|}%127c' er}*porque a operação pré-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)

Isso retorna um fluxo infinito da sequência XOROR. Exemplo de uso (imprima os 5 primeiros elementos da semente "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"

Como 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
fonte
4

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

Descobriu-se que a impressão infinita é mais curta ...

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

Sem jogar com 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 ungolfed:

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
fonte
1
Ainda pode ser jogado muito. Por exemplo, 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);}tem 141 bytes (-36 bytes).
Blackhole
2

C ++

Enésima sequência (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;}}

Un-Golfed

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ª sequência usando a sintaxe do ponteiro em vez da sintaxe da matriz para tornar isso ainda mais 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;}}

Un-Golfed

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

Função de depuração (por diversão)

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
fonte
1
Certamente os resultados dizem que você deve produzir o resultado, não simplesmente devolvê-lo.
Mooing Duck
1
Eu escrevi uma versão em C ++ a partir do zero, comparada com a sua e, em seguida, mesclada, e obtive isso em 158 bytes: coliru.stacked-crooked.com/a/838c29e5d496d2a6
Mooing Duck
@MooingDuck Nice! Provavelmente poderia reduzi-lo ainda mais com int implícito pelo compilador, movendo-se para C.
FatalSleep
claro, vá em frente! Você já escreveu metade desse código
Mooing Duck
2

JAVA 240/280 bytes

A versão popular do Java na época em que escrevi isso afirmava ser de 185 bytes, mas existem dois pontos significativos de falsificação. Primeiro, a medição é presumivelmente apenas para a função, não para a fonte de trabalho completa. Talvez não seja um problema. Segundo, ele usa o BiFunction sem um nome importado ou totalmente qualificado. Adicionar os bits necessários para executá-lo como está (depois minimizá-lo de maneira justa) elevou-o para 348 bytes. Adicionar apenas o nome completo da classe BiFunction leva a 248 bytes.

Por outro lado, acredito que os meus são 240 bytes ao jogar pelas mesmas regras (nenhuma classe, nenhuma saída real, apenas a carne). A classe executável completa é de 280 bytes e tem a seguinte aparência (não minificada):

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

Ou 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
fonte
2

Perl, 47 bytes

Inclui +2 para -lp

Corra com a entrada no STDIN, por exemplo perl -lp xoror.pl <<< "Hello, World!" | head -26

xoror.pl:

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

Isso funciona como está, mas substitua o \x7fpelo valor binário correspondente para obter a pontuação fornecida

Ton Hospel
fonte
1

Swift: 273 caracteres

Uau, Swift é pior que Java! (Todas essas APIs com nomes longos!: 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)
    }
}

Graças a @ CAD97 por mencionar que (A ^ B) | C só pode ser maior que 126 quando é 127.

Eu também percebi que você não precisa de parênteses em torno de A ^ B | C porque o XORing é feito antes do ORing, o que me salvou alguns bytes.

Vocês
fonte