ASCII-Art Zombie Invasion Simulation


13

Para simular una invasión zombie, comience con una cuadrícula de #y representando el mapa:

##   ##
###   #
## ##  
  # ###
#  ####
  • # representa la tierra
  • representa el agua

Los zombies comienzan en un punto del mapa ...

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

... y difundir. %denota tierra infectada por zombies.

Sin embargo, los zombis no pueden nadar . Pueden moverse a través de la tierra de la misma manera que un rey se mueve en el ajedrez: un cuadrado en cualquier dirección diagonal u ortogonal:

!!!
!%!
!!!

Al final de la simulación, algunas tierras estarán infectadas con zombies:

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

Tu tarea es simular la invasión zombie. Escriba un programa (o función) que tome como entrada una cadena que represente el estado inicial de la cuadrícula y dos números que representen las coordenadas del zombi inicial. El programa debe generar (o devolver) el estado final de la invasión.

Especificaciones

  • Su programa puede imprimir una nueva línea final opcional.
  • Puede suponer que la entrada estará en el formato correcto (rellenado con espacios), con una nueva línea final opcional.
  • Puedes asumir que el zombie inicial comenzará en tierra y no morirá de inmediato.
  • Este es el , por lo que gana la respuesta más corta (en bytes).
  • -100% de bonificación si su código también puede resolver el problema de detención para máquinas arbitrarias de Turing.
  • Su programa debe manejar anchos de tablero de hasta 50 caracteres.

¿ Cuál es el problema de detención ?
Mukul Kumar

3
@MukulKumar en.wikipedia.org/wiki/Halting_problem . Es una broma. El problema de detención es imposible de resolver.
Esolanging Fruit

1
nunca se sabe: P
Mukul Kumar


1
No, en serio, elevaría la bonificación por la solución del problema de detención a -200%. La respuesta lo merecería. :)
RudolfJelin

Respuestas:



5

Kotlin 283 218 bytes

Lambda sin nombre (con una función anidada, je).

Golfed

{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)}

Sin golf

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
}

Ahorró bastantes bytes al cambiar a una solución recursiva.


3
"zombies divertidos": P
Esolanging Fruit

4

JavaScript (ES6), 144 bytes

(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))

Donde \nrepresenta el carácter de nueva línea literal. Toma coordenadas indexadas 0.


2

Befunge, 324323 bytes

&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+,\

Pruébalo en línea!

Explicación

Implementar esto en Befunge fue un poco complicado porque estamos limitados a 80x25 caracteres de "memoria" que deben compartirse con el código fuente en sí. El truco para ajustar un mapa de 50x50 en esa área era aplanar el mapa 2D en una matriz 1D con dos ubicaciones de mapa por byte. Esta matriz 1D luego se envuelve en una matriz 2D nuevamente para que pueda caber en el ancho de 80 caracteres del campo de juego Befunge.

El algoritmo de infección comienza convirtiendo las coordenadas iniciales en un desplazamiento en la matriz 1D que empuja a la pila. El bucle principal toma un valor de la pila y busca el estado del mapa para ese desplazamiento. Si es tierra no infectada, se marca como infectada, y se introducen ocho nuevas compensaciones en la pila (que representan la tierra alrededor de la posición actual). Este proceso continúa hasta que la pila esté vacía.

Para evitar tener que buscar valores fuera de rango, el mapa se almacena con un borde de agua de un carácter alrededor de todos los bordes.


1

Pip , 59 bytes

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

Una función que toma una cadena multilínea, la fila del zombie inicial (0 indexado) y la columna del zombie inicial (0 indexado). Pruébalo en línea!

¿Cómo?

Debido a que Pip tiene indexación cíclica (generalmente algo bueno, pero malo para este problema porque no queremos que los bordes del mapa se ajusten), opté por una solución de reemplazo de expresiones regulares.

Ya@?nencuentra el índice de la primera línea nueva (es decir, el ancho de la cuadrícula) y lo extrae y.

(ac+b+b*Ya@?n):'%después de hacer lo anterior, calcula (width + 1) * row + col, es decir c+b+b*y, y establece el carácter en ese índice en %.

L2*#a2*len(a)tiempos de bucles , lo que nos proporciona suficientes iteraciones para que el relleno de inundación se propague completamente y asegura que el recuento de iteraciones sea uniforme (eso es importante).

.`#(.?.?.{`.y-1.`})?%`construye una expresión regular que coincide con un #seguido de a %, con 0, ancho-1, ancho o ancho + 1 caracteres en el medio. (El .principio hace que .la expresión regular coincida con las nuevas líneas). Esta expresión regular coincide con cualquiera de las siguientes configuraciones:

#  
 % 

 # 
 % 

  #
 % 

#% 

aR ... '%.@>_reemplaza las coincidencias de esta expresión regular con el carácter %antepuesto a .todos menos el primer carácter @>de la coincidencia _; en resumen, reemplazando el #con %.

a:RV ...invierte eso y lo asigna de nuevo a a. Revertimos porque la expresión regular solo coincide # antes % en la cadena, no después; pero cuando la cadena se invierte, after se convierte en before y podemos hacerla coincidir en la próxima iteración. Esta es también la razón por la cual el número de iteraciones tiene que ser par.

Una vez que se completa el ciclo, simplemente devolvemos el valor modificado de a.


0

TSQL, 267 bytes

Golfizado:

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 @

Sin golf:

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 @

Pruébalo


0

PHP, 209 189 188 183 bytes

puede ser golfable

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;

Corre con php -r '<code>' '<grid>' <y> <x>


0

J, 152 bytes

No muy bien golfizado, estoy seguro de que hay una manera de eliminar esas últimas estructuras de control.

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]

Implementa un algoritmo de relleno de inundación. La función g formatea la entrada en una matriz de caracteres antes de aplicar f.

Tenga en cuenta que las coordenadas son un poco raras:

0, 0

Es la esquina superior izquierda. Aumentando la primera coordenada:

1, 0

Mueve la posición hacia abajo en la dirección y.

Aparte de eso, las coordenadas son normales.

Ejemplo:

    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.
%%   ##
%%%   #
%% %%  
  % %%%
#  %%%%
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.