มาสร้างแผนที่ของดันเจี้ยนกันเถอะ


9

นานมาแล้วเมื่อฉันใช้เวลาในการเล่นเกม RPG มากขึ้นหนึ่งในปัญหาที่ผู้เล่นบางคนมีคือการติดตามความเคลื่อนไหวของปาร์ตี้และวาดแผนที่ที่เหมาะสม ดังนั้นฉันจึงมีความคิดเพื่อตรวจสอบว่าพวกคุณจัดการกับปัญหานี้อย่างไร

ภารกิจคือการเขียนฟังก์ชั่นซึ่งใช้เป็นรายการพารามิเตอร์อินพุตของทิศทาง (ผ่านเป็นโครงสร้างที่คุณเลือก) ^v<>, แสดงแผนที่ของดันเจี้ยน ในตัวอย่างสำหรับอินพุต: >>>vvv<<<^^^เอาต์พุตจะเป็น:

+----+               +----+
|    |               |>>>v|
| ++ |               |^++v|
| ++ |  because      |^++v|
|    |               |^<<<|
+----+               +----+

Testcases

>>>>>>vvvvv<<<<^^^>>v



 +-------+
 |       |
 +-+---+ |
   |   | |
   | + | |
   | +-+ |
   |     |
   +-----+


^^^^^vvv<<<^^vv>>>>>>>>vv>><<^^^^v>>>>v^<^

          +-+ 
       +-+| | +-++-+
       | || | | ++ ++
       | ++ +-+     |
       |        +-+ |
       +--+ +-+ +-+-+
          | | |   |
          +-+ +---+

เพราะมันเป็นความท้าทายของรหัสกอล์ฟรหัสที่สั้นที่สุดชนะ

มีความสุขในการเล่นกอล์ฟ

แก้ไข ขออภัยการแก้ไขล่าช้าฉันไม่ได้มีเวลามากเมื่อเร็ว ๆ นี้

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

มีสามสัญลักษณ์ที่ใช้ได้ในแผนที่:

  • | ผนังแนวตั้ง
  • | ผนังแนวนอน
  • + จุดตัดของผนังในแนวตั้งและแนวนอน

ความยาวสูงสุดของพา ธ คือ 255 อักขระ (แต่ถ้าทำได้โปรดอย่า จำกัด ตัวเอง)

กรณีทดสอบเพิ่มเติม:

 ><><><><

 +--+
 |  |
 +--+

 >^<v

 +--+
 |  |
 |  |
 +--+

ฉันหวังว่าตอนนี้ทุกอย่างชัดเจน


3
คุณต้องให้คำอธิบายของงาน กรณีทดสอบสองกรณีไม่ได้รับการจัดการในลักษณะที่สอดคล้องกัน - กรณีแรกเพิ่มพื้นที่ที่ถูกตัดการเชื่อมต่อโดยไม่มีเหตุผลที่ชัดเจน
feersum

3
ตัวอย่างที่สองของคุณมีห้องที่ปิดซึ่งตอนแรกฉันคิดว่าเป็นเพราะขอบด้านนอกควรเป็นรูปสี่เหลี่ยมผืนผ้า แต่แล้วตัวอย่างที่สามจะหักล้างความคิดนั้น โปรดใช้Sandboxเพื่อรับข้อเสนอแนะเกี่ยวกับการท้าทายก่อนโพสต์
El'endia Starman

2
ยอดเยี่ยม ฉันยังคงแนะนำให้มีความชัดเจนเกี่ยวกับวิธีการสร้างดันเจี้ยนจากการเคลื่อนไหว
El'endia Starman

1
"display map" หมายถึงอะไร อนุญาตให้ส่งคืนแผนที่จากฟังก์ชันที่อนุญาตหรือไม่
พอลชมิทซ์

3
มันดูน่าสนใจ มีโอกาสที่จะแก้ไขเพื่อให้เปิดขึ้นอีกครั้งหรือไม่ สิ่งที่ต้องดูเป็นพิเศษ: จากตัวอย่างดูเหมือนว่าคุณไม่สนใจช่องว่างพิเศษรอบ ๆ เอาต์พุต แต่มันก็เป็นการดีที่จะชี้แจง นอกจากนี้หากคุณอธิบายลักษณะผนังอย่างชัดเจนและตอบคำถามของนมควรทำให้คำถามชัดเจนเพียงพอ สิ่งหนึ่งที่ผมคิดว่าคุณยังไม่ได้รับการคุ้มครองเป็นสิ่งที่เอาท์พุทvvv>>^^^<<จะผลิต (ข้ามท่อ?)
เดฟ

คำตอบ:


3

Javascript (ES6), 261 254 243 ไบต์

s=>{v=Array(w=32);p=526;b=n=>v[n>>5]&(1<<(n&31));B=(n,i)=>b(p+n)|b(p-n)?i:0;[...0+s].map(c=>v[(p+=[0,1,-1,w,-w]['0><v^'.indexOf(c)])>>5]|=1<<(p&31));for(z='',p=0;p<w*w;z+=' |-+'[b(p)?0:B(1,1)|B(w,2)||B(31,3)|B(33,3)],p++%w||(z+=`
`));return z}

