Espejo mágico locura

22

Introducción

Tengo una habitación llena de espejos mágicos . Son artefactos misteriosos que pueden duplicar cualquier elemento, excepto otro espejo mágico. Más explícitamente, una versión duplicada del elemento aparecerá en el otro lado del espejo, a la misma distancia. Sin embargo, si hay otro espejo mágico en el camino a cada lado, entre el espejo duplicado y cualquier elemento (original o duplicado), el duplicado no se forma. El elemento original puede estar a la izquierda o a la derecha del espejo, y el duplicado aparecerá en el otro lado. Además, el elemento duplicado puede ser duplicado por otro espejo. Los elementos nunca bloquean la duplicación de otros elementos (excepto al estar directamente en la posición del posible duplicado).

Entrada

Su entrada es una cadena que consta de los caracteres .#|, que representan espacios vacíos, elementos y espejos mágicos. Siempre habrá al menos un espejo mágico en la entrada.

Salida

Su salida será otra cadena donde cada espejo mágico ha duplicado todos los elementos que puede, de acuerdo con las reglas anteriores. Puede suponer que siempre habrá un espacio vacío en el lugar donde aparece un elemento duplicado (para que no se salgan de los límites).

Ejemplos

Considere la cadena de entrada

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

donde hemos marcado algunas posiciones para mayor claridad. El espejo Bduplica el elemento A, que termina a su derecha:

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

Mirror Cluego duplica el nuevo elemento:

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

El espejo Cno puede duplicar el elemento A, ya que el espejo Bestá en el camino. Tampoco puede duplicar elementos D, ya que el espejo Bestá en el otro lado. Del mismo modo, el espejo Bno puede duplicar el elemento Do el duplicado al lado, ya que el espejo Cestá en el camino, por lo que esta es la salida correcta.

Para otro ejemplo, considere la entrada

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

El espejo se Dpuede duplicar Ay Bhacia la derecha Ey Ghacia la izquierda. Cy Fya son duplicados el uno del otro. La cuerda se convierte

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

Mirror Hpuede duplicar E, Fy los duplicados de Ay Ba la derecha y Ia la izquierda. Gy Jya son duplicados entre sí, y el espejo Destá en el camino de K. Ahora tenemos

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

Finalmente, el espejo Dpuede duplicar el duplicado de Ia la izquierda. Terminamos con

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

Reglas y puntaje

Puede escribir un programa completo o una función. El conteo de bytes más bajo gana. Los envíos que no usan motores de expresiones regulares compiten por separado de los que sí lo hacen, y pueden marcarse con (sin expresiones regulares) .

Casos de prueba

"|" -> "|"
"..|.." -> "..|.."
".#.|..." -> ".#.|.#."
"..#|.#." -> ".##|##."
".#..|....|.." -> ".#..|..#.|.#"
".|..|.#....." -> "#|#.|.#....."
"...|.#...|....#" -> ".##|##...|...##"
"......#|......." -> "......#|#......"
".#.|.....|......#" -> ".#.|.#...|...#..#"
".......|...#.##|...." -> "##.#...|...#.##|##.#"
"...#..||.......#..#...#" -> "...#..||.......#..#...#"
".##|.#....||#||......#|.#" -> ".##|##....||#||.....##|##"
".##..#...|#..##...|..##....#." -> ".#####..#|#..#####|#####..##."
".#|...||...|#...|..##...|#...." -> ".#|#..||.##|##..|..##..#|#..##"
"....#.|...#.|..|.|.....|..#......" -> "..#.#.|.#.#.|.#|#|#.#..|..#.#...."
"..|....|.....#.|.....|...|.#.|..|.|...#......" -> ".#|#...|...#.#.|.#.#.|.#.|.#.|.#|#|#..#......"
Zgarb
fuente
¿Podemos tomar una matriz de caracteres como entrada y / o salida?
Conor O'Brien el
@ ConorO'Brien No, a menos que sea la representación natural de una cadena en su idioma.
Zgarb

Respuestas:

10

Retina , 50 bytes

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

Pruébalo en línea! (La primera línea habilita un conjunto de pruebas separado por salto de línea).

Supongo que esto es lo contrario de una presentación (sin expresiones regulares).

Explicación

Esto es simplemente una sustitución de expresiones regulares, que se aplica repetidamente ( +) hasta que la cadena deja de cambiar. Estoy usando grupos de equilibrio para asegurarme de que las dos posiciones reflejadas estén a la misma distancia del espejo dado (las referencias traseras no lo harán, ya que la cadena exacta en ambos lados del |puede 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.

Esto se reemplaza con el #$2#que simplemente reemplaza tanto el primer como el último personaje del partido con a #.

Martin Ender
fuente
9

Perl, 49 bytes

Crédito total a @ Martin Ender por este que sugirió esta expresión regular 15 bytes más corta que la mía.

47 bytes de código + -plbanderas

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

Para ejecutarlo:

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

El primero ( ([.#])) y el último ((?!\1)[^|] partes ) son las mismas que en la respuesta Retina (vea la explicación allí).
La parte central ( (\||[^|](?2)[^|])) usa la recursión perl ( (?2)) para hacer coincidir un espejo ( \|) o ( |) dos caracteres no espejos ( [^|]) separados por el mismo patrón ( (?2)).


Mi versión anterior (y más fea): s/([.#])(([^|]*)\|(??{$3=~s%.%[^|]%gr}))(?!\1)[^|]/#$2#/&&redo

Dada
fuente
4

Haskell (sin expresiones regulares), 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
fuente
2

PHP, 123 117 100 bytes

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

El programa toma el argumento de la línea de comandos, expresiones regulares tomadas de @Martin Ender / Dada. Corre con -r.

Tito
fuente
@Zgarb solucionado, gracias
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;}}

Sin golf

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
fuente
1
Creo que puede guardar un par de bytes reemplazando '#'y '.'con 35y 46respectivamente.
artificialnull
Este código se puede jugar al golf ... mucho.
Mukul Kumar
gracias artificialNull, que salvó 3 byes. '|' es 124, por lo que eso no guarda nada (pero tal vez debería cambiar eso, para que sea consistente; aún no estoy seguro). y @Mukul, realmente no veo cómo, sin cambiar mucho el flujo lógico de la misma.
Eyal Lev
compruebe si este código funciona bien 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
1 byte más reemplaza (i! = J) con (ij) y si vas a seguir con c ++, al menos define todo int en un solo 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

Sin golf:

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
fuente