魔镜疯狂


22

介绍

我的房间里装满了魔镜。它们是神秘的文物,可以复制任何物品,但另一个魔镜除外。更明确地说,该项目的重复版本将以相同的距离出现在镜子的另一侧。但是,如果在复制镜和任一物品(原始或复制品)之间的任一侧都有另一个魔术镜,则不会形成复制品。原始项目可以在镜子的左侧或右侧,并且重复项将出现在另一侧。而且,重复项本身可以被另一个镜像复制。项目永远不会阻止其他项目的重复(除非直接位于要复制的位置上)。

输入项

您的输入是一个由字符组成的字符串.#|,它们代表空白,物品和魔镜。输入中将始终至少有一个魔术镜。

输出量

根据上述规则,您的输出将是另一个字符串,其中每个魔术镜都复制了它可以复制的所有物品。您可以假设出现重复项的位置始终有一个空白空间(因此它们不会超出范围)。

例子

考虑输入字符串

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

为了清楚起见,我们在其中标记了一些位置。镜像B重复项item A,其最终在其右边:

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

镜像C然后复制新项目:

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

镜像C无法复制项目A,因为镜像B一直在进行中。它也不能复制项目D,因为镜像B在另一侧。同样,mirror B不能复制项D或旁边的重复项,因为mirror C妨碍了,所以这是正确的输出。

再举一个例子,考虑输入

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

镜子D可以复制AB右侧,并且EG左侧。 C并且F已经是彼此的副本。字符串变成

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

Mirror H可以复制E,,F以及和的重复项,A以及B在右边和I左边的重复项。 G并且J已经是彼此的副本,并且mirror D处于的方式K。现在我们有

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

最后,mirror D可以将的重复项复制I到左侧。我们最终以

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

规则和计分

您可以编写完整的程序或函数。最低字节数获胜。不使用正则表达式引擎的提交将与不使用正则表达式引擎的提交分开竞争,并可能标有(没有正则表达式)

测试用例

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

我们可以将字符数组作为输入和/或输出吗?
Conor O'Brien

@ ConorO'Brien不,除非那是您语言中字符串的自然表示形式。
Zgarb '16

Answers:


10

视网膜,50字节

+`([#.])(([#.])*\|(?>(?<-3>[#.])*))(?!\1)[#.]
#$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个字节的正则表达式,@Martin Ender给予了充分的感谢

47个字节的代码+ -pl标志

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

运行它:

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

第一个(([.#]))和最后一个((?!\1)[^|])部分与Retina答案中的相同(请参阅此处的说明)。
中间部分((\||[^|](?2)[^|]))使用perl递归((?2))来匹配一个镜像(\|)或(|)匹配[^|]由相同模式((?2))分隔的两个非镜像字符()。


我的旧版本(和更丑陋的版本): 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个 117 100字节

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

程序采用命令行参数,正则表达式取自@Martin Ender / Dada。用运行-r


@Zgarb已修复,谢谢
Titus

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
我想你可以通过更换节省了几个字节'#',并'.'3546分别。
虚假的人

这个代码可以打高尔夫..很多。
Mukul Kumar

感谢artificialNull,它节省了3个再见。'|' 是124,因此不会保存任何内容(但也许我应该更改它,以便保持一致;尚不确定)。和@Mukul,在不改变逻辑流程的前提下,我真的看不出来。
Eyal Lev

检查这个代码运行正常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个字节
穆库尔·库马尔

1
1more字节用(ij)替换(i!= j),如果您要坚持使用c ++,那么至少要在一个位置定义所有int ...
Mukul Kumar

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);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.