สัมพัทธ์กับแอบโซลูท


17

หากมีคนหันหน้าไปทางทิศเหนือ ณ จุด A ในตารางนี้ต้องการให้เส้นทางเดินไปตามเส้นทางสีเขียว (เพราะพวกเขาสามารถติดตามเส้นกริดได้เท่านั้น) ไปยังจุด B คุณอาจบอกได้ว่า:

North, North, West, East, East, South, East, Eastไป

หรือเทียบเท่า

Forward, Forward, Left, Back, Forward, Right, Left, Forwardไป
(ในกรณีที่คำสั่งของขวา , ซ้ายหรือกลับไปโดยปริยายหมายถึงการหันไปในทิศทางที่แล้วก้าวไปข้างหน้า.)

เส้นทาง A ไป B

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

หากอาร์กิวเมนต์เป็นสตริงของตัวอักษรNSEWให้ส่งคืนทิศทางสัมพัทธ์เทียบเท่า
เช่นส่งกลับสตริงf("NNWEESEE")FFLBFRLF

หากอาร์กิวเมนต์เป็นสตริงของตัวอักษรFBLRให้ส่งคืนทิศทางแบบสัมบูรณ์ที่เทียบเท่ากัน
เช่นส่งกลับสตริงf("FFLBFRLF")NNWEESEE

สตริงว่างให้ผลผลิตตัวเอง สมมติว่าไม่มีกรณีอินพุตอื่น

หากภาษาของคุณไม่มีฟังก์ชั่นหรือสตริงใช้สิ่งที่ดูเหมือนเหมาะสมที่สุด

รหัสที่สั้นที่สุดในหน่วยไบต์ชนะ


เราคิดว่าคน ๆ หนึ่งมักจะเริ่มด้วยหัวของเขาหันหน้าไปทางทิศเหนือหรือไม่? ด้วยวิธีนี้ในแง่ที่เกี่ยวข้องเพื่อไปทางตะวันออกเขาจะต้องเลี้ยวขวาแทนที่จะพูดไปข้างหน้า
เครื่องมือเพิ่มประสิทธิภาพ

@Optimizer ใช่แล้ว และใช่ไปยังจุดอื่นของคุณ Rเท่ากับEตอนเริ่มต้น
งานอดิเรกของ Calvin

1
เย้! คุณเปลี่ยนรูปเพื่อยืนยันสิ่งที่ฉันคิดเสมอ!
จัสติน

4
คุณติดใจ PPCG อีกครั้งหรือไม่? ;)
Martin Ender

4
@ MartinBüttnerไม่ว่าจะเป็นหรือฉันเก่งในการปลอมแปลงปัญหาการบ้านของฉัน ;)
งานอดิเรกของ Calvin

คำตอบ:


6

CJam, 57 53 49

