Xe của bạn chỉ rẽ phải!


49

Giới thiệu

Bạn có bất hạnh khi bị mắc kẹt trong một chiếc xe chạy trên một chướng ngại vật. Tất cả các tính năng của xe đều không phản hồi, tiết kiệm cho hệ thống lái bị hỏng. Nó có thể lái thẳng, hoặc nó có thể rẽ phải. Xe có thể được hướng dẫn an toàn?

Cơ học

Xe của bạn bắt đầu ở góc trên bên trái của bản đồ 8x8 và đang cố gắng đến nơi an toàn ở góc dưới bên phải. Chiếc xe có một hướng (ban đầu bên phải), được đo theo gia số 90 độ. Chiếc xe có thể thực hiện một trong hai hành động:

  1. Lái một ô vuông về phía trước, hoặc
  2. Xoay 90 độ theo chiều kim đồng hồ, sau đó lái xe về phía trước một hình vuông

Lưu ý rằng chiếc xe không thể quay đủ mạnh để thực hiện quay 180 độ trên một ô vuông duy nhất.

Một số hình vuông là trở ngại. Nếu chiếc xe đi vào một quảng trường chướng ngại vật, nó bị đâm. Tất cả mọi thứ bên ngoài khóa học 8x8 được coi là chướng ngại vật, vì vậy lái xe ra khỏi khóa học tương đương với tai nạn.

Hình vuông bên phải phía dưới là hình vuông an toàn, cho phép chiếc xe thoát khỏi chướng ngại vật. Hình vuông bắt đầu và hình vuông an toàn được giả định không phải là trở ngại.

Bài tập, nhiệm vụ

Bạn phải viết một chương trình hoặc hàm lấy đầu vào là một mảng 8x8 (ma trận, danh sách các danh sách, v.v.), đại diện cho khóa học vượt chướng ngại vật. Chương trình trả về hoặc in Boolean, hoặc một cái gì đó tương tự như sự thật. Nếu chiếc xe có thể đi đến quảng trường an toàn mà không gặp sự cố (nghĩa là nếu bản đồ có thể giải quyết được) True, thì ngược lại, đó là đầu ra False.

Chấm điểm

Quy tắc golf mã tiêu chuẩn - người chiến thắng là mã có ít byte nhất.

Tiền thưởng:

  • Nếu, đối với bản đồ có thể giải được, mã của bạn đưa ra một loạt các đầu vào trình điều khiển hợp lệ hướng dẫn chiếc xe đến quảng trường an toàn, trừ 10 điểm phần trăm từ điểm số của bạn. Một định dạng đầu ra ví dụ có thể là SRSSR(biểu thị Straight, Right, Straight, Straight, Right). Đầu ra này sẽ thay thế Trueđầu ra tiêu chuẩn .

  • Nếu, đối với bản đồ không thể giải quyết, đầu ra mã của bạn phân biệt giữa các tình huống không thể tránh khỏi sự cố và các tình huống có thể lái xe quanh chướng ngại vật mãi mãi, trừ 10 điểm phần trăm từ điểm số của bạn. Một ví dụ đầu ra có thể là Crashnếu một vụ tai nạn là không thể tránh khỏi, hoặc Stucknếu chiếc xe bị kẹt trong quá trình vượt chướng ngại vật mãi mãi. Những đầu ra này sẽ thay thế Falseđầu ra tiêu chuẩn cho một bản đồ không thể phá hủy.

Thí dụ

Nếu chương trình được cung cấp một mảng 8x8 như thế này:

[[0, 0, 0, 0, 0, 1, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 0], 
 [1, 1, 0, 0, 0, 0, 0, 0], 
 [0, 1, 0, 1, 0, 0, 0, 0], 
 [0, 0, 1, 1, 0, 0, 0, 0], 
 [0, 0, 0, 0, 1, 0, 1, 0], 
 [0, 0, 0, 0, 0, 0, 1, 0], 
 [0, 1, 1, 0, 0, 0, 1, 0]]

