ASCII-Art Zombie Invasion Simulation


13

Um eine Zombie-Invasion zu simulieren, beginnen Sie mit einem Raster #und stellen Sie die Karte dar:

##   ##
###   #
## ##  
  # ###
#  ####
  • # Land darstellt.
  • steht für Wasser.

Die Zombies starten an einem Punkt auf der Karte ...

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

... und sich ausbreiten. %bezeichnet von Zombies infiziertes Land.

Allerdings Zombies können nicht schwimmen . Sie können sich auf die gleiche Weise über Land bewegen, wie sich ein König im Schach bewegt - ein Feld in einer beliebigen diagonalen oder orthogonalen Richtung:

!!!
!%!
!!!

Am Ende der Simulation wird ein Teil des Landes mit Zombies infiziert:

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

Ihre Aufgabe ist es, die Zombie-Invasion zu simulieren. Schreiben Sie ein Programm (oder eine Funktion), das eine Zeichenfolge als Eingabe verwendet, die den Anfangszustand des Gitters darstellt, und zwei Zahlen, die die Koordinaten des Anfangszombies darstellen. Das Programm sollte den Endzustand der Invasion ausgeben (oder zurückgeben).

Spezifikationen

  • Ihr Programm druckt möglicherweise eine optionale abschließende Newline.
  • Sie können davon ausgehen, dass die Eingabe im richtigen Format erfolgt (mit Leerzeichen aufgefüllt), mit einer optionalen nachgestellten Newline.
  • Sie können davon ausgehen, dass der erste Zombie an Land startet und nicht sofort stirbt.
  • Das ist , also gewinnt die kürzeste Antwort (in Bytes).
  • -100% Bonus, wenn Ihr Code auch das Halteproblem für beliebige Turing-Maschinen lösen kann .
  • Ihr Programm sollte Kartenbreiten von bis zu 50 Zeichen unterstützen.

was Halteproblem ?
Mukul Kumar

3
@MukulKumar en.wikipedia.org/wiki/Halting_problem . Es ist ein Witz. Das Halteproblem ist unmöglich zu lösen.
Esolanging Fruit

1
du weißt nie: P
Mukul Kumar


1
Nein, im Ernst, ich würde den Bonus für die Lösung des Problems auf -200% erhöhen. Die Antwort würde es verdienen. :)
RudolfJelin

Antworten:



5

Kotlin, 283.218 Bytes

Unbenanntes Lambda (mit einer verschachtelten Funktion, heh).

Golf gespielt

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

Ungolfed

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
}

Durch den Wechsel zu einer rekursiven Lösung wurden einige Bytes eingespart.


3
"Fun Zombies": P
Esolanging Fruit

4

JavaScript (ES6), 144 Byte

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

Wobei \ndas wörtliche Zeilenumbruchzeichen darstellt. Nimmt 0-indizierte Koordinaten.


2

Befunge, 324 323 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+,\

Probieren Sie es online!

Erläuterung

Die Implementierung in Befunge war etwas kompliziert, da der "Speicher" auf 80 x 25 Zeichen begrenzt ist, der mit dem Quellcode selbst geteilt werden muss. Der Trick beim Einpassen einer 50x50-Karte in diesen Bereich bestand darin, die 2D-Karte in ein 1D-Array mit zwei Kartenpositionen pro Byte zu reduzieren. Dieses 1D-Array wird dann erneut in ein 2D-Array eingebunden, sodass es in die Breite von 80 Zeichen des Befunge-Spielfelds passt.

Der Infektionsalgorithmus konvertiert zunächst die Anfangskoordinaten in einen Versatz im 1D-Array, den er auf den Stapel schiebt. Die Hauptschleife entnimmt einen Wert aus dem Stapel und sucht den Kartenstatus für diesen Versatz. Wenn es sich um nicht infiziertes Land handelt, wird es als infiziert markiert, und acht neue Offsets werden auf den Stapel geschoben (wobei das Land um die aktuelle Position herum dargestellt wird). Dieser Vorgang wird fortgesetzt, bis der Stapel leer ist.

Um zu vermeiden, dass auf Werte außerhalb des Bereichs geprüft werden muss, wird die Karte mit einem einstelligen Wasserrahmen an allen Rändern gespeichert.


1

Pip , 59 Bytes

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

Eine Funktion, die eine mehrzeilige Zeichenfolge, die Zeile des anfänglichen Zombies (0-indiziert) und die Spalte des anfänglichen Zombies (0-indiziert) enthält. Probieren Sie es online!

Wie?

Da Pip eine zyklische Indizierung hat (normalerweise eine gute Sache, aber für dieses Problem eine schlechte, weil die Kartenränder nicht umbrochen werden sollen), habe ich mich für eine Regex-Ersatzlösung entschieden.

Ya@?nFindet den Index der ersten neuen Zeile (dh die Breite des Gitters) und zieht ihn hinein y.

(ac+b+b*Ya@?n):'%Berechnet (width + 1) * row + col, dh c+b+b*yund setzt das Zeichen an diesem Index auf% .

L2*#a Schleifen 2*len(a) , die uns genügend Iterationen geben, damit sich die Flutfüllung vollständig ausbreitet, und sicherstellen, dass die Iterationszahl gleichmäßig ist (das ist wichtig).

.`#(.?.?.{`.y-1.`})?%`Erstellt einen regulären Ausdruck, der mit einem #gefolgt von einem %Zeichen (entweder 0, width-1, width oder width + 1) übereinstimmt . (Die .am Anfang .im regulären Ausdruck vorgenommenen Anpassungen entsprechen Zeilenumbrüchen.) Dieser reguläre Ausdruck entspricht einer der folgenden Konfigurationen:

#  
 % 

 # 
 % 

  #
 % 

#% 

aR ... '%.@>_ersetzt Matches dieses regex mit dem Charakter %zu voran .alle , aber dem ersten Zeichen @>des Spiels _; kurz gesagt, ersetzen die #mit %.

a:RV ...kehrt das um und weist es wieder zu a. Wir kehren um, weil der reguläre Ausdruck nur vorher passt# % und nicht nachher in der Zeichenfolge . Wenn die Zeichenfolge umgekehrt wird, wird after zu before und wir können sie bei der nächsten Iteration abgleichen. Dies ist auch der Grund, warum die Anzahl der Iterationen gerade sein muss.

Nachdem die Schleife abgeschlossen ist, geben wir einfach den geänderten Wert von zurück a.


0

TSQL, 267 Bytes

Golf gespielt:

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 @

Ungolfed:

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 @

Versuch es


0

PHP, 209 189 188 183 Bytes

kann golf sein

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;

Laufen Sie mit php -r '<code>' '<grid>' <y> <x>


0

J, 152 Bytes

Ich bin mir sicher, dass es keinen Weg gibt, die letzten Kontrollstrukturen zu entfernen.

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]

Implementiert einen Flood-Fill-Algorithmus. Die Funktion g formatiert die Eingabe in ein Zeichenfeld, bevor f angewendet wird.

Beachten Sie, dass Koordinaten etwas seltsam sind:

0, 0

ist die obere linke Ecke. Erhöhen der ersten Koordinate:

1, 0

Verschiebt die Position in y-Richtung nach unten.

Ansonsten sind die Koordinaten normal.

Beispiel:

    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.
%%   ##
%%%   #
%% %%  
  % %%%
#  %%%%
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.