Cuộc sống là một mê cung: Chúng ta đi sai đường trước khi chúng ta học đi


30

Đầu vào:

Một mê cung chứa các nhân vật:

  • -- (tường ngang);
  • | (tường dọc);
  • + (kết nối);
  • (không gian đi bộ);
  • I (cổng vào);
  • U (lối thoát hiểm).

Tức là một đầu vào có thể trông như thế này:

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

Đầu ra:

Các hiệu quả nhất con đường bạn nên đi bộ để có được từ lối vào đến lối ra của mê cung (qua mê cung), chỉ định bởi các ký tự chỉ ra trái, phải, lên xuống (ví dụ >; <; ^; v).

Quy tắc thử thách:

  • Bạn có thể lấy đầu vào ở bất kỳ định dạng hợp lý. Chuỗi mảng, Chuỗi đơn với dòng mới, mảng char 2D, v.v ... đều là các định dạng đầu vào có thể.
  • Đầu ra có thể bao gồm bất kỳ bốn ký tự riêng biệt. Tức là ><^v; →←↑↓; ⇒⇐⇑⇓; RLUD; 0123; ABCD; v.v.)
  • Bạn được phép thêm khoảng trắng hoặc theo dõi dòng mới vào đầu ra nếu muốn; Đây là tùy chọn.
  • Các bước được tính trên mỗi ô vuông (xem bốn biểu tượng +cho hình vuông) và không tính trên mỗi ký tự.
  • Mê cung có thể có kích thước 5x5 đến 15x15 và sẽ luôn là một hình vuông (vì vậy sẽ không có bất kỳ trường hợp thử nghiệm nào đối với mê cung 5x10).
  • Bạn có thể giả định rằng mọi mê cung đều có một hoặc nhiều đường dẫn hợp lệ từ đầu đến cuối và bạn luôn xuất ra ngắn nhất (xem trường hợp thử nghiệm 4 và 5).
  • Nếu có nhiều đường dẫn có cùng độ dài, bạn có thể chọn đường dẫn nào để xuất (xem trường hợp kiểm tra 6).
  • Bạn không thể 'đi bộ' bên ngoài biên giới của mê cung (xem trường hợp thử nghiệm 7 và 8).

Quy tắc chung:

  • Đây là , vì vậy câu trả lời ngắn nhất bằng byte thắng.
    Đừng để ngôn ngữ mã-golf ngăn cản bạn đăng câu trả lời với các ngôn ngữ không mã hóa. Cố gắng đưa ra một câu trả lời càng ngắn càng tốt cho ngôn ngữ lập trình 'bất kỳ'.
  • Các quy tắc chuẩn áp dụng cho câu trả lời của bạn, vì vậy bạn được phép sử dụng STDIN / STDOUT, các hàm / phương thức với các tham số thích hợp, các chương trình đầy đủ. Cuộc gọi của bạn.
  • Lỗ hổng mặc định bị cấm.
  • Nếu có thể, vui lòng thêm một liên kết với một bài kiểm tra cho mã của bạn.
  • Ngoài ra, xin vui lòng thêm một lời giải thích nếu cần thiết.

Các trường hợp thử nghiệm:

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<

Mazes được tạo bằng công cụ này (và trong một số trường hợp sửa đổi một chút).


10
Tôi đã tìm thấy một giải pháp ngắn hơn cho trường hợp thử nghiệm thứ ba! v<<<<<<^^^^^(luôn luôn nghĩ bên ngoài hộp)
Leo

2
Nếu người ta có thể chứng minh rằng mã của họ sẽ mang lại giải pháp ngắn nhất, đủ thời gian và bộ nhớ, liệu nó có cạnh tranh không? Ngay cả trong trường hợp thời gian thực sự dài (kết thúc thời trang vũ trụ)?
Yytsi

1
@JackBates Đó là một trò đùa. Anh ta thực sự đi bộ quanh hộp đến lối ra: D
Yytsi

1
Tôi nghĩ rằng trường hợp thử nghiệm đầu tiên là sai, nó nên được >v>>>vv<v>>v>v>>vvv>>>.
smls