Nó sẽ được hiểu là một bản đồ như thế này, với các ô vuông màu đen biểu thị chướng ngại vật:

nhập mô tả hình ảnh ở đây

Và một giải pháp khả thi có thể là:

nhập mô tả hình ảnh ở đây

Vì một giải pháp tồn tại, chương trình sẽ trả về / in Truecho bản đồ này. Trình tự di chuyển được hiển thị ở đây là SSSSRSRRRSRSSRRRSSRSSS.


2
Tôi đã viết một số trường hợp thử nghiệm cực kỳ đơn giản cho CrashStuck. Họ ở đây vì họ bao lâu. Hàng 2 đầy, mọi thứ khác trống -> Crash. Hàng 7 đầy, mọi thứ khác trống ->Stuck
ngầmmonailail

3
Tôi bối rối về điểm phần trăm (trái ngược với tỷ lệ phần trăm). Nhận một trong hai phần thưởng nhân số điểm của bạn bằng 0,9. Có phải cả hai nhân nó với 0,8 hoặc 0,9 ^ 2?
ngầmmonailail

3
Chắc chắn, S và C đều ổn. Đầu ra của tôi chỉ là đề xuất.
phosgene

13
"Hai cái sai không tạo nên một cái đúng, nhưng ba cái sai thì có." - Cha.
hoosierEE

2
"Xe của bạn chỉ có thể tạo ra không hoặc ba lần!"
frageum

Câu trả lời:


17

JavaScript (ES6) - 122 124 148 162 172 178 187 190 193 208 byte

Rất cám ơn Trình tối ưu hóa và DocMax về các đề xuất hữu ích về cách cải thiện mã này:

F=a=>(D=(x,y,d)=>!D[i=[x,y,d]]&&(D[i]=1,x-=~d%2,y-=~-~d%2,x*y==49||!((x|y)&8||a[y][x])&&(D(x,y,d)||D(x,y,~-d%4))),D(-1,0))

Trả về true(trung thực) cho khả năng giải quyết và false(giả) cho không thể giải quyết.

Chỉ hoạt động trong Firefox tính đến ngày hôm nay vì các tính năng của JavaScript 1.7.

Ban kiểm tra


1
Đây là 193 byte : D=(x,y,d,t,a)=>!t[i=x+y*8+d*64]&&(t[i]=1,x+=d==0?1:d==2?-1:0,y+=d==1?1:d==3?-1:0,x==7&&y==7||!((x|y)&~7||a[y][x])&&G(x,y,d,t,a));G=(x,y,d,t,a)=>D(x,y,d,t,a)||D(x,y,d+1&3,t,a);F=a=>G(0,0,0,[],a).
Trình tối ưu hóa

1
172: D=d=>!t[i=x+y*8+d/4]&&(t[i]=1,x+=d?d^2?0:-1:1,y+=d^1?d^3?0:-1:1,x==7&&y==7||!((x|y)&~7||b[y][x])&&G(x,y,d));G=(X,Y,d)=>D(d,x=X,y=Y)||D(d+1&3,x=X,y=Y);F=a=>G(0,0,0,b=a,t={})- Đã kiểm tra.
Trình tối ưu hóa

