Последовательность XOROR

23

Сотовые автоматы действительно очаровательны. Те, о которых обычно говорят, являются двоичными, то есть представляемыми числом. Тем не менее, те, на мой взгляд, были сделаны до смерти. Тройные CA более интересны, но мы должны рассмотреть все ASCII! Какое это может быть удовольствие!

Вместо того, чтобы выбирать набор правил для каждого символа, я буду использовать простое решающее правило, о котором я скоро расскажу. Чтобы принять решение о следующем поколении, мы смотрим на три «верхние» клетки, очень похожие на клеточные автоматы. Посмотрите на пример:

QWERTY
X Y Z

«Верх» Y- WERэто ячейки сверху и справа, сверху и сверху и слева. Y будет результатом функции, которую я собираюсь определить, которая является функцией для трехсимвольных строк. «Вершина» Xесть QW, или заполнение пространства в несуществующей / отсутствующую клетке .

Теперь для забавной функции! Я называю эту последовательность последовательностью XOROR по причине. Позвольте Aбыть верхним левым символом ячейки, Bбыть вышеуказанным кодексом ячейки, и Cбыть верхним правым символом ячейки. Затем полученная ячейка - это символ, чей код - (A XOR B) OR Cэто (A^B)|C. (Если результирующее значение больше 126, тогда оно установлено на (CHARCODE % 127) + 32. Ничего не делается, если значение меньше 32.) Вот пример начального числа 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

И мы можем продолжить некоторое время после этого. Эта модификация строки называется последовательностью XOROR.

Цель Вы должны написать программу или функцию, которая выполняет одну из следующих задач:

  1. Учитывая строку sи число n >= 0, выведитеn задана th-ю последовательность в последовательности XOROR с помощью seed s, n = 0являющейся первым преобразованием строки.
  2. Для sзаданной строки выведите (для программ) или сгенерируйте (для функций / генераторов) бесконечный поток последовательности XOROR с начальным числомs . Вы можете остановить, если последовательность повторяется, но это не обязательно.

s всегда будет состоять только из печатных символов ASCII, от пробела до тильды и табуляции (без перевода строки).

Это , поэтому выигрывает самая короткая программа в байтах.

Конор О'Брайен
источник
У меня возникли проблемы при разборе предложения «Итак, какой бы функцией я ни собирался определить строку из трех символов, Y станет». Может ли это быть перефразировано: «Y будет результатом функции, которую я собираюсь определить, функции на трех-символьных строках»?
hYPotenuser
3
Все из них oделают это похоже на порыв зергов .
mbomb007
3
Замечание: поскольку XOR и OR сохраняют количество битов, а все ASCII равны 7 битам, единственный случай, когда CHARCODE> 126, - это 127. Для этого вы можете просто заменить его пробелом (32), поскольку 127%127+32==32.
CAD97
2
Почему n=0не оригинальная строка?
Нил
3
@FatalSleep Что касается вашей первой жалобы, я заявил, что, если ячейка отсутствует, результатом будет пробел, так что, скорее всего, так и будет (d^!)|(space). Что касается второго вопроса, вы выполняете (CHAR%127)+32 после выполнения XOROR.
Конор О'Брайен

Ответы:

4

MATL , 33 31 байт

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

Это работает в выпуске 13.1.0 языка / компилятора, который предшествовал вызову.

Первый вход - это число, второй - строка.

Попробуйте онлайн!

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 байта

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

Было бы неплохо сделать CellularAutomaton[] решение работало, но я продолжал терпеть неудачу. Кто угодно?

Редактировать: некоторые красивые картинки (нажмите, чтобы увеличить)

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

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

60 итераций «Привет, мир!»

plotCA[bXORnotb, 100]:

100 итераций монолога Гамлета

plotCA[raven, 100]:

100 итераций По

hYPotenuser
источник
1
Не могли бы вы просто дать CellularAutomatonсвою функцию обновления? (Фактический номер правила с 127 действительными состояниями был бы безумным.)
Мартин Эндер
@ MartinBüttner Вы можете, но это перетаскивание, пытающееся объяснить поведение по краям, чтобы привести его в соответствие со спецификацией. BlockMap [] был просто короче.
hYPotenuser
7

