Pusula Noktasını Dereceye Dönüştür


18

Bu meydan okumayı bağımsız olarak buldum, ancak Doorknob'un bu meydan okumasının tersi olduğu ortaya çıktı . Spesifikasyonunu gerçekten sevdiğim gibi, kendi açıklamalarımı pişirmek yerine büyük parçalarını çalmaya karar verdim.

Meydan okuma

Pusuladaki 32 noktadan birinin kısaltması göz önüne alındığında, ilgili dereceleri yazdırın. 32 noktanın açıklamasıyla ilgilenmiyorsanız, aşağıdaki tabloya geçmekten çekinmeyin.

İşte tam pusula:

görüntü

Denelson83 (Kendi çalışması) [ GFDL veya CC-BY-SA-3.0 ], Wikimedia Commons aracılığıyla

Her yön öncekinden 11,25 (360/32) derecedir. Örneğin, N (kuzey) 0 derece, NbE (kuzey doğu) 11.25 derece, NNE (kuzey-kuzeydoğu) 22.5 derecedir, vb.

Ayrıntılı olarak, adlar aşağıdaki gibi atanır:

  • 0 derece N, 90 derece E, 180 derece S ve 270 derece W'dir. Bunlara kardinal yönler denir.
  • Kardinal yönler arasındaki yarı noktalar basitçe birleştirilmiş arasındaki kardinal yönlerdir. N veya S her zaman önce gelir ve W veya E her zaman ikinci olur. Bunlara sıralı yönler denir. Ordinal ve kardinal yönler birlikte ana rüzgarları oluşturur.
  • Ana rüzgarlar arasındaki yarım noktalar, birleştirilmiş arasındaki yönlerdir. Önce kardinal yönler, ikinci sırada. Bunlara yarım rüzgar denir.
  • Ana rüzgarlar ile yarı rüzgarlar arasındaki yarım noktalar, ana rüzgardan en yakın kardinal yön "ile" bitişik ana rüzgardır. Bu bir ile gösterilir b. Bunlara çeyrek rüzgar denir.

Bu, aşağıdaki grafikle sonuçlanır:

#   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

İşte daha ayrıntılı bir grafik ve pusulanın noktalarının muhtemelen daha iyi açıklaması.

Göreviniz, üçüncü sütundaki 32 kısaltmadan birini girmek ve ikinci sütundaki ilgili dereceleri çıkarmaktır.

Girdinin her zaman bu 32 dizeden biri olacağını varsayabilirsiniz (ve isteğe bağlı olarak ancak tutarlı bir şekilde tek bir son satır bekleyebilirsiniz). Ayrıca, sıfıra sıfıra izin verilse de, çıktı tam olarak yukarıda listelenen şekilde verilmelidir. İsteğe bağlı olarak tek bir satırsonu çıktısı alabilirsiniz.

STDIN (veya en yakın alternatif), komut satırı bağımsız değişkeni veya işlev bağımsız değişkeni ile girdi alarak ve sonucu STDOUT (veya en yakın alternatif), işlev dönüş değeri veya işlev (çıkış) parametresi aracılığıyla çıktı alarak bir program veya işlev yazabilirsiniz.

Bu kod golf, yani en kısa cevap (bayt cinsinden) kazanır.

Yanıtlar:


2

Pyth, 47 bayt

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

Hexdump, yazdırılamayan karakterler nedeniyle:

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

Test donanımı

Resmi komut satırı derleyicisindeki bir hata nedeniyle, bu kod yalnızca yukarıda belirtilen çevrimiçi derleyici veya -cçevrimdışı derleyicinin bayrağı aracılığıyla çalışır . (Soru sorulduktan sonra hata düzeltildi.)

Bu çözüm, girişi hash etme, sonucu 32 baytlık arama dizesinde arama ve daha sonra 11,25 ile çarpma işlemini kullanarak @ Dennis'in CJam cevabına çok benzer.

Hızlı arama fonksiyonu I kullanımı, bir taban 256 bir tamsayı olduğu gibi bir dizi girdi dönüştürmektedir Csonucu modulo alarak, Cbir ½189 olan, fakat daha üstün ayrıştırma için bir byte kaydeder ve bir dizeye bu geri dönüştürülmesi Cdaha .

11.25 ile çarpma, 45 ile çarpma, daha sonra bir bayt tasarrufu sağlayan 4'e bölme ile gerçekleştirilir.


9

Yakut, 118 106

Martin Büttner'e 12 bayt kurtardı.

Bu bir işlev veya programdan bağımsız olarak şu anda aynı uzunluktadır.

