La sequenza XOROR


23

Gli automi cellulari sono davvero affascinanti. Quelli di cui si parla di solito sono quelli binari, cioè quelli rappresentabili da un numero. Tuttavia, quelli, secondo me, sono stati fatti a morte. Le CA ternarie sono più interessanti, ma dobbiamo considerare tutte le ASCII! Che divertimento potrebbe essere!

Invece di decidere una serie di regole per ogni personaggio, userò una semplice regola decisiva di cui parlerò presto. Per decidere la prossima generazione, esaminiamo le tre celle "top", in modo molto simile agli automi cellulari. Osserva un esempio:

QWERTY
X Y Z

La "cima" di Yè WER, essendo le celle sopra e destra, sopra e sopra e sinistra. Y sarà il risultato della funzione che sto per definire, che è una funzione su stringhe a tre caratteri. Il "top" di Xis QW, o uno spazio che riempie la cella inesistente / mancante .

Ora, per la divertente funzione! Chiamo questa sequenza la sequenza XOROR per un motivo. Lascia che Asia il charcode della cella in alto a sinistra, Bsia il charcode della cella in alto e Csia il charcode della cella in alto a destra. Quindi, la cella risultante è il carattere il cui charcode è (A XOR B) OR C, cioè (A^B)|C. (Se un valore risultante è maggiore di 126, allora è impostato su (CHARCODE % 127) + 32. Nulla viene fatto se un valore è inferiore a 32.) Ecco un esempio del seme 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 possiamo procedere per un po 'di seguito. Questa modifica della stringa è chiamata sequenza XOROR.

Obiettivo È necessario scrivere un programma o una funzione che svolga una delle seguenti attività:

  1. Data una stringa se un numero n >= 0, ngenera la stringa th sulla sequenza XOROR con seed s, n = 0essendo la prima trasformazione della stringa.
  2. Data una stringa s, output (per programmi) o generare (per funzioni / generatori) un flusso infinito della sequenza XOROR con seed s. Puoi scegliere di interrompere se la sequenza si ripete, ma ciò non è necessario.

s consisterà sempre solo di caratteri ASCII stampabili, dallo spazio alla tilde più le schede (nessuna nuova riga).

Questo è un , quindi vince il programma più breve in byte.


Sto riscontrando problemi nell'analizzare la frase "Quindi, qualunque funzione sto per definire su una stringa di tre caratteri, Y diventerà". Questo potrebbe essere riformulato: "Y sarà il risultato della funzione che sto per definire, una funzione su stringhe di tre caratteri".
hYPotenuser

3
Tutti ofanno sembrare una corsa allo zerg .
mbomb007

3
Osservazione: poiché XOR e OR conservano il numero di bit e tutto ASCII è 7 bit, l'unico caso in cui un CHARCODE è> 126 è se è 127. Pertanto, è possibile sostituirlo con uno spazio (32) da allora 127%127+32==32.
CAD97

2
Perché n=0non è la stringa originale?
Neil

3
@FatalSleep Per quanto riguarda la tua prima lamentela, ho affermato che, se non è presente alcuna cella, il risultato è uno spazio, quindi preferirebbe esserlo (d^!)|(space). Per quanto riguarda la tua seconda domanda, ti esibisci (CHAR%127)+32 dopo l'esecuzione di XOROR.
Conor O'Brien,

Risposte:


4

MATL , 33 31 byte

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

Funziona con la versione 13.1.0 del linguaggio / compilatore, che precede la sfida.

Il primo input è il numero, il secondo è la stringa.

Provalo 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 byte

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

Sarebbe bello far funzionare una CellularAutomaton[]soluzione, ma ho continuato a venire breve. Chiunque?

Modifica: alcune belle immagini (clicca per ingrandire)

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

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

60 iterazioni di "Hello, World!"

plotCA[bXORnotb, 100]:

100 iterazioni del soliloquio di Amleto

plotCA[raven, 100]:

100 iterazioni di Poe


1
Non puoi semplicemente dare la CellularAutomatontua funzione di aggiornamento? (Il numero effettivo della regola con 127 stati validi sarebbe folle.)
Martin Ender il