{"NESW""FRBL"_3$&!!:Q$:R^^f#0\{{+0\}Q*_@-R=\}%);}

รุ่นก่อนหน้า

{"NESW""FRBL"_3$0=#W>:Q{\}*:R;f#0\{{+0\}Q*_@-R=\}%);}

ตัวอย่าง:

{"NESW""FRBL"_3$0=#W>:Q{\}*:R;f#0\{{+0\}Q*_@-R=\}%);}:T;
"NNWEESEE"T
N
"FFLBFRLF"T

เอาท์พุท:

FFLBFRLF
NNWEESEE

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

{
  "NESW""FRBL"             " Push the two strings. ";
  _3$0=#W>                 " Check if the first character is in FRBL. ";
  :Q                       " Assign the result to Q. ";
  {\}*                     " Swap the two strings if true. ";
  :R;                      " Assign the top string to R and discard it. ";
  f#                       " Find each character of the input in the string. ";
  0\                       " Push a 0 under the top of the stack. ";
  {                        " For each item (index of character): ";
    {                      " If Q: ";
      +0\                  " A B -> 0 (A+B) ";
    }Q*
    _@-                    " C D -> D (D-C) ";
    R=                     " E -> E-th character in R ";
    \                      " Swap the top two items. ";
  }%
  );                       " Discard the last item in the list. ";
}

6

C ++, 99 97

ข้อมูลต่อไปนี้ถูกจัดรูปแบบเป็นนิพจน์แลมบ์ดา ใช้เวลาหนึ่งchar*อาร์กิวเมนต์และเขียนทับมัน

[](char*s){for(int d=0,n=0,c=*s*9%37&4;*s;d+=n)c?n=*s%11/3-d:n+=*s%73%10,*s++="NESWFRBL"[c|n&3];}

สำหรับผู้ที่ไม่คุ้นเคยกับคุณลักษณะนี้ (เช่นตัวเองเมื่อ 1 ชั่วโมงก่อน) ให้ใช้ดังนี้:

#include <iostream>

int main()
{
    char s[] = "NNWEESEE";
    auto x = [](char*s){for(int d=0,n=0,c=*s*9%37&4;*s;d+=n)c?n=*s%11/3-d:n+=*s%73%10,*s++="NESWFRBL"[c|n&3];};

    x(s); // transform from absolute to relative
    std::cout << s << '\n';

    x(s); // transform from relative to absolute
    std::cout << s << '\n';
}

คำอธิบายบางอย่าง:

  • เมื่อใช้รหัสเช่น flag ? (x = y) : (x += z)วงเล็บปีกกาคู่ที่สองเป็นสิ่งจำเป็นในซีดังนั้นฉันจึงใช้ C ++ แทน!
  • C ++ ต้องระบุประเภทส่งคืนสำหรับฟังก์ชัน นอกจากว่าฉันใช้แลมบ์ดานั่นคือ! โบนัสเพิ่มคือฉันไม่ต้องเสีย 1 ตัวอักษรในชื่อของฟังก์ชั่น
  • รหัส*s*9%37&4ทดสอบไบต์แรก; ผลลัพธ์คือ 4 หากเป็นหนึ่งในNESW; 0 มิฉะนั้น
  • รหัส*s%11/3แปลงไบต์NESWเป็น 0, 1, 2, 3
  • รหัส*s%73%10แปลงไบต์FRBLเป็น 0, 9, 6, 3 (ซึ่งคือ 0, 1, 2, 3 โมดูโล 4)
  • เมื่อแปลงทิศทางสัมพัทธ์เป็นสัมบูรณ์ฉันไม่ต้องการdตัวแปร ฉันพยายามจัดเรียงรหัสใหม่เพื่อกำจัดมันอย่างสมบูรณ์ แต่ดูเหมือนว่าเป็นไปไม่ได้ ...

1
ฉันชอบวิธีที่คุณแปลงตัวอักษรเป็นตัวเลขอย่างมาก :)
Emil

6

JavaScript (E6) 84 86 88 92 104

แก้ไข: การใช้ & แทน%, ตัวดำเนินการที่แตกต่างกันมาก่อน (วงเล็บน้อยกว่า) และทำงานได้ดีขึ้นด้วยตัวเลขติดลบ
Edit2: | แทน +, ลำดับความสำคัญ op อีกครั้ง, -2 ขอบคุณ DocMax
Edit3: ความเข้าใจของอาเรย์คือ 2 chars ที่สั้นกว่า map () สำหรับสตริง

F=p=>[o+=c[d=n,n=c.search(i),n<4?4|n-d&3:n=n+d&3]for(i of n=o='',c='NESWFRBL',p)]&&o

ทดสอบในคอนโซล FireFox / FireBug

console.log(F('NNWEESEE'),F('FFLBFRLF'))

เอาท์พุต

FFLBFRLF NNWEESEE

@Optimizer ไม่มาก และหวังว่าจะหดตัวมากยิ่งขึ้น
edc65

อะไร&& oที่หมายถึงการสิ้นสุดหรือไม่
bebe

2
@bebe ฟังก์ชั่นแผนที่จะส่งกลับอาร์เรย์ภายในผลข้างเคียงฉันเติมสตริง o ซึ่งเป็นสิ่งที่ฉันต้องการคืน array && valueevalute จะvalueเป็นแถว ๆ ประเมินtruthy
edc65

1
ที่สุด! ฉันได้จ้องมองที่นี่ตั้งแต่มันตี 88 เว้นแต่ว่าฉันจะหายไปบางสิ่งบางอย่างคุณสามารถแทนที่4+(n-d&3)ด้วย4|n-d&3และบันทึก 2 ตัวอักษร
DocMax

4

APL, 72

{^/⍵∊A←'NESW':'FRBL'[1+4|-2-/4,3+A⍳⍵]⋄A[1+4|+\'RBLF'⍳⍵]}

หากการกำหนดค่าล่ามสามารถเปลี่ยนแปลงได้โดยไม่มีการลงโทษดังนั้นคะแนนคือ66โดยเปลี่ยน⎕IOเป็น0:

{^/⍵∊A←'NESW':'FRBL'[4|-2-/0,A⍳⍵]⋄A[4|+\'FRBL'⍳⍵]}

3

Python, 171 139

ไม่มีทางใกล้เคียงกับโซลูชันอื่น ๆ แต่ฉันคิดว่ามันควรจะค่อนข้างดีสำหรับสิ่งที่สามารถทำได้ด้วย Python:

def f(i):a,b='NWSE','FLBR';I=map(a.find,'N'+i);return''.join((b[I[k+1]-I[k]],a[sum(map(b.find,i)[:k+1])%4])[-1in I]for k in range(len(i)))

เวอร์ชันขยายสำหรับการอ่านที่ดีขึ้นเล็กน้อย:

def f(i):
    a, b = 'NWSE', 'FLBR'
    I = map(a.find,'N'+i)     # translate to numbers assuming abs. directions
    J = map(b.index,i)        # translate to numbers assuming rel. directions
    if not -1 in I:
        o = [b[I[k+1]-I[k]] for k in range(len(i))]    # rel. dir. is differences of abs. dir.
    else:
        o = [a[sum(J[:k+1])%4] for k in range(len(i))] # abs. dir. is sum of all rel. dir. so far
    return ''.join(o)

1

ไป 201

type q string;func F(s q)q{d,z:=byte(0),make([]byte,len(s));for i,c:=range[]byte(s){if(c^4)*167%3<2{c=c*156%5;z[i],d="LBRF"[(d-c)%4],c-1;}else{c=(c^43)*3%7-1;d=(d+c)%4;z[i]="NESW"[d];};};return q(z);}

รุ่นที่อ่านได้:

func F(s string) string {
    d, z, R, A := 0, make([]byte, len(s)), "LBRFLBR", "NESW"
    for i, c := range []byte(s) {
        switch c {
        case 'N': c = R[d+3]; d = 0
        case 'E': c = R[d+2]; d = 1
        case 'S': c = R[d+1]; d = 2
        case 'W': c = R[d]; d = 3
        case 'F': c = A[d]
        case 'R': d = (d + 1) % 4; c = A[d]
        case 'B': d = (d + 2) % 4; c = A[d]
        case 'L': d = (d + 3) % 4; c = A[d]
        }
        z[i] = c
    }
    return string(z)
}


1

GNU sed, 356 ไบต์

ความท้าทายเรียกร้องให้มีการเปลี่ยนแปลงอย่างง่าย ๆ บนตัวละคร sedตัวแก้ไขสตรีมเป็นตัวเลือกภาษาที่ชัดเจน ;-)