lambda işlevi

->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}

program

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

Bu noktalar arasında kartezyen bir yürüyüş. Karakterler NSEW, içinde depolanan x ve y koordinatlarını 4 ekler veya çıkarır d[]. Bir b(veya dışında herhangi bir sembol NSEW) ile karşılaşıldıktan sonra, bu 1'e düşürülür.

Daha sonra x ve y verileri, açısal argümanı çıkarmak için karmaşık bir sayı olarak ele alınır. Bu 16 / PI = ile çarpılır 5.1. Yaklaşımda bazı geometrik hatalar olmasına rağmen, bu açıyı yuvarlamak doğru sayıyı vermek için yeterlidir -15..+16. Modulo bunu bunu düzeltmek için kullanılır 0..31(Ruby'de %her zaman pozitif döner.) Sonunda sonuç 11.25 ile çarpılır.


1
Yuvarlama ile ne kadar zekice bir fikir! En yakın dik yöne göre alınan açı yerine açının arktanını alırsınız, ancak bu yeterince yakın olur.
xnor

@xnor yuvarlama olmadan NbE 14.05 (+2.8), NNE 26.60 (+4.1), NEbE 51.41 (-4.84) ​​elde ediyorum. n ama bunları dikkatlice seçmek zorunda kaldım.
Level River St

6

Javascript (ES6), 153 bayt

Sadece basit bir topla yuvarlanmak istedim.

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

Özellikle yenilikçi değil, ama işe yarıyor ve belki de ondan türetilebilecek bazı ipuçları var. Endişelenme, başka bir (umarım daha iyi) bir teknik düşüneceğim.


1
Belki de dizeyi sıkıştırabilirsin?
mbomb007

1
Şaşırtıcı olan, hala Python'daki algoritmik yaklaşımı kullanan (gönderilmedi) çözümümden daha kısa.
pawel.boczarski

2

CJam, 49 bayt

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*

Yukarıdaki, ters çevrilebilen bir hexdump'tır xxd -r -c 17 -g 1.

Çevrimiçi ortamda deneyin CJam yorumlayıcısında .

Nasıl çalışır

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 (karakter)

Java'nın kazanamayacağını biliyorum ama yine de çaba sarf etmeyi seviyorum.

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

Komut satırından girdi alır ve konsola çıktılar. Ungolfed sürümü:

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'ye 0-3 atayarak çalışır (veya W varsa N için 4). 4 farklı durumu tanır:

  • parse1 tek harfli noktalar içindir, sadece değeri döndürür.
  • parse2 çift harfli noktalar içindir, 2 noktanın değerlerini ortalar.
  • parse3 üçlü harf puanı içindir, çift ve tek noktaların ortalamasını alır.
  • parse3b4, içinde 'b' olan herkes içindir, 'b' den önceki noktanın değerini hesaplar ve 'b' den sonraki noktanın 'yönüne' dayalı olarak 1/8 ekler veya çıkarır.

Print () öğesinde, gerçek açıyı elde etmek için değer 90 ile çarpılır.


Yazmak gerekli C c=new C(r[0]);mi? Belki new C(r[0]);yeterlidir?
pawel.boczarski

1

Python 3, 149 bayt

Yinelemeli algoritmik bir yaklaşım denedim. Çeyrek rüzgarları ilk başta düşündüğümden daha zordu, bu nedenle bu çözüm nispeten uzadı.

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

Golf edilmiş sürüm, 10 ile çarpılması gereken bir ondalık sayı f("NbW")döndürür ( 34.875bunun yerine döndürür 348.75)
智障 的 人

@ viktorahlström, emin misin? Benim için doğru değeri döndürür. Belki kodu kopyalayıp yapıştırırken son sırayı kaçırdınız mı?
Emil

Üzgünüm, görünüşe göre bu - benim hatam, üzgünüm!
人 的 ​​人

1

Haskell, 206 bayt

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

Uygun test:

*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 bayt

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

Biraz soluksuz:

# 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

Çözülmemiş kodda, avg = e ^ {jArg (v_1 + v_2)}vektörün hala normalleşmesi için iki vektörün ortalamasını sayıyorum . Bununla birlikte, ilk vektörün uzamasından kaynaklanan hatalar henüz özyinelememizde çok az eklemeyle birikmemektedir, bu nedenle golf yaparken normalleştirme adımı kaldırılmıştır ve hesaplama avg = v_1 + v_2basitçe gider . Tam dairenin 1 / 64'ünden daha az hatalar yuvarlanarak filtrelenir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.