1
@Optimizer Tôi vẫn đúng cho trường hợp thử nghiệm thứ hai [[0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]. Điều đó sẽ cho sai.
tôi và con mèo của tôi

2
Đó là bởi vì xycả hai đều là toàn cầu, bạn không thể chạy hai bản thử nghiệm trước khi tải lại trang ...
Trình tối ưu hóa

1
Bạn có thể tiết kiệm tổng cộng 9 điểm nữa bằng cách thay thế x+=d?d^2?0:-1:1bằng x+=d&1?0:1-dy+=d^1?d^3?0:-1:1bằng y+=d&1&&2-d.
DocMax

10

Con trăn 2 - 123 125 133 146 148 150 154 160

Truevề thành công, Falsevề thất bại.

def f(h=1,v=0,b=0,x=0,y=0,c=[]):s=x,y,h,v;a=b,x+h,y+v,c+[s];return(s in c)==(x|y)&8==b[y][x]<(x&y>6or f(h,v,*a)|f(-v,h,*a))

Bạn phải cung cấp đầu vào như thế nào f(b=var_containing_board).

Phiên bản Lambda - 154

Trả về 0(giả) cho thất bại, Truecho thành công.

F=lambda b,x=0,y=0,h=1,v=0,c=[]:0if[x,y,h,v]in c or x|y>7or x|y<0 or b[y][x]else x&y==7or F(b,x+h,y+v,h,v,c+[[x,y,h,v]])or F(b,x+h,y+v,-v,h,c+[[x,y,h,v]])

Cảm ơn Will và Brandon vì đã làm cho chức năng ngắn hơn lambda. Ngoài ra để thêm nhiều cuộn ngang: D

Cảm ơn xnor cho bit bashing và logic cao cấp!

Chỉnh sửa ghi chú: Tôi tin tưởng một cách hợp lý rằng b[y][x]sẽ không bao giờ được thực thi khi đi ra khỏi phạm vi. Vì chúng tôi ở ngoài hội đồng quản trị, kiểm tra lịch sử s in csẽ được False. Sau đó, kiểm tra ranh giới (x|y)&8sẽ được 8. Sau đó, python thậm chí sẽ không kiểm tra giá trị cuối cùng ==bởi vì hai cái đầu tiên đã khác nhau.


1
Phiên bản chức năng có thể kết hợp hai if mà cả hai trả về; khi trả lại một mình trả về Không có gì là giả, bạn cũng không cần phải trả về 0. .chỉ trả lại sự giúp đỡ;)
Will

Nếu bạn lật séc, bạn cũng có thể kết hợp cả hai ifs
Sẽ

Bạn có thể kết hợp cả hai báo cáo trở lại?
Brandon

1
@ Sẽ cảm ơn, tôi biết có một cách tốt hơn để làm điều đó: D Um, tôi không thể tìm thấy bất kỳ khoảng trắng nào để xóa mà không gây ra lỗi cú pháp. Tôi thực sự không hiểu tại sao x|y>7orhoạt động nhưng x|y<0orkhông ...
FryAmTheEggman

1
Bạn có thể làm cho một bát phân bắt đầu bằng chữ 0o.
frageum

9

C (GNU-C), 163 byte * 0.9 = 146.7

#C (GNU-C), 186 byte * 0.9 = 167.4

Phiên bản mới của tôi sử dụng số nguyên đã ký thay vì không dấu. Trước đó tôi đã sợ ký hợp đồng thay đổi, nhưng tôi nhận ra vì bit dấu là bình phương mục tiêu, không có vấn đề gì xảy ra sau đó.

Hàm lấy một mảng các bit (đại diện cho các ô vuông bị chặn) dưới dạng số nguyên 64 bit. Các bit được sắp xếp ít nhất đến quan trọng nhất giống như cách bạn đọc một cuốn sách. Nó trả về -1 cho một vụ tai nạn, 0 cho việc lái xe mãi mãi hoặc 1 cho việc thoát ra góc dưới bên phải.

g(long long o) {
    typeof(o) a=0,i=255,r=1,u=0,l=0,d=0,M=~0LLU/i,D;
    for( ;i--;d = D<<8&~o)
        a |= D = d|r,
        r = (r|u)*2&~M&~o,
        u = (u|l)>>8&~o,
        l = ((l|d)&~M)/2&~o;
    return a<0?:-!(d|r|u|l);
}

Chương trình kiểm tra