/[FRBL]/bx                                     # Jump to label x if relative
:y                                             # label y (start of abs->rel loop)
/[FRBL]$/q                                     # quit if string ends in rel char
s/(^|[FRBL])N/\1F/;ty                          # Substitute next abs char with
s/(^|[FRBL])E/\1R/;tr                          #     rel char, then jump to
s/(^|[FRBL])S/\1B/;tb                          #     relevant rotation label if
s/(^|[FRBL])W/\1L/;tl                          #     a match was found
by                                             # loop back to y
:r;y/NESW/WNES/;by                             # Rotation labels: transform then
:b;y/NESW/SWNE/;by                             #     loop back to y
:l;y/NESW/ESWN/;by
:x                                             # label x (start of rel->abs loop)
/^[NESW]/q                                     # quit if string starts w/ abs char
/F([NESW]|$)/s/F([NESW]|$)/N\1/                # Matches for each direction:
/R([NESW]|$)/y/NESW/ESWN/;s/R([NESW]|$)/E\1/   #     rotate, then substitute
/B([NESW]|$)/y/NESW/SWNE/;s/B([NESW]|$)/S\1/
/L([NESW]|$)/y/NESW/WNES/;s/L([NESW]|$)/W\1/
bx                                             # loop back to x

(ความคิดเห็นและช่องว่างที่ถูกปล้นเพื่อวัตถุประสงค์ในการคำนวณคะแนนกอล์ฟ)

เอาท์พุท:

$ sed -rf absrel.sed <<< NNWEESEE
FFLBFRLF
$ sed -rf absrel.sed <<< FFLBFRLF
NNWEESEE
$ 

คำอธิบาย:

ความคิดที่นี่คือว่าเมื่อเราเปลี่ยนกรอบของการอ้างอิงที่มีอยู่เสมอการทำแผนที่โดยตรงระหว่างและ{N, E, S, W}{F, R, B, L}

ในกรณีของสัมบูรณ์ถึงญาติเราทำงานผ่านสายอักขระ สำหรับตัวละครแต่ละตัวที่เราแผนที่{N, E, S, W}ไป{F, R, B, L}แล้วหมุนที่เหลือ[NESW]ตัวอักษรตามตัวละครที่เราเพิ่งแมปแล้วย้ายไปยังตัวอักษรถัดไป

สำหรับกรณีที่สัมพันธ์กับสัมบูรณ์เราจะย้อนกลับ เราทำงานย้อนกลับผ่านสตริงหมุน[NESW]ตัวอักษรต่อไปนี้ทั้งหมดตามตัวละครทันที จากนั้นเราจับคู่อักขระนั้น{N, E, S, W}กับ{F, R, B, L}จนกระทั่งเราเริ่มต้นของสตริง


0

Haskell, 224

import Data.Function
i=flip(\x->length.takeWhile(/=x))
r=['F','R','B','L']
a=['N','E','S','W']
f s@(x:_)|elem x a=map((r!!).(`mod`4).(4-))$zipWith((-)`on`(i a))('N':s)(s)|True=tail$map((a!!).(`mod`4)).scanl(+)(0)$map(i r) s

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

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