@ MartinBüttner Puoi, ma è una seccatura provare a tenere conto del comportamento ai bordi, per renderlo conforme alle specifiche. BlockMap [] era solo più breve.
hYPotenuser

7

Java, 193 185 byte

Perché Java.

-8 byte passando al looping piuttosto che ricorrendo per renderlo una funzione anonima

Restituisce l'ennesima iterazione di XOROR su 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;}

Versione leggibile:

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 un'implementazione letterale della specifica, con un ciclo ricorsivo per applicare l'operazione n volte. Alcuni byte sono stati salvati, tuttavia, con la mia osservazione che la clausola CHARCODE> 126 accadrà sempre e solo con CHARCODE == 127, il che si traduce in un salvataggio SPACEinvece che in DEL.

Ho eseguito il mio codice su alcune stringhe scelte arbitrariamente e ho trovato questo meraviglioso ciclo:

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

5
Questa risposta sembra ok!
Conor O'Brien,


5

CJam, 38 byte

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

Provalo qui.

Spiegazione

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.
  }%
}*

Penso che puoi risparmiare qualche byte lri){2S*\*3ew{)\:^|}%127c' er}*perché l'operazione pre-modulo dei caratteri non supera mai 127
Luis Mendo

5

Haskell, 123 byte

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)

Ciò restituisce un flusso infinito della sequenza XOROR. Esempio di utilizzo (stampa i primi 5 elementi del seme "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"

Come funziona:

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 byte (con n) | 177 byte (infinito)

Si è scoperto che la stampa infinita è più breve ...

// 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 ungolf:

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
Può ancora essere giocato molto a golf. Ad esempio, 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);}è lungo 141 byte (-36 byte).
Blackhole,

2

C ++

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

Nth-Sequence usando la sintassi del puntatore invece della sintassi dell'array per rendere tutto ciò ancora più 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;
    }
}

Funzione di debug (per divertimento)

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
Abbastanza sicuro i risultati dicono che devi produrre il risultato, non semplicemente restituirlo.
Mooing Duck

1
Ho scritto una versione C ++ da zero, rispetto alla tua e poi li ho uniti, e ho ottenuto questo, a 158 byte: coliru.stacked-crooked.com/a/838c29e5d496d2a6
Mooing Duck

@MooingDuck Nice! Probabilmente potrebbe ridurlo ulteriormente con int implicito da parte del compilatore passando a C.
FatalSleep

certo, vai avanti! Hai già scritto metà di quel codice
Mooing Duck il

2

JAVA 240/280 byte

La popolare versione Java al momento in cui ho scritto questo affermava di essere 185 byte, ma ci sono due significativi punti di fudge. Innanzitutto, la misurazione è presumibilmente solo per la funzione, non per la fonte di lavoro completa. Forse non è un tale problema. In secondo luogo, utilizza BiFunction senza un nome di importazione o completo. L'aggiunta dei bit richiesti per eseguirlo così com'è (quindi minimizzandolo, in modo equo) lo ha portato a 348 byte. L'aggiunta del solo nome completo della classe BiFunction lo porta a 248 byte.

Al contrario, credo che il mio sia di 240 byte quando si gioca con le stesse regole (nessuna classe, nessun output effettivo, solo la carne). La classe eseguibile completa è di 280 byte e assomiglia a questa (non modificata):

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

Oppure, minimizzato:

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 byte

Include +2 per -lp

Esegui con l'ingresso su STDIN, ad es perl -lp xoror.pl <<< "Hello, World!" | head -26

xoror.pl:

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

Funziona così com'è, ma sostituiscilo \x7fcon il corrispondente valore binario per ottenere il punteggio dato


1

Swift: 273 personaggi

Wow, Swift è peggio di Java! (Tutte quelle API con nomi lunghi!: 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)
    }
}

Grazie a @ CAD97 per aver menzionato che (A ^ B) | C può essere maggiore di 126 solo quando è 127.

Mi sono anche reso conto che non è necessaria la parentesi attorno ad A ^ B | C perché XORing viene eseguito prima di ORing, quindi mi ha salvato alcuni byte.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.