f(long long o){typeof(o)a=0,i=255,r=1,u=0,l=0,d=0,M=~0LLU/i,D;for(;i--;d=D<<8&~o)a|=D=d|r,r=(r|u)*2&~M&~o,u=(u|l)>>8&~o,l=((l|d)&~M)/2&~o;return a<0?:-!(d|r|u|l);}
{
    char* s[] = {"Crash", "Stuck", "Escape"};
    #define P(x) puts(s[f(x)+1])
    L ex = 0x4640500C0A034020;
    P(ex);
    L blocked = 0x4040404040404040;
    P(blocked);

    L dead = 0x10002;
    P(dead);

    return 0;
}

Đầu ra

Escape
Stuck
Crash

Trình chuyển đổi mảng-to-hex của Python:

a2b=lambda(A):"0x%X"%sum(A[i/8][i%8]<<i for i in range(64))

1
Thay thế memset(&M,~1,8)(15 ký tự) bằng M=~(-1ULL/255)(14 ký tự).
R ..

@R .. Đẹp quá! -4 byte từ đó.
frageum

2
Tôi thích định dạng đầu vào - rất tuyệt!
phosgene

Tôi nhận được 'crash' for P(0x00fefefefefefefe);= (Nên bắn thẳng lên phía trên bên phải, một lượt, thẳng vào góc. Tương tự cho P(0x00eeeeeeeeeeeeee);(ngõ cụt trên col thứ 4). Tôi không nghĩ bạn cần chỉ định aban đầu.

@tolos Bạn đã chuyển đổi thứ tự hàng / cột chính. Để có hàng trên cùng và cột bên phải mở, nó phải được 0x7f7f7f7f7f7f7f00. Ngoài ra, cần phải khởi tạo abởi vì sau này nó chỉ được sửa đổi bằng cách ORing trong các bit bổ sung, vì vậy tôi không đủ khả năng để có một bit không mong muốn được thiết lập ban đầu.
frageum

6

Con trăn, 187 213

207 ký tự, tiền thưởng 10% cho đường dẫn in

b=map(ord," "*9+" ".join("".join("o "[i]for i in j)for j in input())+" "*9)
def r(p,d,s):
 p+=(1,9,-1,-9)[d]
 if b[p]&1<<d:b[p]^=1<<d;return(s+"S")*(p==79)or r(p,d,s+"S")or r(p,(d+1)%4,s+"R")
print r(8,0,"")

Trên đầu vào kiểm tra, nó tìm thấy một đường dẫn hơi khác: SSSSRSRSRRSSRSSRRSRSSRSSSSS

Cách tiếp cận chung là trước tiên biến đầu vào thành khoảng trắng và os. Các không gian có một hình lục giác 20, vì vậy tất cả bốn bit thấp hơn đều không được đặt. ocó một hex 6F, vì vậy bốn bit thấp được thiết lập.

Một đường viền của os được đặt xung quanh bảng để chúng ta không phải lo lắng về các chỉ số xấu.

Khi chúng tôi đi qua bảng, chúng tôi sử dụng các bit trong mỗi ô để xem liệu chúng tôi có được phép vượt qua khi đến từ phía đó không. Bằng cách này, chúng tôi tránh các vòng lặp vô hạn. Nó không đủ để có một boolean cho mỗi ô, vì hướng thoát của bạn phụ thuộc vào hướng vào của bạn, vì vậy các ô có thể được truy cập hai lần.

Sau đó chúng tôi thực hiện tìm kiếm đệ quy cho một con đường an toàn.


3
"Xe của bạn bắt đầu ở góc trên bên trái của bản đồ 8x8" - bạn không thể hardcode 9thay w=len(b[0])+1, vv?
FryAmTheEggman

@FryAmTheEggman cảm ơn bạn, làm thế nào tôi có thể bỏ qua điều đó? : D
Sẽ

Bạn có thể đảo ngược tuyên bố ternary của bạn và thay thế p==79bằng p-79. Tôi đã có một lỗi cú pháp làm điều này cả hai cách mà không có khoảng trắng trước else. Tôi nghĩ rằng mẹo đó chỉ hoạt động với if.
FryAmTheEggman

@FryAmTheEggman Tôi nghĩ bài kiểm tra chuyên sâu phải có trước khi tái diễn? Thay vào đó, tôi đã chơi với phép nhân bằng boolean.
Sẽ

7
Tôi chỉ tìm thấy một mẹo thực sự gọn gàng. Bạn có thể biết rằng -~x== x+1nhưng cả hai toán tử đơn nguyên có độ ưu tiên cao hơn phép nhân, phép chia và mô đun! Vì vậy, (d+1)%4có thể được -~d%4! Điều này cũng sẽ làm việc với x-1nhưng chỉ sử dụng ~-xthay thế.
FryAmTheEggman

6

Javascript - 270 - 20% = 216 262 - 20% = 210 byte

Vì phải có ít nhất một giải pháp kiếm được cả hai phần thưởng (và không dẫn đến độ sâu ngăn xếp vô lý;) ...

Giảm thiểu:

V=I=>{n=[N=[0,0,0]];v={};v[N]='';O='C';for(S='';n[0];){m=[];n.map(h=>{[x,y,d]=h;D=i=>[1,0,-1,0][d+i&3];p=v[h];for(j=2;j--;){O=v[c=[X=x+D(j),Y=y+D(3-3*j)),d+j&3]]?'K':O;J=X|Y;J<0||J>7||I[Y][X]||v[c]?O:(m.push(c),v[c]=p+'SR'[j])}S=(x&y)>6?p:S});n=m;}return S||O;};

