남북으로 남북으로 도가 아닌 45도를 나타내도록 두

N, S, E 및 W의 문자열이 주어지면 소수 자릿수 5 자리까지 올바른 방위 (북에서 시계 방향 각도)를 출력합니다.

에서 기존의 나침반 표기법 , 문자열은 2 (북북서 또는 ESE 같은) 이러한 문자로 구성되어 있습니다. 여기에는 WNNNSE와 같이 4를 모두 포함하는 문자열도 허용해야합니다 . 인간은 2 개의 기호 만 사용하여 의미를 직관적으로 이해할 수 있습니다. 4 개의 기호를 허용하면 읽기가 끔찍하지만 주어진 정확도로 베어링을 설명하는 짧은 방법을 사용할 수 있습니다.

(AS는 지적 주석 에 의해 user2357112 , 내가 잘못된 가정에이 문제를 기반으로 한 있도록, 특정 방위를 들어, 4 기호 문자열이 두 기호 문자열과 정확히 같은 길이 될 것이라고 증명할 수 밝혀졌습니다. 이 실용적인 목적의 부족이 도전에 대한 즐거움을 방해하지 않기를 바랍니다 …)

정확한 방법은 아래에 설명되어 있으며 기존 표기법과 동일합니다 (변경하지 않고 확장 함).

입력

  • 입력은 문자 만 포함하는 단일 문자열입니다 NESW 입니다.
  • 전처리를 포함하지 않는 경우 원하는 경우 입력이 일련의 문자 일 수 있습니다. 예를 들어 중첩 목록을 가져옵니다.[N, [E, [S, [W]]]] 처리 순서를 돕기 을 것은 허용되지 않습니다.
  • 다른 캐릭터를 사용할 수 없습니다. 1234대신에 문자열을 사용할 수 없습니다NESW .

산출

  • 출력은 10 진수 또는 1의 문자열 표현이어야합니다 (이성 / 분수 아님).
  • 후행 0을 표시 할 필요는 없습니다. 베어링이 9.00000인 경우 출력9 도 소수점 5 자리까지 정확한 것으로 계산됩니다.
  • 출력 범위는 [0, 360)입니다. 즉, 0은 포함하고 360은 제외합니다.
  • 출력은 소수점 다섯 자리로 반올림하여 확인합니다. 베어링이 0.000005 인 경우 0.00001로 반올림합니다. 출력 0.00001과 0.000005는 모두 정확합니다.
  • 일부 입력에 대해서는 과학적 표기법으로 출력 할 수 있습니다. 예를 들어, 1e-5대신 0.00001.

변환

  • 단일 문자 나침반 점 N, E, S, 및 W대응하여 0, 90, 180, 270도 각각.
  • 이 중 하나를 문자열에 추가하면 단일 문자의 베어링과 원래 문자열의 베어링을 이등분하는 베어링이 생성됩니다.
  • NE가 225 도가 아닌 45도를 나타내도록 두 개의 가능한 이등분 베어링 중 가장 가까운 것이 선택됩니다.
  • 이등분 될 각도가 180 도인 경우를 제외하고는 분명합니다. 따라서 NS, SN, WE, 및EW 정의되지 않은 베어링에 해당하고, 입력은 이들의에 끝이 없을 것입니다. 그러나 입력 문자열의 다른 곳에 나타날 수 있습니다. 모호성이 없습니다.
  • 마지막 두 문자가 동일하면 이분법이 동일한 방위를 반환하므로 마지막 문자는 중복됩니다. 이것은 표기법에 아무것도 추가하지 않기 때문에 코드는 이것을 처리 할 필요가 없습니다. 따라서 NN, EE, SS, 그리고 WW정의되지 않은 베어링에 해당하고, 입력은 이들의에 끝이 없을 것입니다. 그러나 입력 문자열의 다른 곳에 나타날 수 있습니다.

N: 0
E: 90
S: 180
SE: halfway between S and E: 135
NSE: halfway between N and SE: 67.5
NNSE: halfway between N and NSE: 33.75
NNNSE: halfway between N and NNSE: 16.875
NNNNSE: halfway between N and NNNSE: 8.4375

테스트 사례

제출은 모든 테스트 사례에 대해 올바른 결과를 제공하는 경우에만 유효합니다. 테스트 케이스는 배정 밀도로 처리 할 수있는 것의 한계까지 밀려납니다. 기본적으로 단 정밀도를 사용하는 언어의 경우 올바른 출력을 얻으려면 바이트를 사용하여 배정 밀도를 지정해야합니다.

테스트 케이스 출력은 소수점 5 자리로 반올림되며 임의의 정밀도로 표시됩니다. 둘 다 유효한 출력입니다.

