แปลงจุดของเข็มทิศเป็นองศา


18

ฉันมากับความท้าทายนี้เป็นอิสระ แต่มันจะออกมาเป็นสิ่งที่ตรงกันข้ามเพื่อความท้าทายนี้โดย Doorknob ในขณะที่ฉันชอบสเป็คของเขาฉันตัดสินใจที่จะขโมยชิ้นส่วนขนาดใหญ่แทนที่จะทำตามคำอธิบายของฉันเอง

ความท้าทาย

รับตัวย่อของหนึ่งใน 32 คะแนนบนเข็มทิศพิมพ์องศาที่สอดคล้องกัน อย่าลังเลที่จะข้ามไปที่ตารางด้านล่างหากคุณไม่สนใจคำอธิบายของ 32 คะแนน

นี่คือเข็มทิศเต็ม:

ภาพ

โดย Denelson83 (ทำงานของตัวเอง) [ GFDLหรือCC-BY-SA-3.0 ] ผ่านWikimedia Commons

แต่ละทิศทางคือ 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นี้จะแสดงด้วย สิ่งเหล่านี้เรียกว่า

ผลลัพธ์นี้ในแผนภูมิต่อไปนี้:

#   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 สตริงเหล่านั้นเสมอ (และคุณอาจเลือก แต่คาดหวังว่าจะมีบรรทัดใหม่ต่อท้ายหนึ่งบรรทัด) ควรให้ผลลัพธ์ตรงตามที่ระบุไว้ข้างต้นแม้ว่าจะอนุญาตให้มีเลขศูนย์ต่อท้ายก็ตาม คุณสามารถเลือกที่จะออกบรรทัดใหม่ต่อท้ายบรรทัดเดียว

คุณสามารถเขียนโปรแกรมหรือฟังก์ชั่น, รับอินพุตผ่าน STDIN (หรือทางเลือกที่ใกล้เคียงที่สุด), อาร์กิวเมนต์บรรทัดคำสั่งหรืออาร์กิวเมนต์ของฟังก์ชันและส่งผลลัพธ์ผ่าน STDOUT (หรือทางเลือกที่ใกล้เคียงที่สุด), ค่าส่งคืนของฟังก์ชันหรือพารามิเตอร์

นี่คือรหัสกอล์ฟดังนั้นคำตอบที่สั้นที่สุด (เป็นไบต์) ชนะ

คำตอบ:


2

Pyth, 47 ไบต์

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

Hexdump เนื่องจากอักขระที่ไม่สามารถพิมพ์ได้:

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แฟล็กของคอมไพเลอร์ออฟไลน์ (ข้อผิดพลาดได้รับการแก้ไขหลังจากคำถามถูกถาม)

วิธีนี้คล้ายกับคำตอบ CJam ของ @ Dennis โดยใช้กระบวนการของการแปลงแป้นพิมพ์ค้นหาผลลัพธ์ในสตริงการค้นหา 32 ไบต์แล้วคูณด้วย 11.25

ฟังก์ชั่นแฮชที่ฉันใช้คือแปลงอินพุตเป็นสตริงราวกับว่ามันเป็นจำนวนเต็มฐาน 256 โดยCรับผลลัพธ์โมดูโลCของ½ซึ่งก็คือ 189 แต่บันทึกไบต์เนื่องจากการแยกวิเคราะห์ที่เหนือกว่าและแปลงกลับเป็นสตริงCอีกครั้ง .

การคูณด้วย 11.25 สามารถทำได้โดยการคูณด้วย 45 แล้วหารด้วย 4 ซึ่งจะบันทึกไบต์


9

ทับทิม, 118 106

ขอบคุณ Martin Büttnerที่บันทึกไว้ 12 ไบต์

ปัจจุบันนี้มีความยาวเท่ากันไม่ว่าจะเป็นฟังก์ชั่นหรือโปรแกรม

ฟังก์ชั่นแลมบ์ดา

->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เพิ่มหรือลบ 4 x และ y d[]พิกัดที่เก็บไว้ใน หลังจาก a b(หรือสัญลักษณ์อื่นใดนอกจากNSEW ) สิ่งนี้จะลดลงเป็น 1

