Kuzey tarafından Kuzey tarafından Güneydoğu tarafından Kuzey tarafından


30

Bir N, S, E ve W dizisi verildiğinde, 5 ondalık basamağa kadar bir yatak (saat yönünde Kuzey yönünde saat yönünde) verin.

Gelen geleneksel pusula gösterimde , bir dize sadece 2 (KKB veya ESE gibi) bu karakterlerin oluşur. Burada 4'ün tümünü içeren dizeleri de kabul etmelisiniz (WNNNSE gibi) . Sadece 2 sembol kullanmak, insanların anlamlarını sezgisel olarak anlamalarını sağlar. 4 sembole izin vermek okumayı zorlaştırır, ancak bir rulmanı belirli bir hassasiyetle tanımlamanın daha kısa yollarına izin verir.

( User2357112 tarafından yapılan yorumlarda belirtildiği gibi , verilen herhangi bir yatak için, 4 simge dizisinin tam olarak 2 simge dizgesiyle aynı uzunlukta olacağını kanıtlayabiliyorsunuz, bu yüzden bu zorluğu yanlış bir varsayıma dayandırdım. Umarım bu pratik bir amaç eksikliği, bu zorluktan zevk almanıza engel değildir ...)

Kesin yöntem aşağıda açıklanmıştır ve geleneksel gösterime eşdeğerdir (değiştirmek yerine üzerinde genişler).

Giriş

  • Giriş, yalnızca karakterleri içeren tek bir dizedir NESW.
  • Bu, herhangi bir ön işleme içermemesi koşuluyla, tercih ederseniz, giriş bir karakter dizisi olabilir. Örneğin, [N, [E, [S, [W]]]]işlem sırasına yardımcı olmak için yuvalanmış bir listeye alınmasına izin verilmez.
  • Farklı karakterler almak yasaktır. Bunun 1234yerine bir dize alamazsınız NESW.

Çıktı

  • Çıktı, bir ondalık sayı veya bir dize gösterimi olmalıdır (rasyonel / kesir değil).
  • Sondaki sıfırların görüntülenmesine gerek yoktur. Eğer yatak ise 9.00000, o zaman da çıkış 95 ondalık basamağa kadar doğru sayılır.
  • Çıkış, [0, 360) aralığındadır. Yani, 0 dahil ancak 360 hariç.
  • Doğrulama, çıkışı 5 ondalık basamağa yuvarlayarak kontrol edilir. Yatak 0.000005 ise, bu 0.00001'e yuvarlanır. 0.00001 ve 0.000005 çıkışlarının her ikisi de doğrudur.
  • Bazı girdiler için bilimsel gösterimde çıktı kabul edilebilir. Örneğin, 1e-5yerine 0.00001.

dönüştürme

  • Tek karakter pusula noktası N, E, Sve Wtekabül 0, 90, 180, ve 270 derece, sırasıyla.
  • Bunlardan birinin bir dizeye hazırlanması, tek karakterin yatağını ve orijinal dizinin yatağını ikiye ayıran yatakla sonuçlanır.
  • İki olası yataklama mekanizmasına en yakın olanı seçilmiştir, böylece NE 225 dereceyi değil 45 dereceyi temsil eder.
  • İkiye ayrılacak açının 180 derece olması haricinde bu kesin değildir. Bu nedenle NS, SN, WEveEW tanımsız rulmanlar karşılıklıdır ve giriş bunlardan herhangi birinde hiç bitmeyecek. Ancak giriş dizesinde başka bir yerde görünebilirler, çünkü bu belirsizlik yaratmaz.
  • Eğer son iki karakter aynıysa, ibreler aynı yatağı geri getireceğinden, son karakter gereksiz olacaktır. Bu, notasyona bir şey eklemediğinden, kodunuzun bununla başa çıkması gerekmez. Bu nedenle NN, EE, SSve WWtanımsız rulmanlar karşılıklıdır ve giriş bunlardan herhangi birinde hiç bitmeyecek. Ancak giriş dizesinde başka bir yerde görünebilirler.

Örnekler

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

Test durumları

Bir başvuru, yalnızca tüm test durumları için doğru çıktı verirse geçerlidir. Test durumlarının, çift hassasiyetle ele alınabilecek sınırlarını zorladığını unutmayın. Tek kesinliğe varsayılan diller için, doğru çıktılar alabilmek için büyük olasılıkla çift duyarlık belirtmek için bayt harcamalısınız.

