나침반 점을도 단위로 변환


18

나는이 도전을 독립적으로 생각해 냈지만 Doorknob 의이 도전에 반대되는 것으로 판명되었습니다 . 나는 그의 스펙을 정말로 좋아하기 때문에 내 자신의 설명을 요리하는 대신 많은 부분을 훔치기로 결정했습니다.

도전

나침반의 32 점 중 하나의 약어가 주어지면 해당 각도를 인쇄하십시오. 32 점에 대한 설명에 관심이 없으면 아래 표를 건너 뛰십시오.

전체 나침반은 다음과 같습니다.

영상

작성자 : Denelson83 (자체 작업) [ GFDL 또는 CC-BY-SA-3.0 ], 위키 미디어 공용

각 방향은 이전보다 11.25 (360/32) 더 먼 거리입니다. 예를 들어, N (북쪽)은 0도, NbE (북쪽 동쪽)는 11.25도, NNE (북동쪽)는 22.5도 등입니다.

세부적으로 이름은 다음과 같이 지정됩니다.

  • 0 도는 N, 90 도는 E, 180 도는 S, 270 도는 W입니다.이를 기본 방향이라고합니다.
  • 기본 방향 사이의 중간 지점은 단순히 연결된 기본 방향입니다. N 또는 S가 항상 먼저 가고 W 또는 E가 항상 두 번째입니다. 이것을 서수 방향이라고합니다. 서수 및 기본 방향은 함께 주풍을 형성합니다.
  • 주풍 사이의 중간 지점은 이들이 연결된 방향입니다. 기본 방향은 먼저, 서수 방향으로 이동합니다. 이것을 반 바람이라고합니다.
  • 주풍과 반풍 사이의 중간 지점은 주풍에서 가장 가까운 기본 방향으로 "주변"인 인접한 주풍입니다. 이것은로 표시됩니다 b. 이것을 1/4 바람이라고합니다.

결과는 다음과 같습니다.

#   Degrees  Abbrv.  Name
1   0        N       North
2   11.25    NbE     North by east
3   22.5     NNE     North-northeast
4   33.75    NEbN    Northeast by north
5   45       NE      Northeast
6   56.25    NEbE    Northeast by east
7   67.5     ENE     East-northeast
8   78.75    EbN     East by north
9   90       E       East
10  101.25   EbS     East by south
11  112.5    ESE     East-southeast
12  123.75   SEbE    Southeast by east
13  135      SE      Southeast
14  146.25   SEbS    Southeast by south
15  157.5    SSE     South-southeast
16  168.75   SbE     South by east
17  180      S       South
18  191.25   SbW     South by west
19  202.5    SSW     South-southwest
20  213.75   SWbS    Southwest by south
21  225      SW      Southwest
22  236.25   SWbW    Southwest by west
23  247.5    WSW     West-southwest
24  258.75   WbS     West by south
25  270      W       West
26  281.25   WbN     West by north
27  292.5    WNW     West-northwest
28  303.75   NWbW    Northwest by west
29  315      NW      Northwest
30  326.25   NWbN    Northwest by north
31  337.5    NNW     North-northwest
32  348.75   NbW     North by west

다음은 나침반의 요점에 대한 자세한 차트와 가능한 더 나은 설명입니다.

당신의 임무는 세 번째 열에서 32 약어 중 하나를 입력으로 사용하고 두 번째 열에 해당 각도를 출력하는 것입니다.

입력이 항상 32 개의 문자열 중 하나라고 가정 할 수 있습니다 (선택적으로 그러나 단일 후행 줄 바꿈을 선택적으로 기대할 수 있음). 후행 0이 허용되지만 출력도 위에 나열된대로 정확하게 제공되어야합니다. 선택적으로 단일 후행 줄 바꿈을 출력 할 수 있습니다.

STDIN (또는 가장 가까운 대안), 명령 행 인수 또는 함수 인수를 통해 입력을 받고 STDOUT (또는 가장 가까운 대안), 함수 리턴 값 또는 함수 (out) 매개 변수를 통해 결과를 출력하는 프로그램 또는 함수를 작성할 수 있습니다.

이것은 코드 골프이므로 가장 짧은 대답 (바이트)이 이깁니다.

답변:


2

Pyth, 47 바이트