จากนั้นข้อมูล x และ y จะถือว่าเป็นจำนวนเชิงซ้อนเพื่อแยกอาร์กิวเมนต์เชิงมุม นี้จะถูกคูณด้วย 16 / PI 5.1= -15..+16แม้ว่าจะมีบางข้อผิดพลาดทางเรขาคณิตในแนวทางปัดเศษมุมนี้ก็เพียงพอที่จะให้ตัวเลขให้ถูกต้อง Modulo ใช้เพื่อแก้ไขสิ่งนี้เป็น0..31(ใน Ruby %จะให้ค่าเป็นบวกเสมอ) ในที่สุดผลลัพธ์จะถูกคูณด้วย 11.25


1
ช่างเป็นความคิดที่ฉลาดแค่ไหนในการปัดเศษ! คุณได้ arctan ของมุมแทนที่จะเป็นมุมถ่ายโดยเทียบกับทิศทางมุมฉากที่ใกล้ที่สุด แต่กลับกลายเป็นใกล้พอ
xnor

@ xnor โดยไม่มีการปัดเศษฉันได้รับ NbE 14.05 (+2.8), NNE 26.60 (+4.1), NEbE 51.41 (-4.84) ​​ดังนั้นฉันจึงมีค่าใช้จ่ายบางอย่างnแต่ฉันต้องเลือกอย่างระมัดระวัง
เลเวลริเวอร์

6

Javascript (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*

ด้านบนเป็นรูปหกเหลี่ยมซึ่งสามารถย้อนกลับได้ด้วย 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

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

ใช้อินพุตจาก commandline และเอาต์พุตไปยังคอนโซล เวอร์ชันที่ไม่ดี:

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

มันทำงานได้โดยกำหนด 0-3 ถึง NW (หรือ 4 สำหรับ N หากเกี่ยวข้องกับ W) รับรู้สถานการณ์ที่แตกต่างกัน 4:

  • parse1 ใช้สำหรับจุดตัวอักษรเดียวมันแค่คืนค่า
  • parse2 สำหรับจุดตัวอักษรสองตัวมันเฉลี่ยค่าของ 2 คะแนน
  • parse3 ใช้สำหรับจุดสามตัวอักษรมันใช้ค่าเฉลี่ยของค่าเฉลี่ยของสองและจุดเดียว
  • parse3b4 มีไว้สำหรับทุกคนที่มี 'b' ในพวกเขามันจะคำนวณค่าของจุดก่อนที่ 'b' และเพิ่มหรือลบ 1/8 ขึ้นอยู่กับ 'ทิศทาง' ของจุดหลัง 'b'

ในการพิมพ์ () ค่าจะถูกคูณด้วย 90 เพื่อให้ได้มุมที่แท้จริง


จำเป็นต้องเขียนC c=new C(r[0]);หรือไม่? อาจnew C(r[0]);จะเพียงพอหรือไม่
pawel.boczarski

1

Python 3, 149 ไบต์

ฉันลองใช้อัลกอริทึมแบบเรียกซ้ำ ลมในไตรมาสนั้นจัดการได้ยากกว่าที่ฉันคิดไว้ตั้งแต่แรกดังนั้นวิธีนี้จึงขยายตัวค่อนข้างยาว

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

Ungolfed:

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

เวอร์ชัน Golfed ส่งคืนทศนิยมที่ต้องคูณด้วย 10 ( f("NbW")ส่งคืน34.875แทน348.75)
智障的人

@ viktorahlströmคุณแน่ใจหรือ มันคืนค่าที่ถูกต้องสำหรับฉัน คุณอาจพลาดศูนย์สุดท้ายเมื่อคัดลอกและวางรหัสหรือไม่
Emil

โอ้ขอโทษเห็นได้ชัดว่ามันเป็นความผิดพลาดของฉันขอโทษ!
智障的人

1

Haskell, 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

Julia, 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

บิต ungolfed:

# 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 ฉันนับค่าเฉลี่ยของเวกเตอร์สองตัวavg = e ^ {jArg (v_1 + v_2)}เพื่อให้เวกเตอร์ยังคงเป็นมาตรฐาน อย่างไรก็ตามข้อผิดพลาดอันเนื่องมาจากการยืดตัวของเวกเตอร์แรกนั้นยังไม่ได้สะสมด้วยการเพิ่มเติมซ้ำในการเรียกซ้ำของเราดังนั้นในขณะที่การเล่นกอล์ฟขั้นตอนการทำให้เป็นมาตรฐานถูกลบออกและการคำนวณเป็นไปavg = v_1 + v_2อย่างง่ายดาย ข้อผิดพลาดน้อยกว่า 1/64 ของวงกลมเต็มจะถูกกรองออกโดยการปัดเศษ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.