ชีวิตคือเขาวงกต: เราใช้เส้นทางที่ผิดก่อนที่เราจะหัดเดิน


30

การป้อนข้อมูล:

เขาวงกตที่มีตัวละคร:

  • -- (ผนังแนวนอน);
  • | (ผนังแนวตั้ง);
  • + (การเชื่อมต่อ);
  • (พื้นที่เดิน);
  • I (ทางเข้า);
  • U (ออก)

เช่นอินพุตอาจมีลักษณะเช่นนี้:

 +--+--+--+--+--+--+--+--+--+--+ 
I               |     |        | 
 +  +--+--+--+  +  +  +  +--+  + 
 |           |     |  |  |     | 
 +--+--+--+  +--+--+  +  +  +--+ 
 |           |     |     |     | 
 +  +--+--+  +  +--+--+  +--+  + 
 |     |     |     |     |     | 
 +--+  +  +--+--+  +--+--+  +  + 
 |     |        |        |  |  | 
 +  +--+--+--+  +--+--+  +  +  + 
 |     |     |     |        |  | 
 +--+  +  +--+--+  +--+--+--+--+ 
 |  |  |                 |     | 
 +  +  +--+--+--+  +--+  +  +  + 
 |     |        |  |  |  |  |  | 
 +--+--+  +  +--+  +  +  +--+  + 
 |        |     |     |  |     | 
 +  +--+--+--+  +  +  +  +  +--+ 
 |           |     |  |         U
 +--+--+--+--+--+--+--+--+--+--+ 

เอาท์พุท:

มีประสิทธิภาพมากที่สุดเส้นทางที่คุณควรจะเดินจะได้รับจากทางเข้าทางออกของเขาวงกต (ผ่านเขาวงกต) แสดงโดยตัวละครที่ระบุซ้าย, ขวา, ขึ้นและลง (เช่น>; <; ^; v)

กฏท้าทาย:

  • คุณสามารถรับอินพุตในรูปแบบที่เหมาะสม String-array, String เดี่ยวที่มีบรรทัดใหม่, char-array 2D และอื่น ๆ ล้วนเป็นรูปแบบอินพุตที่เป็นไปได้ทั้งหมด
  • เอาต์พุตสามารถประกอบด้วยอักขระสี่ตัวที่แตกต่างกัน คือ><^v; →←↑↓; ⇒⇐⇑⇓; RLUD; 0123; ABCD; ฯลฯ )
  • คุณได้รับอนุญาตให้เพิ่มช่องว่างหรือต่อท้ายบรรทัดใหม่ไปยังเอาต์พุตหากต้องการ นี่เป็นทางเลือก
  • ขั้นตอนจะถูกนับต่อตาราง (ดูสี่+-symbols สำหรับช่องสี่เหลี่ยม) และไม่ใช่สำหรับแต่ละอักขระ
  • เขาวงกตมีขนาด 5x5 ถึง 15x15 และจะเป็นรูปสี่เหลี่ยมเสมอ (ดังนั้นจะไม่มีกรณีทดสอบใด ๆ สำหรับเขาวงกต 5x10)
  • คุณสามารถสันนิษฐานได้ว่าเขาวงกตทุกคนมีเส้นทางที่ถูกต้องตั้งแต่หนึ่งเส้นทางขึ้นไปตั้งแต่ต้นจนจบและคุณจะได้ผลลัพธ์ที่สั้นที่สุดเสมอ (ดูกรณีทดสอบ 4 และ 5)
  • หากมีหลายเส้นทางที่มีความยาวเท่ากันคุณสามารถเลือกเส้นทางที่จะส่งออก (ดูกรณีทดสอบ 6)
  • คุณไม่สามารถ 'เดิน' นอกขอบเขตของเขาวงกต (ดูกรณีทดสอบ 7 และ 8)

กฎทั่วไป:

  • นี่คือดังนั้นคำตอบที่สั้นที่สุดในหน่วยไบต์ชนะ
    อย่าปล่อยให้ภาษาโค้ดกอล์ฟกีดกันคุณจากการโพสต์คำตอบด้วยภาษาที่ไม่ได้เข้ารหัส พยายามหาคำตอบสั้น ๆ ที่เป็นไปได้สำหรับภาษาโปรแกรม 'ใด ๆ '
  • กฎมาตรฐานจะใช้สำหรับคำตอบของคุณดังนั้นคุณจึงได้รับอนุญาตให้ใช้ STDIN / STDOUT ฟังก์ชัน / เมธอดพร้อมพารามิเตอร์ที่เหมาะสมโปรแกรมเต็มรูปแบบ การโทรของคุณ
  • ช่องโหว่เริ่มต้นเป็นสิ่งต้องห้าม
  • หากเป็นไปได้โปรดเพิ่มลิงค์พร้อมทดสอบรหัสของคุณ
  • นอกจากนี้โปรดเพิ่มคำอธิบายหากจำเป็น

กรณีทดสอบ:

1. Input:
 +--+--+--+--+--+--+--+--+--+--+ 
I               |     |        | 
 +  +--+--+--+  +  +  +  +--+  + 
 |           |     |  |  |     | 
 +--+--+--+  +--+--+  +  +  +--+ 
 |           |     |     |     | 
 +  +--+--+  +  +--+--+  +--+  + 
 |     |     |     |     |     | 
 +--+  +  +--+--+  +--+--+  +  + 
 |     |        |        |  |  | 
 +  +--+--+--+  +--+--+  +  +  + 
 |     |     |     |        |  | 
 +--+  +  +--+--+  +--+--+--+--+ 
 |  |  |                 |     | 
 +  +  +--+--+--+  +--+  +  +  + 
 |     |        |  |  |  |  |  | 
 +--+--+  +  +--+  +  +  +--+  + 
 |        |     |     |  |     | 
 +  +--+--+--+  +  +  +  +  +--+ 
 |           |     |  |         U
 +--+--+--+--+--+--+--+--+--+--+ 

