마법의 거울 광기 공간이 항상 있다고 가정 할 수 있습니다

소개

나는 마술 거울로 가득 찬 방이있다 . 그들은 다른 마술 거울을 제외한 모든 아이템을 복제 할 수있는 신비한 유물입니다. 보다 명확하게, 항목의 복제 버전이 같은 거리에서 미러의 다른쪽에 나타납니다. 그러나 복제 미러와 항목 (원본 또는 복제본) 사이에 다른쪽에 다른 매직 미러가있는 경우 복제본이 형성되지 않습니다. 원본 항목은 미러의 왼쪽이나 오른쪽에있을 수 있으며 복제본은 다른쪽에 나타납니다. 또한 복제 항목 자체는 다른 미러에 의해 복제 될 수 있습니다. 항목은 다른 항목의 복제를 차단하지 않습니다 (복제 위치에 직접있는 경우 제외).

입력

입력은 .#|빈 공간, 항목 및 마술 거울을 나타내는 문자로 구성된 문자열 입니다. 입력에 항상 하나 이상의 매직 미러가 있습니다.

산출

위의 규칙에 따라 각 매직 미러가 가능한 모든 항목을 복제 한 다른 문자열이 출력됩니다. 중복 항목이 나타나는 곳에 빈 공간이 항상 있다고 가정 할 수 있습니다 (따라서 경계를 벗어나지 않습니다).

입력 문자열을 고려하십시오

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

여기서 우리는 명확성을 위해 몇 가지 입장을 표시했습니다. 미러는 Bitem을 복제 A하여 오른쪽으로 끝납니다.

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

C그런 다음 미러 는 새 항목을 복제합니다.

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

미러 C가 방해가되어 A미러 B가 항목을 복제 할 수 없습니다 . 또한 D미러 B가 반대편에 있기 때문에 item을 복제 할 수 없습니다 . 마찬가지로, 미러 B는 방해가 D되므로 미러 C는 항목 이나 그 옆에있는 복제본을 복제 할 수 없으므로 올바른 출력입니다.

다른 예를 들어, 입력을 고려하십시오

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

미러 D복제 할 수 AB오른쪽에, 그리고 EG(가) 왼쪽으로.
C하고 F있는 이미 서로 복제합니다. 끈은

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

미러 H복제 할 수 있습니다 E, F그리고의 중복 AB오른쪽 및 I왼쪽으로.
G하고 J있는 이미 서로의 복제, 그리고 거울 D의 방법입니다 K. 이제 우리는

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

마지막으로, 미러 DI왼쪽에 복제본을 복제 할 수 있습니다 . 우리는 결국

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

규칙과 득점

전체 프로그램이나 함수를 작성할 수 있습니다. 가장 낮은 바이트 수가 이깁니다. 정규식 엔진을 사용하지 않는 제출물은 정규식 엔진을 사용하지 않는 제출물과 경쟁하며 (정규식 없음) 으로 표시 될 수 있습니다 .

테스트 사례

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


답변

망막 , 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#일치하는 첫 번째 문자와 마지막 문자를 모두 로 대체하는 것으로 대체됩니다 #.


답변

펄, 49 바이트

이 정규식을 내 것보다 15 바이트 짧게 제안한 사람에 대해서는 @Martin Ender 에게 전액 공로를 제공 합니다.

47 바이트의 코드 + -pl플래그

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

그것을 실행하려면 :

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

첫 번째 ( ([.#])) 및 마지막 ( (?!\1)[^|]) 부분은 Retina 답변과 동일합니다 (해당 설명 참조).
가운데 부분 ( (\||[^|](?2)[^|]))은 펄 재귀 ( (?2))를 사용하여 거울 ( \|) 또는 ( |) 두 개의 not-mirrors-character ( [^|])를 동일한 패턴 ( (?2))으로 구분 하여 일치 시킵니다.


나의 더 오래된 (그리고 더 못생긴) 버전 : s/([.#])(([^|]*)\|(??{$3=~s%.%[^|]%gr}))(?!\1)[^|]/#$2#/&&redo


답변

하스켈 (정규식 없음), 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

답변

PHP, 123 (117) 100 바이트

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

프로그램은 명령 행 인수, @Martin Ender / Dada에서 가져온 정규식을 사용합니다. 로 실행하십시오 -r.


답변

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

답변

자바 스크립트 (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);
}