1
@KevinCruijssen Ví dụ: một giải pháp kiểm tra từng tổ hợp "v ^ <>" cho độ dài lên đến số lượng ô trống bên trong mê cung. Giải pháp phù hợp sẽ ở đó, nhưng cần có thời gian để tính toán.
Yytsi

Câu trả lời:


7

Võng mạc , 338 281 275 273 261 byte

¶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|&

Hãy thử trực tuyến!


Ghi chú

  • Do khoảng trắng đáng kể, tất cả các khoảng trắng ( 0x20) được thay thế bằng interpunc ( ·) cả trong câu trả lời này và liên kết TIO. Chương trình hoạt động tốt nếu không gian được khôi phục.
  • Sử dụng AvKrcho lên, xuống, trái và phải, tương ứng. Những người có thể được thay thế bằng bất kỳ chữ cái ngoại trừ I.
  • Mất khoảng 40 giây trên TIO cho trường hợp thử nghiệm 15 × 15. Kiên nhẫn. Làm lại phần để tìm đường đi ngắn nhất khi đường dẫn đến lối ra. Hóa ra là mất rất nhiều thời gian.
  • Có thể phá vỡ hoàn toàn các mê cung rộng từ 66 ô trở lên nhưng có thể xử lý các mê cung có chiều cao tùy ý. Một sửa chữa cho chiều rộng tùy ý mất +1 byte.

Giải trình

Chương trình bao gồm 3 giai đoạn:

  • Một giai đoạn xây dựng để chuyển đổi mê cung thành một định dạng nhỏ gọn dễ làm việc hơn (chi tiết bên dưới).
  • Một giai đoạn lấp đầy để thực sự giải quyết mê cung bằng thuật toán lấp đầy.
  • Một pha quay lại để trả về con đường ngắn nhất ở lối ra.

định dạng

Do định dạng mê cung ban đầu khá khó sử dụng, phần đầu tiên của chương trình chuyển đổi nó thành một định dạng khác.

Tế bào

Trong định dạng ban đầu, mỗi ô được thể hiện dưới dạng vùng 2 × 3:

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

Vì cột bên phải không chứa thông tin, chương trình xác định các ô là bất kỳ vùng 2 × 2 nào có một +ở phía trên bên trái.

Điều này cho chúng ta 3 loại tế bào:

  • I Cells : Các tế bào nằm bên trong mê cung.
  • Tế bào R : Các tế bào nằm bên phải mê cung. Chúng được tạo ra bởi phần đệm được sử dụng để chứa lối vào hoặc lối ra. Ví dụ, lối ra Utrong trường hợp thử nghiệm 1 nằm trong R-Cell.
  • Tế bào B : Các tế bào nằm dưới mê cung. Giống như R-Cell, chúng được tạo ra bằng cách đệm.

Trong định dạng mới, các ô được biểu diễn dưới dạng chuỗi có độ dài thay đổi:

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

Tường bên trái và trên cùng được sao chép từ định dạng ban đầu. Số cột dựa trên vị trí ngang của ô và được sử dụng để căn chỉnh (xác định các ô trực tiếp trên đầu / bên dưới nhau). Đường dẫn là một chuỗi chữ cái được sử dụng trong giai đoạn điền để lưu đường dẫn ngắn nhất để đến ô đó. Đường dẫn và điểm đánh dấu sẽ được giải thích thêm.

Nửa tế bào

Mặc dù hầu hết mê cung là các tế bào, có những vùng của mê cung không phải là các tế bào:

  • R Nửa ô : Nếu không có phần đệm bên phải, +s dọc theo bức tường bên phải sẽ không hình thành các ô vì chúng nằm trên cột cuối cùng.
  • L Nửa ô : Nếu có phần đệm bên trái, các ô không thể hình thành ở đó vì không có +phần bên trái của chúng. Ví dụ, lối vào Itrong trường hợp thử nghiệm 1 nằm trong L nửa ô.

Về mặt kỹ thuật, có một nửa ô phía trên mê cung (khi có phần đệm trên cùng) và nửa ô B (dọc theo thành dưới khi không có phần đệm phía dưới) nhưng chúng không được thể hiện ở định dạng mới.