1. Output:
>v>>>vv<v>>v>v>>vvv>>>

2. Input:
 +--+--+--+--+--+ 
I   |        |  | 
 +  +--+--+  +  + 
 |        |  |  | 
 +  +--+  +  +  + 
 |  |  |     |  | 
 +  +  +--+  +  + 
 |        |     | 
 +--+  +  +--+--+ 
 |     |         U
 +--+--+--+--+--+ 

2. Output:
>vvv>>v>>>

3. Input:
 +--+--+--+--+--+ 
U      |        | 
 +  +  +--+--+  + 
 |  |     |     | 
 +--+--+  +  +--+ 
 |        |     | 
 +  +--+--+--+  + 
 |  |     |     | 
 +  +  +  +  +--+ 
 |     |         I
 +--+--+--+--+--+ 

3. Output:
<<<^<v<^^>>^<^<<

4. Input (test case with two valid paths):
 +--+--+--+--+--+ 
U      |        | 
 +  +  +--+--+  + 
 |  |           | 
 +--+--+  +  +--+ 
 |        |     | 
 +  +--+--+--+  + 
 |  |     |     | 
 +  +  +  +  +--+ 
 |     |         I
 +--+--+--+--+--+ 

4. Output:
<<^>^<^<<^<<     (<<<^<v<^^>>^<^<< is less efficient, and therefore not a valid output)

5. Input (test case with two valid paths):
                               I
+--+--+--+--+--+--+--+--+--+--+  +--+--+--+--+
|     |              |                    |  |
+  +  +  +--+--+--+  +  +--+--+  +--+--+  +  +
|  |     |        |     |        |     |     |
+--+--+--+  +--+  +  +--+--+--+--+  +--+--+--+
|     |  |  |  |     |     |           |     |
+  +  +  +  +  +--+  +  +  +  +--+--+  +--+  +
|  |        |        |  |     |        |     |
+  +--+--+--+  +--+--+  +  +--+  +--+--+  +--+
|  |     |     |        |  |     |     |     |
+  +--+  +  +--+  +--+--+  +--+--+  +  +--+  +
|  |     |        |     |           |        |
+  +  +--+--+--+--+  +  +--+--+--+  +--+  +--+
|     |     |        |        |  |     |     |
+--+--+--+  +  +--+--+  +--+  +  +--+  +--+  +
|              |     |     |        |  |  |  |
+  +--+--+--+--+  +  +  +--+--+--+  +  +  +  +
|     |  |     |  |  |        |        |  |  |
+--+  +  +  +  +  +  +--+--+  +  +  +--+  +  +
|     |     |  |  |  |           |  |     |  |
+--+  +--+--+  +  +  +  +--+--+--+  +  +  +  +
|     |        |  |  |     |        |  |  |  |
+  +--+  +--+--+  +  +--+--+  +  +--+  +  +  +
|        |     |  |     |     |  |     |  |  |
+--+--+--+  +  +  +--+  +  +--+--+  +--+  +  +
|  |        |        |     |        |     |  |
+  +  +--+--+--+--+  +--+--+  +--+--+  +--+  +
|  |              |              |     |     |
+  +  +  +--+--+--+--+--+--+--+--+  +--+  +--+
|     |                                |     |
+--+--+--+--+--+--+--+--+--+  +--+--+--+--+--+
                            U

5. Output:
v<<<v<vv<<v<v>>^>>^^>vvv>>>v>vv<vv<<v<v<^<^^^^<vvvvv<^<v<<v>v>>>>>>>v     (v<<<v<vv<<v<v>>^>>^^>vvv>>>v>vv<vv<<v<v<^<^^^^<vvvvv>v>>>^>>^>^^>vvv<v<v<<v is less efficient, and therefore not a valid output)

6. Input:
 +--+--+--+--+--+
I               |
 +  +  +  +  +  +
 |              |
 +  +  +  +  +  +
 |              |
 +  +  +  +  +  +
 |              |
 +  +  +  +  +  +
 |               U
 +--+--+--+--+--+

6. Output:
>>v>v>v>v> or >v>v>v>v>> or >>>>>vvvv> or etc. (all are equally efficient, so all 10-length outputs are valid)

7. Input:
 I  U
+  +  +--+--+--+
|  |        |  |
+  +--+--+  +  +
|     |     |  |
+--+  +  +--+  +
|        |  |  |
+  +--+  +  +  +
|     |        |
+--+  +--+--+  +
|     |        |
+--+--+--+--+--+

7. Output:
vv>v>^>^<<^

8. Input:
 +--+--+--+--+--+
 |     |        |
 +  +--+  +--+  +
I   |     |  |  |
 +  +  +--+  +  +
U   |     |  |  |
 +--+--+  +  +  +
 |     |     |  |
 +  +--+--+--+  +
 |               
 +--+--+--+--+--+

8. Output:
>v<

เขาสร้างขึ้นโดยใช้เครื่องมือนี้ (และในบางกรณีแก้ไขเล็กน้อย)


10
ฉันพบวิธีแก้ปัญหาที่สั้นกว่าสำหรับกรณีทดสอบครั้งที่สามแล้ว! v<<<<<<^^^^^(คิดนอกกรอบเสมอ)
Leo

2
ถ้าใครสามารถพิสูจน์ได้ว่ารหัสของพวกเขาจะให้ทางออกที่สั้นที่สุดให้เวลาและหน่วยความจำเพียงพอ แม้ในกรณีที่ใช้เวลานานมาก (สิ้นสุดของจักรวาลแฟชั่น)
Yytsi

