การเคลื่อนไหวของหุ่นยนต์ที่มีประสิทธิภาพ


24

การปฏิเสธความรับผิดชอบ: เรื่องราวที่บอกไว้ในคำถามนี้เป็นเรื่องสมมติทั้งหมดและคิดค้นขึ้นเพื่อวัตถุประสงค์ในการให้คำแนะนำ

เจ้านายของฉันได้รับหุ่นยนต์ของเล่นตัวใหม่และเขาต้องการให้ฉันช่วยเขียนโปรแกรม เขาต้องการที่จะป้อนคำแนะนำลูกศรง่าย ๆ เพื่อให้มันเคลื่อนที่ คำแนะนำเหล่านี้คือ: ^ (สำหรับก้าวไปข้างหน้า) <(สำหรับเลี้ยวซ้าย) และ> (สำหรับเลี้ยวขวา) อย่างไรก็ตามตอนนี้ฉันได้ตั้งโปรแกรมหุ่นยนต์แล้วเขาต้องการฟังก์ชั่นเพิ่มเติม เขาต้องการให้ฉันเปลี่ยนลูกศรลำดับใด ๆ ที่เขาป้อนดังนั้นแทนที่จะให้หุ่นยนต์ไปตามเส้นทางที่ระบุมันจะย้ายไปยังตำแหน่งที่ต้องการโดยระบุสถานที่ที่มันจะจบลงถ้ามันใช้เส้นทางอินพุตอย่างมีประสิทธิภาพเช่นเดียวกับ เป็นไปได้ ฉันขอร้องคุณสมาชิกของ PP&CG ที่จะช่วยฉันทำงานนี้

งานของคุณ:

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

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

สตริงลูกศรตามที่ระบุไว้ข้างต้น หากคุณต้องการตัวละครที่แตกต่างกันอาจถูกแทนที่ด้วยลูกศร แต่ต้องแน่ใจว่าได้รวมความจริงที่คุณทำไว้ในคำตอบของคุณ กรณีทดสอบทั้งหมดใช้ลูกศรตามปกติ

เอาท์พุท:

สตริงของลูกศร (หรืออักขระที่เทียบเท่ากัน) ที่นำหุ่นยนต์ไปยังปลายทางที่ต้องการอย่างมีประสิทธิภาพที่สุด

กรณีทดสอบ:

โปรดทราบว่าโซลูชันที่นำเสนอเป็นเพียงความเป็นไปได้และโซลูชันอื่น ๆ อาจใช้ได้

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

เกณฑ์การให้คะแนน:

หน่วยความจำของหุ่นยนต์มี จำกัด ดังนั้นโปรแกรมของคุณต้องมีจำนวนไบต์ต่ำสุดเท่าที่จะเป็นไปได้


เนื่องจากในการป้อนข้อมูลหุ่นยนต์จะจบลงตรงจุดที่มันเริ่มต้นดังนั้นจึงไม่จำเป็นต้องใช้คำสั่งใด ๆ
Gryphon - Reinstate Monica

โอ้เข้าใจผิดสตริง ความผิดฉันเอง.
JungHwan Min

คำขอกรณีทดสอบ^<^^<^^<^^^^-> >^^>^?
JungHwan Min

1
@pizzakingme ขอโทษ แต่เจ้านายของฉันขี้เกียจมากและต้องการพิมพ์อักขระหนึ่งตัวต่อการเคลื่อนไหวเท่านั้น
Gryphon - Reinstate Monica

1
ฉันเขียนโปรแกรมโรบอตแข่งขันและฉันสามารถยืนยันได้ว่ามันทำงานอย่างไร
Joe

คำตอบ:


9

Retina , 103 74 71 ไบต์

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

ลองออนไลน์! ลิงค์มีกรณีทดสอบ คำอธิบาย:

<
>>>

เลี้ยวซ้ายเลี้ยวเป็นเลี้ยวขวาสามครั้ง

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

ลดการเลี้ยวทั้งหมดโมดูโล่ 4

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

ยกเลิกการเคลื่อนไหวในทิศทางตรงกันข้าม

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

