Чарівне дзеркальне божевілля


22

Вступ

У мене є кімната, повна чарівних дзеркал . Вони - таємничі артефакти, які можуть копіювати будь-який предмет, крім іншого магічного дзеркала. Більш чітко, копія версії предмета з’явиться з іншого боку дзеркала, на однаковій відстані. Однак, якщо в обох сторонах є інше магічне дзеркало, між дзеркалом, що повторюється, та будь-яким предметом (оригінальним чи дублікатом), дублікат не утворюється. Оригінальний предмет може бути ліворуч або праворуч від дзеркала, а дублікат з’явиться з іншого боку. Також дублюючий предмет може сам дублюватися іншим дзеркалом. Елементи ніколи не блокують дублювання інших елементів (за винятком того, що вони знаходяться безпосередньо в позиції потенційного дубліката).

Вхідні дані

Ваш вхід - це рядок, що складається з символів .#|, які представляють порожній простір, предмети та магічні дзеркала. На вході завжди буде хоча б одне магічне дзеркало.

Вихідні дані

Ваш вихід повинен бути іншим рядком, де кожне магічне дзеркало дублювало кожен елемент, який може, відповідно до правил вище. Можна припустити, що на місці, де з’явиться дублікат, завжди буде порожнє місце (тому вони не вийдуть за межі).

Приклади

Розглянемо рядок введення

.#.|.....|......#
 A B     C      D

де ми відзначили деякі позиції для наочності. Дзеркало Bкопіює елемент A, який закінчується праворуч:

.#.|.#...|......#
 A B     C      D

CПотім дзеркало дублює новий елемент:

.#.|.#...|...#..#
 A B     C      D

Дзеркало Cне може дублювати елемент A, оскільки дзеркало Bв дорозі. Він також не може дублювати елемент D, оскільки дзеркало Bстоїть на іншому боці. Так само дзеркало Bне може дублювати елемент Dабо дублікат поруч, оскільки дзеркало Cв дорозі, тому це правильний вихід.

Для іншого прикладу розглянемо вхідні дані

.##..#...|#..##...|..##....#.
 AB  C   DE  FG   H  IJ    K

Дзеркало Dможе дублювати Aі Bвправо, а також Eі Gвліво. Cі Fвже є дублікатами один одного. Рядок стає

.##.##..#|#..##.##|..##....#.
 AB  C   DE  FG   H  IJ    K

Дзеркало Hможе дублювати E, Fі дублікати, Aі Bправоруч, і Iзліва. Gі Jвже є дублікатами один одного, і дзеркало Dна шляху K. Зараз у нас є

.##.##..#|#..#####|#####..##.
 AB  C   DE  FG   H  IJ    K

Нарешті, дзеркало Dможе дублювати дублікат Iліворуч. Ми закінчуємо

.#####..#|#..#####|#####..##.
 AB  C   DE  FG   H  IJ    K

Правила та оцінка

Ви можете написати або повну програму, або функцію. Виграє найменший байт. Заявки, які не використовують двигуни регулярного вибору, конкурують окремо від тих, що роблять, і можуть бути позначені символом (без регулярного вираження) .

Тестові кейси

"|" -> "|"
"..|.." -> "..|.."
".#.|..." -> ".#.|.#."
"..#|.#." -> ".##|##."
".#..|....|.." -> ".#..|..#.|.#"
".|..|.#....." -> "#|#.|.#....."
"...|.#...|....#" -> ".##|##...|...##"
"......#|......." -> "......#|#......"
".#.|.....|......#" -> ".#.|.#...|...#..#"
".......|...#.##|...." -> "##.#...|...#.##|##.#"
"...#..||.......#..#...#" -> "...#..||.......#..#...#"
".##|.#....||#||......#|.#" -> ".##|##....||#||.....##|##"
".##..#...|#..##...|..##....#." -> ".#####..#|#..#####|#####..##."
".#|...||...|#...|..##...|#...." -> ".#|#..||.##|##..|..##..#|#..##"
"....#.|...#.|..|.|.....|..#......" -> "..#.#.|.#.#.|.#|#|#.#..|..#.#...."
"..|....|.....#.|.....|...|.#.|..|.|...#......" -> ".#|#...|...#.#.|.#.#.|.#.|.#.|.#|#|#..#......"

Чи можемо ми взяти масив символів як вхідний та / або вихідний?
Conor O'Brien

@ ConorO'Brien Ні, якщо тільки це не є природним поданням рядка у вашій мові.
Згарб

Відповіді:


10

Сітківка , 50 байт

