The XOROR sequence

23

4

Cellular Automata are truly fascinating. The ones that are usually talked about are the binary ones, i.e., the ones representable by a number. However, those, in my opinion, have been done to death. Ternary CAs are more interesting, but we have all of ASCII to consider! What fun could that be!

Instead of deciding a ruleset for each character, I will use a simple deciding rule which I will talk about soon. To decide the next generation, we look at the three "top" cells, much like a cellular automata. Observe an example:

QWERTY
X Y Z

The "top" of Y is WER, being the cells above-and-right, above, and above-and left. Y will be the result of the function I'm about to define, which is a function on three-char strings. The "top" of X is QW, or a space filling in the non-existent/missing cell.

Now, for the fun function! I call this sequence the XOROR sequence for a reason. Let A be the top-left cell charcode, B be the above cell charcode, and C be the top-right cell charcode. Then, the resulting cell is the character whose charcode is (A XOR B) OR C, that is, (A^B)|C. (If a resulting value is greater than 126, then it is set to (CHARCODE % 127) + 32. Nothing is done if a value is less than 32.) Here is an example of the seed 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

And we can proceed on for a while hereafter. This modification of the string is called the XOROR sequence.

Objective You are to write a program or function that does one of the following tasks:

  1. Given a string s and a number n >= 0, output the nth string on the XOROR sequence with seed s, with n = 0 being the first transformation of the string.
  2. Given a string s, output (for programs) or generate (for functions/generators) an infinite stream of the XOROR sequence with seed s. You may choose to stop if the sequence repeats, but this is not necessary.

s will always only consist of printable ASCII characters, from space to tilde plus tabs (no newlines.)

This is a , so the shortest program in bytes wins.

Conor O'Brien

Posted 2016-03-04T17:18:09.230

Reputation: 36 228

I'm having trouble parsing the sentence "So, whatever function I am about to define on a three-char string, Y will become." Could this be reworded: "Y will be the result of the function I'm about to define, a function on three-char strings."? – hYPotenuser – 2016-03-04T17:59:27.760

3

All of the os make it look like a zerg rush.

– mbomb007 – 2016-03-04T18:24:17.760

@hYPotenuser Yes! I will do so. – Conor O'Brien – 2016-03-04T18:29:23.500

3Observation: Since XOR and OR preserve the number of bits and all ASCII is 7 bits, the only case when a CHARCODE is > 126 is if it is 127. Therefor, you can just replace it with a space (32) since 127%127+32==32. – CAD97 – 2016-03-04T21:24:54.393

2Why is n=0 not the original string? – Neil – 2016-03-04T21:59:45.363

@Neil I don't know. It was rather arbitrary. – Conor O'Brien – 2016-03-04T22:06:45.697

I think for 5 the output is o_<c c 4+ o – Luis Mendo – 2016-03-05T00:56:58.867

@CᴏɴᴏʀO'Bʀɪᴇɴ The example cases are broken from step 0. The final result of (d^!|NULL) should be (69 or E) not (101 or e). – FatalSleep – 2016-03-05T13:59:51.147

@CᴏɴᴏʀO'Bʀɪᴇɴ The charcode part is ambiguous. Do you do (CHAR%127)+32 on (A^B)|C or on eachindividual cell A, B and C? – FatalSleep – 2016-03-05T14:35:44.490

3@FatalSleep As for you first complaint, I stated that, if no cell is present, the result is a space, so it would rather be (d^!)|(space). As for you second question, you perform (CHAR%127)+32 after the XOROR is performed. – Conor O'Brien – 2016-03-05T16:24:51.060

Oh whoops! Thank you for the re-clarification. – FatalSleep – 2016-03-05T16:49:50.040

@FatalSleep It's truly my pleasure :) – Conor O'Brien – 2016-03-05T16:50:13.057

@StewieGriffin I'll pretend as if you didn't say your first reason, and move on to the second. "Better safe than sorry" is the main reason I protected it. (and I think you can edit comments.) – Conor O'Brien – 2016-03-06T21:54:03.180

Answers

4

MATL, 33 31 bytes

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

This works in release 13.1.0 of the language/compiler, which predates the challenge.

The first input is the number, the second is the string.

Try it 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

Posted 2016-03-04T17:18:09.230

Reputation: 87 464

21

Mathematica, 133 bytes

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

It would be nice to make a CellularAutomaton[] solution work, but I kept coming up short. Anyone?

Edit: some pretty pictures (click to enlarge)

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

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

60 iterations of "Hello, World!"

