Mở khóa bí mật cho mê cung 1 chiều


41

Lý lịch

Bạn tỉnh táo để thấy mình lạc vào một mê cung một chiều! Một vị thần bí (hoặc một cái gì đó) xuất hiện và giải thích rằng lối ra nằm trước mặt bạn, nhưng giữa bạn và lối ra là một loạt các thử thách. Khi bạn đi lang thang về phía trước, bạn nhận ra rằng tất cả những thách thức được gọi là chỉ là những cánh cửa bị khóa. Trước tiên, bạn nhìn thấy một cánh cửa có lỗ khóa hình chữ T và không có phím nào như vậy, tự tìm lại các bước của mình, tìm kiếm một chìa khóa có Thình dạng.

Thất vọng, bạn tìm thấy một bát súp bảng chữ cái trên mặt đất, không cái nào khớp với cánh cửa bạn đi qua. Bằng một số đột quỵ của thiên tài (hoặc thành ngữ), bạn quyết định rằng tkhóa hình chữ thường có thể có thể nằm gọn trong khe nếu bạn kẹt nó ở đó đủ mạnh. Khi bạn đến gần cánh cửa với tchìa khóa chữ thường trong tay, Tcái lỗ phát sáng màu xanh lá cây và cánh cửa tan biến trước mặt bạn.

Một xuống, nhiều hơn nữa để đi ...

Thử thách

Mục tiêu của thử thách này là đánh dấu bạn cần bao nhiêu bước để thoát khỏi mê cung.

Đầu vào của thử thách này là mê cung: một chuỗi chỉ chứa các ký tự [A-Za-z^$ ]. Bảng chú giải:

  • ^- Không gian bắt đầu. Đầu vào sẽ chứa chính xác một ^.
  • $- Lối ra (tự do!). Đầu vào sẽ chứa chính xác một $.
  • [A-Z]- Chữ in hoa biểu thị cửa. Bạn chỉ có thể đi qua cánh cửa này nếu bạn đã thu thập được chìa khóa cần thiết.
  • [a-z]- Chữ thường viết tắt các phím. Bạn thu thập các phím này bằng cách đi vào khoảng trống chứa khóa.

Sẽ có nhiều nhất một chữ cái viết hoa trong đầu vào. Điều này có nghĩa là tổng số cửa sẽ nằm trong khoảng 0-26.

Mỗi cánh cửa bị khóa [A-Z]sẽ có chính xác một phím chữ thường tương ứng [a-z]. Có thể có bất kỳ số lượng khoảng trắng ( ) trong đầu vào.

Tất cả các cửa sẽ ở bên phải của điểm bắt đầu và bên trái lối ra. Do đó, sẽ không có cửa thừa. Tất cả các đầu vào sẽ được giải quyết.

Đầu ra cho thử thách này sẽ là một con số, số bước cần thực hiện để thoát khỏi mê cung.

Thuật toán

Phương pháp tiếp cận có phương pháp của bạn để thoát khỏi nơi tồi tệ này như sau:

  • Bắt đầu từ đầu ( ^) và di chuyển về phía trước (phải) để thu thập bất kỳ khóa nào bạn gặp.
  • Khi bạn đi qua một cánh cửa, nếu bạn có chìa khóa chính xác, bạn tiến lên phía trước cánh cửa. Nếu bạn không có chìa khóa chính xác, bạn đi ngược (trái) thu thập các phím bạn gặp cho đến khi bạn tìm thấy chìa khóa cho cánh cửa gần đây nhất mà bạn không thể mở.
  • Khi bạn thu thập chìa khóa cho cánh cửa rắc rối hiện tại, bạn quay lại bên phải và tiếp tục.
  • Lặp lại quá trình này cho đến khi bạn bước vào exit ( $).

Những người chơi golf có kinh nghiệm sẽ hiểu rằng mã của bạn không phải thực hiện thuật toán cụ thể này miễn là nó mang lại kết quả giống như khi bạn chạy thuật toán này.

Đếm