เลี้ยวขวาสามทางกลับไปเป็นเลี้ยวซ้าย นอกจากนี้ยังจัดการกับกรณีของการที่ต้องกลายเป็น>>^>^<^<^

<?>*$

ลบการเลี้ยวที่ไม่จำเป็น


ประทับใจ ฉันรู้ว่าต้องมีวิธีในการรับย่อย 100 ไบต์ในบางภาษาและคำตอบของคุณก็ใกล้เคียงกันมาก่อน +1
Gryphon - Reinstate Monica

6

Mathematica, 135 ไบต์

{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]&

รับค่าListสตริงเป็นอินพุต

คำอธิบาย

j=0;i=1

ตั้งค่าjเป็น 0 และตั้งค่าiเป็น 1

/@#

สำหรับแต่ละอักขระในอินพุต ...

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

ถ้าตัวละครเป็น>คูณiด้วยหน่วยจินตภาพ ถ้าตัวละครเป็น>หารiด้วยหน่วยจินตภาพ ถ้าตัวอักษรเป็น^เพิ่มiเพื่อjเพื่อ

ReIm[ ... ;j]

นำชิ้นส่วนจริงและจินตภาพของ jใช้เวลาส่วนจริงและจินตภาพของสิ่งนี้ทำให้พิกัดคาร์ทีเซียนของหุ่นยนต์

... &@@

ใช้สิ่งต่อไปนี้กับผลลัพธ์นี้:


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

ตั้งaเป็นฟังก์ชั่นที่สร้างสตริงด้วย(input)หรือ0ตัวละคร^ s แล้วแต่จำนวนใดจะใหญ่กว่า

{ ... }

Listประกอบด้วย ...

a@#

aนำไปใช้กับอินพุตแรก (ส่วนที่แท้จริงของj)

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

หากอินพุตวินาที (ส่วนจินตภาพของj) มีขนาดใหญ่กว่า,0 >มิฉะนั้น, <. ชุดsเป็นอักขระผลลัพธ์

a@Abs@#2

a นำไปใช้กับค่าสัมบูรณ์ของอินพุตที่สอง

