マジックミラーの狂気


22

前書き

魔法の鏡でいっぱいの部屋があります。それらは、別の魔法の鏡を除いて、あらゆるアイテムを複製できる神秘的なアーティファクトです。より明確には、アイテムの複製バージョンが同じ距離でミラーの反対側に表示されます。ただし、複製ミラーとアイテム(オリジナルまたは複製)の間に、両側に別のマジックミラーがある場合、複製は形成されません。元のアイテムはミラーの左または右に配置でき、複製は反対側に表示されます。また、複製したアイテム自体を別のミラーで複製できます。アイテムが他のアイテムの複製をブロックすることはありません(複製される予定の位置に直接いることを除く)。

入力

入力は、.#|空のスペース、アイテム、マジックミラーを表す文字で構成される文字列です。入力には常に少なくとも1つのマジックミラーがあります。

出力

出力は、上記のルールに従って、各マジックミラーが可能なすべてのアイテムを複製した別の文字列になります。重複するアイテムが表示される場所には常に空きスペースがあると想定できます(したがって、アイテムが範囲外に出ることはありません)。

入力文字列を考えます

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

ここでは明確にするためにいくつかの位置をマークしています。ミラーBはitemを複製Aし、最終的に右になります。

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

ミラーCは新しいアイテムを複製します:

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

ミラーCが邪魔になっているAため、ミラーBはアイテムを複製できません。DミラーBが反対側にあるため、itemを複製することもできません。同様に、ミラーBが邪魔になるため、DミラーCはアイテムまたはその隣のアイテムを複製できません。したがって、これは正しい出力です。

別の例として、入力を考えます

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

ミラーは、D複製することができますAし、B右へ、そしてEそしてG左へ。 既に互いに重複CFています。文字列は

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

ミラーはH複製することができEFとの重複AB右へ、そしてI左へ。 GJは既に互いに重複しており、ミラーDはの邪魔になりKます。今、私たちは持っています

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

最後に、ミラーは左のD複製を複製できIます。で終わる

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

ルールとスコアリング

完全なプログラムまたは関数のいずれかを作成できます。最も低いバイトカウントが優先されます。正規表現エンジンを使用しない送信は、正規表現エンジンとは別に競合し、(正規表現なし)とマークされる場合があります。

テストケース

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

入力および/または出力として文字の配列を使用できますか?
コナーオブライエン

@ ConorO'Brienいいえ、それがあなたの言語の文字列の自然な表現でない限り。
ズガルブ

回答:


10

網膜、50バイト

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

オンラインでお試しください!(最初の行は、改行で区切られたテストスイートを有効にします。)

これは(正規表現なしの)提出の反対だと思います。

説明

これは単なる正規表現の置換であり+、文字列の変更が停止するまで繰り返し適用されます()。私が使用している分散グループをミラー化された2つの位置が与えられたミラーから同じ距離(後方参照は、両側の正確な文字列から、しないだろうしていることを確認するために|異なる場合があります)。

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

これは#$2#、マッチの最初と最後の両方の文字を単にに置き換えることで置き換えられ#ます。


9

Perl、49バイト

この正規表現が私のものより15バイト短いことを提案したこの1人の@Martin Enderに対する完全なクレジット。

47バイトのコード+ -plフラグ

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

実行するには:

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

最初の(([.#]))と最後の((?!\1)[^|])の部分は、Retinaアンサーの場合と同じです(その説明を参照)。
中央部分((\||[^|](?2)[^|]))は、perl再帰((?2))を使用して、ミラー(\|)または(|[^|]まったく同じパターン((?2))で区切られた2つの非ミラー文字()のいずれかに一致します。


私の古い(そしてugい)バージョン: s/([.#])(([^|]*)\|(??{$3=~s%.%[^|]%gr}))(?!\1)[^|]/#$2#/&&redo


4

Haskell(正規表現なし)、117バイト

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 117100バイト

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

プログラムはコマンドライン引数を取り、正規表現は@Martin Ender / Dadaから取ります。で実行し-rます。


@Zgarb修正、ありがとう
タイタス

2

C、176バイト

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

非ゴルフ

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
私はあなたが交換することによってカップルのバイトを保存することができると思う'#''.'35し、46それぞれ。
人工

このコードは多くのことができます。
ムクルクマール

3バイトを節約したartificialNullに感謝します。「|」124であるため、何も保存されません(ただし、変更する必要があるため、一貫性がありますが、まだ不明です)。そして@Mukul、私はそれの論理フローを大きく変えない限り、どうやって見るのか本当に分かりません。
エイアルレフ

このコードが細かい実行されている場合、チェック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バイト-
Mukulクマール

1
1moreバイト(IJ)と(I = J!)を交換しますが、C ++、その後少なくとも...一つの場所ですべてのint型を定義するに固執しようとしている場合
Mukulクマール

1

JavaScript(ES6)、170バイト

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

ゴルフをしていない:

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);
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.