Mỗi lần bạn bước từ hình vuông này sang hình vuông khác, nó được tính là một bước. Quay 180º không phát sinh thêm bước. Bạn không thể bước lên cửa mà không có chìa khóa cần thiết. Bạn phải bước lên một chìa khóa để nhặt nó lên, và phải bước lên lối ra để giành chiến thắng. Sau lần di chuyển đầu tiên của bạn, không gian bắt đầu ( ^) hoạt động giống như mọi không gian thông thường khác.

Ví dụ

Trong những ví dụ này, tôi đã để lại khoảng trống dưới dạng dấu gạch dưới cho khả năng đọc của con người.

Đầu vào là _a_^_A__$__. Đầu ra là 11. Bạn 1bước về phía trước, nhận thấy rằng bạn không có chìa khóa cho Acánh cửa, và sau đó về mặt. Bạn đi lùi về phía sau cho đến khi bạn chiếm không gian chứa a( 3bước lùi, bây giờ là 4tổng số). Sau đó, bạn đi về phía trước cho đến khi bạn chiếm không gian chứa lối ra ( 7bước về phía trước, 11tổng số).

Đầu vào là b__j^__a_AJB_$. Đầu ra là 41Bạn thực hiện hai chuyến đi riêng biệt đến phía sau mê cung, một chuyến để lấy jchìa khóa và chuyến tiếp theo để lấy bchìa khóa.

Đầu vào là __m__t_^__x_T_MX_$____. Đầu ra là 44. Bạn sẽ không thực hiện thêm bất kỳ chuyến đi nào để lấy xchìa khóa, khi bạn nhặt nó trên đường từ đầu đến cửa T.

Đầu vào là g_t_^G_T$. Đầu ra là 12. Bạn không thể di chuyển lên Gkhông gian mà không có chìa khóa, và ngay lập tức đối mặt. Bạn đủ may mắn để nhặt tchìa khóa trên đường đến gchìa khóa, và do đó mở cả hai cánh cửa trên đường đến tự do.

Đầu vào là _^_____$. Đầu ra là 6. Điều đó thật dễ dàng.

Nguyên tắc I / O và tiêu chí chiến thắng

Quy tắc I / O tiêu chuẩn được áp dụng. Đây là một thách thức .


17
Ngoài thử thách thú vị, tôi muốn nhận xét cách diễn đạt và giải thích tốt như thế nào
Luis Mendo

4
"Như vậy sẽ không có cửa thừa." Tôi nghĩ rằng Atrong bA^aB$sẽ không được thừa một trong hai. ;)
Martin Ender

4
@orlp Tôi thích thú hơn khi thấy mọi người chơi thuật toán lang thang trong bóng tối này. Có vẻ tầm thường khi thực hiện giải pháp tối ưu là "đi lấy tất cả chìa khóa rồi mở tất cả các cửa".
turbulencetoo

2
@PeterTaylor và turbulencetoo Không phải vậy, ai sẽ nói tất cả các phím nằm ở bên trái và tất cả các cửa ở bên phải? Và chìa khóa / cửa không cần thiết cũng sẽ rất thú vị. Nó sẽ khá thú vị, vì nó có nghĩa là giải quyết một biểu đồ phụ thuộc.
orlp

5
Mỗi cánh cửa đều có chìa khóa. Có phải tất cả các chìa khóa có một cánh cửa?
dùng2357112

Câu trả lời:


3

CJam, 45

1q_'$#<'^/~\W%:A;ee{~32+A#)_T>{:T+2*+}&]0=)}/

Dùng thử trực tuyến

Giải trình:

1         initial step count; this 1 is actually for the last step :)
q_'$#<    read the input and only keep the part before the '$'
'^/~      split by '^' and dump the 2 pieces on the stack
\W%:A;    take the first piece, reverse it and store it in A
ee        enumerate the other piece (making [index char] pairs)
{…}/      for each [index char] pair
  ~32+    dump the index and character on the stack, and add 32 to the character;
           uppercase letters become lowercase and other chars become garbage
  A#)     find the index of this character in A and increment it (not found -> 0)
  _T>     check if this index (number of steps from '^' back to the key)
           is greater than T (which is initially 0)
  {…}&    if that's true (we need to go back), then
    :T    store that index in T (keeping track of how far we go back before '^')
    +     add to the other index (from the pair, number of steps we took after '^')
    2*    double the result (going back and forth)
    +     add it to the step count
  ]0=     keep only the first value from the bottom of the stack (step count)
           (if the condition above was false, we'd have 2 extra values)
  )       increment the step count (for the current step)

