Tương đối so với tuyệt đối


17

Nếu ai đó quay mặt về hướng bắc tại điểm A trong lưới này muốn chỉ đường đi theo con đường màu xanh lá cây (vì họ chỉ có thể đi theo đường lưới) đến điểm B, bạn có thể nói với họ:

Go North, North, West, East, East, South, East, East.

hoặc tương đương

Go Forward, Forward, Left, Back, Forward, Right, Left, Forward.
(Trường hợp một lệnh của Phải , Trái hoặc Quay lại có nghĩa là quay theo hướng đó, sau đó đi tiếp.)

Đường dẫn từ A đến B

Viết hàm với một đối số dịch giữa các hướng tuyệt đối và tương đối này trên cùng một đường dẫn , không chỉ đến cùng một điểm. Giả sử người được chỉ dẫn luôn bắt đầu hướng về phía bắc.

Nếu đối số là một chuỗi các chữ cái NSEW, trả về các hướng tương đối tương đương.
ví dụ f("NNWEESEE")trả về chuỗi FFLBFRLF.

Nếu đối số là một chuỗi các chữ cái FBLR, trả về các hướng tuyệt đối tương đương.
ví dụ f("FFLBFRLF")trả về chuỗi NNWEESEE.

Chuỗi rỗng mang lại chính nó. Giả sử không có trường hợp đầu vào khác.

Nếu ngôn ngữ của bạn không có chức năng hoặc chuỗi sử dụng bất cứ điều gì có vẻ phù hợp nhất.

Mã ngắn nhất tính bằng byte thắng.


Chúng ta có cho rằng một người luôn bắt đầu quay đầu về phía Bắc không? Theo cách đó, về mặt tương đối để đi về phía Đông, nó sẽ yêu cầu anh ta rẽ phải, thay vì chỉ nói Chuyển tiếp
Trình tối ưu hóa

@Optimizer Vâng, phía bắc. Và có cho điểm khác của bạn. Rbằng Elúc bắt đầu.
Sở thích của Calvin

1
Yay! Bạn đã thay đổi hình ảnh của bạn để xác nhận những gì tôi luôn nghĩ!
Justin

4
Bạn có nối lại PPCG không? ;)
Martin Ender

4
@ MartinBüttner Hoặc là vậy hoặc tôi rất giỏi trong việc ngụy trang các vấn đề bài tập về nhà của mình. ;)
Sở thích của Calvin

Câu trả lời:


6

Camam, 57 53 49

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

Phiên bản trước

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

Thí dụ:

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

Đầu ra:

FFLBFRLF
NNWEESEE

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

{
  "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

Dưới đây được định dạng như một biểu thức lambda. Nó cần một char*đối số và ghi đè lên nó.

[](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];}

Đối với những người không quen thuộc với tính năng này (như bản thân tôi 1 giờ trước), hãy sử dụng tính năng này như sau:

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

Một số giải thích:

  • Khi sử dụng mã như thế flag ? (x = y) : (x += z), cặp dấu ngoặc đơn thứ hai được yêu cầu trong C. Vì vậy, tôi đã sử dụng C ++ thay thế!
  • C ++ yêu cầu chỉ định kiểu trả về cho hàm. Trừ khi tôi sử dụng một biểu thức lambda, đó là! Một phần thưởng được thêm vào là tôi không cần lãng phí 1 ký tự vào tên của hàm.
  • *s*9%37&4kiểm tra byte đầu tiên; kết quả là 4 nếu nó là một trong số đó NESW; 0 khác
  • *s%11/3chuyển đổi các byte NESWthành 0, 1, 2, 3
  • *s%73%10chuyển đổi các byte FRBLthành 0, 9, 6, 3 (là 0, 1, 2, 3 modulo 4)
  • Khi chuyển đổi hướng tương đối thành tuyệt đối, tôi không cần dbiến. Tôi đã thử sắp xếp lại mã để loại bỏ nó hoàn toàn, nhưng dường như không thể ...

1
Tôi thích cách bạn chuyển đổi các chữ cái thành số rất nhiều. :)
Emil

6

JavaScript (E6) 84 86 88 92 104

Chỉnh sửa: sử dụng & thay vì%, ưu tiên toán tử khác nhau (ít dấu ngoặc) và hoạt động tốt hơn với các số âm
Edit2: | thay vì +, op ưu tiên một lần nữa, -2. Cảm ơn DocMax
Edit3: khả năng hiểu mảng ngắn hơn 2 ký tự so với map (), đối với chuỗi

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

Kiểm tra trong bảng điều khiển FireFox / FireBug

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

Đầu ra

FFLBFRLF NNWEESEE

@Optimizer không còn nữa. Và hy vọng sẽ thu nhỏ hơn nữa.
edc65

Những gì hiện && otại giá trị trung bình kết thúc?
bebe

2
@bebe hàm map trả về một mảng, bên trong nó, như một hiệu ứng phụ, tôi điền vào chuỗi o đó là những gì tôi cần trả về. array && valueevalute đến valuenhư bất kỳ mảng đánh giá đểtruthy
edc65

1
Cuối cùng! Tôi đã được nhìn chằm chằm vào cái này vì nó nhấn 88. Trừ khi tôi đang thiếu một cái gì đó, bạn có thể thay thế 4+(n-d&3)với 4|n-d&3và tiết kiệm 2 chars.
DocMax

4

APL, 72

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

Nếu cấu hình trình thông dịch có thể được thay đổi mà không bị phạt, thì điểm là 66 , bằng cách thay đổi ⎕IOthành 0:

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

3

Con trăn, 171 139

Không có cách nào gần như ngắn như các giải pháp khác, nhưng tôi đoán nó sẽ tương đối tốt cho những gì có thể được thực hiện với 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)))

Phiên bản mở rộng để dễ đọc hơn một chút:

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

Đi, 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);}

Phiên bản dễ đọc:

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 byte

Thử thách đòi hỏi một sự chuyển đổi đơn giản trên một dòng các nhân vật. sed, trình chỉnh sửa luồng là sự lựa chọn rõ ràng của ngôn ngữ ;-)

/[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

(Nhận xét và khoảng trắng bị tước cho mục đích tính điểm golf)

Đầu ra:

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

Giải trình:

Ý tưởng ở đây là khi chúng ta thay đổi khung tham chiếu, luôn có một ánh xạ trực tiếp giữa {N, E, S, W}{F, R, B, L}.

Trong trường hợp tuyệt đối với tương đối, chúng tôi làm việc fowards thông qua chuỗi. Đối với mỗi nhân vật chúng ta ánh xạ {N, E, S, W}tới {F, R, B, L}, sau đó xoay các [NESW]ký tự còn lại theo ký tự chúng ta vừa ánh xạ, sau đó chuyển sang ký tự tiếp theo.

Đối với trường hợp tương đối tuyệt đối, chúng tôi làm ngược lại. Chúng tôi làm việc ngược qua chuỗi, xoay tất cả các [NESW]ký tự theo ký tự ngay trước mặt. Sau đó, chúng ta ánh xạ ký tự đó {N, E, S, W}đến {F, R, B, L}, cho đến khi chúng ta bắt đầu chuỗi.


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ều này gán các số xoay cho các hướng tương đối và các số định hướng cho các hướng tuyệt đối, sau đó tìm các phép quay giữa các hướng liên tiếp hoặc các hướng sau các phép quay liên tiếp. Các ichức năng tìm thấy các chỉ số trong vòng hai huyền thoại.

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.