Волшебное зеркало безумия


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

Правила и оценки

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

Контрольные примеры

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

Можем ли мы взять массив символов в качестве ввода и / или вывода?
Конор О'Брайен

@ 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#который просто заменяет и первый и последний символ матча с #.


9

Perl, 49 байт

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

47 байт кода + -plфлаги

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

Чтобы запустить это:

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

Части first ( ([.#])) и last ( (?!\1)[^|]) такие же, как в ответе Retina (см. Объяснение там).
Средняя часть ( (\||[^|](?2)[^|])) использует perl recursion ( (?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;}}

Ungolfed

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соответственно.
искусственный

Этот код может быть в гольфе .. много.
Мукул Кумар

спасибо искусственное, что спасло 3 байса. '|' это 124, так что это ничего не сохраняет (но, возможно, я должен изменить это, так что это будет согласованно; пока не уверен). и @Mukul, я действительно не вижу, как, без значительного изменения логического потока этого.
Эяль Лев

проверить, работает ли этот код нормально 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 байт
Mukul Kumar

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

Ungolfed:

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.