Verimli Robot Hareketi


24

Feragatname: Bu soruda anlatılan hikaye tamamen kurgusaldır ve yalnızca bir tanıtım sağlamak amacıyla icat edilmiştir.

Patronum yeni bir oyuncak robot aldı ve programlamama yardım etmemi istiyor. Hareket etmesi için basit ok talimatlarını girebilmek istiyor. Bu talimatlar: ^ (ileri gitmek için) <(sola dönüş için) ve> (sağa dönüş için). Ancak şimdi robotu programladığım için ek işlevsellik istiyor. Girdiği herhangi bir ok dizisini dönüştürmemi istiyor, böylece robotun belirtilen yolu izlemesinden ziyade, girilen yolu izlemişse, girilen yolu izlemişse, biteceği yer ile belirtilen istenen yere hareket ediyor. mümkün. PP&CG üyeleri, bu konuda bana yardımcı olmaları için size çağrıda bulundum.

Senin görevin:

Oklardan oluşan bir dizgeyi, girdi tarafından belirtilen yere mümkün olduğunca çabuk ulaşacak dizgeye dönüştürmek için bir program veya işlev yazın. Tornalama tam olarak geriye veya ileriye doğru hareket ettiği sürece devam eder.

Giriş:

Yukarıda belirtildiği gibi bir ok dizisi. İsterseniz, oklar için farklı karakterler ikame edilebilir, ancak cevabınıza bunu yaptığınızdan emin olun. Tüm test durumları okları normal şekilde kullanır.

Çıktı:

Robotu mümkün olduğu kadar verimli bir şekilde istenen hedefe götüren bir ok dizisi (veya eşdeğer karakterleriniz).

Test Durumları:

Sunulan çözümlerin yalnızca olasılıklar olduğunu ve diğer çözümlerin geçerli olabileceğini unutmayın.

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

puanlama:

Robotun hafızası sınırlıdır, bu nedenle programınız mümkün olan en düşük bayt sayısına sahip olmalıdır.


Çünkü girişte robot tam olarak başladığı yerde sona ermektedir, bu nedenle onu mümkün olduğunca verimli bir şekilde taşımak için herhangi bir komut gerekmez.
Gryphon - Monica

Oh, ipi yanlış okudum. Benim hatam.
JungHwan Min

Test senaryosu isteği ^<^^<^^<^^^^-> >^^>^?
JungHwan Min

1
@pizzakingme, üzgünüm, ama patronum çok tembel ve sadece hareket başına bir karakter yazmak istiyor.
Gryphon - Monica

1
Rekabetçi robotlar programlarım ve bunun tam olarak nasıl çalıştıklarını onaylayabilirim.
Joe

Yanıtlar:


9

Retina , 103 74 71 bayt

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

Çevrimiçi deneyin! Link, test durumlarını içerir. Açıklama:

<
>>>

Sola dönüşleri üçlü dönüşlere çevirin.

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

Tüm dönüşleri azaltın modulo 4.

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

Hareketleri zıt yönlerde iptal edin.

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

Üçlü sağa dönüş, sola dönüş. Bu aynı zamanda bir durumda işler >>^>^hale kaydetmesi gereken <^<^.

<?>*$

Gereksiz sondaki dönüşleri silin.


Etkileyici. Bu alt 100 baytı bir dilde almanın bir yolu olduğunu biliyordum ve cevabınız daha önce çok yakındı. +1
Gryphon - Monica

6

Mathematica, 135 bayt

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

Bir Alır Listgirdi olarak dizeleri.

açıklama

j=0;i=1

Set j0'a, ve set i1'e.

/@#

Girilen her karakter için ...

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

Karakter ise >, ihayali birim ile çarpın . Karakter ise hayali birime >bölün i. Karakter ise ^, eklemek iiçin j.

ReIm[ ... ;j]

Bunun hayali ve hayali parçalarını alın j. Bu robotun Kartezyen koordinatını verir.

... &@@

Aşağıdakileri bu sonuca uygulayın:


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

Hangisi daha büyükse, s karakteriyle veya s karakteriyle aoluşturulan bir işleve ayarlayın .(input)0^

{ ... }

Bir Listoluşan ...

a@#

ailk girişe uygulanan (gerçek kısım j)

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

İkinci giriş (hayali bölümü ise j) daha büyük olduğunu 0, >. Aksi takdirde <,. sOrtaya çıkan karaktere ayarlayın .

a@Abs@#2

a ikinci girişin mutlak değerine uygulanır.