Test senaryosu çıktıları, 5 ondalık basamağa ve ayrıca isteğe bağlı kesinliğe yuvarlatılmış olarak gösterilir. Her ikisi de geçerli çıktılar.

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

puanlama

Bu . Skor kaynak kodun bayt cinsinden uzunluğu ve en az kazanılan puandır.


bilgiçlik taslama

"Kuzeyden Kuzeye doğru Kuzey" in geçerli bir pusula yönü olduğunu düşünerek hata yaptım. Mutlu bir hata, çünkü bu zor bir fikir doğurdu, fakat daha sonra Wikipedia sayfasından keşfettim :

"Kuzeybatı tarafından Kuzey’de bulunan Alfred Hitchcock 1959 filminin ismi aslında 32 rüzgar pusulasındaki bir yön noktası değil, ama film, Northwest Airlines'a bir referans içeriyor. "

Ayrıca, bu zorluk için kullanılan yöntemin yalnızca 16 nokta pusulayı da içeren geleneksel pusula noktaları ile tutarlı olduğu ortaya çıktı. Bu sayfada tarif edilen 32 rüzgar pusulası çok farklı ve bu zorluk için varlığını rahatlıkla gözden kaçırdım.

Son olarak, "Güney Doğu" yerine "Güneydoğu" yu kullanmam gerektiğini düşünenler için.


WNNNSE<= yayınınızın başlangıcındaki bu örnek girdi için çıktı ne olur? benim için geçersiz gibi geliyor, ama anlatması zor.
Tensibai

@Tensibai Girdi WNNNSEiçin çıktı olacaktır 323.4375. Bu durumda aynı şekilde uygulanacak bir örnek için örnek bölüme bakın.
trichoplax

Giriş f(N,N,N,S,E)tamam mı?
Karl Napf

@KarlNapf Netleştirmek için giriş bölümünü genişlettim. Doğru anlarsam, birden fazla argüman içeren örnek girişiniz bir karakter dizisine eşdeğer görünüyor, bu nedenle kabul edilebilir.
trichoplax

2
"4 sembole izin vermek okumayı zorlaştırır, ancak bir rulmanı belirli bir hassasiyetle tanımlamanın daha kısa yollarına izin verir." - bundan emin misin? Aynı yatağı tanımlayan tüm girdiler aynı uzunluktadır, çünkü her yatağı 0 ila 1 arasında bir rasyonel rasyonel atarsanız, N> 1 olan bir uzunluk-N dizgisi her zaman payda 2 ^ (N ile eşit olan rasyonel bir rasyona karşılık gelir. +1) en düşük düzeyde. Ayrıca, bir yatağa ikiden fazla farklı harfin girilmesi anlamlı bir güç katmaz; 3 veya 4 harfle ifade edilen herhangi bir yatak 2 ile ifade edilebilir
user2357112

Yanıtlar:


13

JavaScript (ES6), 84 80 78 74 72 bayt

@Titus sayesinde 1 byte kaydedildi, @Neil ile 1 adet teşekkürler

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

Biraz zaman aldı ama sanırım sonunda formülü mükemmelleştirdim ...

Test snippet'i

açıklama

En basit durumla başlayalım: tek karakterli bir dize. Sonuç, dizedeki (0 dizine NESWalınmış ) konumunun 90 ile çarpılmasıdır.

İki karakterli bir dizgede sonuç, ilk karakterin sonucu ile ikinci karakterin arasında yer alır. Bununla birlikte, bir mandal var: ikisi arasındaki mutlak fark 180'den büyükse (örneğin NWveya WN), açıya 180 gerekir, böylece ters yöne işaret etmemeliyiz.

Daha uzun olan herhangi bir dize için, sonuç ilk karakterin sonucu ile dizenin geri kalanının sonucu arasında yer alır. Bu, aşağıdaki şekilde genelleştirilebilir:

  • Giriş tek bir karakter ise, dizinini NESW90 kere döndürün.
  • Aksi halde, ilk karakterin dizinini dizge NESWsürelerinde 45, artı dizinin geri kalanının yarısı kadar döndürün; İkisi arasındaki mutlak fark 90'dan büyükse, fazladan 180 ekleyin.

Dizeden ilk karakteri kesmek için mükemmel bir yol! Değerleri 45'e bölünmüş değerlerle hesaplarsanız bir bayt tasarruf edebilirsiniz.
Titus

@Titus Bu teknikle 2 byte tasarruf edebilirim, teşekkürler!
ETHProductions,