plotCA[bXORnotb, 100]:

100 iterations of Hamlet soliloquy

plotCA[raven, 100]:

100 iterations of Poe

hYPotenuser

Posted 2016-03-04T17:18:09.230

Reputation: 707

1Can't you just give CellularAutomaton your update function? (The actual rule number with 127 valid states would be insane.) – Martin Ender – 2016-03-04T21:10:26.850

@MartinBüttner You can, but it's a drag trying to account for the behavior at the edges, to get it to be compliant with the spec. BlockMap[] was just shorter. – hYPotenuser – 2016-03-04T21:24:51.953

7

Java, 193 185 bytes

Because Java.

-8 bytes by switching to looping rather than recursing to make it an anonymous function

Returns the n'th iteration of XOROR on 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;}

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

Pretty much a literal implementation of the spec, with a recursive loop to apply the operation n times. Some bytes were saved, however, with my observation that the CHARCODE>126 clause will only ever happen with CHARCODE==127, which results in saving SPACE instead of DEL.

I ran my code over a few arbitrarily chosen strings and found this wonderful cycle:

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

CAD97

Posted 2016-03-04T17:18:09.230

Reputation: 1 367

5This answer looks ok! – Conor O'Brien – 2016-03-05T16:25:59.083

3http://esolangs.org/wiki/ook%21 – The Vee – 2016-03-06T12:06:31.653

5

CJam, 38 bytes

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

Test it here.

Explanation

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

Posted 2016-03-04T17:18:09.230

Reputation: 184 808

I think you can save a few bytes with lri){2S*\*3ew{)\:^|}%127c' er}* because the chars pre-modulo operation never exceed 127

– Luis Mendo – 2016-03-05T00:57:39.013

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)

This returns an infinite stream of the XOROR sequence. Usage example (print the first 5 elements of the seed "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"

How it works:

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

Posted 2016-03-04T17:18:09.230

Reputation: 34 639

4

PHP, 186 bytes (with n) | 177 bytes (infinite)

It turned out that infinite printing is shorter...

// 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 with 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 infinite:

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

Posted 2016-03-04T17:18:09.230

Reputation: 824

1It can still be golfed a lot. For instance, 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);} is 141 bytes long (-36 bytes). – Blackhole – 2016-03-05T17:16:29.503

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 using pointer syntax instead of array syntax to make this all the more confusing: (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;
    }
}

Debug Function (For Fun)

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

Posted 2016-03-04T17:18:09.230

Reputation: 143

1Pretty sure the results say you must output the result, not simply return it. – Mooing Duck – 2016-03-06T18:01:10.550

1

I wrote a C++ version from scratch, compared to yours and then merged them, and got this, at 158 bytes: http://coliru.stacked-crooked.com/a/838c29e5d496d2a6

– Mooing Duck – 2016-03-06T18:42:46.627

@MooingDuck Nice! Could probably reduce it further with implicit int by the compiler via moving to C. – FatalSleep – 2016-03-06T23:03:06.300

of course, go ahead! You already wrote half of that code – Mooing Duck – 2016-03-07T00:56:15.737

2

JAVA 240/280 Bytes

The popular Java version at the time I wrote this claimed to be 185 bytes, but there are two significant fudge points. First, the measurement is presumably only for the function, not for the complete working source. Maybe not such a problem. Second, it uses BiFunction without either an import or a fully qualified name. Adding the required bits to run it as-is (then minimizing it, fairly) brought it to 348 bytes. Adding only the fully qualified name of the BiFunction class brings it to 248 bytes.

In contrast, I believe mine is 240 bytes when playing by the same rules (no class, no actual output, just the meat). The full runnable class is 280 bytes, and looks like this (unminified):

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

Or, minified:

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

Posted 2016-03-04T17:18:09.230

Reputation: 21

2

Perl, 47 bytes

Includes +2 for -lp

Run with the input on STDIN, e.g. perl -lp xoror.pl <<< "Hello, World!" | head -26

xoror.pl:

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

This works as is, but replace the \x7f by the corresponding binary value to get the given score

Ton Hospel

Posted 2016-03-04T17:18:09.230

Reputation: 14 114

1

Swift: 273 Characters

Wow, Swift is worse than Java! (All those APIs with long names! :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)
    }
}

Thanks to @CAD97 for mentioning that (A^B)|C can only be greater than 126 when it's 127.

I also realized that you don't need parenthesis around A^B|C because XORing is done before ORing, so that saved me a few bytes.

You

Posted 2016-03-04T17:18:09.230

Reputation: 141