1
@JackBates มันเป็นเรื่องตลก แท้จริงเขาเดินไปรอบ ๆ กล่องเพื่อออก: D
Yytsi

1
>v>>>vv<v>>v>v>>vvv>>>ผมคิดว่ากรณีการทดสอบครั้งแรกเป็นความผิดที่มันควรจะเป็น
smls

1
@KevinCruijssen ตัวอย่างเช่นโซลูชันที่ทดสอบแต่ละชุดของ "v ^ <>" สำหรับความยาวจนถึงจำนวนกล่องเปล่าภายในเขาวงกต ทางออกที่ถูกต้องจะอยู่ที่นั่น แต่ใช้เวลาในการคำนวณทางดาราศาสตร์
Yytsi

คำตอบ:


7

Retina , 338 281 275 273 261 ไบต์

¶U
¶&
+`·(\w.+)$
|$1
((.)+I.+¶.+¶(?<-2>.)+)·
$1v
+`((.)*)\+(.).*(¶(?<-2>.)*.)((\w)|·)·?
$1$4$.4$3$6
·v
-v
G`1
·U
&
{`\B·\d+.(\w+)
$1K$&
(\w+)·\d+.\B
$&$1r
(?<=\D\2.(\w+).+?¶.*\D(\d+)[·&])\B
$1v
)`\D(\d+).\B(?=.+¶.*\D\1·(\w+))
$&$2A
^.+\d·(\w+)
&$1A
M!`&\w+
I|&

ลองออนไลน์!


หมายเหตุ

  • เนื่องจากช่องว่างที่สำคัญช่องว่างทั้งหมด ( 0x20) จะถูกแทนที่ด้วย interpunct ( ·) ทั้งในคำตอบนี้และลิงก์ TIO โปรแกรมทำงานได้ดีหากมีการคืนพื้นที่
  • ใช้AvKrสำหรับขึ้นลงซ้ายและขวาตามลำดับ เหล่านั้นสามารถถูกแทนที่ด้วยใด ๆตัวอักษรIยกเว้น
  • ใช้เวลาประมาณ 40 วินาทีสำหรับ TIO สำหรับกรณีทดสอบ 15 × 15 ใจเย็น ๆ ทำใหม่ส่วนสำหรับการค้นหาเส้นทางที่สั้นที่สุดเมื่อเส้นทางมาถึงทางออก ปรากฎว่าใช้เวลามาก
  • สามารถแยกเขาวงกตที่มีความกว้าง 66 เซลล์ขึ้นไปได้อย่างสมบูรณ์ แต่สามารถจัดการเขาวงกตที่มีความสูงตามอำเภอใจได้ การแก้ไขความกว้างโดยพลการใช้เวลา +1 ไบต์

คำอธิบาย

โปรแกรมประกอบด้วย 3 ขั้นตอน:

  • ขั้นตอนการก่อสร้างการแปลงเขาวงกตในรูปแบบที่มีขนาดกะทัดรัดที่ง่ายต่อการทำงานร่วมกับ (รายละเอียดด้านล่าง)
  • เฟสเติมเพื่อแก้ปัญหาจริงเขาวงกตใช้วิธีเติมน้ำท่วม
  • ขั้นตอนการกลับมาจะกลับเส้นทางที่สั้นที่สุดที่ประตูทางออก

รูป

เนื่องจากรูปแบบเขาวงกตดั้งเดิมนั้นค่อนข้างไม่แน่นอนส่วนแรกของโปรแกรมจะแปลงเป็นรูปแบบอื่น

เซลล์

ในรูปแบบดั้งเดิมแต่ละเซลล์จะแสดงเป็นภูมิภาค 2 × 3:

+               <top wall>      <top wall>
<left wall>     <data/space>    <space>

เนื่องจากคอลัมน์ด้านขวาไม่มีข้อมูลโปรแกรมจึงระบุเซลล์เป็นพื้นที่ 2 × 2 ใด ๆ ที่มี+ที่ด้านบนซ้าย

สิ่งนี้ทำให้เรามีเซลล์ 3 ชนิด:

  • I Cells : เซลล์ที่อยู่ภายในเขาวงกตอย่างถูกต้อง
  • R Cells : เซลล์ที่อยู่ทางขวาของเขาวงกต สิ่งเหล่านี้ถูกสร้างขึ้นโดยการขยายที่ใช้เพื่อเป็นทางเข้าหรือออก ตัวอย่างเช่นทางออกUในกรณีทดสอบ 1 อยู่ใน R-Cell
  • B Cells : เซลล์ที่อยู่ต่ำกว่าเขาวงกต เช่นเดียวกับ R-Cell สิ่งเหล่านี้ถูกสร้างโดยการเติมเต็ม

ในรูปแบบใหม่เซลล์จะแสดงเป็นสตริงที่มีความยาวผันแปรได้:

<left wall> <column number> <top wall/exit marker> <path>

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

ครึ่งเซลล์

แม้ว่าเขาวงกตส่วนใหญ่จะเป็นเซลล์ แต่ก็มีบริเวณของเขาวงกตที่ไม่ใช่เซลล์:

  • R Half-cells : หากไม่มีช่องว่างภายใน+ที่เหมาะสมผนังด้านขวาจะไม่ก่อตัวเนื่องจากอยู่ในคอลัมน์สุดท้าย
  • L เซลล์ครึ่งหนึ่ง : หากมีช่องว่างภายในเซลล์จะไม่สามารถเกิดขึ้นได้เนื่องจากไม่มี+ทางด้านซ้าย ตัวอย่างเช่นทางเข้าIในกรณีทดสอบ 1 อยู่ใน L Half-cell

