ASCII-Art Zombie Invasion Simulation


13

Чтобы симулировать вторжение зомби, начните с сетки #и представляющей карту:

##   ##
###   #
## ##  
  # ###
#  ####
  • # представляет землю.
  • представляет воду.

Зомби начинаются в точке на карте ...

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

... и распространяться. %обозначает землю, зараженную зомби.

Однако зомби не умеют плавать . Они могут перемещаться по земле так же, как король в шахматах - один квадрат в любой диагонали или ортогональном направлении:

!!!
!%!
!!!

В конце симуляции некоторые земли будут заражены зомби:

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

Ваша задача - симулировать вторжение зомби. Напишите программу (или функцию), которая принимает в качестве входных данных строку, представляющую начальное состояние сетки, и два числа, представляющие координаты исходного зомби. Программа должна вывести (или вернуть) окончательное состояние вторжения.

Характеристики

  • Ваша программа может распечатать дополнительный завершающий перевод строки.
  • Вы можете предположить, что ввод будет в правильном формате (дополненный пробелами), с дополнительным завершающим переводом строки.
  • Вы можете предположить, что начальный зомби начнется на земле и не умрет немедленно.
  • Это , поэтому выигрывает самый короткий ответ (в байтах).
  • Бонус -100%, если ваш код также может решить проблему остановки для произвольных машин Тьюринга.
  • Ваша программа должна обрабатывать доски шириной до 50 символов.

в чем проблема остановки ?
Мукул Кумар

3
@MukulKumar en.wikipedia.org/wiki/Halting_problem . Это шутка. Проблему остановки невозможно решить.
Esolanging Fruit

1
Вы никогда не знаете: P
Мукул Кумар


1
Нет, серьезно, я бы поднял бонус за решение проблемы остановки до -200%. Ответ заслуживает этого. :)
РудольфДжелин

Ответы:



5

Котлин, 283 218 байт

Безымянная лямбда (с вложенной функцией, хе).

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

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
}

Сохранено немало байтов путем переключения на рекурсивное решение.



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 символами «памяти», которые должны использоваться совместно с самим исходным кодом. Хитрость в размещении карты 50х50 в этой области заключалась в том, чтобы сгладить 2D-карту в одномерный массив с двумя местоположениями карты на байт. Этот 1D массив затем снова оборачивается в 2D массив, чтобы он мог уместиться в 80 символов ширины игрового поля Befunge.

Алгоритм заражения начинается с преобразования начальных координат в смещение в массиве 1D, которое он помещает в стек. Основной цикл берет значение из стека и ищет состояние карты для этого смещения. Если это неинфицированная земля, она помечается как зараженная, и в стек помещается восемь новых смещений (представляющих землю вокруг текущей позиции). Этот процесс продолжается до тех пор, пока стек не станет пустым.

Чтобы избежать необходимости проверки значений вне диапазона, карта хранится с водной границей из одного символа по всем краям.


1

Пип , 59 байт

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

Функция, которая принимает многострочную строку, строку исходного зомби (с 0 индексами) и столбец исходного зомби (с 0 индексами). Попробуйте онлайн!

Как?

Поскольку у Пипа есть циклическая индексация (обычно это хорошо, но плохо для этой проблемы, потому что мы не хотим, чтобы края карты были перенесены), я выбрал решение с заменой регулярных выражений.

Ya@?nнаходит индекс первой новой строки (то есть ширину сетки) и возвращает его в y.

(ac+b+b*Ya@?n):'%выполнив вышесказанное, вычисляет (width + 1) * row + col, т.е. c+b+b*yи устанавливает символ с этим индексом в %.

L2*#aпетли 2*len(a)раз, что дает нам достаточно итераций для заливки полностью распространяются и удостоверяется счетчик итераций даже (это важно).

.`#(.?.?.{`.y-1.`})?%`создает регулярное выражение, соответствующее a, #за которым следуют %0, ширина-1, ширина или ширина + 1 знак между ними. (В .начале .в регулярном выражении отображаются новые строки.) Это регулярное выражение соответствует любой из следующих конфигураций:

#  
 % 

 # 
 % 

  #
 % 

#% 

aR ... '%.@>_заменяет совпадения этого регулярного выражения на символ, %добавленный перед .всеми, кроме первого символа @>совпадения _; Короче говоря, заменяя #с %.

a:RV ...полностью изменяет это и назначает это назад a. Мы обращаемся к обратному, потому что регулярное выражение совпадает только # перед % строкой, а не после; но когда строка переворачивается, after становится before, и мы можем сопоставить ее на следующей итерации. Вот почему количество итераций должно быть четным.

После завершения цикла мы просто возвращаем измененное значение a.


0

TSQL, 267 байт

Golfed:

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 @

Попробуйте это


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.
%%   ##
%%%   #
%% %%  
  % %%%
#  %%%%
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.