ASCII-Art Zombie Invasion Simulation

13

Aby zasymulować inwazję zombie, zacznij od siatki #i reprezentującej mapę:

##   ##
###   #
## ##  
  # ###
#  ####
  • # reprezentuje ziemię.
  • reprezentuje wodę.

Zombie zaczynają się w punkcie na mapie ...

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

... i się rozprzestrzeniają. %oznacza ziemię zainfekowaną zombie.

Jednak zombie nie mogą pływać . Mogą poruszać się po lądzie w taki sam sposób, w jaki król porusza się w szachach - jedno pole w dowolnym ukośnym lub prostopadłym kierunku:

!!!
!%!
!!!

Pod koniec symulacji część ziemi zostanie zainfekowana zombie:

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

Twoim zadaniem jest symulacja inwazji zombie. Napisz program (lub funkcję), który przyjmuje jako dane wejściowe ciąg reprezentujący początkowy stan siatki oraz dwie liczby reprezentujące współrzędne początkowego zombie. Program powinien wypisać (lub zwrócić) końcowy stan inwazji.

Dane techniczne

  • Twój program może wydrukować opcjonalny znak nowej linii.
  • Możesz założyć, że dane wejściowe będą miały poprawny format (wypełniony spacjami), z opcjonalnym końcowym znakiem nowej linii.
  • Możesz założyć, że początkowy zombie zacznie się na lądzie i nie umrze natychmiast.
  • To jest , więc wygrywa najkrótsza odpowiedź (w bajtach).
  • -100% bonusu, jeśli Twój kod może rozwiązać problem zatrzymania dla dowolnych maszyn Turinga.
  • Twój program powinien obsługiwać tablice o szerokości do 50 znaków.
Esolanging Fruit
źródło
co jest problemem zatrzymania ?
Mukul Kumar,
3
@MukulKumar en.wikipedia.org/wiki/Halting_problem . To żart. Problemu zatrzymania nie można rozwiązać.
Esolanging Fruit
1
nigdy nie wiadomo: P
Mukul Kumar
1
Nie, poważnie, podniosłbym premię za rozwiązanie problemu zatrzymania do -200%. Odpowiedź zasługuje na to. :)
RudolfJelin

Odpowiedzi:

1

APL (Dyalog) , 44 bajty

{{c'%'[⌊⌿'%#'∊¨⍵(c4⊃⍵)]}∘,⌺3 3⍣≡'%'@(⊂⍺)⊢⍵}

Wypróbuj online!

Zakłada ⎕IO←0.

Lewy argument: 0 r% indeksowany wiersz , 0% indeksowany kolumna c%: r c
Prawy argument: Matryca znaków

Erik the Outgolfer
źródło
5

Kotlin, 283 218 bajtów

Nienazwana lambda (z funkcją zagnieżdżoną, heh).

Grał w golfa

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

Nie golfił

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
}

Zaoszczędzono sporo bajtów, przechodząc na rozwiązanie rekurencyjne.

Tyler MacDonell
źródło
3
„fun zombie”: P
Esolanging Fruit
4

JavaScript (ES6), 144 bajty

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

Gdzie \nreprezentuje dosłowny znak nowej linii. Przyjmuje współrzędne 0-indeksowane.

Neil
źródło
2

Befunge, 324 323 bajty

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

Wypróbuj online!

Wyjaśnienie

Wdrożenie tego w Befunge było trochę skomplikowane, ponieważ jesteśmy ograniczeni do 80x25 znaków „pamięci”, które muszą być współdzielone z samym kodem źródłowym. Sztuczka polegająca na dopasowaniu mapy 50x50 w tym obszarze polegała na spłaszczeniu mapy 2D do tablicy 1D z dwoma lokalizacjami mapy na bajt. Ta tablica 1D jest następnie ponownie zawijana w tablicę 2D, aby zmieściła się na szerokości 80 znaków na polu gry Befunge.

