Relatif vs Absolute

17

Jika seseorang menghadap ke utara di titik A di kisi ini ingin arah mengikuti jalur hijau (karena mereka hanya bisa mengikuti garis kisi) ke titik B Anda mungkin memberi tahu mereka:

Pergi North, North, West, East, East, South, East, East.

atau setara

Pergi Forward, Forward, Left, Back, Forward, Right, Left, Forward.
(Di mana perintah Kanan , Kiri , atau Kembali secara implisit berarti berbalik ke arah itu, lalu maju.)

Jalur A ke B

Tulis fungsi dengan satu argumen yang menerjemahkan antara arah absolut dan relatif ini di sepanjang jalur yang sama , bukan hanya ke titik yang sama. Anggaplah orang yang diarahkan selalu mulai menghadap ke utara.

Jika argumennya adalah serangkaian huruf NSEW, kembalikan arah relatif yang setara.
mis. f("NNWEESEE")mengembalikan string FFLBFRLF.

Jika argumennya adalah serangkaian huruf FBLR, kembalikan arah absolut yang setara.
mis. f("FFLBFRLF")mengembalikan string NNWEESEE.

String kosong menghasilkan dirinya sendiri. Asumsikan tidak ada kasus input lainnya.

Jika bahasa Anda tidak memiliki fungsi atau string gunakan apa pun yang tampaknya paling sesuai.

Kode terpendek dalam byte menang.

Hobi Calvin
sumber
Apakah kita berasumsi bahwa seseorang selalu mulai dengan kepalanya menghadap ke Utara? Dengan begitu, secara relatif untuk menuju ke Timur, itu akan mengharuskan dia untuk Belok Kanan, daripada hanya mengatakan Maju
Pengoptimal
@Optimizer Ya, utara. Dan ya ke poin Anda yang lain. Rsama dengan Edi awal.
Calvin Hobbies
1
Yay! Anda mengubah gambar Anda untuk mengonfirmasi apa yang selalu saya pikirkan!
Justin
4
Apakah Anda terhubung dengan PPCG lagi? ;)
Martin Ender
4
@ MartinBüttner Entah itu atau saya sangat pandai menyamarkan masalah pekerjaan rumah saya. ;)
Hobi Calvin

Jawaban:

6

CJam, 57 53 49

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

Versi sebelumnya

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

Contoh:

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

Keluaran:

FFLBFRLF
NNWEESEE

Bagaimana itu bekerja

{
  "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. ";
}
jimmy23013
sumber
6

C ++, 99 97

Berikut ini diformat sebagai ekspresi lambda. Dibutuhkan satu char*argumen dan menimpanya.

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

Bagi mereka yang tidak terbiasa dengan fitur ini (seperti saya 1 jam yang lalu), gunakan sebagai berikut:

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

Beberapa penjelasan:

  • Saat menggunakan kode suka flag ? (x = y) : (x += z) , pasangan kedua tanda kurung diperlukan dalam C. Jadi saya menggunakan C ++!
  • C ++ membutuhkan menentukan tipe pengembalian untuk suatu fungsi. Kecuali saya menggunakan ekspresi lambda, itu! Bonus tambahan adalah saya tidak perlu membuang 1 karakter untuk nama fungsi.
  • Kode *s*9%37&4menguji byte pertama; hasilnya 4 jika salahNESW ; 0 sebaliknya
  • Kode *s%11/3mengubah byteNESW menjadi 0, 1, 2, 3
  • Kode *s%73%10mengubah byteFRBL ke 0, 9, 6, 3 (yaitu 0, 1, 2, 3 modulo 4)
  • Ketika mengubah arah relatif menjadi absolut, saya tidak perlu dvariabel. Saya mencoba menata ulang kode untuk menghilangkannya sepenuhnya, tetapi tampaknya mustahil ...
anatolyg
sumber
1
Saya suka cara Anda mengubah huruf menjadi angka sangat banyak. :)
Emil
6

JavaScript (E6) 84 86 88 92 104

Sunting: menggunakan & alih-alih%, prioritas operator yang berbeda (kurang kurung) dan berfungsi lebih baik dengan angka negatif
Sunting2: | bukannya +, op didahulukan lagi, -2. Terima kasih DocMax
Edit3: pemahaman array adalah 2 karakter lebih pendek dari peta (), untuk string

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

Uji di konsol FireFox / FireBug

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

Keluaran

FFLBFRLF NNWEESEE
edc65
sumber
@Optimizer tidak lagi. Dan berharap semakin menyusut.
edc65
Apa artinya && opada akhirnya?
bebe
2
@ Bebe fungsi peta mengembalikan sebuah array, di dalamnya, sebagai efek samping, saya mengisi o string itulah yang saya butuhkan untuk kembali. array && valueEvalute to valuesebagai array yang dievaluasi ketruthy
edc65
1
Akhirnya! Saya telah menatap yang satu ini sejak mencapai 88. Kecuali jika saya kehilangan sesuatu, Anda dapat mengganti 4+(n-d&3)dengan 4|n-d&3dan menyimpan 2 karakter.
DocMax
4

APL, 72

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

Jika konfigurasi juru bahasa dapat diubah tanpa penalti, maka skornya adalah 66 , dengan mengubah ⎕IOke 0:

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

Python, 171 139

Tidak ada cara yang sesingkat solusi lain, tapi saya kira itu seharusnya relatif baik untuk apa yang dapat dilakukan dengan 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)))

Versi diperluas untuk keterbacaan yang sedikit lebih baik:

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)
Emil
sumber
1

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

Versi yang dapat dibaca:

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

David
sumber
1

GNU sed, 356 bytes

Tantangannya menuntut transformasi sederhana pada aliran karakter. sed, editor aliran adalah pilihan bahasa yang jelas ;-)

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

(Komentar dan spasi dilucuti untuk keperluan perhitungan skor golf)

Keluaran:

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

Penjelasan:

Idenya di sini adalah bahwa ketika kita mengubah kerangka acuan, selalu ada pemetaan langsung antara {N, E, S, W}dan {F, R, B, L}.

Dalam kasus absolut ke relatif, kami bekerja melalui string. Untuk setiap karakter kita peta {N, E, S, W}untuk {F, R, B, L}, kemudian memutar sisa [NESW]karakter sesuai dengan karakter kita hanya dipetakan, kemudian pindah ke karakter berikutnya.

Untuk kasus relatif ke absolut, kami melakukan sebaliknya. Kami bekerja mundur melalui string, memutar semua [NESW]karakter berikut sesuai dengan karakter di depan. Kemudian kita memetakan bahwa karakter {N, E, S, W}ke {F, R, B, L}, sampai kita ke awal string.

Trauma Digital
sumber
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

Ini menetapkan angka rotasi ke arah relatif, dan nomor orientasi ke arah absolut, kemudian menemukan rotasi antara orientasi berurutan atau orientasi setelah rotasi berurutan. The iFungsi menemukan indeks dalam dua legenda.

archaephyrryx
sumber