ASCII艺术僵尸入侵模拟


13

要模拟僵尸入侵,请从#代表地图的网格开始:

##   ##
###   #
## ##  
  # ###
#  ####
  • # 代表土地。
  • 代表水。

僵尸始于地图上的某个点。

##   ##
###   #
## %#  
  # ###
#  ####

...并传播。%表示被僵尸感染的土地。

但是,僵尸不会游泳。他们可以像国王下象棋一样在陆地上移动-在任何对角线或正交方向上都是一个正方形:

!!!
!%!
!!!

在模拟结束时,一些土地将被僵尸感染:

%%   ##
%%%   #
%% %%  
  % %%%
#  %%%%

您的任务是模拟僵尸入侵。编写一个程序(或函数),该程序将代表网格初始状态的字符串和代表初始僵尸坐标的两个数字作为输入。程序应输出(或返回)入侵的最终状态。

技术指标

  • 您的程序可能会打印可选的尾随换行符。
  • 您可以假定输入将采用正确的格式(用空格填充)以及可选的尾随换行符。
  • 您可以假设最初的僵尸将在陆地上开始并且不会立即死亡。
  • 这是,因此最短的答案(以字节为单位)获胜。
  • 如果您的代码还可以解决任意图灵机的暂停问题,则可获得-100%的奖励。
  • 您的程序应处理的木板宽度最多为50个字符。

什么是暂停问题
Mukul Kumar

3
@MukulKumar en.wikipedia.org/wiki/Halting_problem。开个玩笑。停止问题是无法解决的。
硕果累累

1
你永远不会知道:P
Mukul Kumar


1
不,认真的说,我将停止问题解决方案的奖金提高到-200%。答案是应该的。:)
RudolfJelin

Answers:



5

Kotlin,283218字节

未命名的lambda(具有嵌套功能,呵呵)。

打高尔夫球

{i:String,x:Int,y:Int->val m=i.lines().map{it.toCharArray()};fun v(x:Int,y:Int){try{if(m[y][x]=='#'){m[y][x]='%';for(c in-1..1)for(d in-1..1)if(!(c==0&&d==0))v(x+c,y+d)}}catch(e:Exception){}};v(x, y);m.map(::println)}

不打高尔夫球

fun zombies(input: String, startX: Int, startY: Int) {
    val m = input.lines().map(String::toCharArray)      // build game map
    fun invade(x: Int, y: Int) {                        // nested functions, woo!
        try {
            if (m[y][x] == '#') {                       // if land
                m[y][x] = '%'                           // mark as invaded
                for (dx in -1..1) {                      // generate neighbour tiles
                    for (dy in -1..1) {
                        if (!(dx == 0 && dy == 0)) {
                            invade(x + dx, y + dy)        // attempt to invade neighbours
                        }
                    }
                }
            }
        } catch(e: Exception) {}                        // catches ArrayIndexOutOfBounds
    }

    invade(startX, startY)                              // start the invasion
    m.map(::println)                                    // print final state
}

通过切换到递归解决方案,节省了很多字节。


3
“有趣的僵尸”:P
硕果累累

4

JavaScript(ES6),144个字节

(s,x,y,l=s.search`\n`,g=s=>s==(s=s.replace(eval(`/(#|%)(.?[^]{${l-1}}.?)?(?!\\1)[#%]/`),`%$2%`))?s:g(s))=>g(s.slice(0,x+=y*l)+`%`+s.slice(x+1))

其中\n代表文字换行符。取0索引坐标。


2

Befunge,324个 323字节

&00p&10p20p~$v<p02+g02*!g02:+1$$$$<
 #<%>\"P"/8+p>1+:::~:0`!#v_:85+`!#^_2%\2%3*1+*\2/:"P"%\"P"/8+g+\2/:"P"
:+**73"="+g00*g02g010$$$$<v
02:\-<v/"P"\%"P":/2::_|#:$<:+1+g02\+g02:\-1+g02:\+1:\-1:\+1-g
\:20g^>g:30p\2%3*1+/4%1->#^_::2%6*2+30g+\2/:"P"%\"P"/p:20g-1-
0<v2\g+8/"P"\%"P":/2::<\_@#`0:-g
2^>%3*1+/4%1g,1+:20g%#^_1+55+,\

在线尝试!

说明

在Befunge中实施此操作有点复杂,因为我们只能将80x25个字符的“内存”与源代码本身共享。将50x50映射适合到该区域的技巧是将2D映射展平为一个1D数组,每个字节有两个映射位置。然后,将该1D数组再次包装为2D数组,使其可以适合Befunge运动场的80个字符的宽度。

感染算法首先将初始坐标转换为一维数组中的偏移量,然后将其推入堆栈。主循环从堆栈中获取一个值,并查找该偏移量的映射状态。如果它是未感染的土地,则将其标记为已感染,并将八个新的偏移量推入堆栈(代表当前位置周围的所有土地)。该过程一直持续到堆栈为空。

