ASCII-Art Zombie Invasion Simulation


13

หากต้องการจำลองการบุกรุกของซอมบี้ให้เริ่มจากตาราง#และแสดงแผนที่:

##   ##
###   #
## ##  
  # ###
#  ####
  • # หมายถึงที่ดิน
  • แสดงถึงน้ำ

ซอมบี้เริ่มต้นที่จุดบนแผนที่ ...

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

... และแพร่กระจาย %หมายถึงแผ่นดินที่ติดเชื้อจากซอมบี้

อย่างไรก็ตามซอมบี้ไม่สามารถว่ายน้ำได้ พวกมันสามารถเคลื่อนที่ข้ามฝั่งได้ในลักษณะเดียวกับที่กษัตริย์เคลื่อนไปในหมากรุกหนึ่งตารางในทิศทางทแยงมุมหรือมุมฉาก:

!!!
!%!
!!!

ในตอนท้ายของการจำลองดินแดนบางแห่งจะติดเชื้อซอมบี้:

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

งานของคุณคือการจำลองการบุกรุกของซอมบี้ เขียนโปรแกรม (หรือฟังก์ชั่น) ที่ใช้เป็นอินพุตสตริงที่แทนสถานะเริ่มต้นของกริดและตัวเลขสองตัวที่แทนพิกัดของซอมบี้เริ่มต้น โปรแกรมควรแสดงผล (หรือกลับ) สถานะสุดท้ายของการบุกรุก

ข้อมูลจำเพาะ

  • โปรแกรมของคุณอาจพิมพ์บรรทัดใหม่ต่อท้ายที่เป็นตัวเลือก
  • คุณสามารถสันนิษฐานว่าอินพุตจะอยู่ในรูปแบบที่ถูกต้อง (บุด้วยช่องว่าง) โดยมีบรรทัดใหม่ต่อท้ายที่เป็นตัวเลือก
  • คุณสามารถสันนิษฐานว่าซอมบี้เริ่มต้นจะเริ่มขึ้นบนบกและจะไม่ตายทันที
  • นี่คือดังนั้นคำตอบที่สั้นที่สุด (เป็นไบต์) ชนะ
  • -100% โบนัสหากรหัสของคุณสามารถแก้ปัญหาการหยุดชะงักสำหรับเครื่องทัวริงโดยพล
  • โปรแกรมของคุณควรรองรับความกว้างของบอร์ดสูงสุด 50 ตัวอักษร

ปัญหาการหยุดชะงักคืออะไร
Mukul Kumar

3
@MukulKumar en.wikipedia.org/wiki/Halting_problem มันเป็นเรื่องตลก ปัญหาการหยุดชะงักไม่สามารถแก้ไขได้
แยกผลไม้

1
คุณไม่มีทางรู้หรอก P
Mukul Kumar

1
ที่เกี่ยวข้อง: codegolf.stackexchange.com/questions/83808/flood-fill-a-2d-grid
Angs

1
ไม่อย่างจริงจังฉันจะยกโบนัสสำหรับวิธีการแก้ปัญหาที่หยุดชะงักไป -200% คำตอบก็สมควรได้รับมัน :)
RudolfJelin

คำตอบ:



5

Kotlin, 283 218 ไบต์

แลมบ์ดา Unnamed (พร้อมฟังก์ชันซ้อนกัน, เฮ้)

แข็งแรงเล่นกอล์ฟ