Ява, 193 185 байт

Потому что Java.

-8 байт, переключаясь на цикл, а не на повторение, чтобы сделать его анонимной функцией

Возвращает n-ю итерацию XOROR для 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;}

Читаемая версия:

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

Практически буквальная реализация спецификации с рекурсивным циклом для применения операции n раз. Некоторые байты были сохранены, однако, с моим наблюдением, что предложение CHARCODE> 126 будет когда-либо происходить только с CHARCODE == 127, что приводит к сохранению SPACEвместо DEL.

Я пробежал свой код по нескольким произвольно выбранным строкам и нашел этот замечательный цикл:

oook$ok$ok$ok$
ook$ok$ok$ok$o
oo$ok$ok$ok$ok
oook$ok$ok$ok$
CAD97
источник
5
Этот ответ выглядит ok!
Конор О'Брайен
5

CJam, 38 байт

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

Проверьте это здесь.

объяснение

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.
  }%
}*
Мартин Эндер
источник
Я думаю, что вы можете сэкономить несколько байтов, lri){2S*\*3ew{)\:^|}%127c' er}*потому что операция pre-modulo символов никогда не превышает 127
Luis Mendo
5

Haskell, 123 байта

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)

Это возвращает бесконечный поток последовательности XOROR. Пример использования (выведите первые 5 элементов семени "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"

Как это работает:

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 байт (с n) | 177 байт (бесконечно)

Оказалось, что бесконечная печать короче ...

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

Разгромленный

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

Бесконечный бесконечный

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
источник
1
Это все еще можно много играть в гольф. Например, 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);}имеет длину 141 байт (-36 байт).
Blackhole
2

C ++

N-я последовательность (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-последовательность, использующая синтаксис указателя вместо синтаксиса массива, чтобы сделать это еще более запутанным: (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;
    }
}

Функция отладки (для удовольствия)

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
источник
1
Уверен, что результаты говорят, что вы должны вывести результат, а не просто вернуть его.
Mooing Duck
1
Я написал версию C ++ с нуля, сравнил ее с вашей, а затем объединил их и получил 158 байт: coliru.stacked-crooked.com/a/838c29e5d496d2a6
Duck
@MooingDuck Хорошо! Возможно, может уменьшить его еще больше с неявным int компилятором через переход к C.
FatalSleep
конечно, давай! Вы уже написали половину этого кода
Mooing Duck
2

JAVA 240/280 байт

Популярная версия Java на момент написания этой статьи утверждала, что она имеет размер 185 байт, но есть две важные особенности. Во-первых, измерение предположительно только для функции, а не для всего рабочего источника. Может быть, не такая проблема. Во-вторых, он использует BiFunction без импорта или полного имени. Добавление требуемых битов для запуска «как есть» (затем минимизации, справедливо) довело его до 348 байт. Добавление только полностью определенного имени класса BiFunction приводит к его увеличению до 248 байтов.

Напротив, я считаю, что у меня 240 байтов при игре по тем же правилам (без класса, без фактического вывода, только мясо). Полный исполняемый класс имеет размер 280 байт и выглядит следующим образом (без объединения):

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

Или, минимизированный:

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
источник
2

Perl, 47 байт

Включает +2 для -lp

Запустите с помощью ввода на STDIN, например, perl -lp xoror.pl <<< "Hello, World!" | head -26

xoror.pl:

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

Это работает как есть, но замените \x7fего на соответствующее двоичное значение, чтобы получить заданную оценку

Тон Хоспел
источник
1

Свифт: 273 персонажа

Ух ты, Свифт хуже Явы! (Все эти API с длинными именами!: 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)
    }
}

Благодаря @ CAD97 за упоминание о том, что (A ^ B) | C может быть больше 126, когда это 127.

Я также понял, что вам не нужны круглые скобки вокруг A ^ B | C, потому что XOR выполняется перед ORing, поэтому я сэкономил несколько байтов.

Вы
источник