상대 대 절대


17

이 그리드의 A 지점에서 북쪽을 향한 누군가가 B를 향한 녹색 경로를 따라가는 방향을 원한다면 B에게 지시 할 수 있습니다.

간다 North, North, West, East, East, South, East, East.

또는 동등하게

간다 Forward, Forward, Left, Back, Forward, Right, Left, Forward.
여기서 Right , Left 또는 Back 명령은 암시 적으로 해당 방향으로 돌았 다가 앞으로 나아가는 것을 의미합니다.

A에서 B 로의 경로

하나의 인수로 함수를 작성 하여 동일한 지점뿐만 아니라 동일한 경로를 따라 이러한 절대 방향과 상대 방향 사이를 변환 하십시오. 지시 된 사람이 항상 북쪽을 향하기 시작한다고 가정하십시오.

인수가 문자의 문자열 인 NSEW경우 동등한 상대 방향을 반환하십시오.
예를 들어 f("NNWEESEE")문자열을 반환합니다 FFLBFRLF.

인수가 문자의 문자열 인 FBLR경우 동등한 절대 방향을 반환하십시오.
예를 들어 f("FFLBFRLF")문자열을 반환합니다 NNWEESEE.

빈 문자열은 자체를 산출합니다. 다른 입력 사례가 없다고 가정합니다.

언어에 함수 나 문자열이 없으면 가장 적합한 것으로 사용하십시오.

바이트 단위 의 가장 짧은 코드 이깁니다.


우리는 항상 머리가 북쪽을 향한 채로 시작한다고 가정합니까? 그런 식으로, 동쪽을 향한 상대적인 관점에서, 단순히 전진이라고 말하지 않고 우회전해야합니다.
Optimizer

@Optimizer 예, 북쪽. 그리고 당신의 다른 점으로 그렇습니다. 처음에 R같습니다 E.
Calvin 's Hobbies

1
예이! 당신은 항상 생각했던 것을 확인하기 위해 사진을 변경했습니다!
저스틴

4
PPCG에 다시 연결되어 있습니까? ;)
Martin Ender

4
@ MartinBüttner 또는 숙제 문제를 가장 잘 알고 있습니다. ;)
Calvin 's Hobbies

답변:


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 ++을 사용했습니다!
  • C ++에는 함수에 대한 반환 유형을 지정해야합니다. 내가 람다 식을 사용하지 않으면, 즉! 추가 보너스는 기능 이름에 1 문자를 낭비 할 필요가 없다는 것입니다.
  • 코드 *s*9%37&4는 첫 번째 바이트를 테스트합니다. 결과가 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

자바 스크립트 (E6) 84 86 88 92104

편집 : % 대신에 &를 사용하고 다른 연산자 우선 순위 (대괄호)와 음수로 더 잘 작동합니다.
Edit2 : | + 대신 op 우선 순위 -2. 감사합니다 DocMax
Edit3 : 배열 이해는 문자열의 경우 map ()보다 2 자 짧습니다.

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 map 함수는 그 안에 배열을 반환합니다. 부작용으로, 반환해야 할 문자열을 채 웁니다. array && value에 evalute value어떤 배열로 평가로truthy
edc65

1
드디어! 그것이 내가 뭔가를 놓친 거지하지 않는 한, 당신은 대체 할 수있는 88 명중 때문에 나는이 일에보고 된 4+(n-d&3)4|n-d&32 개 문자 저장합니다.
DocMax

4

APL, 72

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

인터프리터 구성을 패널티없이 변경할 수있는 경우 다음 으로 변경 하여 점수는 66입니다 .⎕IO0

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

3

파이썬, (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

하스켈, 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.