为了避免必须检查超出范围的值,该地图在所有边缘周围都带有一个字符的水边框。


1

,59字节

{(ac+b+b*Ya@?n):'%L2*#aa:RVaR.`#(.?.?.{`.y-1.`})?%`'%.@>_a}

该函数采用多行字符串,初始僵尸的行(索引为0)和初始僵尸的列(索引为0)。在线尝试!

怎么样?

因为Pip具有循环索引(通常是一件好事,但是对这个问题不利,因为我们不想包装地图边缘),因此我寻求了正则表达式替换解决方案。

Ya@?n找到第一条换行符的索引(即网格的宽度)并将其拉入y

(ac+b+b*Ya@?n):'%完成上述操作后,计算(width + 1) * row + colc+b+b*y并将该索引处的字符设置为%

L2*#a循环2*len(a)时间,这使我们有足够的迭代次数来完全填充洪水,并确保迭代次数是偶数(这很重要)。

.`#(.?.?.{`.y-1.`})?%`构造一个匹配#后跟a的正则表达式,%介于0,width-1,width或width + 1个字符之间。(该.开头使.regex匹配换行符。)此regex匹配以下任何配置:

#  
 % 

 # 
 % 

  #
 % 

#% 

aR ... '%.@>_用除匹配的第一个字符外的所有字符%前面的字符替换此正则表达式的匹配; 总之,替换用。.@>_#%

a:RV ...将其反转并将其分配回a。我们扭转,因为正则表达式只匹配# 之前 %的字符串,而不是之后; 但是当字符串反转时,之后变为之前,我们可以在下一次迭代中将其匹配。这也是为什么迭代次数必须是偶数的原因。

循环完成后,我们只需返回的修改值a


0

TSQL,267个字节

打高尔夫球:

USE master
DECLARE @ varchar(max)=
'##   ##
###   #
## %#  
  # ###
#  ####'

WHILE @@rowcount>0WITH C as(SELECT x+1i,substring(@,x+1,1)v,x/z r,x%z c
FROM spt_values CROSS APPLY(SELECT number x,charindex(char(10),@)z)z
WHERE type='P'and x<len(@))SELECT @=stuff(@,d.i,1,'%')FROM C,C D
WHERE'#%'=d.v+c.v and abs(c.r-d.r)<2and abs(c.c-d.c)<2PRINT @

取消高尔夫:

USE master-- the script needs to be executed on the default master database
DECLARE @ varchar(max)=
'##   ##
###   #
## %#  
  # ###
#  ####'

WHILE @@rowcount>0
WITH C as
(
  SELECT x+1i,substring(@,x+1,1)v,x/z r,x%z c
  FROM
    spt_values
  CROSS APPLY(SELECT number x,charindex(char(10),@)z)z
  WHERE type='P'and x<len(@)
)
SELECT @=stuff(@,d.i,1,'%')FROM C,C D
WHERE'#%'=d.v+c.v and abs(c.r-d.r)<2and abs(c.c-d.c)<2

PRINT @

试试看


0

PHP,209个 189 188 183字节

可能是高尔夫球

for($w=strpos($s=($a=$argv)[1],10),$s[$a[2]*++$w+$a[3]]="%";$t<$s;)for($t=$s,$i=0;""<$c=$s[$i++];)if($c>"$")for($y=-2;++$y<2;)for($x=3;$x--;)$s[$p=$i+$y*$w-$x]>"!"?$s[$p]="%":0;echo$s;

与运行 php -r '<code>' '<grid>' <y> <x>


0

J,152字节

打高尔夫球不太好,我敢肯定有一种方法可以删除最后几个控制结构。

f=:4 :0
c=.(' '"_)`({~&<y)@.((*./y<$x)*.*./y>:0 0)x if.c='#' do.x=.'%'(<y)}x[i=.0 while.i<9 do.i=.>:i[x=.x f y+i<:@(|~,<.@%)3 end.end.x
)
g=:>@cutLF@[f]

实现泛洪填充算法。函数g在应用f之前将输入格式化为字符数组。

注意,坐标有点奇怪:

0, 0

是左上角。增加第一个坐标:

1, 0

沿y方向向下移动位置。

除了那个坐标是正常的。

例:

    land =: 0 : 0    NB. Define a multi-line string
##   ##
###   #
## ##  
  # ###
#  ####
)

    ] l =. >@cutLF land    NB. Cut 'land' on new lines, and form into an array. Assign to 'l'
##   ##
###   #
## ##  
  # ###
#  ####
    NB. Looks the same, but it isn't.

    '%' (<2 3)} l    NB. 'Infect' the land at 2, 3
##   ##
###   #
## %#  
  # ###
#  ####

    l f 2 3    NB. Flood fill on l (already formatted), starting at 2 3
%%   ##
%%%   #
%% %%  
  % %%%
#  %%%%

    land g 2 3    NB. Flood fill on land, formats for us.
%%   ##
%%%   #
%% %%  
  % %%%
#  %%%%
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.