JSFiddle


คุณสามารถลบreturnโดยแทนที่;ด้วย,และ{}ด้วย()
Cyoce

@Cyoce - มีforวงวนอยู่ในนั้นซึ่งไม่สามารถฝังในแบบนั้นได้
Arnauld

จากนั้นแทนที่{ด้วยeval("และ}ด้วย")เพื่อลบcodegolf.stackexchange.com/a/80967/41042 ออก
Cyoce

@Cyoce - แต่น่าเสียดายที่ฉันคิดว่าฉันต้องหลบหนีจากการระบาดของตัวอักษรราวกับ'\\n'ว่าฉันทำเช่นนั้น หากฉันนับถูกต้องสิ่งนั้นจะนำไปสู่ ​​+1 ไบต์ หรือมีวิธีที่ดีกว่าในการฝัง linebreak ใน eval?
Arnauld

คุณต้องการเพียงอย่างเดียว\nเนื่องจากสตริงเทมเพลตรองรับบรรทัดใหม่ตามตัวอักษร แต่มันจะยังคงอยู่ที่จำนวนไบต์เดียวกัน โอ้ดี
Cyoce

3

C, 246 ไบต์

n,y,*g,*p;main(c,v)char**v;{for(n=c*2+3,g=calloc(n*n,8),p=g+(n+1)*(c+1);c--;y=*v[c],p-=(y>70?n:1)*(y%5%4?-1:1))*p=1;for(y=n-1;--y;)for(c=n-1;c--;putchar(c?" |-++|-+"[*p?0:p[1]|p[-1]|(p[n]|p[-n])*2|(p[1+n]|p[1-n]|p[n-1]|p[-n-1])*4]:10))p=g+y*n+c;}

ใช้อินพุตเป็นอักขระแยกตัวอย่างเช่น:

./mapper '>' '>' '>' 'v' 'v' 'v' '<' '<' '<' '^' '^' '^'

หรือสะดวกยิ่งขึ้นรูปแบบ (ไม่ต้องใส่เครื่องหมาย!)

./mapper $(echo '>>>vvv<<<^^^' | fold -w1)

หรือสำหรับอินพุตแบบสุ่ม (ไม่มีประสิทธิภาพ)

./mapper $(LC_CTYPE=C tr -dc '0-3' < /dev/urandom | tr '0123' '<>^v' | head -c 10 | fold -w1)

และสุดท้ายการใช้awkการครอบตัดผลลัพธ์หมายความว่าเราสามารถใหญ่ขึ้นได้มาก:

./mapper $(LC_CTYPE=C tr -dc '0-3' < /dev/urandom | tr '0123' '<>^v' | head -c 500 | fold -w1) | awk '/[^ ]/{l=match($0,"\\+");if(l&&(l<L||!L))L=l;v[i++]=$0}END{for(;j<i;){l=v[j++];print substr(l,L,match(l," *$")-L)}}'

 +-----+
 |     |
 |     +-+  +-----+
 |       |+-+     |
++       +|      ++
|         |      |
|         +      +-+
+--+               |
 +-+               +--+
 |     ++             |
 +-+  +-++           +-+
   ++   |+--+          |
    +-+ | |        ++  |
     ++ | ++   + +--+ ++
     |  |  +---|      |
     |  |     ++  +---+
     ++ |-+   |   |
      | | +--+-+  |
      | +    +    |
      |        +--+
      +--------+

ส่งออกไปยัง stdout ใช้ข้อเท็จจริงที่อนุญาตให้มีการเสริมรอบแผนที่ (สร้างแผนที่ที่มีความยาวขอบ 2 * n + 1 วางตำแหน่งสุดท้ายตรงกลาง)

ทำให้พังถล่ม

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

n,                                  // Size of internal grid
y,                                  // Loop counter / current character
*g,                                 // Internal grid memory
*p;                                 // Current working pointer
main(c,v)char**v;{                  // K&R style function declaration
    for(                            // Step 1: identify visited cells
        n=c*2+3,                    //  Set output grid size
        g=calloc(n*n,8),            //  Allocate map storage space
        p=g+(n+1)*(c+1);            //  Start at centre
        c--;                        //  Loop over directions in reverse
        y=*v[c],                    //  Get current direction
        p-=(y>70?n:1)*(y%5%4?-1:1)  //  Move in reverse
    )*p=1;                          //  Mark cell visited
    for(y=n-1;--y;)                 // For each row (except edges)
        for(c=n-1;c--;              //   For each column (except edges, +1 for \n)
            putchar(c?" |-++|-+"[   //   Print wall using lookup table
                *p?0:p[1]|p[-1]|(p[n]|p[-n])*2|(p[1+n]|p[1-n]|p[n-1]|p[-n-1])*4
            ]:10)                   //   Or newline
        )p=g+y*n+c;                 //   Set current cell (happens first)
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.