Folie du miroir magique


22

introduction

J'ai une pièce pleine de miroirs magiques . Ce sont des artefacts mystérieux qui peuvent reproduire n'importe quel élément, à l'exception d'un autre miroir magique. Plus explicitement, une version en double de l'élément apparaîtra de l'autre côté du miroir, à la même distance. Cependant, s'il y a un autre miroir magique sur le chemin de chaque côté, entre le miroir de duplication et l'un ou l'autre élément (original ou dupliqué), le doublon n'est pas formé. L'article d'origine peut être à gauche ou à droite du miroir, et le duplicata apparaîtra de l'autre côté. De plus, l'élément en double peut lui-même être dupliqué par un autre miroir. Les éléments ne bloquent jamais la duplication d'autres éléments (sauf en étant directement sur la position du double potentiel).

Contribution

Votre entrée est une chaîne composée des caractères .#|, qui représentent un espace vide, des objets et des miroirs magiques. Il y aura toujours au moins un miroir magique dans l'entrée.

Sortie

Votre sortie doit être une autre chaîne où chaque miroir magique a dupliqué chaque élément qu'il peut, selon les règles ci-dessus. Vous pouvez supposer qu'il y aura toujours un espace vide à l'endroit où un élément en double apparaît (afin qu'ils ne sortent pas des limites).

Exemples

Considérez la chaîne d'entrée

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

où nous avons marqué certaines positions pour plus de clarté. Le miroir Bduplique l'article A, qui se termine à sa droite:

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

Miroir Cduplique ensuite le nouvel élément:

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

Le miroir Cne peut pas dupliquer l'élément A, car le miroir Best sur le chemin. Il ne peut pas non plus dupliquer l'élément D, car le miroir Best sur le chemin de l'autre côté. De même, le miroir Bne peut pas dupliquer l'élément Dou le doublon à côté, car le miroir Cest sur le chemin, c'est donc la sortie correcte.

Pour un autre exemple, considérons l'entrée

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

Le miroir Dpeut être dupliqué Aet Bà droite, Eet Gà gauche. Cet Fsont déjà des doublons les uns des autres. La chaîne devient

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

Mirror Hpeut dupliquer E, Fet les doublons de Aet Bvers la droite et Ivers la gauche. Get Jsont déjà des doublons les uns des autres, et le miroir Dest sur le chemin de K. Maintenant nous avons

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

Enfin, le miroir Dpeut dupliquer le doublon de Ivers la gauche. On se retrouve avec

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

Règles et notation

Vous pouvez écrire soit un programme complet soit une fonction. Le nombre d'octets le plus bas gagne. Les soumissions qui n'utilisent pas de moteurs d'expression régulière sont en concurrence distincte de celles qui le font et peuvent être marquées d'un (pas d'expression régulière) .

Cas de test

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

Pouvons-nous prendre un tableau de caractères en entrée et / ou en sortie?
Conor O'Brien

@ ConorO'Brien Non, à moins que ce soit la représentation naturelle d'une chaîne dans votre langue.
Zgarb

Réponses:


10

Rétine , 50 octets

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

Essayez-le en ligne! (La première ligne active une suite de tests séparés par un saut de ligne.)

Je suppose que c'est l'opposé d'une soumission (sans regex).

Explication

Il s'agit simplement d'une substitution d'expression régulière, qui est appliquée à plusieurs reprises ( +) jusqu'à ce que la chaîne cesse de changer. J'utilise des groupes d'équilibrage pour m'assurer que les deux positions en miroir sont à la même distance du miroir donné (les références inverses ne le feront pas, car la chaîne exacte des deux côtés de la |peut être différente).

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

Il est remplacé par #$2#ce qui remplace simplement le premier et le dernier caractère du match par un #.


9

Perl, 49 octets

Un crédit complet à @Martin Ender pour celui qui a suggéré cette expression régulière 15 octets plus courte que la mienne.

47 octets de code + -pldrapeaux

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

Pour l'exécuter:

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

Les première ( ([.#])) et dernière ( (?!\1)[^|]) parties sont les mêmes que dans la réponse Retina (voir l'explication là-bas).
La partie centrale ( (\||[^|](?2)[^|])) utilise perl recursion ( (?2)) pour faire correspondre un miroir ( \|) ou ( |) deux non-mirrors-characters ( [^|]) séparés par le même motif ( (?2)).


Ma version plus ancienne (et plus laide): s/([.#])(([^|]*)\|(??{$3=~s%.%[^|]%gr}))(?!\1)[^|]/#$2#/&&redo


4

Haskell (pas d'expression régulière), 117 octets

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 octets

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

le programme prend l'argument de la ligne de commande, l'expression régulière extraite de @Martin Ender / Dada. Courez avec -r.


@Zgarb corrigé, merci
Titus

2

C, 176 octets

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

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

1
Je pense que vous pouvez économiser quelques octets en remplaçant '#'et '.'par 35et 46respectivement.
artificialnull

Ce code peut être joué beaucoup.
Mukul Kumar

merciificialNull, qui a sauvé 3 byes. «|» est 124, donc cela ne sauve rien (mais je devrais peut-être changer cela, donc ce sera cohérent; je ne suis pas encore sûr). et @Mukul, je ne vois pas vraiment comment, sans en changer considérablement le flux logique.
Eyal Lev

vérifier si ce code fonctionne correctement 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 octets
Mukul Kumar

1
1 octet de plus remplacer (i! = J) par (ij) et si vous allez vous en tenir à c ++ alors définissez au moins tous les int à un seul endroit ...
Mukul Kumar

1

JavaScript (ES6), 170 octets

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

Non 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);
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.