If[#<0,s,""]

İlk giriş 0'dan küçükse s,. Aksi takdirde, boş dize.

a@-#

aGiriş sürelerine negatif olanı uygulayın .

... <>""

Dizelere katılın.


2

Mathematica 119 Bayt

JungHwan'ın yol kodundaki son konumu benimkinden daha kısaydı, bu yüzden bunu kullandın. Sanırım bunu yapmanın daha da kısa bir yolu var ...

Yerleşik AnglePathişlevi son pozisyona karar vermek için kullanıyorum. Birkaç alıntı karakterini kaydetmek için ayrıca "<", "^" ve ">" için L, F ve R sembollerini de tanımlarım.

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

Kullanımı:

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

Çıktı:

FFLF

2

Ruby , 130 bayt

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

Nasıl çalışır

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

Çevrimiçi deneyin!


2

J, 90 bayt

çözüm

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

açıklama

karmaşık sayıları kullanarak düzgün bir numara var ( i ile çarparak 90 derece sola dönüş, ve -i size doğru olanı verir).

bu yüzden girdilerimizi karmaşık sayılar olarak kabul ediyoruz: 1, "ileri yürü" ve i / -i'yi temsil eder. sola ve sağa dönüşleri temsil eder.

nihai konum bu temsil ile zahmetsizce hesaplanır. Bunun, yukarıdaki son ifademin ilk (en sağdaki) kısmı olduğuna dikkat edin:

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

Yukarıdaki kısa çizgi sorunu çözen şeydir. Geriye kalan her şey sadece cevabın nasıl biçimlendirileceğini bulmak ve kesinlikle daha fazla golf oynamak olabilir.

Yukarıdaki kısa satırı anlamak için */\(kısmi ürünlerin taranması) size girişteki her bir endekste karşılaştığınız konumların bir listesini verdiğini unutmayın : i kuzey, 1 ve -1 doğu ve batı, -i güney . Biz kuzeye bakan başlatmak beri Ama biz tarafından tüm bu çarpmak zorunda i J tarafından temsil edildiği,j. (bir an için o cümlede çiğnemek).

Biz aslında sadece orijinal giriş 1 olduğunda "hareket" yaparız, bu yüzden bu sonucu elementwise ile orjinal giriş 1 ve 0 olan 1 olan boole dizisi ile çarparız =&1*. Sonucu bu çarpma "yönlü adımlar" bir dizidir. Nihai konumumuz bu adımların toplamıdır:+/

test yapmak

Maalesef bunun TIO’da çalışmasını bir nedenden ötürü alamam, ancak aşağıdakileri J konsoluna yapıştırmak işe yarayacağını doğrular:

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 bayt

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

Çevrimiçi deneyin!

Girdi olarak bir dize alır ve girişin alacağı en kısa yolu çıkarır.


Ungolfed ve Yorumlandı

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 bayt

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

Çevrimiçi deneyin!

Boşluk ile Golf sürüm

-14 bayt @Neil tarafından


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

Kullanım t&3yerine t%4negatif ile bu işler çünkü tkaldırmak böylece 4+ve ()s. 1 baytlık bir tasarruf için (x?"":t)+tyazılabilir (x?t:t+t). Yön hareket kodu çok uzun görünüyor. Ayrıca muhtemelen yerini almalı indexOfve Math.abskarşılaştırmalar yapmalısın .
Neil

@Neil Teşekkürler! indexOfBir kıyaslama yapmak yerine biraz daha detaylandırabilir misiniz ?
Birjolaxew

Yapabileceğim en iyi şeydi t-=b=c<'>'||-(c<'^').
Neil

1

Python 2 , 174 169 165 bayt

Yönü 0-3 aralığında olacak şekilde izin vererek ve boşlukları kaldırarak 1: -5 bayt'ı düzenleyin.

OP izin verdiği için girişi (<, ^,>) yerine (1, 2, 3) olarak değiştirerek 2: -4 bayt'ı düzenleyin ve koordinat sistemimi mesafe hesaplamamı düşürmeme izin verecek şekilde değiştirin.

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]

Çevrimiçi deneyin!

Nihai koordinatları sözlüğün yürütülmekte olan değerleri üzerinden belirler, ardından yalnızca bitiş hedefine giden doğrudan yolu yazdırır.


0

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

/</?$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

Çevrimiçi deneyin!


0

JavaScript (document.getElementById () tür), 343 karakter

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

genişletilmiş:

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)

}

Kullanımı:

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

uyarıları: >^^>^

Tersine sahip bir robot faydalı olurdu.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.