ในทางเทคนิคแล้วมีเซลล์ครึ่ง Tอยู่เหนือเขาวงกต (เมื่อมีช่องว่างด้านบน) และB ครึ่งเซลล์ (ตามผนังด้านล่างเมื่อไม่มีช่องว่างด้านล่าง) แต่ไม่ได้แสดงในรูปแบบใหม่

แถวบนของครึ่งเซลล์จะถูกลบออกเป็นส่วนหนึ่งของการสร้างเซลล์แบบเต็มในแถวเดียวกันดังนั้นครึ่งเซลล์จะถูกแสดงในรูปแบบใหม่ดังนี้

<wall/exit marker>? <path>

|อาครึ่งเซลล์เป็นเพียง L Half-cells มีเพียงแค่Iเป็นเส้นทางเพียงเครื่องหมายทางออกและเส้นทางที่ว่างเปล่าหรือเพียงแค่ผนังที่ว่างเปล่า

ทางเข้าและทางออก

หากทางเข้าอยู่ทางซ้ายขวาหรือด้านล่างของเขาวงกตเครื่องหมายทางเข้าIจะรวมอยู่ในเซลล์ (ครึ่ง -) เป็นเส้นทางซึ่งสามารถลบออกได้เมื่อกลับสู่เส้นทางสุดท้าย

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

หากทางออกอยู่ทางซ้ายขวาหรือด้านล่างของเขาวงกตก็Uจะรวมอยู่ในเซลล์ (ครึ่ง -) ตามธรรมชาติ เพื่อหลีกเลี่ยงการเข้าใจผิดว่าเป็นเส้นทางเครื่องหมายทางออกที่ไม่ใช่ alphanum ใช้แทน& Uเครื่องหมายออกจะถูกฝังลงในเซลล์หรือครึ่งเซลล์ (ตามที่ระบุไว้ด้านบน)

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

สุดท้ายเซลล์ B ใด ๆ ที่มีทางเข้าหรือทางออกจะต้องปิดผนังด้านซ้ายเพื่อป้องกัน "แก้ไข" เขาวงกตด้วยการเดินไปตามเซลล์ B ทางเข้าและออกใน R Cells หรือ L Half-cell ไม่ต้องการการประมวลผลเพิ่มเติมเนื่องจากอัลกอริธึมเติมน้ำท่วมไม่อนุญาตให้มีการเคลื่อนที่ตามแนวตั้งไปยัง / จากพวกเขา

ตัวอย่าง

เป็นตัวอย่างกรณีทดสอบครั้งแรก

·+--+--+--+--+--+--+--+--+--+--+·
I···············|·····|········|·
·+··+--+--+--+··+··+··+··+--+··+·
·|···········|·····|··|··|·····|·
·+--+--+--+··+--+--+··+··+··+--+·
·|···········|·····|·····|·····|·
·+··+--+--+··+··+--+--+··+--+··+·
·|·····|·····|·····|·····|·····|·
·+--+··+··+--+--+··+--+--+··+··+·
·|·····|········|········|··|··|·
·+··+--+--+--+··+--+--+··+··+··+·
·|·····|·····|·····|········|··|·
·+--+··+··+--+--+··+--+--+--+--+·
·|··|··|·················|·····|·
·+··+··+--+--+--+··+--+··+··+··+·
·|·····|········|··|··|··|··|··|·
·+--+--+··+··+--+··+··+··+--+··+·
·|········|·····|·····|··|·····|·
·+··+--+--+--+··+··+··+··+··+--+·
·|···········|·····|··|·········U
·+--+--+--+--+--+--+--+--+--+--+·

คือ

I·3-·6-·9-·12-·15-|18-·21-|24-·27-·30-|33·
·|3··6-·9-·12-|15··18·|21·|24·|27-·30·|33·
·|3-·6-·9-·12·|15-·18-|21··24·|27··30-|33·
·|3··6-|9-·12·|15··18-|21-·24·|27-·30·|33·
·|3-·6·|9··12-·15-|18··21-·24-|27·|30·|33·
·|3··6-|9-·12-|15··18-|21-·24··27·|30·|33·
·|3-|6·|9··12-·15-·18··21-·24-|27-·30-|33·
·|3··6·|9-·12-·15-|18·|21-|24·|27·|30·|33·
·|3-·6-·9·|12··15-|18··21·|24·|27-·30·|33·
·|3··6-·9-·12-|15··18·|21·|24··27··30-·33&

ในรูปแบบใหม่ คุณสามารถแปลงเขาวงกตอื่น ๆที่นี่


ขั้นตอนการก่อสร้าง

เฟสการก่อสร้างสร้างขึ้นเป็น 13 บรรทัดแรกของโปรแกรม

¶U
¶&

แปลงทางออกใน L เซลล์ครึ่งเพื่อออกเครื่องหมาย

+`·(\w.+)$
|$1

เพิ่มกำแพงทางด้านซ้ายของทางเข้าและออกใน B Cells

((.)+I.+¶.+¶(?<-2>.)+)·
$1v

ทำขั้นตอนแรกถ้าทางเข้าอยู่เหนือเขาวงกต

+`((.)*)\+(.).*(¶(?<-2>.)*.)((\w)|·)·?
$1$4$.4$3$6

ดำเนินการแปลงจริง

·v
-v

ปิดรูทางเข้าด้านบน

G`1

1ช่วยให้เส้นเดียวที่มี เนื่องจากเขาวงกตมีความกว้างอย่างน้อย 5 เซลล์และหมายเลขคอลัมน์เกิดขึ้นทีละ 3 บรรทัดที่มีเซลล์รูปแบบใหม่จะต้องมีหมายเลขคอลัมน์ระหว่าง 10 ถึง 19

·U
&

แปลงทางออกในเซลล์ R หรือเซลล์ B เพื่อออกเครื่องหมาย


เติมเฟส

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

{`