WNE 337.5 337.5
WEN 337.5 337.5
WEWEWEWEWEWEWEWEWEWEWEN 330.00001 330.000007152557373046875
NESWNESWNESWNESWNESWNESWNESW 90 89.99999932944774627685546875
NNNNNNNNNNNNNNNNNNNNNNNE 0.00001 0.0000107288360595703125
NNNNNNNNNNNNNNNNNNNNNNNW 359.99999 359.9999892711639404296875
SNNNNNNNNNNNNNNNNNNNNNNNE 90.00001 90.00000536441802978515625
SNNNNNNNNNNNNNNNNNNNNNNNW 269.99999 269.99999463558197021484375

채점

이것은 입니다. 점수는 소스 코드의 길이 (바이트)이며 가장 짧은 승입니다.


페단 트리

“North by North West”가 올바른 나침반 방향이라고 생각하는 실수를했습니다. 그것은 도전 생각을했다,하지만 난 다음에서 발견 된 이후 행복한 실수, 위키 백과 페이지 :

“알프레드 히치콕 1959 영화의 제목, 북북서로 진로를 돌려라는 실제로 32 바람 나침반 방향 지점이 아니라, 영화에는 노스 웨스트 항공에 대한 언급이 포함되어 있습니다. ”

또한이 과제에 사용 된 방법은 16 포인트 나침반을 포함하여 기존 나침반 포인트와 만 일치한다는 것이 밝혀졌습니다. 해당 페이지에 설명 된 32- 바인 컴퍼스는 미묘하게 다르며이 과제에 대한 존재를 편리하게 간과했습니다. .

마지막으로 “South East”대신 “Southeast”를 사용해야한다고 생각하는 사람은



답변

JavaScript (ES6), 84 80 78 74 72 bytes

Saved a byte thanks to @Titus, 1 thanks to @Neil

f=([c,...s],b="NESW".search(c))=>b*90-(s[0]?(b-=f(s)/90)-4*(b*b>4):0)*45

It took a while, but I think I’ve finally perfected the formula…

Test snippet

f=([c,...s],b="NESW".search(c))=>b*90-(s[0]?(b-=f(s)/90)-4*(b*b>4):0)*45
g=(s,n)=>console.log('f("'+s+'"):',f(s),"expected:",n)

g("N", 0)
g("NE", 45)
g("E", 90)
g("SE", 135)
g("S", 180)
g("SW", 225)
g("W", 270)
g("NW", 315)
g("WNE", 337.5)
g("WEN", 337.5)
g("WEWEWEWEWEWEWEWEWEWEWEN", 330.00001)
g("NESWNESWNESWNESWNESWNESWNESWNESWNESWNESWNESWNESWNESW", 90)
g("NNNNNNNNNNNNNNNNNNNNNNNE", 0.00001)
g("NNNNNNNNNNNNNNNNNNNNNNNW", 359.99999)
g("SNNNNNNNNNNNNNNNNNNNNNNNE", 90.00001)
g("SNNNNNNNNNNNNNNNNNNNNNNNW", 269.99999)

Explanation

Let’s start with the simplest case: a single-char string. The result is simply its (0-indexed) position in the string NESW, multiplied by 90.

For a two-char string, the result lies halfway between the result of the first char and the result of the second. However, there’s a catch: if the absolute difference between the two is greater than 180 (e.g. NW or WN), we must 180 to the angle so that it’s not pointing the opposite direction.

For any longer string, the result lies halfway between the result of the first char and the result of the rest of the string. This can be generalized in the following way:

  • If the input is a single char, return its index in the string NESW times 90.
  • Otherwise, return the index of the first char in the string NESW times 45, plus half the result of the rest of the string; add an extra 180 if the absolute difference between the two is greater than 90.

답변

C#6, 226 217 207 185 bytes

using System.Linq;double N(string s){double b=f(s.Last());foreach(var c in s.Reverse()){b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0))/2;b=(b+4)%4;}return b*90;}int f(char x)=>"NESW".IndexOf(x);

Edit: -10 bytes by “borrowing” idea from ETHproductions’s submission
-22 bytes thanks to @Titus

Ungolfed

// Call this method
double N(string s){
    // Initialize bearing with last direction
    double b=f(s.Last());
    // Do backward. Doing last direction once more doesn't impact result
    foreach(var c in s.Reverse()){
        // Average current bearing with new bearing, adjusted with wrapping
        b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0))/2;
        // Make bearing back to range [0,4)
        b=(b+4)%4;
    }
    // Change from "full circle = 4" unit to degree
    return b*90;
}
// helper method to convert direction to bearing. This returns bearing with full circle = 4.
int f(char x)=>"NESW".IndexOf(x);

답변

PHP, 95 88 86 100 127 104 101 bytes

  • -7 bytes with the null coalescing operator
  • -2 bytes by not replacing N (and more, because that allows to put the translation to the loop head: N is truthy, but evaluates to 0 in the calculation.)
  • +41 bytes for fixing the bisection (cough)
  • -7 bytes directly and -16 indirectly inspired by @ETHproductions´ code
  • -3 bytes by replacing strtr with one of my bit jugglings