Mở rộng:

V = I => {
    n = [N=[0,0,0]];
    v = {};
    v[N] = '';
    O = 'C';

    for( S = ''; n[0]; ) {
        m = [];
        n.map( h => {
            [x,y,d] = h;
            D = i => [1,0,-1,0][d+i&3];
            p = v[h];
            for( j = 2; j--; ) {
                O = v[c = [X = x+D(j),Y = y+D(3-3*j),d+j&3]] ? 'K' : O;
                J = X|Y;
                J<0 || J>7 || I[Y][X] || v[c] ? O : (
                    m.push( c ),
                    v[c] = p + 'SR'[j]
                );
            }

            S = (x&y) > 6 ? p : S;
        } );
        n = m;
    }
    return S || O;
};

vlà một hashtable với các khóa là bộ ba trạng thái (x,y,d)tương ứng với tọa độ (x, y) và hướng nhập cảnh d. Mỗi khóa có một giá trị liên quan là chuỗi di chuyển S(thẳng) và R(rẽ phải) cần thiết để đạt đến trạng thái được đại diện bởi khóa.

Mã này cũng duy trì một bộ ba (trong biến n) chưa được xử lý. Ngăn xếp ban đầu chỉ chứa bộ ba (0,0,0), tương ứng với trạng thái mà ô tô phải đối mặt ngay trong ô (0,0). Trong vòng lặp bên ngoài, for( S = ... )kiểm tra thường xuyên nếu còn ba lần chưa xử lý. Nếu vậy, nó chạy từng bộ ba chưa được xử lý thông qua vòng lặp bên trong , n.map( ....

Vòng lặp bên trong thực hiện năm điều:

  1. tính hai động tác có thể (lái thẳng, rẽ phải) ra khỏi trạng thái hiện tại
  2. nếu một trong những di chuyển này dẫn đến trạng thái đã được đăng ký trong hashtable, nó sẽ bị bỏ qua để xử lý thêm. KTuy nhiên, chúng tôi gắn cờ đầu ra FALSE là (bị kẹt), vì chúng tôi đã tìm thấy ít nhất một vòng lặp trong đó chiếc xe có thể tiếp tục vòng tròn mãi mãi mà không gặp sự cố.
  3. nếu một trạng thái là hợp pháp và mới lạ, nó sẽ được thêm vào hàm băm ( v) và vào ngăn xếp ba lần chưa được xử lý ( m) cho lần chuyển tiếp theo của vòng lặp bên ngoài
  4. khi trạng thái mới được đăng ký v, giá trị của nó được đặt thành giá trị của trạng thái ban đầu (chuỗi di chuyển) cộng Rhoặc Sdựa trên di chuyển hiện tại
  5. nếu xy7, giá trị của trạng thái khởi tạo (chuỗi di chuyển được thực hiện để đạt đến trạng thái ban đầu) được sao chép vào S, vì chuỗi di chuyển này là một giải pháp cho vấn đề

Sau khi vòng lặp bên trong chấm dứt, n(ngăn xếp) được thay thế bằng m(ngăn xếp mới).

Sau khi vòng lặp bên ngoài chấm dứt (không đạt được trạng thái mới), hàm sẽ trả về đầu ra của nó. Nếu đã đạt đến ô (7,7), Ssẽ chứa một chuỗi các bước di chuyển dẫn đến ô này và điều này được xuất ra. Nếu ô không đạt được, Ssẽ là chuỗi trống và thường trình rơi vào đầu ra O, nó sẽ chứa K(bị kẹt) nếu và chỉ khi một vòng lặp được tìm thấy, hoặc C(tai nạn) nếu xe chắc chắn sẽ gặp sự cố.


1
Nhận được xác nhận từ OP, bạn có thể đổi tên 'Crash' và 'Stuck' thành 'C' và 'S'.
FryAmTheEggman

Ah. Điều đó tiết kiệm một chút, sau đó. Cảm ơn. ;)
COTO

