Chuyển động robot hiệu quả


24

Tuyên bố miễn trừ trách nhiệm: Câu chuyện được kể trong câu hỏi này hoàn toàn hư cấu và được phát minh chỉ nhằm mục đích cung cấp phần giới thiệu.

Ông chủ của tôi đã nhận được một robot đồ chơi mới, và ông ấy muốn tôi giúp lập trình nó. Anh ta muốn có thể nhập các hướng dẫn mũi tên đơn giản để làm cho nó di chuyển. Các hướng dẫn này là: ^ (để di chuyển về phía trước) <(cho rẽ trái) và> (cho rẽ phải). Tuy nhiên, bây giờ tôi đã lập trình robot, anh ta muốn có thêm chức năng. Anh ta muốn tôi biến đổi bất kỳ chuỗi mũi tên nào mà anh ta nhập vào, thay vì để robot đi theo chỉ dẫn, nó di chuyển đến vị trí mong muốn, được chỉ định bởi nơi nó sẽ kết thúc nếu nó đi theo đường đi vào, một cách hiệu quả như khả thi. Tôi kêu gọi bạn, các thành viên của PP & CG, giúp tôi thực hiện nhiệm vụ này.

Nhiệm vụ của bạn:

Viết chương trình hoặc hàm để chuyển đổi một chuỗi được tạo thành từ các mũi tên thành một chuỗi sẽ đến vị trí được chỉ định bởi đầu vào càng nhanh càng tốt. Quay mất chính xác miễn là di chuyển lùi hoặc tiến.

Đầu vào:

Một chuỗi các mũi tên, như được chỉ ra ở trên. Nếu bạn muốn, các ký tự khác nhau có thể được thay thế cho các mũi tên, nhưng hãy chắc chắn bao gồm thực tế là bạn làm như vậy trong câu trả lời của bạn. Tất cả các trường hợp thử nghiệm sử dụng các mũi tên bình thường.

Đầu ra:

Một chuỗi các mũi tên (hoặc các ký tự tương đương của bạn), đưa robot đến đích mong muốn một cách hiệu quả nhất có thể.

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

Lưu ý rằng các giải pháp được cung cấp chỉ là các khả năng và các giải pháp khác có thể hợp lệ.

>^<<^^>^^    -> ^^<^
^^^^>^^^^    -> ^^^^>^^^^
>>>^^^^^^    -> <^^^^^^
>^>^>^>^     -> (empty string)
^<^^<^^<^^^^ -> >^^>^

Ghi điểm:

Bộ nhớ của robot bị giới hạn, vì vậy chương trình của bạn phải có số byte thấp nhất có thể.


Bởi vì trong đầu vào, robot kết thúc chính xác nơi nó bắt đầu, vì vậy không có lệnh nào là cần thiết để di chuyển nó đến đó hiệu quả nhất có thể.
Gryphon - Tái lập Monica

Oh, đọc sai chuỗi. Lỗi của tôi.
JungHwan Min

Yêu cầu thử nghiệm trường hợp ^<^^<^^<^^^^-> >^^>^?
JungHwan Min

1
@pizzakingme, xin lỗi, nhưng sếp của tôi rất lười biếng và chỉ muốn gõ một ký tự cho mỗi chuyển động.
Gryphon - Tái lập Monica

1
Tôi lập trình robot cạnh tranh và tôi có thể xác nhận đây chính xác là cách chúng hoạt động.
Joe

Câu trả lời:


9

Võng mạc , 103 74 71 byte

<
>>>
+`(>(\^*>){3})\^
^$1
+`\^(>\^*>)\^
$1
>>(\^*)>(\^+)
<$2<$1
<?>*$

Hãy thử trực tuyến!Liên kết bao gồm các trường hợp thử nghiệm. Giải trình:

<
>>>

Rẽ trái rẽ thành ba rẽ phải.

+`(>(\^*>){3})\^
^$1

Giảm tất cả các lượt modulo 4.

+`\^(>\^*>)\^
$1

Hủy bỏ các phong trào theo hướng ngược lại.

>>(\^*)>(\^+)
<$2<$1

Rẽ ba rẽ phải trở lại rẽ trái. Điều này cũng xử lý các trường hợp >>^>^cần phải trở thành<^<^ .

<?>*$

Xóa các dấu vết không cần thiết.


Ấn tượng. Tôi biết rằng phải có một cách để có được 100 byte phụ này trong một số ngôn ngữ và câu trả lời của bạn đã rất gần trước đó. +1
Gryphon - Phục hồi Monica

6

Toán học, 135 byte

