Loucura do espelho mágico

22

Introdução

Eu tenho uma sala cheia de espelhos mágicos . Eles são artefatos misteriosos que podem duplicar qualquer item, exceto outro espelho mágico. Mais explicitamente, uma versão duplicada do item aparecerá no outro lado do espelho, à mesma distância. No entanto, se houver outro espelho mágico no caminho de ambos os lados, entre o espelho de duplicação e o item (original ou duplicado), a duplicata não será formada. O item original pode ser esquerdo ou direito do espelho e a duplicata aparecerá no outro lado. Além disso, o item duplicado pode ser duplicado por outro espelho. Os itens nunca bloqueiam a duplicação de outros itens (exceto por estar diretamente na posição da possível duplicata).

Entrada

Sua entrada é uma sequência que consiste nos caracteres .#|, que representam espaço vazio, itens e espelhos mágicos. Sempre haverá pelo menos um espelho mágico na entrada.

Saída

Sua saída será outra string em que cada espelho mágico duplicou todos os itens possíveis, de acordo com as regras acima. Você pode assumir que sempre haverá um espaço vazio no local onde um item duplicado aparece (para que eles não saiam dos limites).

Exemplos

Considere a sequência de entrada

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

onde marcamos algumas posições para maior clareza. O espelho Bduplica o item A, que termina à sua direita:

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

O espelho Cduplica o novo item:

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

O espelho Cnão pode duplicar o item A, pois o espelho Bestá no caminho. Ele também não pode duplicar o item D, pois o espelho Bestá no caminho do outro lado. Da mesma forma, o espelho Bnão pode duplicar o item Dou a duplicata ao lado, pois o espelho Cestá no caminho, portanto esta é a saída correta.

Para outro exemplo, considere a entrada

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

O espelho Dpode duplicar Ae Bpara a direita Ee Gpara a esquerda. Ce Fjá são duplicados um do outro. A cadeia se torna

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

Espelho Hpode duplicar E, Fe as cópias de Ae Bpara a direita, e Ià esquerda. Ge Jjá são duplicados um do outro, e o espelho Destá no caminho K. Agora temos

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

Finalmente, o espelho Dpode duplicar a duplicação de Ipara a esquerda. Acabamos com

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

Regras e pontuação

Você pode escrever um programa completo ou uma função. A menor contagem de bytes vence. Os envios que não usam mecanismos regex competem separadamente daqueles que o fazem e podem ser marcados com (sem regex) .

Casos de teste

"|" -> "|"
"..|.." -> "..|.."
".#.|..." -> ".#.|.#."
"..#|.#." -> ".##|##."
".#..|....|.." -> ".#..|..#.|.#"
".|..|.#....." -> "#|#.|.#....."
"...|.#...|....#" -> ".##|##...|...##"
"......#|......." -> "......#|#......"
".#.|.....|......#" -> ".#.|.#...|...#..#"
".......|...#.##|...." -> "##.#...|...#.##|##.#"
"...#..||.......#..#...#" -> "...#..||.......#..#...#"
".##|.#....||#||......#|.#" -> ".##|##....||#||.....##|##"
".##..#...|#..##...|..##....#." -> ".#####..#|#..#####|#####..##."
".#|...||...|#...|..##...|#...." -> ".#|#..||.##|##..|..##..#|#..##"
"....#.|...#.|..|.|.....|..#......" -> "..#.#.|.#.#.|.#|#|#.#..|..#.#...."
"..|....|.....#.|.....|...|.#.|..|.|...#......" -> ".#|#...|...#.#.|.#.#.|.#.|.#.|.#|#|#..#......"
Zgarb
fonte
Podemos usar uma matriz de caracteres como entrada e / ou saída?
Conor O'Brien
@ ConorO'Brien Não, a menos que seja a representação natural de uma string no seu idioma.
Zgarb

Respostas:

10

Retina , 50 bytes

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

Experimente online! (A primeira linha ativa um conjunto de testes separado por avanço de linha.)

Eu acho que isso é o oposto de uma submissão (sem regex).

Explicação

Isso é simplesmente uma substituição de regex, que é aplicada repetidamente ( +) até que a string pare de mudar. Estou usando grupos de balanceamento para garantir que as duas posições espelhadas estejam à mesma distância do espelho fornecido (as referências anteriores não o farão, pois a seqüência exata em ambos os lados |pode ser diferente).

([#.])            # 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.

Isso é substituído pelo #$2#que simplesmente substitui o primeiro e o último caractere da partida por a #.

Martin Ender
fonte
9

Perl, 49 bytes

Crédito total para @Martin Ender por este que sugeriu esse regex 15 bytes mais curto que o meu.

47 bytes de código + -plsinalizadores

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

Para executá-lo:

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

A primeira ( ([.#])) e a última ( (?!\1)[^|]) partes são as mesmas da resposta da Retina (veja a explicação ali).
A parte do meio ( (\||[^|](?2)[^|])) usa perl recursion ( (?2)) para corresponder a um espelho ( \|) ou ( |) dois caracteres não espelhos ( [^|]) separados pelo mesmo padrão ( (?2)).


Minha versão mais antiga (e mais feia): s/([.#])(([^|]*)\|(??{$3=~s%.%[^|]%gr}))(?!\1)[^|]/#$2#/&&redo

dada
fonte
4

Haskell (sem regex), 117 bytes

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
dianne
fonte
2

PHP, 123 117 100 bytes

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

O programa recebe um argumento de linha de comando, regex retirado de @Martin Ender / Dada. Corra com -r.

Titus
fonte
@Zgarb corrigido, obrigado
Titus
2

C, 176 bytes

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;
        }
}
Eyal Lev
fonte
1
Eu acho que você pode salvar alguns bytes substituindo '#'e '.'com 35e 46respectivamente.
artificialnull
Este código pode ser jogado .. muito.
precisa
graças artificialNull, que salvou 3 byes. '|' é 124, então isso não salva nada (mas talvez eu deva mudar isso, para que seja consistente; ainda não tenho certeza). e @Mukul, eu realmente não vejo como, sem alterar muito o fluxo lógico dele.
Eyal Lev
verificar se este código é executado finas 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 bytes
Mukul Kumar
1
1more byte substituir (i = j!) Com (i, j) e se você estiver indo para ficar com c ++, em seguida, definir pelo menos todos int em um lugar ...
Mukul Kumar
1

JavaScript (ES6), 170 bytes

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