7

Bình thường, 51 byte

JxQ"^"K-xQ"$"JVQI&}NrG1>JxQrN0=JxQrN0=+K*2t-xQNJ;pK

tổng khoảng cách giữa cửa và chìa khóa của nó (nhân đôi, để thực hiện chuyến đi khứ hồi), bỏ qua các phím "lồng" và khoảng cách từ đầu đến cuối:

JxQ"^"                                              #Initialize the farther point with the starting position
      K-xQ"$"J                                      #Initialize the step counter with the difference between the exit and the start
              VQ                                    #iterate over the input
                I&}NrG1>JxQrN0                      #check if is upper and if the keys is father than one stored (to eliminate nested keys)
                              =JxQrN0               #update the farther key
                                     =+K*2t-xQNJ;   #update step counter with the round trip door<>key
                                                 pK #print the step counter

cùng đại số trong python2.7:

lab=raw_input()
farther_key=lab.index('^')
steps = lab.index('$') - farther_key
for i in lab:
    if i.isupper():
        if farther_key> lab.index(i.lower()):
            farther_key=lab.index(i.lower())
            steps+=((lab.index(i) - farther_key)-1)*2
print steps

5

Python 2, 155 154 134 128 byte

Chỉnh sửa: Cảm ơn @ user2357112 và @loovjo vì những bình luận của họ đã giúp tôi loại bỏ 20 26 byte khác khỏi giải pháp của mình!

def f(l):
 i=l.index;b=i('^');t=i('$')-b
 for d in filter(str.isupper,l):
  k=i(d.lower())
  if k<b:b=k;t+=2*(i(d)-k-1)
 print t

1
Bạn có thể kết hợp dòng thứ hai và thứ ba với dấu chấm phẩy, tiết kiệm một byte. Ngoài ra, biến i có vẻ không cần thiết trong vòng lặp.
Loovjo

Đồng ý trên dòng thứ 2 và thứ 3, @Loovjo, nhưng tại sao bạn nói ilà không cần thiết? itheo dõi vị trí của cửa hiện đang được xử lý và được yêu cầu nếu khóa của nó chưa được chọn (nghĩa là nếu k- vị trí của khóa - nhỏ hơn f- cách xa nhất chúng ta đã đi - thì chúng ta cần thêm 2*(i-k-1)bước tới tổng số của chúng tôi (đi bên trái để lấy chìa khóa và đi bộ trở lại cửa) ...?
Ken 'Joey' Mosher

1
Nhưng không ithể thay thế bằng l.index(d)dòng thứ năm và chuyển nhượng bằng cách loại bỏ ở dòng thứ tư?
Loovjo

Các biến efcác biến trông có vẻ dư thừa. Ngoài ra, bạn có thể lưu một loạt các ký tự bằng cách lưu l.indexvào một biến.
dùng2357112

@loovjo: Yup, bạn nói đúng ... Tôi đã hiểu nhầm ý kiến ​​của bạn lúc đầu. @ user2357112: hoàn toàn chính xác. xlà dư thừa là tốt. Đoán noob-iness golf của tôi đang hiển thị. :) Cảm ơn đã giúp đỡ!
Ken 'Joey' Mosher

4

C, 136 byte

q,x,p[300],z,c,k;main(i){for(;p[c=getchar()]=++i,c-36;z&&(k+=(x=p[c+32])&&x<q?(q=q>x?x:q,2*i-2*x-1):1))z=p[94],q||(q=z);printf("%d",k);}

4

PHP 5.3, 123 byte

Đây là bài đăng đầu tiên của tôi trên Code Golf, hy vọng đây là bài có chất lượng golf đủ cao cho bài đầu tiên. Chắc chắn là một thử thách thú vị và một câu hỏi tuyệt vời!