{a="^"~Table~Ramp@#&;a@#,s=If[#2>0,">","<"],a@Abs@#2,If[#<0,s,""],a@-#}<>""&@@ReIm[j=0;i=1;Switch[#,">",i*=I,"<",i/=I,"^",j+=i]&/@#;j]&

Lấy một Listchuỗi làm đầu vào.

Giải trình

j=0;i=1

Đặt jthành 0 và đặt ithành 1.

/@#

Đối với mỗi ký tự trong đầu vào ...

Switch[#,">",i*=I,"<",i/=I,"^",j+=i]

Nếu nhân vật là >, nhân ivới đơn vị tưởng tượng. Nếu nhân vật là >, chia icho đơn vị tưởng tượng. Nếu nhân vật là ^, thêm ivào j.

ReIm[ ... ;j]

Lấy phần thực và tưởng tượng của j. Điều này mang lại cho tọa độ Cartesian của robot.

... &@@

Áp dụng như sau vào kết quả này:


a="^"~Table~Ramp@#&;

Đặt athành một hàm tạo ra một chuỗi có (input)hoặc 0ký tự ^s, tùy theo giá trị nào lớn hơn.

{ ... }

Một Listbao gồm ...

a@#

aáp dụng cho đầu vào đầu tiên (phần thực của j)

s=If[#2>0,">","<"]

Nếu đầu vào thứ hai (phần ảo của j) lớn hơn 0, >. Nếu không , <. Đặt sthành ký tự kết quả.

a@Abs@#2

a áp dụng cho giá trị tuyệt đối của đầu vào thứ hai.

If[#<0,s,""]

Nếu đầu vào đầu tiên nhỏ hơn 0 , s. Nếu không, chuỗi rỗng.

a@-#

Áp dụng acho lần đầu vào âm một.

... <>""

Tham gia chuỗi.


2

Toán học 119 byte

Vị trí cuối cùng của mã đường dẫn của JungHwan ngắn hơn của tôi, vì vậy sử dụng nó. Tôi nghĩ có lẽ có một cách thậm chí còn ngắn hơn để làm điều này ...

Tôi sử dụng AnglePathchức năng tích hợp để quyết định vị trí cuối cùng. Tôi cũng xác định các ký hiệu L, F và R cho "<", "^" và ">", để lưu một vài ký tự trích dẫn.

L={0,Pi/2};R=-L;F={1,0};{a="F"~Table~Ramp@#&;a@#,s=If[#2>0,"L","R"],a@Abs@#2,If[#<0,s,""],a@-#}<>""&@@Last@AnglePath@#&

Sử dụng:

%@{R,F,L,L,F,F,R,F,F}

Đầu ra:

FFLF

2

Ruby , 130 byte

->s{w,d=0,1;s.bytes{|b|b>93?w+=d:d*=1i*(b<=>61)};r,c=w.rect;[w=(d=">><"[c<=>0])+?^*c.abs,?^*r.abs+w,w+d+?^*r.abs][r<=>0].chomp ?>}

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

->s{
    # We start from (0,0i), direction is +1
    w,d=0,1

    s.bytes{|b|
        # If it's ASCII 94, go one step forward,
        # else multiply direction by +i or -i
        b>93?w+=d:d*=1i*(b<=>61)
    }

    # Get the rectangular representation of the result
    r,c=w.rect

    # Now, create 2 strings of "^" (call them x and y) for horizontal and vertical moves
    # And a single ">" or "<" (call it d) for the direction change
    # If x>0, output x+d+y
    # If x==0, output d+y
    # If x>0, output d+y+d+x
    [w=(d=">><"[c<=>0])+?^*c.abs,?^*r.abs+w,w+d+?^*r.abs][r<=>0]

    #If y==0 we get an extra ">" sometimes
    .chomp ?>
}

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


2

J, 90 byte

dung dịch

t=.{&' ><'@*
g=.'^'#~|
(t,g@{.,t@-@(*/),g@{:`g@{:,t@{.,g@|@{.@.(0<:{:))@+.@(+/)@(=&1*j.**/\)

giải trình

có một mẹo gọn gàng bằng cách sử dụng các số phức (nhân với i là xoay trái 90 độ và -i cho bạn một số phải).

vì vậy chúng tôi lấy đầu vào là số phức: 1 đại diện cho "đi về phía trước" và i / -i đại diện cho rẽ trái và phải.

vị trí cuối cùng được tính toán dễ dàng với đại diện này. Lưu ý đây là phần đầu tiên (ngoài cùng bên phải) trong biểu thức cuối cùng của tôi ở trên:

(+/)@(=&1*j.**/\)

Dòng ngắn trên là những gì giải quyết vấn đề. Mọi thứ khác chỉ là tìm ra cách định dạng câu trả lời, và chắc chắn có thể bị đánh golf xuống nhiều hơn đáng kể.

Để hiểu dòng ngắn ở trên, lưu ý rằng */\(quét các sản phẩm một phần) cung cấp cho bạn danh sách các vị trí bạn đang đối mặt tại mỗi chỉ số trong đầu vào: i ở phía bắc, 1 và -1 là phía đông và phía tây và -i là phía nam . Nhưng vì chúng ta bắt đầu hướng về phía bắc, chúng ta phải nhân tất cả những thứ đó với i , trong J, được biểu thị bằng j.(nhai câu đó trong giây lát).

Chúng tôi chỉ thực sự "di chuyển" khi đầu vào ban đầu là 1, vì vậy sau đó chúng tôi nhân kết quả đó theo từng phần tử với mảng boolean là 1 trong đó đầu vào ban đầu là 1 và 0 khác : =&1*. Kết quả của phép nhân đó là một mảng "các bước định hướng". Vị trí cuối cùng của chúng tôi chỉ đơn giản là tổng của các bước đó:+/

thử nghiệm

Thật không may, tôi không thể làm điều này hoạt động trong TIO vì một số lý do, nhưng dán phần sau vào bảng điều khiển J sẽ xác minh rằng nó hoạt động:

t=.{&' ><'@*
g=.'^'#~|
f=.(t,g@{.,t@-@(*/),g@{:`g@{:,t@{.,g@|@{.@.(0<:{:))@+.@(+/)@(=&1*j.**/\)

NB. test cases
NB. format input as complex numbers
convert=. {&0j1 0j_1 1@:('<>^'&i.)

s=. '^<^^<^^<^^^^'  NB. >^^>^
echo f convert s
s=. '>^<<^^>^^'     NB. ^^<^
echo f convert s
s=. '^^^^>^^^^'     NB. ^^^^>^^^^
echo f convert s
s=. '>>>^^^^^^'     NB. <^^^^^^
echo f convert s
s=. '>^>^>^>^'      NB. empty string
echo f convert s

1

C # (.NET Core) , 349 byte

n=>{int a=0,b=0,x=0,y=1,t=0,j=0,k=0,w,e,r;var p="";foreach(var c in n){if(c==62){t=x;x=y;y=-t;}if(c<61){t=x;x=-y;y=t;}if(c>63){a+=x;b+=y;}}while(a!=j|b!=k){w=0;e=a-j;r=b-k;if(r>=e&r>=-e){w=b-k;k+=w;}else if(r<=e&r<=-e){p+=">>";w=k-b;k-=w;}else if(r>=e&r<=-e){p+="<";w=j-a;j-=w;}else if(r<=e&r>=-e){p+=">";w=a-j;j+=w;}p+=new string('^',w);}return p;}

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

Lấy một chuỗi làm đầu vào và đưa ra con đường ngắn nhất mà đầu vào sẽ đi.


Ungolfed & Bình luận

n =>
{
    // First, calculate the route that the robot is going to take, represented by xy
    int a = 0, b = 0; // The current coordinates (a=x, b=y)
    int x = 0, y = 1; // The movement vector
    int t = 0; // A temp variable
    var p = ""; // The path we are going to return
    // Calculate the path the robot is going to take by input
    foreach (var c in n)
    {
        if (c == '>') { t = x; x = y; y = -t; } // Turn movement vector right
        if (c == '<') { t = x; x = -y; y = t; } //                      left
        if (c == '^') { a += x; b += y; }       // Move forward
    }
    int j = 0, k = 0; // The new movement coordinates (j=x,k=y)
    // While the target position is not reached, move the robot
    while (a != j | b != k)
    {
        int w = 0; // The forward variable, counting how many times we have to go forward
        int e = a - j, r = b - k; // The target position minus the current position (e=x,r=y)
        if (r >= e & r >= -e) { w = b - k; k += w; } // Up
        else if (r <= e & r <= -e) { p += ">>"; w = k - b; k -= w; } // Down
        else if (r >= e & r <= -e) { p += "<"; w = j - a; j -= w; } // Left
        else if (r <= e & r >= -e) { p += ">"; w = a - j; j += w; } // Right
        p += new string('^', w);
    }
    // Return the final path
    return p;
}

1

JavaScript (Node.js) , 187 byte

s=>{x=y=t=0;r=x=>"^".repeat(x<0?-x:x);for(c of s){t-=b=c<">"||-(c<"^");if(!b)[z=>++y,z=>++x,z=>--y,z=>--x][t&3]()}t=x<0?"<":">";return (y>0?r(y):"")+(x?t+r(x):"")+(y<0?(x?t:t+t)+r(y):"")}

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

Phiên bản chơi gôn với khoảng trắng

-14 byte bởi @Neil


Ung dung:

s=>{
  // convert turns to up/down/left/right movements to final destination
  let directions = [
    z=>++y, // up
    z=>++x, // right
    z=>--y, // down
    z=>--x  // left
  ];
  let x = y = direction = 0;
  for(c of s){
    let relativeDirection = "<^>".indexOf(c)-1; // relative turn offset: -1 = left, 1 = right
    direction += relativeDirection;
    if(direction<0){direction+=4} // make sure direction%4 > 0
    if(c==="^"){directions[direction%4]()} // do the movement if going forwards
  }
  // convert destination back to turns
  // the most efficient output has up before left/right before down
  let absoluteRepeat = num => "^".repeat(Math.abs(num));
  let turn = x<0 ? "<" : ">";
  let outp = "";
  if (y>0) { outp += absoluteRepeat(y) } // handle up before left/right
  if (x) { outp+=turn+absoluteRepeat(x) } // handle left/right
  if (y<0) { outp += (outp?turn:turn+turn)+absoluteRepeat(y)) } // handle down (including w/o left/right)
  return outp;
}

Sử dụng t&3thay t%4vì bởi vì nó hoạt động với tiêu cực tđể bạn có thể loại bỏ 4+()s. (x?"":t)+tcó thể được viết (x?t:t+t)để tiết kiệm 1 byte. Mã chuyển hướng có vẻ quá dài. Ngoài ra tôi nghĩ rằng bạn có lẽ nên thay thế indexOfMath.absso sánh.
Neil

@Neil Cảm ơn! Bạn có thể giải thích một chút về việc thay thế indexOfbằng một so sánh?
Birjolaxew

Điều tốt nhất tôi có thể làm là t-=b=c<'>'||-(c<'^').
Neil

1

Python 2 , 174 169 165 byte

Chỉnh sửa 1: -5 byte bằng cách cho phép hướng nằm ngoài phạm vi 0-3 và xóa khoảng trắng.

Chỉnh sửa 2: -4 byte bằng cách thay đổi đầu vào thành (1, 2, 3) thay vì (<, ^,>) vì OP cho phép nó, cũng như thay đổi hệ tọa độ của tôi để cho phép tôi giảm tính toán khoảng cách.

n,d=[0,0],0
for c in input():exec'd-=1 n[d%2]+=(-1)**(d/2%2) d+=1'.split()[ord(c)-49]
print'2'*n[0]+'13'[n[1]>0]*any(n)+'2'*abs(n[1])+'13'[n[1]>0]*(n[0]<0)+'2'*-n[0]

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

Xác định tọa độ cuối cùng thông qua các giá trị của từ điển đang được thực thi, sau đó chỉ cần in đường dẫn trực tiếp đến mục tiêu cuối cùng.


0

Perl 5 , 185 + 1 (-p) = 186 byte

/</?$d--:/>/?$d++:/\^/?$m[$d%4]++:0for/./g;$y=$m[0]-$m[2];$x=$m[1]-$m[3];$q='^'x abs$x;$_=A.$q.B.('^'x-$y);$x<0?y/AB/</:$x?y/AB/>/:0;$_=('^'x$y).($x<0?'<':$x>0?'>':'').$q if$y>0;y/AB//d

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


0

JavaScript (loại tài liệu.getEuityById ()), 343 ký tự

function b(s){s=s.split('');c=[0,0];r=0;p='';w='<';e='>';n='^';for(i in s){r+=s[i]==e?.5:s[i]==w?-.5:0;r=r>1?-.5:r<-.5?1:r;c[1-Math.ceil(Math.abs(r%1))]+=s[i]==n?r>0?1:-1:0;}x=c[0];y=c[1];j=x<0?-x:x;k=y<0?-y:y;f=function(a){p+=a==j?x<0?w:x>0?e:'':j>k?y<0?w:y>0?e:'':y>0?e+e:'';for(i=0;i<a;i++){p+=n}};if(j>k){f(j);f(k)}else{f(k);f(j)}alert(p)}

mở rộng:

function b(s){

s = s.split('');
c = [0, 0];
r = 0;
p = '';
w = '<';
e = '>';
n = '^';

for(i in s){

    r += s[i] == e ? .5 : s[i] == w ? -.5 : 0;
    r = r > 1 ? -.5 : r < -.5 ? 1 : r;

    c[1 - Math.ceil( Math.abs( r%1 ) )] += s[i] == n ? r > 0 ? 1 : -1 : 0;

}

x = c[0];
y = c[1];
j = x < 0 ? -x : x;
k = y < 0 ? -y : y;

f = function(a){

    p += a == j ? x < 0 ? w : x > 0 ? e : '' : j > k ? y < 0 ? w : y > 0 ? e : '' : y > 0 ? e+e : '';

    for( i = 0; i < a; i++){
        p += n
    }

};

if( j>k ){

    f(j);
    f(k)

} else {

    f(k);
    f(j)

}

alert(p)

}

Sử dụng:

b('^<^^<^^<^^^^')

cảnh báo: >^^>^

Một robot với đảo ngược sẽ có ích.

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.