Bạn có thể giải thích những gì mã của bạn đang làm? Tôi không thể làm cho đầu hoặc đuôi của nó.
phosgene

@phosgene: Tôi đã bao gồm một lời giải thích chi tiết nội tuyến.
COTO

Đó là một thủ tục thông minh. Không có gì là lãng phí.
phosgene

4

Python 339 - 10% = 305 byte

Tôi đã sử dụng một tìm kiếm theo chiều sâu đệ quy, được kết thúc sớm khi thành công thông qua exit. Cũng in đường dẫn thành công ở dạng 00001010101010101010101110100111001000, 0cho thẳng, 1cho đúng. Câu trả lời sẽ dài hơn tối ưu, vì nó là chiều sâu. Tôi chắc chắn rằng một số tối ưu hóa cho thuật toán có thể làm giảm số lượng byte xuống một chút.

b=input()
D=[(-1,0),(0,-1),(1,0),(0,1)]
def a(l):
 x,y=0,0
 v=2
 for d in l:
  if d=='1':v=(v+1) % 4
  x+=D[v][0]
  y+=D[v][1]
  if x<0 or x>7 or y<0 or y>7:return 0,x,y
  if b[y][x]:return -1,x,y
 return 1,x,y
def c(l):
 if len(l) < 39:
  t,x,y=a(l)
  if t==1:
   if (x,y)==(7,7):
    print l;exit(0)
   c(l+"0")
   c(l+"1")
c("")
print 0

3
Do đây là Python 2, bạn có thể trộn các tab và không gian cho indents, giống như trong a's forvòng lặp. Bạn cũng không cần khoảng trắng xung quanh toán tử, ví dụ (v+1) % 4-> (v+1)%4. Bạn cũng có thể tham gia nhiều câu lệnh trên một dòng bằng cách sử dụng ;nếu không có ifhoặc for, vv trên dòng, ví dụ c(l+"0");c(l+"1"). Một số Tất chơi gôn khác: x,y,v=0,0,2, x|y>7 or x|y<0, x==y==7. Chúc may mắn :)
FryAmTheEggman
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.