c*45x"NuMD¢¼Ew
XSj.{§/gWbZ¹°"C%CzC\½4

인쇄 할 수없는 문자로 인한 16 진 덤프 :

0000000: 632a 3435 7822 4e86 754d 0344 a2bc 4504  c*45x"N.uM.D..E.
0000010: 770a 9518 1c58 536a 2e7b a77f 2f67 5762  w....XSj.{../gWb
0000020: 5ab9 15b0 8798 2243 2543 7a43 5cbd 34    Z....."C%CzC\.4

테스트 하네스

공식 명령 행 컴파일러의 버그로 인해이 코드는 위에 링크 된 온라인 컴파일러 또는 -c오프라인 컴파일러 의 플래그를 통해서만 작동합니다 . (질문이 묻은 후에 버그가 수정되었습니다.)

이 솔루션은 @Dennis의 CJam 답변과 매우 유사합니다. 입력을 해시하고 32 바이트 조회 문자열에서 결과를 찾은 다음 11.25를 곱하는 프로세스를 사용합니다.

내가 사용하는 해시 함수는 입력을을 사용하여 기본 256 정수 인 것처럼 문자열로 변환하고 C결과 modulo C½189를 취하지 만 우수한 구문 분석으로 인해 바이트를 저장하고 C다시 문자열로 다시 변환 합니다. .

11.25를 곱하면 45를 곱한 다음 4로 나누어 바이트를 절약 할 수 있습니다.


9

루비, 118 106

12 바이트 절약 된 Martin Büttner에게 감사드립니다.

함수인지 프로그램인지에 관계없이 현재 길이는 같습니다.

람다 함수

->s{n=4
d=0,0
s.chars{|e|c="SWNE".index e
c ?d[c%2]+=c/2*2*n-n :n=1}
(Complex(*d).arg*5.1).round%32*11.25}

프로그램

n=4
d=0,0
gets.chars{|e|c="SWNE".index e
c ?d[c%2]+=c/2*2*n-n :n=1}
p (Complex(*d).arg*5.1).round%32*11.25

이것은 점을 통한 직교 보행입니다. 문자는 NSEW에 저장된 x 및 y 좌표에서 4를 더하거나 뺍니다 d[]. 후 b(또는 이외의 심볼 NSEW발생)이 1로 감소된다.

그런 다음 x 및 y 데이터는 각 인수를 추출하기 위해 복소수로 처리됩니다. 16 / PI =을 곱합니다 5.1. 접근 방식에 약간의 기하학적 오류가 있지만이 각도를 반올림하면 올바른 수를 제공하기에 충분합니다 -15..+16. Modulo는 이것을 수정하기 위해 사용됩니다 0..31(Ruby에서는 %항상 양수를 반환합니다). 마지막으로 결과에 11.25를 곱합니다.


1
반올림으로 얼마나 영리한 아이디어입니까! 가장 가까운 직교 방향을 기준으로 한 각도 대신 각도의 아크 탄을 얻지 만 충분히 가깝습니다.
xnor

반올림없이 @ xnor은 NbE 14.05 (+2.8), NNE 26.60 (+4.1), NEbE 51.41 (-4.84)을 얻으므로 값에 약간의 여유가 n있었지만 신중하게 선택해야했습니다.
Level River St

6

자바 스크립트 (ES6), 153 바이트

그냥 간단한 공으로 구르기를 원했습니다.

x=>'N NbE NNE NEbN NE NEbE ENE EbN E EbS ESE SEbE SE SEbS SSE SbE S SbW SSW SWbS SW SWbW WSW WbS W WbN WNW NWbW NW NWbN NNW NbW'.split` `.indexOf(x)*45/4

특히 혁신적이지는 않지만 효과가 있으며 아마도 그로부터 얻을 수있는 몇 가지 팁이있을 것입니다. 걱정하지 마십시오. 또 다른 (더 나은) 기술을 생각할 것입니다.


1
아마도 문자열을 압축 할 수 있습니까?
mbomb007

1
놀랍게도 알고리즘 접근법을 사용하는 Python의 (제출되지 않은) 솔루션보다 여전히 짧습니다.
pawel.boczarski

2

CJam, 49 바이트

0000000: 72 34 62 32 35 33 25 63 22 4e bf 6f f1 80 e8 dc 38  r4b253%c"N.o....8
0000011: 45 3d f0 2e 94 3c d3 12 53 24 e5 5f a6 63 28 60 57  E=...<..S$._.c(`W
0000022: 5b 14 20 92 17 81 d1 22 23 31 31 2e 32 35 2a        [. ...."#11.25*

위의 16 진 덤프는로 바꿀 수 있습니다 xxd -r -c 17 -g 1.

CJam 통역사 에서 온라인으로 사용해보십시오 .

작동 원리

r      e# Read a token from STDIN.
4b     e# Convert the string (array of code points) from base 4 to integer.
253%   e# Take the result modulo 253.
c      e# Cast to character.
"…"    e# Push a 32 byte lookup table.
#      e# Find the index of the character.
11.25* e# Multiply the index by 11.25.

1

자바, 653 자

Java가 이길 수는 없지만 어쨌든 노력하고 싶습니다.

class C{float c=1/8f;int n=0;float a;public C(String s){if(s.contains("W"))n=4;switch(s.length()){case 1:p(d(s));case 2:p(e(s));case 3:if(s.contains("b"))f(s,1);g(s);}f(s,2);}int v(char x){switch(x){case 'N':return n;case 'E':return 1;case 'S':return 2;}return 3;}int d(String s){return v(s.charAt(0));}float e(String s){return (v(s.charAt(0))+v(s.charAt(1)))/2f;}void f(String s,int i){if(i<2)a=v(s.charAt(0));else a=e(s.substring(0,i));if(v(s.charAt(1+i))<a)c=-c;p(a+c);}void g(String s){p((d(s.substring(0,1))+e(s.substring(1)))/2f);}void p(float x){System.out.printf("%.2f",x*90);System.exit(0);}public static void main(String[]r){C c=new C(r[0]);}}

명령 줄에서 입력을 받아 콘솔로 출력합니다. 언 골프 버전 :

class Compass
{
    float c = 1/8f;
    int n = 0;
    float a;

    public Compass( String s )
    {
        if( s.contains( "W" ) )
        {
            n = 4;
        }
        switch( s.length() )
        {
            case 1:
                print( parse1( s ) );
            case 2:
                print( parse2( s ) );
            case 3:
                if( s.contains( "b" ) )
                {
                    parse3b4( s , 1 );
                }
                parse3( s );
        }
        parse3b4( s , 2 );
    }

    int getValue( char x )
    {       
        switch( x )
        {           
            case 'N':
                return n;
            case 'E':
                return 1;
            case 'S':
                return 2;           
        }
        return 3;
    }

    int parse1( String s )
    {
        return getValue( s.charAt( 0 ) );
    }

    float parse2( String s )
    {
        return ( getValue( s.charAt( 0 ) ) + getValue( s.charAt( 1 ) ) ) / 2f;
    }

    void parse3b4( String s , int i )
    {
        if( i < 2 ) a = getValue( s.charAt( 0 ) );
        else a = parse2( s.substring( 0 , i ) );
        if( getValue( s.charAt( 1 + i ) ) < a )
        {
            c = -c;
        }
        print( a + c );
    }

    void parse3( String s )
    {
        print( ( parse1( s.substring( 0 , 1 ) ) + parse2( s.substring( 1 ) ) ) / 2f );
    }

    void print( float x )
    {       
        System.out.printf( "%.2f" , x * 90 );
        System.exit( 0 );
    }

    public static void main( String[] args )
    {
        Compass compass = new Compass( args[ 0 ] );
    }
}

NW에 0-3을 할당하여 작동합니다 (W가 관련된 경우 N에 4). 다음 4 가지 상황을 인식합니다.

  • parse1은 단일 문자 포인트 용이며 값을 반환합니다.
  • parse2는 이중 문자 포인트이며 2 포인트의 평균입니다.
  • parse3은 트리플 문자 포인트를위한 것이며, 더블 및 싱글 포인트의 평균의 평균을 취합니다.
  • parse3b4는 'b'가 포함 된 모든 항목에 대해 'b'앞의 점 값을 계산하고 'b'뒤의 점의 '방향'에 따라 1/8을 더하거나 뺍니다.

print ()에서 실제 각도를 얻기 위해 값에 90을 곱합니다.


작성 C c=new C(r[0]);해야합니까? 아마도 new C(r[0]);충분할까요?
pawel.boczarski

1

파이썬 3, 149 바이트

재귀 알고리즘 접근법을 시도했습니다. 1/4 바람은 처음에 생각했던 것보다 다루기가 어려웠으므로이 솔루션은 상대적으로 길어졌습니다.

def f(s):
 if'W'in s:s=s.replace(*'Nn')
 a=(len(s)-2)/8;return'b'in s and(1-a)*f(s[:-2])+a*f(s[-1])or a>=0and(f(s[0])+f(s[1:]))/2or'NESWn'.find(s)*90

언 골프 드 :

def f(s):
    if 'W'in s:
        s = s.replace('N','n')
    a=(len(s)-2)/8
    if 'b' in s:
        a = 1/8 if len(s)==3 else 1/4
        return (1-a)*f(s[:-2])+a*f(s[-1])
    else:
        if len(s)==1:
            return 'NESWn'.find(s)*90
        else:
            return (f(s[0])+f(s[1:]))/2

골프 버전은 10을 곱해야하는 10 진수를 f("NbW")반환합니다 ( 34.875대신에 반환 348.75)
智障 的 人

@ viktorahlström, 확실합니까? 그것은 나를 위해 올바른 값을 반환합니다. 코드를 복사하여 붙여 넣을 때 마지막 0을 놓친 것일 수 있습니다.
Emil

오, 미안, 분명히 그랬어-내 실수, 미안!
智障 的 人

1

하스켈, 206 바이트

c l=11.25*(fromIntegral$b$l)
b l|(p y l)<0=a l+16|0<1=mod(a l)32
a l=round$(16/pi*)$atan$d$l
d l=p x l/p y l
p z[]=0.0
p z('b':[r])=z r/4
p z(a:r)=z a+p z r
x 'E'=4
x 'W'=(-4)
x c=0
y 'N'=4
y 'S'=(-4)
y c=0

편리한 테스트 :

*Main> map c ["N","NbE","NNE","NEbN","NE","NEbE","ENE","EbN","E","EbS","ESE","SEbE","SE","SEbS","SSE","SbE","S","SbW","SSW","SWbS","SW","SWbW","WSW","WbS","W","WbN","WNW","NWbW","NW","NWbN","NNW","NbW"]
[0.0,11.25,22.5,33.75,45.0,56.25,67.5,78.75,90.0,101.25,112.5,123.75,135.0,146.25,157.5,168.75,180.0,191.25,202.5,213.75,225.0,236.25,247.5,258.75,270.0,281.25,292.5,303.75,315.0,326.25,337.5,348.75]

0

PowerShell-350

Comapss_gui_in_powershell

Add-Type -AssemblyName *sys*forms*
$f=new-object windows.forms.form
$c=new-object windows.forms.combobox
$c.DataSource=(-split"N NbE NNE NEbN NE NEbE ENE EbN E EbS ESE SEbE SE SEbS SSE SbE S SbW SSW SWbS SW SWbW WSW WbS W WbN WNW NWbW NW NWbN NNW NbW")
$c.Parent=$f
$c.Add_SelectedValueChanged({$f.text=$c.SelectedIndex*11.25})
$f.ShowDialog()

0

줄리아 151 147 142 바이트

t=strchr
p=s->if ""==s 0;else i=t(s,'b')
(32/2^i)^sign(i)*p(i>0?s[1:i-1]:s[2:])+im^t("ESWN",s[i+1])end
f=s->90int(16mod(angle(p(s)),2pi)/pi)/8

언 골프 :

# return approx. direction in term of complex number of absolute value 1,
# whose argument is the direction:
# N -> 0, E -> 0+1j, S -> -1, W -> 0-1j
function p(s)
    if ""==s 0;
    else
        i=strchr(s,'b');
        if i!=0
            # if 'b' is 2nd in the word, following direction weight is 1/8,
            # if 'b' is 3rd in the word, following direction weight is 1/4.
            weight=2^(5-i)
            # the first term to count avg is all before 'b'
            first_term=s[1:i-1]
        else
            # weights are equal for the counted and the new (eg. 'NNW <= avg(N, NW)')
            weight=1
            # the first term to count avg is all after the first character
            first_term=s[2:]
        end
        # the return value - average of two vectors
        # s[i+1] evaluates to FIRST character if 'b' didn't occur
        # or to the LAST CHARACTER (after 'b') if it did.
        e^(im*angle(weight*p(first_term)+im^t("ESWN",s[i+1])));
    end
end

# ... And the proper function for returning angle
# there are errors (sic!) in the counted direction, but dividing by 11.25,
# rounding and remultiplying by 11.25 filters them out
f=s->int32(mod(angle(p(s)),2pi)/pi*16)*11.25

ungolfed 코드에서는 평균 = e ^ {jArg (v_1 + v_2)}벡터가 여전히 정규화되도록 두 벡터의 평균을 계산합니다 . 그러나 첫 번째 벡터의 연장으로 인한 오류는 아직 재귀에 거의 추가되지 않으므로 정규화 단계가 제거되고 계산이 평균 = v_1 + v_2간단 해집니다. 전체 원의 1/64 미만의 오류는 반올림하여 필터링됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.