1
searchindexOfsana bir bayt kaydetmek yerine .
Neil

@Neil Tekrar teşekkürler! Denklemi tamamen yeniden düzenleyerek üç tane daha golf oynamayı başardım.
ETHProductions

10

C # 6, 226 217 207 185 bayt

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

Düzenleme: ETHproductions'un gönderiminden "ödünç alma" fikri ile -10 bayt @Titus
sayesinde -22 bayt

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

Aralık ayarınızı%
0,3

@trichoplax Ondalık kesmeyecek mi?
Titus,


1
b=(b+360)%360;Bunun yerine 10 bayt kaydedin b+=b>360?-360:b<0?360:0;. Her şeyi 90'a bölerek 12 bayttan daha tasarruf edin return b*90;.
Titus,

1
İşte 10 tane daha bayt: iki ödevi birleştirin ve parantezleri kaldırın: b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0)+8)/2%4;daha sonra +8üçlü sonuçlara dağıtınb=(b+f(c)+(b-f(c)>2?12:f(c)-b>2?4:8))/2%4;
Titus

8

PHP, 95 88 86 100 127 104 101 bayt

  • -Null birleştirme operatörüyle 7 bayt
  • -2 bayt değiştirmeyerek N(ve daha fazlası, çünkü çeviriyi döngü başlığına koymaya izin verir: Ntruthy, ama 0hesaplamada değerlendirir .)
  • Biseksiyonu düzeltmek için +41 bayt ( öksürük )
  • -7 bayt doğrudan ve -16 dolaylı olarak @ ETHproductions’in kodundan ilham aldı
  • strtrBenim bit hokkabazlardan biriyle değiştirerek -3 bayt

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;

Bu resmen boş birleştirme operatörünü kullandığım ilk kez. İle koş -r.

PHP 7.1

Yaklaşan PHP sürümünde Negatif dize uzaklıklar 12 bayt kurtaracak:
Değiştir strlen($s=$argv[1])ile 0ve $sile $argv[1].


(Neredeyse) herkes için ücretsiz bayt:

  • 0,90,180,270 yerine 0,1,2,3 ile hesaplanması ve nihai sonucun 90 ile çarpılması iki bayt kazandıracak ve muhtemelen daha fazla golf oynamaya izin verecektir.
  • Karakterlerin ASCII kodlarında bazı desenler vardır. Bunlardan birini kendi dilinizde deneyin:
    • (a/2%6+2)%5
    • a<87?a/2&3^3:3 veya a/2&3^3*(a<87)
    • a&1?a&2|a/4&1:0
    • a/.8-1&3

5

Python 3, 133 113 bayt

Sadece @ L3viathan'ın cevabını geliştirerek bu hesabı yaptım ve bu nedenle henüz yorum yapamadım.

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

Programming Puzzles & Code
Golf'a

Cevabınızı görmedim, ama Titus'un da benzer bir fikri vardı, artı bir tane daha vardı, şimdi 98'e düştüm :)
düştüm

5

05AB1E ,48 42 37 32 bayt

Emigna sayesinde 6 bayt kaydedildi. Titus'un [0,4] aralığında çalışabilme fikri sayesinde 5 byte tasarruf sağladı ve sonunda 90 ile çarpın. Adnan'ın antik xor / modulo metamorfoz ustalığı sayesinde 5 bayt kurtarıldı.

Böylece her açı, uygulama boyunca [0,360 [aralığında] [0,4 [] aralığındadır. Sonuç daha sonra 90 ile çarpılır ve gösterilir.

Ç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

Çevrimiçi deneyin!

Potansiyel golf oynama eksenleri:

  • Mod 4 gerekli olup olmadığından emin değil (2 bayt kaydeder). Bütün test vakaları onsuz çalışır, ama belki de zor bir durum vardır. Ya doğrulamak ya da geçersiz kılmak için matematiksel bir kanıt birinci sınıf olacaktır.
  • Sonucun gösterilmesinden başka gizli bir şey yoktur (alıntı işaretlerini kapatmak, parantezleri kapatmak).

1
İstenilen sonucu NNNNNNNNNNNNNNNNNNNNNNNEve SNNNNNNNNNNNNNNNNNNNNNNNEtest davalarında verilmiş gibi görünmüyor .
Emigna

2
Tuhaf. Şimdi ben de yapıyorum. Yanlış yapıştırmış olmalıyım, üzgünüm. Kodu kısaltabilirsiniz v"NESW"yk90*})R¬U¦vXy+;DX-Ä89›180*+360%U}X.
Emigna