วางเฟสการเติมทั้งหมดลงบนลูปเพื่อเติมทั้งเขาวงกต

\B·\d+.(\w+)
$1K$&

แต่ละเซลล์สามารถเลื่อนไปทางซ้ายได้ เซลล์สามารถเลื่อนไปทางซ้ายได้ถ้า

  1. มันมีเส้นทางที่ไม่ว่างเปล่า
  2. มันมีกำแพงด้านซ้ายที่ว่างเปล่า และ
  3. เซลล์หรือ L ครึ่งเซลล์ทางซ้ายมีเส้นทางที่ว่างเปล่า
(\w+)·\d+.\B
$&$1r

จากนั้นแต่ละเซลล์สามารถเลื่อนไปทางขวาทำเช่นนั้น เซลล์สามารถเคลื่อนที่ได้ถ้า

  1. มันมีเส้นทางที่ไม่ว่างเปล่า
  2. เซลล์ทางด้านขวามีผนังด้านซ้ายที่ว่างเปล่า และ
  3. เซลล์ทางด้านขวามีเส้นทางที่ว่างเปล่า
(?<=\D\2.(\w+).+?¶.*\D(\d+)[·&])\B
$1v

จากนั้นแต่ละเซลล์สามารถเลื่อนลงได้ เซลล์สามารถเลื่อนลงได้ถ้า

  1. มันมีเส้นทางที่ไม่ว่างเปล่า
  2. มีอย่างน้อยหนึ่งเซลล์หรือครึ่งเซลล์ทางด้านขวา (เช่นไม่ใช่เซลล์ R)
  3. เซลล์ด้านล่าง (เช่นเซลล์ในบรรทัดถัดไปที่มีหมายเลขคอลัมน์เดียวกัน) มีผนังด้านบนที่ว่างเปล่าหรือมีเครื่องหมายออก และ
  4. เซลล์ด้านล่างมีเส้นทางที่ว่างเปล่า

โปรดทราบว่า L เซลล์ครึ่งเซลล์ไม่สามารถเลื่อนลงได้เนื่องจากไม่มีหมายเลขคอลัมน์

\D(\d+).\B(?=.+¶.*\D\1·(\w+))
$&$2A

จากนั้นแต่ละเซลล์สามารถเลื่อนขึ้นได้ เซลล์สามารถเลื่อนขึ้นได้หาก

  1. มันมีเส้นทางที่ไม่ว่างเปล่า
  2. มันมีผนังด้านบนที่ว่างเปล่า
  3. เซลล์ด้านบนมีเซลล์อย่างน้อยหนึ่งเซลล์หรือครึ่งเซลล์ทางด้านขวา และ
  4. เซลล์ด้านบนมีเส้นทางที่ว่างเปล่า

กลับเฟส

เฟสที่ส่งคืนประกอบด้วย 5 บรรทัดสุดท้ายของโปรแกรม เฟสนี้ค้นหาและส่งคืนพา ธ ที่เติมลงในเซลล์ออก

รูปแบบของเส้นทางที่ทางออกขึ้นอยู่กับว่าทางออกคืออะไร:

  1. ถ้าทางออกอยู่ใน L Half-cell แล้วก็ครึ่งเซลล์นั้นจะเป็น & <path>
  2. หากทางออกอยู่ในเซลล์ R หรือเซลล์ B เซลล์นั้นจะเป็น <left wall> <column number> & <path>
  3. หากทางออกอยู่ใน T Half-cell ดังนั้นตามที่ระบุไว้ข้างต้น I Cell ที่นำไปสู่ทางออกจะ<left wall> <column number> · <path>อยู่ในแถวบนสุด
^.+\d·(\w+)
&$1A

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