function n($m){while('$'!=$o=$m[$i++])$o=='^'?$b=$i+$c=0:$o>'Z'||$b<=$k=stripos($m,$o))?$c++:$c+=2*$i-3-2*$b=$k;return$c;}

Chương trình này lạm dụng một cách độc đáo thực tế rằng PHP không cần bạn khai báo trước bất kỳ biến nào trước khi bạn sử dụng chúng.

Nó cũng hóa ra là một vài byte ngắn hơn trong giải pháp cuối cùng của tôi để bắt đầu từ 0 và đặt lại số bước khi tìm thấy ký tự bắt đầu, thay vì bắt đầu từ '^'.

Bất kỳ lời khuyên chắc chắn được chào đón!


3

JavaScript (ES6), 110 byte

s=>(i=c=>s.indexOf(c),p=i`^`,l=i`$`-p,s.replace(/[A-Z]/g,(c,j)=>p>(t=i(c.toLowerCase()))?l+=j-(p=t)-1<<1:0),l)

Cảng của câu trả lời Pyth @ Rob.


2

Python 2.7, 234 199 179

a=raw_input()
x=a.index
v=x('^')
b=x('$')-v
l=filter(str.islower,a[:v])[::-1]
for i in filter(str.isupper,a):
 k=i.lower()
 if k in l:b+=(x(i)-x(k)-1)*2;l=l[l.index(k)+1:]
print b

1

AWK, 174 byte

func f(xmS){x+=S
c=a[x]
if(c~/^[A-Z]/&&!k[c]){C=c
S=-S
s--}else{c=toupper(c)
k[c]=1
s++
if(c==C){S=-S;C=9}}if(c=="$"){print s}else f(x,S)}{split($0,a,"")
f(index($0,"^"),1)}

Có lẽ có một thuật toán chặt chẽ hơn, nhưng đây là những gì tôi nghĩ ra.

Xin lưu ý rằng tôi đang sử dụng gawk. Một số triển khai AWKcó thể không phân tách một chuỗi ""theo cách này.


1

C #, 309 byte

class P{static void Main(string[]a){string m=Console.ReadLine(),k="";var f=true;char b,c=b=' ';int j=m.IndexOf('^'),t=0;for(;m[j]!='$';j+=f?1:-1){c=m[j];if(char.IsUpper(c)){if(k.IndexOf(char.ToLower(c))<0){f=!f;b=c;t--;}}if(char.IsLower(c)){k+=c;if(char.ToUpper(c)==b){f=!f;t--;}}t++;}Console.WriteLine(t);}}

Phiên bản bị đánh cắp:

    class P
{
    static void Main(string[] a)
    {
        string m = Console.ReadLine(), k = "";
        var f = true;
        char b, c = b = ' ';
        int j = m.IndexOf('^'), t = 0;
        for (; m[j] != '$'; j += f ? 1 : -1)
        {
            c = m[j];
            if (char.IsUpper(c))
            {
                if (k.IndexOf(char.ToLower(c)) < 0)
                {
                    f = !f; b = c; t--;
                }
            }

            if (char.IsLower(c))
            {
                k += c;
                if (char.ToUpper(c) == b) { f = !f; t--; }
            }


            t++;
        }
        Console.WriteLine(t);
        Console.ReadKey();

    }
}

Không có gì lạ mắt ở đây, chỉ cần lặp qua chuỗi và thay đổi hướng dựa trên ký tự và liệu khóa có được chứa trong chuỗi khóa hay không.

m = chuỗi mê cung

k = chuỗi phím

f = hướng (đúng là chuyển tiếp trong mê cung)

b = chìa khóa để tìm kiếm khi quay lại

c = giữ chỗ cho m [j] để lưu một số byte do sử dụng thường xuyên

j = chỉ số char của chuỗi cần xem xét

t = số

Vẫn còn khá mới mẻ đối với việc chơi golf vì vậy nếu bạn thấy ở đâu đó tôi có thể giảm nó xuống, hãy cho tôi biết!

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.