If[#<0,s,""]

หากอินพุตแรกมีค่าน้อยกว่า 0 s0, มิฉะนั้นสตริงว่าง

a@-#

ใช้ aไปกับการป้อนข้อมูลครั้งหนึ่งลบ

... <>""

เข้าร่วมสตริง


2

Mathematica 119 ไบต์

ตำแหน่งสุดท้ายของจองฮวานกับรหัสเส้นทางนั้นสั้นกว่าของฉันดังนั้นใช้มัน ฉันคิดว่าอาจมีวิธีที่สั้นกว่านี้ในการทำเช่นนี้ ...

ฉันใช้AnglePathฟังก์ชันในตัวเพื่อตัดสินใจตำแหน่งสุดท้าย ฉันยังกำหนดสัญลักษณ์ L, F และ R สำหรับ "<", "^" และ ">" เพื่อบันทึกอักขระเครื่องหมายคำพูดไม่กี่ตัว

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@#&

การใช้งาน:

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

เอาท์พุท:

FFLF

2

ทับทิมขนาด 130 ไบต์

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

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

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

ลองออนไลน์!


2

J, 90 ไบต์

วิธีการแก้

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

คำอธิบาย

มีเคล็ดลับเรียบร้อยโดยใช้ตัวเลขที่ซับซ้อน (การคูณด้วยiคือการหมุนซ้าย 90 องศาและ-iให้คุณได้ถูกต้อง)

ดังนั้นเราจึงใส่ข้อมูลของเราเป็นตัวเลขที่ซับซ้อน: 1 หมายถึง "เดินไปข้างหน้า" และฉัน / -iแทนซ้ายและขวา

ตำแหน่งสุดท้ายจะถูกคำนวณอย่างง่ายดายด้วยการเป็นตัวแทนนี้ โปรดทราบว่านี่เป็นส่วนแรก (ขวาสุด) ของนิพจน์สุดท้ายของฉันด้านบน:

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

บรรทัดสั้น ๆ ข้างต้นนั้นเป็นสิ่งที่แก้ปัญหาได้ ทุกสิ่งทุกอย่างเป็นเพียงการหาวิธีจัดรูปแบบคำตอบและสามารถลงสนามได้มากขึ้นอย่างแน่นอน

เพื่อให้เข้าใจบรรทัดสั้นด้านบนโปรดทราบว่า*/\(การสแกนผลิตภัณฑ์บางส่วน) ให้รายการของตำแหน่งที่คุณกำลังเผชิญกับแต่ละดัชนีในอินพุต: iคือทิศเหนือ 1 และ -1 เป็นตะวันออกและตะวันตกและ-iอยู่ทางทิศใต้ . แต่เมื่อเราเริ่มหันหน้าไปทางทิศเหนือเราจะต้องคูณพวกมันทั้งหมดด้วยiซึ่งใน J แทนด้วยj.(เคี้ยวประโยคนั้นสักครู่)

เราจริง "ย้าย" เมื่อป้อนข้อมูลเดิมคือ 1, เพื่อให้เราแล้วคูณผล elementwise โดยอาร์เรย์แบบบูลซึ่งเป็น 1 ที่ป้อนข้อมูลเดิมคือ 1 และ 0 =&1*เป็นอย่างอื่น ผลมาจากการที่คูณเป็นอาร์เรย์ของ "ขั้นตอนทิศทางที่" ตำแหน่งสุดท้ายของเราเป็นเพียงผลรวมของขั้นตอนเหล่านั้น:+/

การทดสอบ

น่าเสียดายที่ฉันไม่สามารถทำงานใน TIO ด้วยเหตุผลบางอย่างได้ แต่การวางต่อไปนี้ในคอนโซล J จะตรวจสอบว่ามันใช้งานได้:

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 ไบต์

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

ลองออนไลน์!

รับสตริงเป็นอินพุตและเอาต์พุตพา ธ ที่สั้นที่สุดที่อินพุตจะใช้


Ungolfed & แสดงความคิดเห็น

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 ไบต์

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):"")}

ลองออนไลน์!

รุ่น Golfed พร้อมช่องว่าง

-14 ไบต์โดย @Neil


Ungolfed:

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

ใช้t&3แทนt%4เพราะผลงานที่มีเชิงลบtเพื่อให้คุณสามารถลบ4+และ()s (x?"":t)+tสามารถเขียน(x?t:t+t)เพื่อการประหยัด 1 ไบต์ รหัสที่บอกทิศทางนั้นดูยาวเกินไป นอกจากนี้ฉันคิดว่าคุณอาจจะแทนที่indexOfและMath.absเปรียบเทียบ
Neil

@ Neil ขอบคุณ! คุณช่วยอธิบายเพิ่มเติมเล็กน้อยเกี่ยวกับการแทนที่indexOfด้วยการเปรียบเทียบหรือไม่?
Birjolaxew

t-=b=c<'>'||-(c<'^')ที่ดีที่สุดที่ผมทำได้คือ
Neil

1

Python 2 , 174 169 165 ไบต์

แก้ไข 1: -5 ไบต์โดยอนุญาตให้ทิศทางอยู่นอกช่วง 0-3 และลบช่องว่างออก

แก้ไข 2: -4 bytes โดยเปลี่ยนอินพุตเป็น (1, 2, 3) แทน (<, ^,>) เนื่องจาก OP อนุญาตให้มันรวมถึงการเปลี่ยนระบบพิกัดของฉันเพื่อให้ฉันลดการคำนวณระยะทาง

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]

ลองออนไลน์!

กำหนดพิกัดสุดท้ายผ่านค่าของพจนานุกรมที่จะดำเนินการจากนั้นเพียงพิมพ์เส้นทางโดยตรงไปยังเป้าหมายสุดท้าย



0

JavaScript (document.getElementById () ชนิด), 343 ตัวอักษร

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

ขยาย:

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)

}

การใช้งาน:

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

การแจ้งเตือน: >^^>^

หุ่นยนต์ที่มีการย้อนกลับจะมีประโยชน์

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