La séquence XOROR

23

Les automates cellulaires sont vraiment fascinants. Ceux dont on parle habituellement sont les binaires, c'est-à-dire ceux représentables par un nombre. Cependant, ceux-ci, à mon avis, ont été tués à mort. Les AC ternaires sont plus intéressants, mais nous avons tous à considérer ASCII! Quel plaisir cela pourrait-il être!

Au lieu de décider d'un ensemble de règles pour chaque personnage, j'utiliserai une règle de décision simple dont je parlerai bientôt. Pour décider de la prochaine génération, nous examinons les trois cellules "supérieures", un peu comme les automates cellulaires. Observez un exemple:

QWERTY
X Y Z

Le "haut" de Yest WER, étant les cellules au-dessus et à droite, au-dessus et au-dessus et à gauche. Y sera le résultat de la fonction que je m'apprête à définir, qui est une fonction sur des chaînes de trois caractères. Le "haut" de Xest QW, ou un espace remplissant la cellule inexistante / manquante .

Maintenant, pour la fonction amusante ! J'appelle cette séquence la séquence XOROR pour une raison. Soit Ale code de cellule en haut à gauche, Ble code de cellule ci-dessus et le code de cellule en Chaut à droite. Ensuite, la cellule résultante est le caractère dont le code de caractère est (A XOR B) OR C, c'est-à-dire (A^B)|C. (Si une valeur résultante est supérieure à 126, elle est alors définie sur (CHARCODE % 127) + 32. Rien n'est fait si une valeur est inférieure à 32.) Voici un exemple de la graine 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

Et nous pouvons continuer un peu plus tard. Cette modification de la chaîne est appelée séquence XOROR.

Objectif Vous devez écrire un programme ou une fonction qui effectue l'une des tâches suivantes:

  1. Étant donné une chaîne set un nombre n >= 0, nsortez la e chaîne sur la séquence XOROR avec seed s, avec n = 0comme première transformation de la chaîne.
  2. Étant donné une chaîne s, produire (pour les programmes) ou générer (pour les fonctions / générateurs) un flux infini de la séquence XOROR avec seed s. Vous pouvez choisir d'arrêter si la séquence se répète, mais ce n'est pas nécessaire.

s sera toujours uniquement composé de caractères ASCII imprimables, de l'espace aux onglets tilde plus (pas de nouvelle ligne.)

Il s'agit d'un , donc le programme le plus court en octets l'emporte.

Conor O'Brien
la source
J'ai du mal à analyser la phrase "Donc, quelle que soit la fonction que je suis sur le point de définir sur une chaîne de trois caractères, Y deviendra." Serait-il possible de reformuler ceci: "Y sera le résultat de la fonction que je suis sur le point de définir, une fonction sur des chaînes de trois caractères."?
hYPotenuser
3
Tous les os font ressembler à une ruée vers les zergs .
mbomb007
3
Observation: étant donné que XOR et OR conservent le nombre de bits et que tous les ASCII sont de 7 bits, le seul cas où un CHARCODE est> 126 est s'il est de 127. Pour cela, vous pouvez simplement le remplacer par un espace (32) depuis 127%127+32==32.
CAD97
2
Pourquoi n=0la chaîne d'origine n'est-elle pas?
Neil
3
@FatalSleep En ce qui concerne votre première plainte, j'ai déclaré que si aucune cellule n'est présente, le résultat est un espace, alors ce serait plutôt (d^!)|(space). Quant à votre deuxième question, vous effectuez (CHAR%127)+32 après l'exécution du XOROR.
Conor O'Brien

Réponses:

4

MATL , 33 31 octets

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

Cela fonctionne dans la version 13.1.0 du langage / compilateur, qui est antérieure au défi.

La première entrée est le nombre, la seconde est la chaîne.

Essayez-le en ligne!

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
la source
21

Mathematica, 133 octets

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

Ce serait bien de faire fonctionner une CellularAutomaton[]solution, mais je suis resté court. N'importe qui?

Edit: quelques jolies photos (cliquez pour agrandir)

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

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

60 itérations de "Hello, World!"

plotCA[bXORnotb, 100]:

100 itérations du soliloque Hamlet

plotCA[raven, 100]:

100 itérations de Poe

hYPotenuser
la source
1
Ne pouvez-vous pas simplement donner CellularAutomatonvotre fonction de mise à jour? (Le numéro de règle réel avec 127 états valides serait fou.)
Martin Ender
@ MartinBüttner Vous pouvez, mais c'est une traînée essayant de tenir compte du comportement sur les bords, pour le rendre conforme à la spécification. BlockMap [] était juste plus court.
hYPotenuser
7

Java, 193 185 octets

Parce que Java.

-8 octets en passant en boucle plutôt qu'en récursif pour en faire une fonction anonyme

Renvoie la nième itération de XOROR sur 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;}

