ASCII-Art Zombie Invasion Simulation


13

Pour simuler une invasion de zombies, commencez par une grille #et représentant la carte:

##   ##
###   #
## ##  
  # ###
#  ####
  • # représente la terre.
  • représente l'eau.

Les zombies commencent à un point de la carte ...

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

... et se propager. %désigne une terre infectée par des zombies.

Cependant, les zombies ne savent pas nager . Ils peuvent se déplacer à travers les terres de la même manière qu'un roi se déplace aux échecs - une case dans n'importe quelle direction diagonale ou orthogonale:

!!!
!%!
!!!

À la fin de la simulation, certains terrains seront infectés par des zombies:

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

Votre tâche consiste à simuler l'invasion de zombies. Écrivez un programme (ou une fonction) qui prend en entrée une chaîne représentant l'état initial de la grille et deux nombres représentant les coordonnées du zombie initial. Le programme devrait sortir (ou retourner) l'état final de l'invasion.

Caractéristiques

  • Votre programme peut imprimer une nouvelle ligne de fin facultative.
  • Vous pouvez supposer que l'entrée sera au format correct (avec des espaces), avec un retour à la ligne facultatif.
  • Vous pouvez supposer que le zombie initial commencera sur terre et ne mourra pas immédiatement.
  • Il s'agit de , donc la réponse la plus courte (en octets) l'emporte.
  • -100% de bonus si votre code peut également résoudre le problème d'arrêt pour les machines de Turing arbitraires.
  • Votre programme doit gérer des largeurs de carte pouvant atteindre 50 caractères.

quel est le problème d'arrêt ?
Mukul Kumar

3
@MukulKumar en.wikipedia.org/wiki/Halting_problem . C'est une blague. Le problème de l'arrêt est impossible à résoudre.
Esolanging Fruit

1
on ne sait jamais: P
Mukul Kumar


1
Non, sérieusement, je porterais le bonus pour la solution du problème d'arrêt à -200%. La réponse le mériterait. :)
RudolfJelin

Réponses:



5

Kotlin, 283218 octets

Lambda sans nom (avec une fonction imbriquée, heh).

Golfé

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

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

Quelques octets enregistrés en passant à une solution récursive.


3
"zombies amusants": P
Esolanging Fruit

4

JavaScript (ES6), 144 octets

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

\nreprésente le caractère de nouvelle ligne littéral. Prend des coordonnées indexées 0.


2

Befunge, 324 323 octets

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

Essayez-le en ligne!

Explication

L'implémentation de cela dans Befunge a été un peu compliquée car nous sommes limités à 80x25 caractères de "mémoire" qui doivent être partagés avec le code source lui-même. L'astuce pour ajuster une carte 50x50 dans cette zone était d'aplatir la carte 2D en un tableau 1D avec deux emplacements de carte par octet. Ce tableau 1D est ensuite à nouveau enveloppé dans un tableau 2D afin qu'il puisse tenir dans la largeur de 80 caractères du champ de jeu Befunge.

L'algorithme d'infection commence par convertir les coordonnées initiales en un décalage dans le tableau 1D qu'il pousse sur la pile. La boucle principale prend une valeur de la pile et recherche l'état de la carte pour ce décalage. S'il s'agit d'un terrain non infecté, il est marqué comme infecté et huit nouveaux décalages sont poussés sur la pile (représentant le terrain tout autour de la position actuelle). Ce processus se poursuit jusqu'à ce que la pile soit vide.

Pour éviter d'avoir à vérifier les valeurs hors plage, la carte est stockée avec une bordure d'eau à un caractère sur tous les bords.


1

Pip , 59 octets

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

Fonction qui prend une chaîne multiligne, la ligne du zombie initial (indexé 0) et la colonne du zombie initial (indexée 0). Essayez-le en ligne!

Comment?

Parce que Pip a une indexation cyclique (généralement une bonne chose, mais mauvaise pour ce problème parce que nous ne voulons pas que les bords de la carte soient encapsulés), j'ai opté pour une solution de remplacement d'expression régulière.

Ya@?ntrouve l'index de la première nouvelle ligne (c.-à-d. la largeur de la grille) et le retire y.

(ac+b+b*Ya@?n):'%après avoir fait ce qui précède, calcule (width + 1) * row + col, c'est-à-dire c+b+b*y, et définit le caractère de cet index sur %.

L2*#aLoops 2*len(a)Times, ce qui nous donne suffisamment d'itérations pour que le remplissage de l'inondation se propage entièrement et assure que le nombre d'itérations est pair (c'est important).

.`#(.?.?.{`.y-1.`})?%`construit une expression régulière qui correspond à un #suivi d'un %, avec 0, largeur-1, largeur ou largeur + 1 caractères entre les deux. (Le .début fait. le regex correspond aux nouvelles lignes.) Ce regex correspond à l'une des configurations suivantes:

#  
 % 

 # 
 % 

  #
 % 

#% 

aR ... '%.@>_remplace les correspondances de cette expression régulière par le caractère %ajouté à .tous sauf le premier caractère @>de la correspondance _; bref, remplacer le# par %.

a:RV ...inverse cela et le réattribue a. Nous inversons parce que l'expression régulière ne correspond # qu'avant % dans la chaîne, pas après; mais lorsque la chaîne est inversée, après devient avant et nous pouvons le faire correspondre à la prochaine itération. C'est aussi pourquoi le nombre d'itérations doit être pair.

Une fois la boucle terminée, nous renvoyons simplement la valeur modifiée de a.


0

TSQL, 267 octets

Golfé:

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 @

Non 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 @

Essaye le


0

PHP, 209 189 188 183 octets

peut être jouable au golf

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;

Courir avec php -r '<code>' '<grid>' <y> <x>


0

J, 152 octets

Pas très bien joué au golf, je suis sûr qu'il existe un moyen de supprimer ces dernières structures de contrôle.

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]

Implémente un algorithme de remplissage d'inondation. La fonction g formate l'entrée dans un tableau de caractères avant d'appliquer f.

Notez que les coordonnées sont un peu bizarres:

0, 0

est le coin supérieur gauche. Augmenter la première coordonnée:

1, 0

Déplace la position vers le bas dans la direction y.

À part cela, les coordonnées sont normales.

Exemple:

    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.
%%   ##
%%%   #
%% %%  
  % %%%
#  %%%%
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.