+`([#.])(([#.])*\|(?>(?<-3>[#.])*))(?!\1)[#.]
#$2#

Спробуйте в Інтернеті! (Перший рядок включає тестовий набір, відокремлений виведенням ліній.)

Я здогадуюсь, це протилежне поданню (без регулярного вираження).

Пояснення

Це просто підстановка з регулярними виразами, яка застосовується повторно ( +), поки рядок не перестане змінюватися. Я використовую балансуючі групи, щоб переконатися, що дві дзеркальні позиції знаходяться на однаковій відстані від заданого дзеркала (зворотній зв'язок не буде робити, оскільки точна рядок з обох сторін |може бути різною).

([#.])            # Match and capture a non-mirror cell.
(                 # This will match and capture everything up to its corresponding
                  # cell so that we can write it back in the substitution.
  ([#.])*         #   Match zero or more non-mirror cells and push each one onto
                  #   group 3. This counts the distance from our first match to
                  #   the mirror.
  \|              #   Match the mirror.
  (?>             #   Atomic group to prevent backtracking.
    (?<-3>[#.])*  #     Match non-mirror while popping from group 3.
  )               #   There are three reasons why the previous repetition
                  #   might stop:
                  #   - Group 3 was exhausted. That's good, the next position
                  #     corresponds to the first character we matched.
                  #   - We've reached the end of the string. That's fine,
                  #     the last part of the regex will cause the match to fail.
                  #   - We've hit another mirror. That's also fine, because
                  #     the last part of the regex will still fail.
)
(?!\1)            # Make sure that the next character isn't the same as the first
                  # one. We're looking for .|# or #|., not for #|# or .|.
[#.]              # Match the last non-mirror character.

Це замінюється тим, #$2#що просто замінює і перший, і останній символи матчу на "a" #.


9

Perl, 49 байт

Повна заслуга @Martin Ender для цього, хто запропонував цей регулярний вираз на 15 байт коротше мого.

47 байт коду + -plпрапори

s/([.#])(\||[^|](?2)[^|])(?!\1)[^|]/#$2#/&&redo

Щоб запустити його:

perl -plE 's/([.#])(\||[^|](?2)[^|])(?!\1)[^|]/#$2#/&&redo' <<< ".##..#...|#..##...|..##....#."

Перша ( ([.#])) та остання ( (?!\1)[^|]) частини такі ж, як у відповіді Ретина (див. Пояснення там).
Середня частина ( (\||[^|](?2)[^|])) використовує рекурсію perl ( (?2)), щоб збігати дзеркало ( \|) або ( |) два символи-дзеркала ( [^|]), розділені тим самим малюнком ( (?2)).


Моя старша (і гірша) версія: s/([.#])(([^|]*)\|(??{$3=~s%.%[^|]%gr}))(?!\1)[^|]/#$2#/&&redo


4

Haskell (без регулярного вираження), 117 байт

r=reverse
s=span(<'|')
m=zipWith min
g a|(b,l:c)<-s a,(d,e)<-s c=b++l:g(m(r b++[l,l..])d++e)|0<1=a
f x=m(g x)$r.g.r$x

2

PHP, 123 117 100 байт

for($t=$argv[1];$t!=$s;)$t=preg_replace("%([.#])(\||[.#](?2)[.#])(?!\g1)[.#]%","#$2#",$s=$t);echo$t;

Програма бере аргумент командного рядка, регулярний вираз, узятий з @Martin Ender / Dada. Бігайте з -r.


@Zgarb виправлено, спасибі
Тіт

2

C, 176 байт

void t(char*a){int x=0;for(int i=0;a[i];i++)if(a[i]=='|'){for(int j=x;a[j]&&j<=i*2-x;j++){if((a[j]==35)&&(a[2*i-j]==46)){a[2*i-j]=35;i=-1;}if((i-j)&&(a[j]=='|'))break;}x=i+1;}}

Безумовно

void t(char*a)
{
    int x=0;
    for(int i=0;a[i];i++)
        if(a[i]=='|')
        {
            for(int j=x;a[j]&&j<=i*2-x;j++)
            {
                if((a[j]=='#')&&(a[2*i-j]=='.'))
                {
                    a[2*i-j]='#';
                    i=-1;
                    break;
                }
                if((i!=j)&&(a[j]=='|'))
                    break;
            }
            x=i+1;
        }
}

1
Я думаю , що ви можете заощадити пару байт, замінюючи '#'і '.'з 35і 46відповідно.
штучний

Цей код можна пограти в гольф.
Мукул Кумар

спасибі штучнийNull, що врятувало 3 бади. '|' це 124, так що нічого не економить (але, можливо, я повинен це змінити, щоб це було послідовно; поки не впевнений). і @Mukul, я насправді не бачу, як, не сильно змінивши логічний потік цього.
Eyal Lev

перевірте, чи добре працює цей код x,i,j;void t(char*a){while(a[i]++)if(a[i]=='|'){for(j=x;a[j++]&&j<=i*2-x;j++){if((a[j]==35)&&(a[2*i-j]==46)){a[2*i-j]=35;i=-1;break;}if((i-j)&&(a[j]=='|'))break;}x=i+1;}}- 170 байт
Мукул Кумар

1
1 Більше замініть байт (i! = J) на (ij), і якщо ви збираєтесь дотримуватися c ++, то принаймні визначте всі int в одному місці ...
Mukul Kumar

1

JavaScript (ES6), 170 байт

s=>s.replace(/#/g,(c,i)=>(g(i,-1),g(i,1)),g=(i,d,j=h(i,d))=>j-h(j=j+j-i,-d)|s[j]!='.'||(s=s.slice(0,j)+'#'+s.slice(j+1),g(j,d)),h=(i,d)=>s[i+=d]=='|'?i:s[i]?h(i,d):-1)&&s

Безголівки:

function mirror(s) {
    for (var i = 0; i < s.length; i++) {
        // Reflect each # in both directions
        if (s[i] == '#') s = reflect(reflect(s, i, true), i, false);
    }
    return s;
}
function reflect(s, i, d) {
    // Find a mirror
    var j = d ? s.indexOf('|', i) : s.lastIndexOf('|', i);
    if (j < 0) return s;
    // Check that the destination is empty
    var k = j + (j - i);
    if (s[k] != '.') return s;
    // Check for an intervening mirror
    var l = d ? s.lastIndexOf('|', k) : s.indexOf('|', k);
    if (l != j) return s;
    // Magically duplicate the #
    s = s.slice(0, k) + '#' + s.slice(k + 1);
    // Recursively apply to the new #
    return reflect(s, k, d);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.