Version lisible:

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

Presque une implémentation littérale de la spécification, avec une boucle récursive pour appliquer l'opération n fois. Certains octets ont été enregistrés, cependant, avec mon observation que la clause CHARCODE> 126 ne se produira jamais qu'avec CHARCODE == 127, ce qui entraîne une sauvegarde SPACEau lieu de DEL.

J'ai exécuté mon code sur quelques chaînes choisies arbitrairement et j'ai trouvé ce merveilleux cycle:

oook$ok$ok$ok$
ook$ok$ok$ok$o
oo$ok$ok$ok$ok
oook$ok$ok$ok$
CAD97
la source
5
Cette réponse ressemble ok!
Conor O'Brien
5

CJam, 38 octets

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

Testez-le ici.

Explication

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
la source
Je pense que vous pouvez économiser quelques octets avec lri){2S*\*3ew{)\:^|}%127c' er}*car l'opération de pré-modulo de caractères ne dépasse jamais 127
Luis Mendo
5

Haskell, 123 octets

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)

Cela renvoie un flux infini de la séquence XOROR. Exemple d'utilisation (imprimez les 5 premiers éléments de la graine "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"

Comment ça marche:

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
la source
4

PHP, 186 octets (avec n) | 177 octets (infini)

Il s'est avéré que l'impression infinie est plus courte ...

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

Non golfé avec 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;
}

Infini non 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
la source
1
Il peut encore être beaucoup joué au golf. Par exemple, 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);}est de 141 octets de long (-36 octets).
Blackhole
2

C ++

Nième séquence (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;}}

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

Nième séquence utilisant la syntaxe du pointeur au lieu de la syntaxe du tableau pour rendre cela encore plus déroutant: (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;}}

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

Fonction de débogage (pour le plaisir)

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
la source
1
Je suis sûr que les résultats indiquent que vous devez produire le résultat, pas simplement le renvoyer.
Mooing Duck
1
J'ai écrit une version C ++ à partir de zéro, comparée à la vôtre, puis je les ai fusionnées, et j'ai obtenu ceci, à 158 octets: coliru.stacked-crooked.com/a/838c29e5d496d2a6
Mooing Duck
@MooingDuck Nice! Pourrait probablement le réduire davantage avec un int implicite par le compilateur en passant à C.
FatalSleep
bien sûr, allez-y! Vous avez déjà écrit la moitié de ce code
Mooing Duck
2

JAVA 240/280 octets

La version Java populaire au moment où j'ai écrit cela prétendait être de 185 octets, mais il y a deux points de fudge importants. Premièrement, la mesure est vraisemblablement uniquement pour la fonction, pas pour la source de travail complète. Peut-être pas un tel problème. Deuxièmement, il utilise BiFunction sans importation ni nom complet. L'ajout des bits requis pour l'exécuter tel quel (puis le minimiser, équitablement) l'a porté à 348 octets. L'ajout uniquement du nom complet de la classe BiFunction l'amène à 248 octets.

En revanche, je crois que le mien est de 240 octets lorsque vous jouez selon les mêmes règles (pas de classe, pas de sortie réelle, juste la viande). La classe exécutable complète est de 280 octets, et ressemble à ceci (non minimisé):

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, minifié:

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
la source
2

Perl, 47 octets

Comprend +2 pour -lp

Exécuter avec l'entrée sur STDIN, par exemple perl -lp xoror.pl <<< "Hello, World!" | head -26

xoror.pl:

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

Cela fonctionne tel quel, mais remplacez le \x7fpar la valeur binaire correspondante pour obtenir le score donné

Ton Hospel
la source
1

Swift: 273 personnages

Wow, Swift est pire que Java! (Toutes ces API avec des noms longs!: 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)}}

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

Merci à @ CAD97 avoir mentionné que (A ^ B) | C ne peut être supérieur à 126 que lorsqu'il est 127.

J'ai également réalisé que vous n'avez pas besoin de parenthèses autour de A ^ B | C car XORing est fait avant ORing, ce qui m'a fait économiser quelques octets.

Toi
la source