将指南针的点转换为度


18

我独立提出了这个挑战,但是事实证明,这与Doorknob提出的挑战相反。因为我真的很喜欢他的规格,所以我决定窃取大部分规格,而不是自己解释。

挑战

给定指南针上32个点之一的缩写,请打印相应的度数。如果您对这32点的解释不感兴趣,请随时跳到下表。

这是完整的指南针:

图片

由Denelson83(自己的作品)[ GFDLCC-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(或最接近的替代方案),函数返回值或函数(out)参数输出结果。

这是代码高尔夫球,因此最短的答案(以字节为单位)获胜。

Answers:


2

Pyth,47个字节

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

十六进制转储,由于无法打印的字符:

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,取结果模C½,这是189,但一个字节由于优越解析节省,而且回转换为字符串与C再次。

乘以11.25的方法是乘以45,然后除以4,这样就节省了一个字节。


9

红宝石,118 106

感谢MartinBüttner节省了12个字节。

当前是相同的长度,而不管它是函数还是程序。

lambda函数

->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但是我必须仔细选择它们。
水平河圣

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

它从命令行获取输入并输出到控制台。非高尔夫版本:

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用于双字母点,将两个点的值取平均值。
  • parse3用于三字母点,它取双点和单点平均值的平均值。
  • parse3b4用于其中所有带有“ b”的对象,它计算“ b”之前的点的值,并根据“ b”之后的点的“方向”来加或减1/8。

在print()中,该值乘以90得到实际角度。


有必要写C c=new C(r[0]);吗?也许new C(r[0]);足够了?
pawel.boczarski 2015年

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

取消高尔夫:

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(f("NbW")返回34.875而不是348.75
智障的人2015年

@viktorahlström,您确定吗?它为我返回正确的值。也许您在复制和粘贴代码时错过了最后一个零?
艾米尔(Emil)2015年

哦,对不起,显然是-我的错,对不起!
智障的人2015年

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

利亚,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

在ungolf代码中,我对两个向量的平均值进行计数,avg = e ^ {jArg(v_1 + v_2)}以使向量仍然归一化。但是,由于第一个矢量的延长导致的误差在递归中添加的次数很少,因此尚未累积,因此在打高尔夫球时,无需进行归一化步骤,因此计算变得平均= v_1 + v_2简单。小于整圆的1/64的误差将通过舍入过滤掉。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.