1
Harika bir açıklama! 89›Tamsayı parçasının 89'dan büyük olduğu, tam sayının 90'dan büyük veya ona eşit olduğunu söylemeye eşdeğer bir not içermesi faydalı olabilir (yine de tam olarak 90'ının gerçekleşmemesi gerektiği için hala iyi çalışır). Şu içinde açıklama kod kodunuzu çok net doğru 90. Büyüktür denetlemelidir test durumları geçer oysa o, 89 Büyüktür için kontrol ediyormuş gibi ses yapar açıkladı
placozoa

1
Açıklamayı düzenledim, ancak operatörün negatif kayan nokta değerlerine karşı nasıl davranması gerektiğinden emin olmadığım için "tamsayıya dönüştür" yazdım . Mutlak değer üzerinde çalıştığı için burada sorun yok, ancak operatör hakkında çok güçlü varsayımlar yapmamayı tercih ediyorum.
Osable

1
:) v"NESW"yk})ile değiştirebilirsinizÇ30^5%
Adnan

5

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

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

fDize ile arayın .


...0elseİkisini fırlatıp, SyntaxErrors alamazsınız .
Jonathan Allan,

@JonathanAllan Hangi Python sürümünü kullanıyorsunuz? 3.5.2 yaşıyorum ve işe yarıyor.
L3viathan

3.3.3'te çalıştırdım - elseve arasındaki boşluğu kaldırabilir misiniz -? (3.3.3'te olabilir)
Jonathan Allan,

@JonathanAllan Evet yapabilirim! Teşekkürler, bu bana başka bir bayt kazandırır.
L3viathan

2
@Titus d.find, bir dakika önce tam bir fikrim vardı; güncellenmiş cevaba bakınız.
L3viathan,

5

C, 184 bayt

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

şamandıra kullanarak, size gereken hassasiyeti sağlamaz gibi görünüyor.
Eyal Lev

4
PPCG'ye Hoşgeldiniz! : D
mbomb007

İşlevlerin adları birbiriyle çakışmaz dmı ( ikisi de ikisi olduğundan )?
clismique

@qwerp, farklı imzalar (biri char * alır, diğeri sadece char alır)
Eyal Lev

2
İşlev isimleri, C ++ 'da olduğu gibi, C ++' da olduğu gibi adlandırılmaz, bu nedenle C olmasını istiyorsanız, bir tanesini yeniden adlandırmanız gerekir.
Klas Lindbäck

3

R, 172 146 bayt

z=rev((0:3*90)[match(scan(,""),c("N","E","S","W"))]);p=z[1];l=length(z);for(i in 2:l)p=(p+z[i])/2+(abs(p-z[i])>180)*180;if(l<2)p=z;sprintf("%f",p)

Ungolfed

z=rev((0:3*90)[match(scan,""),c("N","E","S","W"))]); #1
p=z[1];                                              #2
l=length(z)                                          #3
for(i in 2:l)p=(p+z[i])/2+(abs(p-z[i])>180)*180;     #4
if(l<2)p=z                                           #5
sprintf("%f",p)                                      #6

Açıklaması

  1. Stdin'den girişi oku
    • Girdiyi dizine göre eşle c("N","E","S","W")
    • Eşleşen indekslerden: derece vektörüyle eşleşin 0:3*90(yerine c(0,90,180,270))
    • Ters çevir ve sakla z
  2. Girişteki pson karaktere eşdeğer dereceye sıfırla
  3. Girişin depo uzunluğu l
  4. Yinelemeli olarak, olası iki ikiye ayrılma yatağının en yakınını hesaplayın.
  5. Sadece bir giriş yapılırsa, set piçinz
  6. Biçimlendir ve yazdır

R-fiddle'daki test durumlarını deneyin (bunun R-fiddle'da çalışmadığından dolayı bir fonksiyon olduğunu unutmayın scan)


Çıktının 5 ondalık basamağa kadar doğru olması koşuluyla, yuvarlama işlemini yapmanız gerekmez. Outputs 0.00001 and 0.000005 are both correct.
Zorluktan

@trichoplax Anladım. Giriş, aynı zamanda karakter dizelerinin bir vektörü olabilir. c("N","N","E")yerine "NNE"? Bu iç içe geçmiş olmayan bir python listesine eşdeğerdir ["N","N","E"].
Billywob