Algorytm infekcji rozpoczyna się od konwersji początkowych współrzędnych na przesunięcie w tablicy 1D, którą wypycha na stos. Główna pętla pobiera wartość ze stosu i sprawdza stan mapy dla tego przesunięcia. Jeśli jest to niezainfekowana ziemia, zostaje oznaczona jako zainfekowana, a osiem nowych odsunięć jest wypychanych na stos (reprezentujących ziemię wokół bieżącej pozycji). Proces ten trwa, dopóki stos nie będzie pusty.

Aby uniknąć konieczności sprawdzania wartości spoza zakresu, mapa jest przechowywana z jednoznakową ramką wodną wokół wszystkich krawędzi.

James Holderness
źródło
1

Pip , 59 bajtów

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

Funkcja, która pobiera wielowierszowy ciąg, wiersz początkowego zombie (0-indeksowany) i kolumnę początkowego zombie (0-indeksowany). Wypróbuj online!

W jaki sposób?

Ponieważ Pip ma cykliczne indeksowanie (zwykle jest to dobra rzecz, ale złe dla tego problemu, ponieważ nie chcemy, aby krawędzie mapy się zawijały), wybrałem rozwiązanie zastępujące wyrażenia regularne.

Ya@?nznajduje indeks pierwszego nowego wiersza (tj. szerokość siatki) i ciągnie go do y.

(ac+b+b*Ya@?n):'%po wykonaniu powyższego oblicza (width + 1) * row + col, tj. c+b+b*yi ustawia znak pod tym indeksem na %.

L2*#a2*len(a)razy pętli , co daje nam wystarczającą liczbę iteracji, aby wypełnienie powodziowe mogło się w pełni rozprzestrzenić i zapewnia, że ​​liczba iteracji jest równa (to ważne).

.`#(.?.?.{`.y-1.`})?%`konstruuje wyrażenie regularne, #po którym następuje a %, z 0, szerokość-1, szerokość lub szerokość + 1 znaków pomiędzy. (Na .początku sprawia, .że wyrażenie regularne dopasowuje nowe wiersze.) To wyrażenie regularne pasuje do dowolnej z następujących konfiguracji:

#  
 % 

 # 
 % 

  #
 % 

#% 

aR ... '%.@>_zastępuje dopasowania tego wyrażenia regularnego znakiem %poprzedzającym .wszystko oprócz pierwszego znaku @>dopasowania _; w skrócie, zastępując #z %.

a:RV ...odwraca to i przypisuje z powrotem do a. Odwracamy, ponieważ regex pasuje tylko # przed % ciągiem, a nie po nim; ale gdy łańcuch jest odwrócony, po staje się przed i możemy dopasować go przy następnej iteracji. Dlatego też liczba iteracji musi być parzysta.

Po zakończeniu pętli po prostu zwracamy zmodyfikowaną wartość parametru a.

DLosc
źródło
0

TSQL, 267 bajtów

Gra w golfa:

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 @

Nie golfowany:

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 @

Wypróbuj to

t-clausen.dk
źródło
0

PHP, 209 189 188 183 bajtów

może być golfa

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;

Biegnij z php -r '<code>' '<grid>' <y> <x>

Tytus
źródło
0

J, 152 bajtów

Nie bardzo dobrze gra w golfa, jestem pewien, że istnieje sposób na usunięcie tych ostatnich struktur kontrolnych.

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]

Implementuje algorytm wypełniania zalania. Funkcja g formatuje dane wejściowe do tablicy znaków przed zastosowaniem f.

Pamiętaj, że współrzędne są nieco dziwne:

0, 0

to lewy górny róg. Zwiększenie pierwszej współrzędnej:

1, 0

Przesuwa pozycję w dół w kierunku y.

Poza tym współrzędne są normalne.

Przykład:

    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.
%%   ##
%%%   #
%% %%  
  % %%%
#  %%%%
Bolce Bussiere
źródło