for($i=strlen($s=$argv[1]);$i--;$p=($q+$p=$p??$q)/2+2*(abs($q-$p)>2))$q=ord($s[$i])/.8+3&3;echo$p*90;

This is officially the first time ever that I use the null coalescing operator. Run with -r.

PHP 7.1

Negative string offsets in the upcoming PHP version will save 12 bytes:
Replace strlen($s=$argv[1]) with 0 and $s with $argv[1].


Free bytes for (almost) everyone:

  • Calculating with 0,1,2,3 instead of 0,90,180,270 and multiplying the final result with 90 will save two bytes and probably allow further golfing.
  • There are some patterns in the ASCII codes of the characters. Try one of these in your language:
    • (a/2%6+2)%5
    • a<87?a/2&3^3:3 or a/2&3^3*(a<87)
    • a&1?a&2|a/4&1:0
    • a/.8-1&3

답변

Python 3, 133 113 bytes

Just improving on @L3viathan’s answer because I just made this account and therefore can’t make comments yet.

d={"N":0,"E":.5,"S":1,"W":1.5}
def B(s):
 b=d[s[-1]]
 for c in s[::-1]:b=(b+d[c])/2+(abs(b-d[c])>1)
 return b*180

답변

05AB1E, 48 42 37 32 bytes

Saved 6 bytes thanks to Emigna.
Saved 5 bytes thanks to Titus’ idea to work on range [0,4[ and multiply by 90 at the end.
Saved 5 bytes thanks to Adnan’s mastery of ancient xor/modulo metamorphosis.

So every angle is reduced from range [0,360[ to range [0,4[ throughout the execution. Result is then multiplied by 90 and displayed.

Ç30^5%R¬U¦vXy+;DX-Ä0›2*+4%U}X90*

It can be divided into two sequentially called subprograms.
First program: convert input string into an array of the corresponding angles in range [0,4[
Ç      Take the ascii value of all input characters
 30^5% Dark ascii manipulation that yields [0,1,2,3] for [N,E,S,W]

Now we have an array of integers in range [0,4[.

Second program: actually compute the final angle
R                          Reverse the array
 ¬                         Take the first value (the last of the non-reversed array)
  U                        Pop it from the stack and set X to the same value
   ¦                       Strip the first element
    v                      For each remaining element
     Xy+;                  Compute the average value between the leftmost value and X
         DX-Ä0›            Push 1 if angular distance cast to integer is > 0 (i.e. if it is >= 1), 0 otherwise. It's equivalent to checking >= 90 degrees
               2*+         Multiply by 2 (=2 if angular distance is >= 1 and 0 otherwise) and add it to the formerly computed average value. It's equivalent to multiplying by 180
                  4%       Perform mod 4. It's equivalent to performing mod 360
                    U      Store the result back to X
                     }     End for, mandatory if input has only one character
                      X90* Push X*90 and implicitly display it

Try it online!

Potential axes of golfing:

  • Not sure if that mod 4 is required (it would save 2 bytes). All test cases work without it, but maybe there exists a tricky case. A mathematical proof to either validate it or nullify it would be top-notch.
  • There is no implicit stuff besides displaying the result (closing quote marks, closing brackets).

답변

Python 3, 146 145 117 107 97 94 93 92 bytes

f(s):u='NESW'.find(s[0])*90;return(u+f(s[1:]))/2+180*(abs(u-‌​f(s[1:]))>180)if s[1:]else u

Call f with the string.


답변

C, 184 bytes

double h(char c){return ((c=='E')+(c=='S')*2+(c=='W')*3);}double d(char*s){double f=h(*s);if(s[1]){double t=f;f=(f+d(s+1)/90)/2;if(((t-f)>1)||((f-t)>1))f+=2;if(f>=4)f-=4;}return f*90;}

Ungolfed

// a helper function
double direction_(char ch)
{
    if (ch=='N')
        return 0.;
    else if (ch=='E')
        return 90.;
    else if (ch=='S')
        return 180.;
    else
        return 270.;
}

// this is the main function to call
double direction(char* str)
{
    double fAngle = direction_(str[0]);
    if (str[1])
    {
        double tmp = fAngle + direction(str+1);
        if (tmp>=360.)
            tmp-=360.;
        tmp/=2;

        if (((tmp-fAngle)>90.) || ((tmp-fAngle)<-90.))
        { //  check if we need to take the "other side"; if the resulting angle is more than 90 degrees away, we took the wrong on
            if (tmp>=180.)
                tmp-=180.;
            else
                tmp+=180.;
        }
        fAngle = tmp;
    }
    return fAngle;
}