Hàng trên cùng của một nửa ô sẽ bị xóa như là một phần của việc xây dựng các ô đầy đủ trong cùng một hàng, vì vậy một nửa ô được thể hiện ở định dạng mới như

<wall/exit marker>? <path>

Một nửa tế bào R là chỉ |. Một nửa L có Icác đường dẫn giống như đường dẫn, chỉ là điểm đánh dấu thoát và đường dẫn trống hoặc chỉ là một bức tường trống.

Lối vào và lối ra

Nếu lối vào nằm ở bên trái, phải hoặc dưới cùng của mê cung, thì điểm đánh dấu lối vào Isẽ tự nhiên được bao gồm trong ô (một nửa) dưới dạng đường dẫn, có thể được loại bỏ khi trả về đường dẫn cuối cùng.

Nếu lối vào nằm trên mê cung, bước đầu tiên (đi xuống) được thực hiện trong giai đoạn xây dựng vì các ô T được loại bỏ trong quá trình xây dựng. Điều này giữ cho một đường dẫn khả thi trong một ô đầy đủ. Các bức tường trên được đóng lại sau đó.

Nếu lối ra nằm ở bên trái, phải hoặc dưới cùng của mê cung, thì đương Unhiên sẽ được đưa vào ô (một nửa). Để tránh bị nhầm lẫn là một đường dẫn, đánh dấu thoát không phải là chữ và số &được sử dụng thay vì U. Dấu thoát được nhúng vào một ô hoặc nửa ô (như được chỉ định ở trên).

Nếu lối ra nằm trên mê cung, thì đó sẽ là lỗ duy nhất có thể vượt lên trên hàng ô trên cùng (vì cái cho lối vào, nếu có, sẽ bị đóng lại). Bất kỳ con đường nào đi đến lỗ đó đều có thể thoát khỏi mê cung bằng cách bước lên.

Cuối cùng, bất kỳ Ô B nào có lối vào hoặc lối ra đều phải đóng bức tường bên trái của nó để ngăn "giải quyết" mê cung bằng cách đi dọc theo các Tế bào B. Lối vào và lối ra trong R Cell hoặc L Half-cell không cần xử lý thêm vì thuật toán lấp lũ không cho phép di chuyển dọc đến / từ chúng.

Thí dụ

Ví dụ, trường hợp thử nghiệm đầu tiên

·+--+--+--+--+--+--+--+--+--+--+·
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&

ở định dạng mới. Bạn có thể chuyển đổi các mê cung khác ở đây .


Giai đoạn xây dựng

Giai đoạn xây dựng tạo thành 13 dòng đầu tiên của chương trình.

¶U
¶&

Chuyển đổi lối ra trong L Half-cell thành điểm đánh dấu thoát

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

Thêm các bức tường ở bên trái của lối vào và lối ra trong B Cells

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

Bước đầu tiên nếu lối vào nằm trên mê cung

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

Thực hiện chuyển đổi thực tế

·v
-v

Đóng lỗ trên cùng

G`1

Chỉ giữ các dòng với a 1. Vì các mê cung có ít nhất 5 ô và số cột xuất hiện ở mức tăng 3, nên một dòng có các ô có định dạng mới phải có số cột chứa từ 10 đến 19.

·U
&

Chuyển đổi lối ra trong R Cell hoặc B Cell thành điểm đánh dấu thoát


Pha đầy

Giai đoạn điền vào tạo thành 8 dòng tiếp theo của chương trình. Nó sử dụng thuật toán lấp đầy để lấp đầy tất cả các ô với con đường ngắn nhất để đến đó từ lối vào.

{`

Đặt toàn bộ giai đoạn điền vào một vòng lặp để lấp đầy toàn bộ mê cung.

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

Mỗi tế bào có thể di chuyển trái làm như vậy. Một tế bào có thể di chuyển sang trái nếu

  1. nó có một con đường không trống
  2. nó có một bức tường bên trái trống rỗng; và
  3. ô hoặc L nửa ô bên trái có một đường trống
(\w+)·\d+.\B
$&$1r