{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 ตัวที่จะต้องแชร์กับซอร์สโค้ดเอง เคล็ดลับในการปรับแผนที่ 50x50 ให้เหมาะกับพื้นที่นั้นคือการทำให้แผนที่ 2D แบนเป็นอาร์เรย์ 1D ที่มีตำแหน่งแผนที่สองตำแหน่งต่อไบต์ อาร์เรย์ 1D นี้จะถูกรวมเข้าไปในอาร์เรย์ 2D อีกครั้งเพื่อให้สามารถปรับความกว้างได้ 80 ตัวอักษรของสนามเด็กเล่น Befunge

อัลกอริทึมการติดเชื้อเริ่มต้นด้วยการแปลงพิกัดเริ่มต้นเป็นออฟเซ็ตในอาร์เรย์ 1D ซึ่งจะผลักลงบนสแต็ก วนรอบหลักใช้ค่าจากสแต็กและค้นหาสถานะแผนที่สำหรับออฟเซ็ตนั้น หากเป็นที่ดินที่ไม่มีการติดเชื้อจะมีการทำเครื่องหมายว่าติดเชื้อและมีการผลัก 8 ออฟเซ็ตใหม่ไปยังสแต็ก (แสดงถึงที่ดินโดยรอบตำแหน่งปัจจุบัน) กระบวนการนี้จะดำเนินต่อไปจนกว่าสแต็กจะว่างเปล่า

เพื่อหลีกเลี่ยงการตรวจสอบค่านอกช่วงแผนที่จะถูกจัดเก็บด้วยเส้นขอบน้ำหนึ่งอักขระรอบขอบทั้งหมด


1

Pip , 59 ไบต์

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

ฟังก์ชั่นที่ใช้สตริงหลายบรรทัดแถวของซอมบี้เริ่มต้น (ดัชนี 0) และคอลัมน์ของซอมบี้เริ่มต้น (ดัชนี 0) ลองออนไลน์!

อย่างไร?

เนื่องจาก Pip มีการจัดทำดัชนีตามวัฏจักร (โดยปกติจะเป็นสิ่งที่ดี แต่ไม่ดีสำหรับปัญหานี้เพราะเราไม่ต้องการให้ขอบของแผนที่ห่อ) ฉันจึงไปหาโซลูชันการเปลี่ยน regex

Ya@?nพบว่าดัชนีของการขึ้นบรรทัดใหม่ครั้งแรก (เช่นความกว้างของตาราง) และ yanks yมันเข้าไป

(ac+b+b*Ya@?n):'%หลังจากทำข้างต้นคำนวณ(width + 1) * row + colเช่นและชุดตัวอักษรที่ดัชนีที่c+b+b*y%

L2*#aวน2*len(a)ครั้งซึ่งทำให้เรามีการทำซ้ำมากพอสำหรับการเติมน้ำท่วมเพื่อเผยแพร่อย่างเต็มที่และทำให้แน่ใจว่าจำนวนการทำซ้ำนั้นเป็นเท่ากัน (นั่นสำคัญ)

.`#(.?.?.{`.y-1.`})?%`สร้าง regex ที่ตรงกับที่#ตามมาด้วย%มีทั้ง 0, ความกว้าง-1, ความกว้างหรือความกว้าง + 1 ตัวละครในระหว่าง ( .การเริ่มต้นทำ.ใน regex ตรงกับการขึ้นบรรทัดใหม่) regex ตรงกับการกำหนดค่าต่อไปนี้:

#  
 % 

 # 
 % 

  #
 % 

#% 

aR ... '%.@>_แทนที่การแข่งขันของ regex นี้กับตัวละครตัวนี้%ใช้ได้กับ.ทุกคน แต่ตัวอักษรตัวแรก@>ของการแข่งขัน_; ในระยะสั้นการแทนที่ด้วย#%

a:RV ...aหลีที่และกำหนดมันกลับไป เราย้อนกลับเพราะ regex จับคู่# มาก่อน %ในสตริงเท่านั้นไม่ใช่หลัง แต่เมื่อสตริงถูกย้อนกลับหลังจากกลายเป็นก่อนและเราสามารถจับคู่ในการทำซ้ำต่อไป นี่คือสาเหตุที่ต้องมีการวนซ้ำ

aหลังจากที่วงเสร็จแล้วเราก็กลับค่าการแก้ไขของ


0

TSQL, 267 ไบต์

แข็งแรงเล่นกอล์ฟ:

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.
%%   ##
%%%   #
%% %%  
  % %%%
#  %%%%
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.