Zauberspiegel Wahnsinn

22

Einführung

Ich habe einen Raum voller Zauberspiegel . Es handelt sich um mysteriöse Artefakte, die jedes Objekt, mit Ausnahme eines weiteren magischen Spiegels, duplizieren können. Genauer gesagt wird eine doppelte Version des Elements auf der anderen Seite des Spiegels im gleichen Abstand angezeigt. Befindet sich jedoch auf beiden Seiten ein anderer magischer Spiegel zwischen dem duplizierenden Spiegel und einem Gegenstand (Original oder Duplikat), wird das Duplikat nicht gebildet. Das Originalelement kann sich entweder links oder rechts vom Spiegel befinden, und das Duplikat wird auf der anderen Seite angezeigt. Das duplizierte Element kann auch selbst von einem anderen Spiegel dupliziert werden. Gegenstände blockieren niemals die Vervielfältigung anderer Gegenstände (es sei denn, sie befinden sich direkt an der Position des möglichen Gegenstands).

Eingang

Ihre Eingabe ist eine Zeichenfolge, die aus den Zeichen besteht .#|, die Leerzeichen, Objekte und magische Spiegel darstellen. In der Eingabe befindet sich immer mindestens ein Zauberspiegel.

Ausgabe

Ihre Ausgabe soll eine andere Zeichenfolge sein, in der jeder Magic Mirror alle Objekte dupliziert hat, die er kann, gemäß den obigen Regeln. Sie können davon ausgehen, dass an der Stelle, an der ein doppeltes Element angezeigt wird, immer ein leerer Bereich vorhanden ist (sodass diese Bereiche nicht überschritten werden).

Beispiele

Betrachten Sie die Eingabezeichenfolge

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

wo wir aus Gründen der Übersichtlichkeit einige Positionen markiert haben. Der Spiegel Bdupliziert das Element A, das rechts davon endet:

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

Spiegeln Cdupliziert dann das neue Objekt:

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

Spiegeln Ckann kein Objekt duplizieren A, da Spiegeln Bim Weg ist. Es kann auch kein Objekt dupliziert werden D, da der Spiegel Bauf der anderen Seite im Weg ist. Ebenso kann der Spiegel Bnicht das Objekt Doder das Duplikat daneben duplizieren, da der Spiegel Cim Weg ist, sodass dies die richtige Ausgabe ist.

Betrachten Sie für ein anderes Beispiel die Eingabe

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

Mirror Dkann duplizieren Aund Bnach rechts Eund Gnach links. Cund Fsind bereits Duplikate voneinander. Die Zeichenfolge wird

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

Mirror Hkann duplizieren E, Fund die Duplikate von Aund Brechts und Ilinks. Gund Jsind bereits Duplikate voneinander, und der Spiegel Dsteht im Weg von K. Jetzt haben wir

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

Schließlich kann Mirror Ddas Duplikat von Ilinks duplizieren . Wir enden mit

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

Regeln und Wertung

Sie können entweder ein vollständiges Programm oder eine Funktion schreiben. Die niedrigste Byteanzahl gewinnt. Einsendungen, die keine regulären Ausdrücke verwenden, konkurrieren getrennt von denen, die dies tun, und können mit (kein regulärer Ausdruck) gekennzeichnet sein .

Testfälle

"|" -> "|"
"..|.." -> "..|.."
".#.|..." -> ".#.|.#."
"..#|.#." -> ".##|##."
".#..|....|.." -> ".#..|..#.|.#"
".|..|.#....." -> "#|#.|.#....."
"...|.#...|....#" -> ".##|##...|...##"
"......#|......." -> "......#|#......"
".#.|.....|......#" -> ".#.|.#...|...#..#"
".......|...#.##|...." -> "##.#...|...#.##|##.#"
"...#..||.......#..#...#" -> "...#..||.......#..#...#"
".##|.#....||#||......#|.#" -> ".##|##....||#||.....##|##"
".##..#...|#..##...|..##....#." -> ".#####..#|#..#####|#####..##."
".#|...||...|#...|..##...|#...." -> ".#|#..||.##|##..|..##..#|#..##"
"....#.|...#.|..|.|.....|..#......" -> "..#.#.|.#.#.|.#|#|#.#..|..#.#...."
"..|....|.....#.|.....|...|.#.|..|.|...#......" -> ".#|#...|...#.#.|.#.#.|.#.|.#.|.#|#|#..#......"
Zgarb
quelle
Können wir ein Array von Zeichen als Eingabe und / oder Ausgabe verwenden?
Conor O'Brien
@ ConorO'Brien Nein, es sei denn, dies ist die natürliche Darstellung einer Zeichenfolge in Ihrer Sprache.
Zgarb

Antworten:

10

Netzhaut , 50 Bytes

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

Probieren Sie es online! (Die erste Zeile aktiviert eine durch Zeilenvorschub getrennte Testsuite.)

Ich denke, dies ist das Gegenteil einer (nicht regulären) Einreichung.

Erläuterung

Dies ist einfach eine reguläre Ersetzung, die wiederholt angewendet wird ( +), bis sich die Zeichenfolge nicht mehr ändert. Ich benutze Bilanzgruppen , um sicherzustellen, dass die beiden gespiegelten Positionen den gleichen Abstand zum angegebenen Spiegel haben (Rückreferenzen reichen nicht aus, da die exakte Zeichenfolge auf beiden Seiten der |möglicherweise unterschiedlich ist).

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

Dies wird ersetzt #$2#, indem einfach sowohl das erste als auch das letzte Zeichen der Übereinstimmung durch a ersetzt werden #.

Martin Ender
quelle
9

Perl, 49 Bytes

Voller Dank an @Martin Ender für diesen, der diese Regex vorgeschlagen hat, die 15 Byte kürzer ist als meine.

47 Byte Code + -plFlags

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

Um es auszuführen:

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

Der erste ( ([.#])) und der letzte ( (?!\1)[^|]) Teil sind die gleichen wie in der Retina-Antwort (siehe die Erklärung dort).
Der mittlere Teil ( (\||[^|](?2)[^|])) verwendet die Perl-Rekursion ( (?2)), um entweder einen Spiegel ( \|) oder ( |) zwei Nicht-Spiegel-Zeichen ( [^|]) zuzuordnen, die durch dasselbe Muster ( (?2)) getrennt sind.


Meine ältere (und hässlichere) Version: s/([.#])(([^|]*)\|(??{$3=~s%.%[^|]%gr}))(?!\1)[^|]/#$2#/&&redo

Dada
quelle
4

Haskell (kein regulärer Ausdruck), 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
Dianne
quelle
2

PHP, 123 117 100 Bytes

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

Das Programm übernimmt das Kommandozeilenargument regex von @Martin Ender / Dada. Laufen Sie mit -r.

Titus
quelle
@ Zgarb behoben, danke
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
quelle
1
Ich denke , man kann durch das Ersetzen ein paar Bytes speichern '#'und '.'mit 35und 46jeweils.
künstliche
Dieser Code kann gespielt werden.
Mukul Kumar
danke artificialNull, der 3 byes gerettet hat. '|' ist 124, das spart also nichts (aber vielleicht sollte ich das ändern, damit es konsistent wird; noch nicht sicher). und @Mukul, ich verstehe nicht wirklich, wie, ohne den logischen Ablauf stark zu verändern.
Eyal Lev
Überprüfen Sie, ob dieser Code gut läuft 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 weiteres Byte ersetze (i! = J) durch (ij) und wenn du bei c ++ bleiben willst, dann definiere atleast all int an einem Ort ...
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);
}
Neil
quelle