Sau đó, mỗi tế bào có thể di chuyển đúng làm như vậy. Một tế bào có thể di chuyển đúng nếu

  1. nó có một con đường không trống
  2. ô bên phải của nó có một bức tường bên trái trống rỗng; và
  3. ô bên phải có một đường trống
(?<=\D\2.(\w+).+?¶.*\D(\d+)[·&])\B
$1v

Sau đó, mỗi tế bào có thể di chuyển xuống làm như vậy. Một tế bào có thể di chuyển xuống nếu

  1. nó có một con đường không trống
  2. nó có ít nhất một ô hoặc nửa ô bên phải (nghĩa là nó không phải là ô R)
  3. ô bên dưới nó (tức là ô trên dòng tiếp theo có cùng số cột) có một bức tường trên cùng trống hoặc có điểm đánh dấu thoát; và
  4. ô bên dưới nó có một đường trống

Lưu ý rằng L Half-cell không thể di chuyển xuống vì chúng không có số cột.

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

Sau đó, mỗi tế bào có thể di chuyển lên làm như vậy. Một tế bào có thể di chuyển lên nếu

  1. nó có một con đường không trống
  2. nó có một bức tường trống
  3. ô phía trên nó có ít nhất một ô hoặc nửa ô bên phải; và
  4. ô phía trên nó có một đường trống

Giai đoạn trở lại

Giai đoạn trở lại tạo nên 5 dòng cuối cùng của chương trình. Giai đoạn này tìm kiếm và trả về đường dẫn được điền vào ô thoát.

Mẫu của đường dẫn ở lối ra phụ thuộc vào vị trí của lối ra:

  1. Nếu lối ra nằm trong một nửa L, thì nửa ô đó sẽ là & <path>
  2. Nếu lối ra nằm trong Ô R hoặc Ô B, thì ô đó sẽ là <left wall> <column number> & <path>
  3. Nếu lối ra nằm trong một nửa ô T, thì như đã lưu ý ở trên, ô I dẫn đến lối ra sẽ nằm <left wall> <column number> · <path>ở hàng trên cùng.
^.+\d·(\w+)
&$1A

Tìm một ô trên dòng trên cùng với một bức tường trên cùng trống và một con đường không trống. Điều này quan tâm đến trường hợp cuối cùng bằng cách thêm bước cuối cùng và điểm đánh dấu thoát.