Evet. "Dizi" yi diziler, vektörler, listeler, tuples gibi şeyleri içeren genel bir terim olarak tasarladım.
trichoplax

1
Her şeyi 90'a ve printf'e (p * 90) bölerseniz 4 bayt kaydedebileceğinizi düşünüyorum.
Titus,

3

Haskell, 109 105 103 bayt

h=180
a#b|abs(a-b)<h=n|n>h=n-h|1>0=n+h where n=(a+b)/2 -- calculates the new "mean" on the cirlce
f 'N'=0                                          -- translates characters to angles
f 'E'=90
f 'S'=h
f _=270
foldr1(#).map f                                  -- traverses the whole string

-2 byte @xnor için teşekkürler!


Kapsamlı liste fuzun görünüyor, ancak daha kısa bir şey bulmakta sorun yaşıyorum. En yakınım oldu f c=90*until(\i->"NESW"!!i==c)(+1)0(35). Sana yerini alabilir mi 'W'sahip _.
xnor

Evet, ayrıca daha kısa bir şey olmasını beklerdim ama hiçbir şey bulamadım. İçin teşekkürler _!
kusur

3

Dyalog APL , 55 45 38 bayt

Çözüm

⎕IO←0Birçok sistemde varsayılan olan gerektirir . Yön için sorar.

360|÷○÷180×12○(+÷(|+))/¯12○○2÷⍨'NES'⍳⍞

açıklama

Bir kompleks sayı için harflere dönüştürerek sorunu çevresinde Goes 1∠ İçeride ISTV melerin RWMAIWi'ninbir + b · i , daha sonra her bir aşamada bir miktar sağdan soldan azalma (APL forte) ise normalize yapıyor. Son θ daha sonra derecelere dönüştürülür ve [0, 360) dahilinde normalleştirilir:

'NES'⍳⍞"NES" deki her giriş harfinin göstergeleri; N → 0, E → 1, S → 2, başka bir şey → 3

○2÷⍨radyan cinsinden açılara dönüşür; θ = π · x 2

¯12○birim daire üzerindeki karmaşık sayılara dönüştürmek; e i · θ

(... )/listeyi ... ile azaltın (yani, işlevi ... öğelerinin arasına yerleştirin)

+÷(|+)... normalize edilmiş miktar; x n - 1 + x n| x n - 1 + x n |

12○açıya dönüştürmek; θ

÷○÷180×derecelere dönüştürmek; 1 / π · 1 / 180 · x

360| 360'a bölündüğünde bölünme kalanı

TryAPL çevrimiçi!

anekdot

Girdi ve çıktı dikgen karmaşık birimler halinde olsaydı, çözümün tamamı şöyle olurdu:

(+÷(|+))/

Kodun geri kalanı girdiyi ayrıştırıyor ve çıktıyı formatlıyor.


Test çıktılarının zorluk altındakilerle 5 ondalık basamağa uymadığını fark ettim, bu geçersiz. Dyalog APL'nin çift hassasiyet kullanma seçeneği var mı?
trichoplax

@trichoplax Evet, ⎕FR←1287128 bit float kullanır, ancak TryAPL izin vermiyor.
Kasım’da 15:16

64 bitlik yüzerlikten büyük veya ona eşit bir şeyin çalışması gerektiğini düşünüyorum (ancak Python'da test ettim). Bu, kodu geçerli hale getirebileceğiniz anlamına mı geliyor, ancak daha sonra yalnızca dili yükleyen kişiler için işe yarayacak mı? Belki puanın geçerli kodunu gösterebilir ve gerekli algoritmaya sahip olmayan çevrimiçi sürümü ekleyebilir, böylece insanlar algoritmanın doğru olduğunu görebilirler.
trichoplax

@trichoplax Aslında, TryAPL çift hassasiyet kullanır, ancak test durumlarınız 53 bitin ötesinde hatalar biriktirir.
Saat

Farkın, IEEE 754 standardının yorumundaki farklardan kaynaklanabileceği gösteriliyorsa, yine de standart uyumludur, o zaman her iki yorumlamanın da aynı ondalık basamağa aynı sonucu vermesini sağlamak için test durumlarını ayarlayacağım. Test durumlarını, hem float (çift hassasiyetli) hem de keyfi hassasiyetli ondalık sayılar için Python'da 5 ondalık basamağa aynı sonucu verecek şekilde seçtim. Bir göz atacağım.
trichoplax

2

Ortak Lisp, 347 327 bayt

Bir kaç kalkış için @Titus'a teşekkürler

Bu muhtemelen daha çok golf oynayabilir, ama en azından işe yarıyor (bence):

(defun d(c)(if(eql c #\N)0(if(eql c #\E)1(if(eql c #\S)2(if(eql c #\W)3)))))(defun m(a b)(if(> a b)(rotatef a b))(if(<(+(- 4 b)a)(- b a))(+(/(+(- 4 b)a)2)b)(+(/(- b a)2)a)))(defun f(s)(let((c))(setf c(d(char s(1-(length s)))))(do((a)(p(-(length s)2)(1- p)))((< p 0))(setf a(char s p))(setf c(m(d a)c)))(format t"~5$"(* c 90))))

Kullanımı:

* (f "WNE")
337.50000
NIL

Fonksiyon dbir karakter alır N, E, W, veya Sve iadeler uygun derecede. İşlev m, verilen iki yönü verilen toplam kombine derecesini alır. İşlev fsağlanan dizgiyi yineler, uygun dereceyi hesaplar ve kayan nokta olarak yazdırır.


LISP'im paslı, ancak her şeyi 90'lık tasarrufla 6 bayta bölebilir mi?
Titus,

@Titus, olacağını düşünüyorum. Başka iyileştirmeler de gerçekleştirdim, bu yüzden bunu bilgisayarımdayken ekleyeceğim
artificialnull

2

Befunge, 183 181 175 bayt

>~#+:#25#%6*#/`#2_$>5%4*:00p"Z}"4*:***20g#v_+2/00g10g-:8`\0\-8`+!v
v5:+*:*:"d"/+55+5$_^#!:\p01/**:*4"}Z":p020<%**:*"(2Z"+**5*:*"0}"!<
>5>+#<%#56#58#:*#/+\#5:#5_$$$,,,".">:#,_@

Çevrimiçi deneyin!

açıklama

Bu, diğer cevapların çoğuna benzer bir algoritmayı izler, yalnızca Befunge kayan noktayı desteklemediğinden tam sayılarla taklit edilmiş sabit nokta hesaplamaları kullanır.

ASCII-to-int rutini için @Titus'a teşekkürler .

 ~ : 5 6* ` _$        while ((c = getchar()) > 30)  // ends with any ctrl char or EOF
> + 2 %6 / 2            push(c / 2 % 6 + 2)         // partial conversion to int

                      do {
  5%                    dir = pop() % 5             // completes the conversion to int   
  4*:00p                dir *= 4; lowres_dir = dir  // used by the 180-flip calculation
  "Z}"4*:***            dir *= 22500000             // this is 90000000 / 4 
  20g_                  if (!first_pass) {
    +2/                   dir = (dir+last_dir)/2    // last_dir is second item on stack
    00g10g-               diff = lowres_dir - last_lowres_dir
    :8`\0\-8`+!!          flip = diff>8 || -diff>8
    "}0"*:*5**+           dir += flip * 180000000   // add 180 degrees if we need to flip
    "Z2("*:**%            dir %= 360000000          // keep within the 360 degree range
                        }
  020p                  first_pass = false
  :"Z}"4*:**/10p        last_lowres_dir = dir / 22500000
  \                     last_dir = dir              // saved as second item on stack
  :!_                 } while (!stack.empty())

$                     pop()                         // this leaves the final dir on top
5+55+/                dir = (dir + 5)/10            // round down to 5 decimal places
"d":*:*+              dir += 100000000              // add a terminating digit
                      while (true) {                // convert into chars on stack
:55 + % 6 8 * +\ : _    push(dir%10+'0'); if (!dir) break
   > < 5 5 : /+ 5 5     dir /= 10
                      }

$$$                   pop() x 3                     // drop the chars we don't need
,,,                   putchar(pop()) x 3            // output first three chars
"."                   push('.')                     // add a decimal point
>:#,_@                while(c=pop()) putchar(c)     // output the remaining chars

Bu sadece daha büyük bir sabit nokta tipini taklit etmeniz gerektiği anlamına mı geliyor (daha fazla ondalık basamak)? Test durumları, 17'den fazla önemli rakamdan (maksimum 16 ondalık basamaktan) fazla olmayan çift hassasiyet gerektirecek şekilde tasarlanmıştır ve 14 ondalık basamak muhtemelen yeterli olabilir.
trichoplax

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.