Follia allo specchio magico


22

introduzione

Ho una stanza piena di specchi magici . Sono artefatti misteriosi che possono duplicare qualsiasi oggetto, tranne un altro specchio magico. Più esplicitamente, una versione duplicata dell'elemento apparirà sull'altro lato dello specchio, alla stessa distanza. Tuttavia, se c'è un altro specchio magico tra i due lati, tra lo specchio duplicato e uno degli oggetti (originale o duplicato), il duplicato non si forma. L'elemento originale può essere a sinistra oa destra dello specchio e il duplicato apparirà sull'altro lato. Inoltre, l'elemento duplicato può essere duplicato da un altro mirror. Gli oggetti non bloccano mai la duplicazione di altri oggetti (tranne per il fatto di trovarsi direttamente nella posizione dell'aspirante duplicato).

Ingresso

Il tuo input è una stringa composta dai caratteri .#|, che rappresentano spazio vuoto, oggetti e specchi magici. Ci sarà sempre almeno uno specchio magico nell'input.

Produzione

Il tuo output deve essere un'altra stringa in cui ogni specchio magico ha duplicato ogni oggetto che può, secondo le regole sopra. Puoi presumere che ci sarà sempre uno spazio vuoto nel punto in cui appare un elemento duplicato (quindi non andranno oltre i limiti).

Esempi

Considera la stringa di input

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

dove abbiamo segnato alcune posizioni per chiarezza. Il mirror Bduplica l'elemento A, che finisce alla sua destra:

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

Mirror Cquindi duplica il nuovo elemento:

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

Il mirror Cnon può duplicare l'elemento A, poiché il mirror Bè in mezzo. Inoltre, non è possibile duplicare l'elemento D, poiché il mirror si Btrova sull'altro lato. Allo stesso modo, mirror Bnon può duplicare l'elemento Do il duplicato accanto ad esso, poiché mirror Cè in mezzo, quindi questo è l'output corretto.

Per un altro esempio, considerare l'input

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

Il mirror Dpuò duplicare Asia Ba destra Eche Ga sinistra. Ce Fsono duplicati già uno dall'altro. La stringa diventa

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

Mirror Hpuò duplicare E, Fe i duplicati di Ae Bverso destra e Iverso sinistra. Ge Jsono già duplicati l'uno dell'altro, e mirror Dè in mezzo a K. Ora abbiamo

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

Infine, il mirror Dpuò duplicare il duplicato di Ia sinistra. Finiamo con

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

Regole e punteggio

È possibile scrivere un programma completo o una funzione. Vince il conteggio dei byte più basso. I contributi che non utilizzano i motori regex competono separatamente da quelli che lo fanno e possono essere contrassegnati con (nessun regex) .

Casi test

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

Possiamo prendere una matrice di caratteri come input e / o output?
Conor O'Brien,

@ ConorO'Brien No, a meno che non sia la rappresentazione naturale di una stringa nella tua lingua.
Zgarb,

Risposte:


10

Retina , 50 byte

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

Provalo online! (La prima riga abilita una suite di test separata da avanzamento riga.)

Immagino che questo sia l'opposto di una presentazione (senza regex).

Spiegazione

Questa è semplicemente una sostituzione regex, che viene applicata ripetutamente ( +) fino a quando la stringa non smette di cambiare. Sto usando i gruppi di bilanciamento per assicurarmi che le due posizioni specchiate siano alla stessa distanza dal mirror dato (i riferimenti indietro non lo faranno, poiché la stringa esatta su entrambi i lati |potrebbe essere diversa).

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

Questo viene sostituito con il #$2#quale sostituisce semplicemente sia il primo che l'ultimo carattere della partita con a #.


9

Perl, 49 byte

Riconoscimento completo a @Martin Ender per questo che ha suggerito questo regex 15 byte più corto del mio.

47 byte di codice + -plflag

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

Per eseguirlo:

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

Le parti first ( ([.#])) e last ( (?!\1)[^|]) sono le stesse della risposta Retina (vedere la spiegazione laggiù).
La parte centrale ( (\||[^|](?2)[^|])) usa perl recursion ( (?2)) per far corrispondere a mirror ( \|) o ( |) due caratteri non-mirror ( [^|]) separati dallo stesso pattern ( (?2)).


La mia versione più vecchia (e più brutta): s/([.#])(([^|]*)\|(??{$3=~s%.%[^|]%gr}))(?!\1)[^|]/#$2#/&&redo


4

Haskell (no regex), 117 byte

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 byte

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

il programma accetta l'argomento della riga di comando, regex preso da @Martin Ender / Dada. Corri con -r.


@Zgarb risolto, grazie
Tito

2

C, 176 byte

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
Penso che puoi salvare un paio di byte sostituendo '#'e '.'con 35e 46rispettivamente.
Artificialnull

Questo codice può essere giocato a golf ... molto.
Mukul Kumar,

grazie artificialNull, che ha salvato 3 bye. '|' è 124, quindi non salva nulla (ma forse dovrei cambiarlo, quindi sarà coerente; non sono ancora sicuro). e @Mukul, non vedo davvero come, senza cambiare notevolmente il flusso logico di esso.
Eyal Lev,

controlla se questo codice funziona bene 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 byte
Mukul Kumar il

1
1more byte sostituisce (i! = J) con (ij) e se hai intenzione di rimanere con c ++ allora almeno definisci tutto int in un unico posto ...
Mukul Kumar

1

JavaScript (ES6), 170 byte

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);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.