M!`&\w+

Khớp và trả về một đường dẫn không trống sau điểm đánh dấu thoát.

I|&

Xóa dấu thoát và Itiền tố của đường dẫn.


Tại sao AvKr? Chúng có nghĩa / chúng là chữ viết tắt cho lên, xuống, trái và phải trong ngôn ngữ mẹ đẻ của bạn hay có lý do nào khác khiến bạn chọn những ký tự cụ thể đó không?
Kevin Cruijssen

@KevinCruijssen Đơn giản vì tôi phải sử dụng các ký tự chữ và số và AvKrlà thứ gần nhất với các mũi tên trong chữ và số.
TwiNight

12

Perl 6 , 259 295 byte

{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...*]}

Làm thế nào nó hoạt động

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

Điều này siết chặt mê cung sao cho bên trong mỗi ô là 1x1 thay vì 2x1 ký tự khoảng trắng:

 + - + - + - + - + - + + - + - + - + - + - + 
Tôi | | | Tôi | | |
 + + - + - + + + + + - + - + + + 
 | | | | | | | |
 + + - + + + + + + - + + + + + 
 | | | | | -> | | | | |
 + + + - + + + + + + - + + + + 
 | | | | | |
 + - + + + - + - + + - + + + - + - + 
 | | U | | Bạn
 + - + - + - + - + - + + - + - + - + - + - +

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

Đây là hàm tìm đường đệ quy. Phải mất ba tham số: Tọa độ hiện tại c=(y,x), danh sách tọa độ đã truy cập vvà đường dẫn pđược thực hiện cho đến nay (dưới dạng danh sách các ký tự mũi tên).

Nếu nhân vật ở tọa độ hiện tại là một khoảng trắng, nó sẽ đệ quy cho bốn hàng xóm của nó.
Nếu ký tự ở tọa độ hiện tại là a I, nó sẽ đệ quy cho hai hàng xóm không "dọc theo rìa", để buộc các giải pháp đi qua mê cung chứ không phải xung quanh nó.
Nếu ký tự ở tọa độ hiện tại là a U, nó gọi takechuỗi đường dẫn tích lũy.

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

Hàm đệ quy ban đầu được gọi với tọa độ của chữ cái I, được tìm thấy bằng cách sử dụng biểu thức chính quy.

Các gathertừ khóa thu thập tất cả các giá trị mà trên đó takeđược gọi là bên trong hàm, tức là tất cả các đường dẫn không chu kỳ có giá trị thông qua các mê cung.

Con đường ngắn nhất được chọn, mỗi mũi tên thứ hai được thả xuống để giải thích cho thực tế là cần phải di chuyển hai bước giống nhau từ ô này sang ô khác và các mũi tên còn lại được nối để tạo thành chuỗi được trả về từ lambda.


Trước hết, công việc tuyệt vời là người đầu tiên hoàn thành thử thách của tôi! :) Thông minh như thế nào bạn đã thay đổi hai không gian thành một để giảm bớt sự di chuyển / đếm thực tế. +1 từ tôi. Dù sao, sau khi một số ý kiến ​​hai trường hợp thử nghiệm mới đã được thêm vào. Bạn có thể xác minh những công việc này với giải pháp của bạn là tốt? (Ngoài ra, Perl 6 có TIO hoặc trình biên dịch trực tuyến khác mà bạn có thể thêm liên kết tới không?)
Kevin Cruijssen

@KevinCruijssen: Nó đã đi vòng quanh mê cung trong các trường hợp thử nghiệm mới. :( Tôi đã sửa mã ngay bây giờ. Tio.run hỗ trợ Perl 6, nhưng vì một số lý do, điều này không hoạt động ở đó ... có lẽ nó có phiên bản Perl 6 quá cũ không?
smls

Tuyệt vời sửa mã. Xin lỗi vì đã chỉ định quy tắc phải đi qua mê cung sau khi bạn đã đăng câu trả lời của mình, nhưng chapeau đã sửa nó quá nhanh. Và liên quan đến phiên bản TIO tôi không có ý tưởng. Không thực sự là chuyên môn của tôi ..
Kevin Cruijssen

Vì bạn là người đầu tiên trả lời thử thách của tôi bốn tháng trước, tôi đã đưa tiền thưởng cho bạn. :) Và Chấp nhận dành cho câu trả lời Retina ngắn hơn một chút.
Kevin Cruijssen

5

Python 2: 302 byte

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)

Lấy đầu vào là một chuỗi các chuỗi có cùng độ dài. In 0cho phải, 1cho xuống, 2cho trái, và 3lên.

Giải trình

Tôi đã thực hiện một cách tiếp cận khác với các câu trả lời khác. Ý tưởng chung: tìm kiếm đệ quy bằng cách tìm con đường ngắn nhất giữa đi thẳng về phía trước và xoay bảng 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)

Hãy thử trực tuyến!


3
Chào mừng đến với PPCG! Đây là một câu trả lời đầu tiên tuyệt vời và tôi rất ấn tượng khi bạn quyết định thực hiện một thử thách khá khó khăn như lần đầu tiên. Cũng thông minh như thế nào bạn đã đặt các bức tường xung quanh Iđể ngăn chặn con đường đi ra ngoài mê cung. Tận hưởng kì nghỉ của bạn, và +1 từ tôi. :)
Kevin Cruijssen

2

JavaScript (ES6), 356 byte

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

Đưa đầu vào dưới dạng một mảng 2D của các ký tự. Mỗi dòng phải được đệm trái bởi một khoảng trắng và không có dấu cách, bất kể điểm bắt đầu / điểm kết thúc ở đâu.

Sử dụng ý tưởng của smls về squishing mê cung để tạo ra mỗi ô 1x1 và loại bỏ các mũi tên lặp đi lặp lại từ đầu ra.

Ungolfed và giải thích

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
)

Kiểm tra đoạn trích


1

Võng mạc , 416 byte

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

Hãy thử trực tuyến! Tôi đã thấy câu hỏi này khi nó được đăng lần đầu, đây có lẽ là câu trả lời tôi sẽ đưa ra, vì vậy dù sao tôi cũng sẽ đăng nó, mặc dù có câu trả lời hay hơn ở Retina. Giải trình:

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

Điền vào đường viền. Điều này tránh đi bộ xung quanh bên ngoài mê cung (ví dụ cho trường hợp thử nghiệm 7).

I
#

Đặt một điểm đánh dấu không chữ cái ở lối vào.

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

Lấp đầy từ lối ra đến lối vào. Ở mỗi bước, sử dụng một chữ cái để chỉ hướng đi tốt nhất (wasd - điều này có thể quen thuộc với các game thủ; tôi cũng đã xem xét hjkl nhưng tôi thấy nó quá khó hiểu). Ngoài ra, thích lặp lại cùng một hướng; điều này tránh đi sang trái / phải ở giữa hai ô liền kề theo chiều dọc.

^
w¶

Giả sử bước đầu tiên là xuống.

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

Nhưng nếu có một chữ cái ở trên, bên trái hoặc bên phải của lối vào, hãy thay đổi nó thành bước đầu tiên.

{`^(.*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 

Di chuyển điểm đánh dấu theo hướng di chuyển cuối cùng, đọc hướng di chuyển tiếp theo từ hình vuông mà điểm đánh dấu đang di chuyển đến và thêm nó vào danh sách các hướng. Điều này lặp lại cho đến khi Uđạt được.

s`U.*

Xóa mọi thứ sau các hướng dẫn vì nó không cần thiết nữa.

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

Lưới ban đầu nằm trên bố cục 3 × 2. Trong khi di chuyển theo chiều dọc nếu chúng ta zig-zag theo chiều ngang, vùng lũ sẽ tối ưu hóa chuyển động và chỉ di chuyển 3n-1 ký tự theo chiều ngang, vì vậy khi chia cho ba, chúng ta cần làm tròn lên. Theo chiều dọc, chúng tôi chỉ chia cho 2.

Tôi cũng đã nghiên cứu một giải pháp lưới vuông thực sự, tức là trong đó ma trận ký tự là hình vuông chứ không phải là bố cục 3 × 2 với đường viền tùy chọn. Mặc dù có thể không phù hợp với câu hỏi, khả năng chuyển đổi đã giảm số byte xuống còn 350: Hãy thử trực tuyến!


Câu trả lời hay, +1! Tôi thấy trong liên kết TIO của bạn, bạn đã thêm hai -xung quanh cả ký tự lối vào và lối ra. Vì thử thách chủ yếu là đi xuyên qua mê cung, tôi đoán nó ổn, nhưng tôi tò mò: vấn đề là gì khi bạn không đặt những bức tường đó lên trên / bên dưới IU? Ngoài ra, bạn có thể xác minh công việc này cho trường hợp thử nghiệm 7 với IUở trên cùng thay vì hai bên không? TIO vượt quá giới hạn 60 giây, vì vậy tôi không thể tự kiểm tra. Mặc dù đọc lời giải thích của bạn về lần đầu tiên cố gắng đi xuống theo mặc định, tôi cho rằng nó sẽ hoạt động tốt.
Kevin Cruijssen

@KevinCruijssen Câu trả lời "phụ" hoạt động cho trường hợp thử nghiệm 7 nhưng yêu cầu thêm ký tự: Hãy thử trực tuyến! tiếp tục ...
Neil

@KevinCruijssen Câu trả lời "chính" có một lỗi mà theo đó nó không thể đối phó với lối ra trên dòng trên cùng. Nó cũng có một lỗi tương tự như câu trả lời "phụ", theo đó nó thích đi bộ bên ngoài mê cung nếu có thể. (Ngoài ra, tôi đã không nhận được bất cứ nơi nào gần giới hạn 60 giây.)
Neil

Trên thực tế, tôi có thể sửa cả hai câu trả lời bằng cách điền vào đường viền. Tôi sẽ làm điều đó sau khi tôi có thời gian.
Neil
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.