M!`&\w+

จับคู่และส่งคืนพา ธ ที่ไม่ว่างหลังเครื่องหมายออก

I|&

ลบเครื่องหมายออกและIคำนำหน้าของเส้นทาง


ทำไมAvKr? พวกเขามีความหมาย / พวกเขาเป็นตัวย่อสำหรับขึ้นลงซ้ายและขวาในภาษาพื้นเมืองของคุณหรือมีเหตุผลอื่นทำไมคุณเลือกตัวละครเฉพาะเหล่านั้นหรือไม่
Kevin Cruijssen

@KevinCruijssen เพียงเพราะฉันต้องใช้ตัวอักษรและตัวเลขและAvKrเป็นสิ่งที่ใกล้เคียงที่สุดสำหรับลูกศรใน alphanum
TwiNight

12

Perl 6 , 259 295 ไบต์

{my \a=S:g/(.)$0+/{$0 x($/.comb+.5)*2/3}/;sub f (\c,\v,*@p) {with (c ne any v)&&a.lines».comb[+c[0];+c[1]] ->$_ {for (/\s/??10011221!!/I/??a~~/^\N*I|I\N*$/??2101!!1012!!'').comb X-1 {f [c Z+$^a,$^b],(|v,c),@p,chr 8592+$++}
take @p if /U/}}
[~] (gather f a~~/(\N+\n)*(.)*I/,[]).min(+*)[1,3...*]}

มันทำงานอย่างไร

  1. my \a = S:g/ (.) $0+ /{ $0 x ($/.chars + .5) * 2/3 }/;

วิธีนี้บีบเขาวงกตเพื่อให้ด้านในของแต่ละเซลล์มี 1x1 แทนที่จะเป็นอักขระเว้นวรรค 2x1:

 + - + - + - + - + - + - - + - + - + - + - + - 
ฉัน | | | ฉัน | | |
 + + - + - + + + + + - - + - + 
 | | | | | | | |
 + + - + + + + + + - - + + + 
 | | | | | -> | | | | |
 + + + - + + + + + + - - + + 
 | | | | | |
 + - + + + - + - + + - - + + - + - + 
 | | U | | ยู
 + - + - + - + - + - + - - + - + - + - + - + -

  1. sub f (\c,\v,*@p) {
        with (c ne any v) &&                   # If the coordinate wasn't visited yet
             lines».comb[+c[0];+c[1]] -> $_ {  # and a character exists there...
            for (                          # For each vector...
                 /\s/ ?? 10011221 !!       #  from a cell: (0,-1), (-1,0), (0,1), (1,0)
                 /I/  ?? a~~/^\N*I|I\N*$/
                          ?? 2101          #  from a top/bottom entrance: (1,0), (-1,0)
                          !! 1012          #  from a left/right entrance: (0,-1), (0,1)
                      !! ''                #  otherwise: none
                ).comb X-1 {
                f                       #   Recurse with arguments:
                    [c Z+ $^a, $^b],    #     c plus the vector
                    (|v, c),            #     v with c appended
                    @p, chr 8592 + $++  #     p with the correct Unicode arrow appended
            }
            take @p if /U/
        }
    }

นี่คือฟังก์ชันการค้นหาเส้นทางแบบเรียกซ้ำ มันใช้พารามิเตอร์สามตัว: พิกัดปัจจุบันc=(y,x)รายการของพิกัดที่เยี่ยมชมแล้วvและเส้นทางที่pนำมาจนถึง (เป็นรายการของตัวอักษรลูกศร)

หากตัวละครที่พิกัดปัจจุบันเป็นช่องว่างมันจะเกิดขึ้นกับเพื่อนบ้านทั้งสี่ของมัน
หากตัวละครในพิกัดปัจจุบันเป็น a Iมันจะเกิดขึ้นกับเพื่อนบ้านทั้งสองที่ไม่ได้ "ตามขอบ" เพื่อบังคับให้สารละลายผ่านเขาวงกตและไม่อยู่ใกล้เคียง
หากอักขระที่พิกัดปัจจุบันคือ a Uมันจะเรียกtakeใช้สตริงเส้นทางที่สะสม

  1. [~] (gather f a ~~ /(\N+\n)*(.)*I/, []).min(+*)[1,3...*]

ฟังก์ชันเรียกซ้ำเรียกว่าเริ่มต้นด้วยพิกัดของจดหมายIซึ่งพบได้โดยใช้ regex

gatherคำหลักเก็บค่าทั้งหมดที่takeถูกเรียกว่าฟังก์ชั่นภายในคือเส้นทางที่ถูกต้องทั้งหมดไม่ใช่วัฏจักรผ่านเขาวงกต

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


ก่อนอื่นงานที่ยอดเยี่ยมในการเป็นคนแรกที่จะผ่านการท้าทายของฉัน! :) วิธีที่ชาญฉลาดในการเปลี่ยนทั้งสองช่องว่างให้เป็นหนึ่งเดียวเพื่อให้ง่ายต่อการเคลื่อนไหว / นับจริง +1 จากฉัน อย่างไรก็ตามหลังจากความเห็นบางกรณีสองกรณีทดสอบใหม่ถูกเพิ่ม คุณช่วยตรวจสอบงานเหล่านี้ด้วยโซลูชันของคุณด้วยหรือไม่ (ยังไม่ Perl 6 มี TIO หรือคอมไพเลอร์ออนไลน์อื่น ๆ ที่คุณสามารถเพิ่มลิงค์ไปยัง?)
เควิน Cruijssen

@KevinCruijssen: มันไปรอบ ๆ เขาวงกตในกรณีทดสอบใหม่ :( ฉันคงรหัสตอนนี้ tio.run สนับสนุน Perl 6 แต่ด้วยเหตุผลบางอย่างนี้ไม่ได้ทำงานที่นั่น ... บางทีมันอาจจะมีเก่าเกินไป Perl 6 รุ่น.
smls

งานที่ยอดเยี่ยมในการแก้ไขรหัส ขออภัยที่ต้องระบุกฎว่าจะต้องผ่านเขาวงกตหลังจากที่คุณโพสต์คำตอบของคุณแล้ว แต่ Chapeau สำหรับการแก้ไขอย่างรวดเร็ว และเกี่ยวกับรุ่น TIO ฉันไม่มีความคิด ไม่ใช่ความเชี่ยวชาญของฉันจริงๆ ..
Kevin Cruijssen

เนื่องจากคุณเป็นคนแรกที่ตอบความท้าทายของฉันเมื่อสี่เดือนที่แล้วฉันจึงให้ความกรุณากับคุณ :) และการยอมรับสำหรับคำตอบของจอประสาทตาที่สั้นกว่าเล็กน้อย
Kevin Cruijssen

5

Python 2: 302 ไบต์

from re import*
r=lambda x:[''.join(_)for _ in zip(*x)][::-1]
z=',l)for l in s]'
def f(s,b=1,o=0,n=0):
 exec("s=[sub('(..).(?!$)',r'\\1'%s;"%z+"s=r([sub(' I ','+I+'%s);"%z*4)*b+"t=[sub('I  ','@@I'"+z
 if'I U'in`s`or n>3:return`o%4`+n/4*`s`
 return min(`o%4`+f(t,0,o,4*(t==s)),f(r(s),0,o+1,n+1),key=len)

รับอินพุตเป็นอาร์เรย์ของสตริงทั้งหมดที่มีความยาวเท่ากัน พิมพ์0ทางขวา1ลงล่าง2ซ้ายและ3ขึ้น

คำอธิบาย

ฉันใช้วิธีที่แตกต่างจากคำตอบอื่น แนวคิดทั่วไป: ค้นหาซ้ำโดยค้นหาเส้นทางที่สั้นที่สุดระหว่างการไปข้างหน้าและหมุนกระดาน 90 องศา

from re import*
r=lambda x:[''.join(_)for _ in zip(*x)][::-1] #Rotates the board counterclockwise
z=',l)for l in s]'    #Suffix for hacky exec golfing
def f(s,b=1,o=0,n=0): #b is 1 on initial call, 0 on every recursion
                      #o is orientation
                      #n is number of rotations
 exec("s=[sub('(..).(?!$)',r'\\1'%s;"%z  #Squeeze the maze
      +"s=r([sub(' I ','+I+'%s);"%z*4)   #Add walls around the I to keep it in the maze
      *b                                 #Only if b is 1
      +"t=[sub('I  ','@@I'"+z            #Attempt to move right

 if'I U'in`s`or n>3:return`o%4`+n/4*`s`  #If the I is next to the U, return the orientation
                                         #If there were 4 rotations, return a long string
 return min(                             #Return the path with the shortest length:
            `o%4`+f(t,0,o,4*(t==s)),       #Moving forward if possible
            f(r(s),0,o+1,n+1),             #Rotating the board
        key=len)

ลองออนไลน์!


3
ยินดีต้อนรับสู่ PPCG! นี่เป็นคำตอบแรกที่ดีมากและฉันประทับใจที่คุณตัดสินใจทำสิ่งที่ท้าทายอย่างแรก ยังฉลาดว่าคุณได้วางกำแพงล้อมรอบIเพื่อป้องกันไม่ให้เส้นทางออกไปข้างนอกเขาวงกต สนุกกับการเข้าพักของคุณและ +1 จากฉัน :)
Kevin Cruijssen

2

JavaScript (ES6), 356 ไบต์

a=>(a=a.map(s=>s.filter((_,i)=>!i|i%3)),g=([x,y])=>a[y]&&a[y][x],o=[],c=([x,y],m="",v=[])=>[[0,1],[1,0],[0,-1],[-1,0]].map(([j,k],i)=>(p=[x+j,y+k],!m&(!y|y>a[l="length"]-2)==i%2|v.includes(""+p)||(g(p)<"!"?c(p,m+"v>^<"[i],[...v,""+p]):g(p)=="U"?o.push(m.replace(/(.)\1/g,"$1")):0))),a.map((h,i)=>h.map((k,j)=>k=="I"&&c([j,i]))),o.sort((a,b)=>a[l]-b[l])[0])

รับอินพุตเป็นอาร์เรย์ของอักขระ 2 มิติ แต่ละบรรทัดต้องถูกบุด้วยซ้ายหนึ่งช่องว่างและไม่มีช่องว่างต่อท้ายไม่ว่าจุดเริ่มต้น / จุดสิ้นสุดจะอยู่ที่ใด

ใช้ความคิดของ smls ในการ squilling the maze เพื่อทำให้แต่ละเซลล์ 1x1 และลบลูกศรซ้ำออกจากผลลัพธ์

Ungolfed และอธิบาย

a=>(
    a=a.map(s=>s.filter((_,i)=>!i|i%3)),    // squish the maze to 1x1 cells
    g=([x,y])=>a[y]&&a[y][x],               // helper func to get maze value
    o=[],                                   // resulting movesets
    c=([x,y], m="", v=[]) =>                // recursive func to search
                                            // takes current point, moves, and visited spots
        [[0,1],[1,0],[0,-1],[-1,0]].map(([j,k],i)=>(// for each direction
            p=[x+j,y+k],
            !m & (!y | y>a[l="length"]-2) == i%2 |  // if first move, prevent moving out of maze
                v.includes(""+p) || (               // also prevent if already visited
                    g(p)<"!" ?                      // is this a space?
                        c(p, m+"v>^<"[i], [...v,""+p]) // check this spot recursively
                    : g(p)=="U" ?                   // if this the end?
                        o.push(                     // add moves to moveset
                            m.replace(/(.)\1/g,"$1")) // with double arrows removed
                    : 0
                )
        )),

    a.map((h,i)=>h.map((k,j)=>      // find the starting "I" and
        k=="I" && c([j,i])          // begin recursion at that point
    )),

    o.sort((a,b)=>a[l]-b[l])[0]     // get shortest path
)

ตัวอย่างการทดสอบ


1

เรติน่า 416 ไบต์

T` `+`^.*| ?¶.|.*$
I
#
{+` (\w)
d$1
+`(\w) 
$1a
+`(¶(.)*) (.*¶(?<-2>.)*(?(2)(?!))\w)
$1s$3
}+m`(^(.)*\w.*¶(?<-2>.)*(?(2)(?!))) 
$1w
^
w¶
w((.|¶)*(¶(.)*#.*¶(?<-4>.)*(?(4)(?!))(s)|#(d)|(a)#))
$4$5$6¶$1
{`^(.*d)(¶(.|¶)*)#(\w)
$1$4$2 #
^(.*a)(¶(.|¶)*)(\w)#
$1$4$2# 
^(.*s)(¶(.|¶)*¶(.)*)#(.*¶(?<-4>.)*(?(4)(?!)))(\w)
$1$6$2 $5#
}`^(.*w)(¶(.|¶)*¶(.)*)(\w)(.*¶(?<-4>.)*(?(4)(?!)))#
$1$5$2#$6 
s`U.*

(a|d)\1\1?
$1
ss
s
ww
w

ลองออนไลน์! ถ้าฉันเห็นคำถามนี้เมื่อโพสต์เริ่มแรกนี่อาจเป็นคำตอบที่ฉันจะได้รับดังนั้นฉันจึงโพสต์คำถามต่อไปแม้ว่าจะมีคำตอบที่ดีกว่าใน Retina คำอธิบาย:

T` `+`^.*| ?¶.|.*$

เติมในเส้นขอบ หลีกเลี่ยงการเดินไปรอบ ๆ ด้านนอกของเขาวงกต (เช่นสำหรับกรณีทดสอบ 7)

I
#

วางเครื่องหมายที่ไม่ใช่ตัวอักษรที่ทางเข้า

{+` (\w)
d$1
+`(\w) 
$1a
+`(¶(.)*) (.*¶(?<-2>.)*(?(2)(?!))\w)
$1s$3
}+m`(^(.)*\w.*¶(?<-2>.)*(?(2)(?!))) 
$1w

เติมน้ำท่วมจากทางออกสู่ทางเข้า ในแต่ละขั้นตอนให้ใช้ตัวอักษรเพื่อระบุทิศทางที่ดีที่สุดที่จะไป (WASD - นี่อาจเป็นที่คุ้นเคยสำหรับนักเล่นเกมฉันยังพิจารณา hjkl แต่ฉันพบว่ามันสับสนเกินไป) นอกจากนี้ชอบทำซ้ำทิศทางเดียวกัน; เพื่อหลีกเลี่ยงการไปทางซ้าย / ขวาในระหว่างเซลล์ทั้งสองที่อยู่ติดกันในแนวตั้ง

^
w¶

สมมติว่าขั้นตอนแรกไม่ทำงาน

w((.|¶)*(¶(.)*#.*¶(?<-4>.)*(?(4)(?!))(s)|#(d)|(a)#))
$4$5$6¶$1

แต่ถ้ามีจดหมายด้านบนทางซ้ายหรือทางขวาของทางเข้าให้เปลี่ยนเป็นขั้นตอนแรก

{`^(.*d)(¶(.|¶)*)#(\w)
$1$4$2 #
^(.*a)(¶(.|¶)*)(\w)#
$1$4$2# 
^(.*s)(¶(.|¶)*¶(.)*)#(.*¶(?<-4>.)*(?(4)(?!)))(\w)
$1$6$2 $5#
}`^(.*w)(¶(.|¶)*¶(.)*)(\w)(.*¶(?<-4>.)*(?(4)(?!)))#
$1$5$2#$6 

ย้ายเครื่องหมายไปในทิศทางของการเคลื่อนไหวครั้งสุดท้ายอ่านทิศทางของการเคลื่อนไหวครั้งต่อไปจากสี่เหลี่ยมจัตุรัสที่เครื่องหมายถูกย้ายไปและเพิ่มเข้าไปในรายการทิศทาง สิ่งนี้ซ้ำจนกว่าUจะถึง

s`U.*

ลบทุกอย่างหลังจากเส้นทางเนื่องจากไม่จำเป็นอีกต่อไป

(a|d)\1\1?
$1
ss
s
ww
w

กริดดั้งเดิมอยู่ในรูปแบบ 3 × 2 ในขณะที่เคลื่อนที่ในแนวตั้งหากเราเคลื่อนที่เป็นรูปฟันปลาในแนวนอนการเติมน้ำท่วมจะทำให้การเคลื่อนไหวมีประสิทธิภาพสูงสุดและย้ายเฉพาะอักขระ 3n-1 ในแนวนอนเท่านั้นดังนั้นเมื่อทำการหารด้วยสามเราจะต้องปัดเศษขึ้น เราหารด้วย 2 ในแนวตั้ง

ฉันยังตรวจสอบวิธีแก้ปัญหากริดสแควร์ที่แท้จริงเช่นที่เมทริกซ์ตัวละครเป็นสแควร์แทนที่จะเป็นเลย์เอาต์ 3 × 2 ที่มีขอบเป็นตัวเลือก ในขณะที่อาจไม่สอดคล้องกับคำถามความสามารถในการแปลงลดจำนวนไบต์เป็น 350: ลองออนไลน์!


คำตอบที่ดี +1! ฉันเห็นในลิงก์ TIO ของคุณที่คุณเพิ่มสอง-ตัวอักษรทั้งทางเข้าและออก เนื่องจากความท้าทายส่วนใหญ่เกี่ยวกับการผ่านเขาวงกตฉันคิดว่ามันโอเค แต่ฉันอยากรู้อยากเห็น: ปัญหาอะไรที่คุณไม่ได้วางกำแพงเหล่านั้นไว้ด้านบน / ล่างIและU? คุณสามารถตรวจสอบงานนี้สำหรับกรณีทดสอบ 7 ด้วยIและUที่ด้านบนแทนด้านข้างได้หรือไม่ TIO เกินขีด จำกัด 60 วินาทีดังนั้นฉันจึงไม่สามารถทดสอบด้วยตนเองได้ แม้ว่าการอ่านคำอธิบายของคุณก่อนที่จะพยายามลงไปโดยค่าเริ่มต้นฉันคิดว่ามันควรจะทำงานได้ดี
Kevin Cruijssen

@KevinCruijssen คำตอบ "รอง" ใช้ได้กับกรณีทดสอบ 7 แต่ต้องการตัวอักษรพิเศษ: ลองออนไลน์! ดำเนินการต่อ ...
Neil

@KevinCruijssen คำตอบ "หลัก" มีข้อผิดพลาดเพราะมันไม่สามารถรับมือกับทางออกบนบรรทัดที่ทุกคน นอกจากนี้ยังมีจุดบกพร่องคล้ายกับคำตอบ "รอง" โดยที่มันชอบเดินไปรอบ ๆ ด้านนอกของเขาวงกตหากทำได้ (นอกจากนี้ฉันไม่ได้มาใกล้ขีด จำกัด 60 วินาที)
Neil

ที่จริงฉันสามารถแก้ไขทั้งสองคำตอบได้ด้วยการเติมเส้นขอบ ฉันจะทำในภายหลังเมื่อฉันมีเวลา
Neil
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.