Utara oleh Utara oleh Utara oleh Tenggara

30

Diberikan string N, S, E dan W, menghasilkan arah (sudut searah jarum jam dari Utara dalam derajat), dikoreksi ke 5 tempat desimal.

Dalam notasi kompas tradisional , string hanya terdiri dari 2 karakter ini (seperti NNW atau ESE). Di sini Anda juga harus menerima string yang berisi semua 4 (seperti WNNNSE) . Menggunakan hanya 2 simbol memungkinkan manusia untuk memahami makna secara intuitif. Membiarkan 4 simbol membuatnya mengerikan untuk dibaca, tetapi memungkinkan cara yang lebih singkat untuk menggambarkan bantalan ke akurasi yang diberikan.

(Seperti yang ditunjukkan dalam komentar oleh user2357112 , ternyata Anda dapat membuktikan bahwa untuk setiap bantalan yang diberikan, string 4 simbol akan sama persis panjangnya dengan string 2 simbol, jadi saya telah mendasarkan tantangan ini pada asumsi yang salah. Semoga ketiadaan tujuan praktis ini tidak mengurangi kesenangan Anda terhadap tantangan ...)

Metode yang tepat dijelaskan di bawah ini, dan setara dengan notasi tradisional (itu memperluas itu daripada mengubahnya).

Memasukkan

  • Input adalah string tunggal yang hanya berisi karakter NESW.
  • Input dapat berupa urutan karakter jika Anda mau, asalkan ini tidak termasuk preprocessing. Misalnya, mengambil daftar bersarang [N, [E, [S, [W]]]]untuk membantu urutan pemrosesan tidak diizinkan.
  • Mengambil karakter yang berbeda tidak diizinkan. Anda tidak boleh mengambil string 1234sebagai gantinya NESW.

Keluaran

  • Output harus berupa angka desimal atau representasi string dari satu (bukan rasional / fraksi).
  • Nol trailing tidak perlu ditampilkan. Jika bantalan adalah 9.00000, maka output 9juga dihitung sebagai benar ke 5 tempat desimal.
  • Outputnya dalam kisaran [0, 360). Yaitu, termasuk 0 tetapi tidak termasuk 360.
  • Kebenaran diperiksa dengan membulatkan output ke 5 tempat desimal. Jika bantalan 0,000005, ini akan menjadi 0,00001. Output 0,00001 dan 0,000005 keduanya benar.
  • Output dalam notasi ilmiah untuk beberapa input dapat diterima. Misalnya, 1e-5bukannya 0.00001.

Konversi

  • Single karakter kompas poin N, E, S, dan Wsesuai dengan 0, 90, 180, dan 270 derajat masing-masing.
  • Melekatkan salah satu dari ini ke string menghasilkan bantalan yang membagi dua bantalan karakter tunggal dan bantalan string asli.
  • Yang paling dekat dari dua bantalan yang membagi dua mungkin dipilih, sehingga NE mewakili 45 derajat, bukan 225 derajat.
  • Ini tidak ambigu kecuali di mana sudut yang akan dibagi dua adalah 180 derajat. Oleh karena itu NS, SN, WE, dan EWsesuai dengan bantalan terdefinisi, dan masukan tidak akan pernah berakhir di salah satu ini. Namun mereka dapat muncul di tempat lain di string input, karena ini tidak menyebabkan ambiguitas.
  • Jika dua karakter terakhir identik, karakter terakhir akan redundan karena pembagian dua akan menghasilkan bantalan yang sama. Karena ini tidak menambah apa pun pada notasi, kode Anda tidak perlu menangani ini. Oleh karena itu NN, EE, SS, dan WWsesuai dengan bantalan terdefinisi, dan masukan tidak akan pernah berakhir di salah satu ini. Namun mereka dapat muncul di tempat lain di string input.

Contohnya

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

Uji kasus

Pengajuan hanya valid jika memberikan hasil yang benar untuk semua kasus uji. Perhatikan bahwa test case mendorong hingga batas yang dapat ditangani dengan presisi ganda. Untuk bahasa-bahasa yang default ke presisi tunggal, Anda mungkin perlu menghabiskan byte untuk menentukan presisi ganda untuk mendapatkan output yang benar.

Output kasus uji ditampilkan dibulatkan ke 5 tempat desimal, dan juga ke presisi sewenang-wenang. Keduanya adalah output yang valid.

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

Mencetak gol

Ini adalah . Skor adalah panjang kode sumber dalam byte, dan yang terpendek menang.


Sifat suka menonjolkan keilmuan

Saya membuat kesalahan dengan berpikir bahwa "Utara oleh Barat Laut" adalah arah kompas yang valid. Kesalahan yang membahagiakan, karena mengarah pada ide tantangan, tetapi saya kemudian menemukan dari halaman Wikipedia :

"Judul film Alfred Hitchcock 1959, North by Northwest, sebenarnya bukan titik arah pada kompas 32-angin, tetapi Film berisi referensi ke Northwest Airlines. "

Ternyata juga metode yang digunakan untuk tantangan ini hanya konsisten dengan titik kompas tradisional hingga dan termasuk kompas 16 titik. Kompas 32-angin yang dijelaskan pada halaman itu sedikit berbeda dan saya dengan mudah mengabaikan keberadaannya untuk tantangan ini.

Akhirnya, bagi siapa pun yang berpikir saya harus menggunakan "Tenggara" daripada "Tenggara",.

trichoplax
sumber
WNNNSE<= apa yang akan menjadi output untuk entri contoh ini di awal posting Anda? kedengarannya tidak valid untuk saya, tetapi sulit untuk mengatakannya.
Tensibai
@Tensibai Untuk input WNNNSEhasilnya 323.4375. Lihat bagian contoh untuk langkah-langkah yang akan berlaku dengan cara yang sama untuk kasus ini.
trichoplax
Apakah input seperti f(N,N,N,S,E)apa?
Karl Napf
@KarlNapf Saya telah memperluas bagian input untuk mengklarifikasi. Jika saya mengerti dengan benar, input contoh Anda dengan beberapa argumen tampaknya setara dengan urutan karakter, jadi itu akan diterima.
trichoplax
2
"Membiarkan 4 simbol membuatnya mengerikan untuk dibaca, tetapi memungkinkan cara yang lebih pendek untuk menggambarkan kaitan dengan akurasi yang diberikan." - Apa kamu yakin akan hal itu? Sepertinya semua input yang menggambarkan bantalan yang sama memiliki panjang yang sama, karena jika Anda menetapkan masing-masing bantalan rasional diad dari 0 ke 1, string panjang-N dengan N> 1 selalu sesuai dengan rasional diadik dengan penyebut 2 ^ (N +1) dalam istilah terendah. Juga, membiarkan lebih dari 2 huruf berbeda dalam bantalan tidak menambah daya ekspresif; setiap bantalan yang dinyatakan dengan 3 atau 4 huruf dapat diekspresikan dengan 2.
user2357112 mendukung Monica

Jawaban:

13

JavaScript (ES6), 84 80 78 74 72 byte

Menyimpan satu byte berkat @Titus, 1 terima kasih ke @Neil

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

Butuh beberapa saat, tapi saya pikir saya akhirnya menyempurnakan formula ...

Cuplikan tes

Penjelasan

Mari kita mulai dengan case paling sederhana: string single-char. Hasilnya hanyalah posisinya (0-diindeks) dalam string NESW, dikalikan dengan 90.

Untuk string dua-char, hasilnya terletak di tengah-tengah antara hasil dari char pertama dan hasil dari yang kedua. Namun, ada yang menarik: jika perbedaan absolut antara keduanya lebih besar dari 180 (misalnya NWatau WN), kita harus 180 ke sudut sehingga tidak menunjuk ke arah yang berlawanan.

Untuk string yang lebih panjang, hasilnya terletak di tengah-tengah antara hasil char pertama dan hasil dari sisa string. Ini dapat digeneralisasi dengan cara berikut:

  • Jika input adalah satu karakter, kembalikan indeksnya dalam string NESWkali 90.
  • Jika tidak, kembalikan indeks char pertama dalam string NESWkali 45, ditambah setengah hasil dari sisa string; tambahkan ekstra 180 jika perbedaan absolut antara keduanya lebih besar dari 90.
Produksi ETH
sumber
Cara terbaik untuk memotong karakter pertama dari string! Anda dapat menyimpan satu byte jika Anda menghitung dengan nilai dibagi dengan 45.
Titus
@ Titus saya bisa menghemat 2 byte dengan teknik itu, terima kasih!
ETHproduk
1
searchalih-alih indexOfmenghemat satu byte.
Neil
@Neil Terima kasih lagi! Saya berhasil bermain golf tiga lagi dengan menata ulang persamaannya.
Produksi ETH
10

C # 6, 226 217 207 185 byte

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

Sunting: -10 byte dengan ide "meminjam" dari pengajuan ETHproduk
-22 byte berkat @Titus

Tidak disatukan

// 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);
Tautan Ng
sumber
Saya pikir Anda dapat membuat penyesuaian rentang kembali ke [0,360) lebih pendek dengan menggunakan%
trichoplax
@trichoplax Tidak akankah itu memotong desimal?
Titus
1
Hemat 10 byte dengan b=(b+360)%360;sebagai gantinya b+=b>360?-360:b<0?360:0;. Simpan 12 byte lagi dengan membagi semuanya dengan 90 dan return b*90;.
Titus
1
Berikut adalah 10 byte lagi: gabungkan dua tugas dan hapus kawat gigi: b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0)+8)/2%4;kemudian bagikan +8ke hasil ternaryb=(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 byte

  • -7 byte dengan operator penggabungan nol
  • -2 byte dengan tidak mengganti N(dan banyak lagi, karena itu memungkinkan untuk menempatkan terjemahan ke kepala loop: Nbenar, tetapi mengevaluasi 0dalam perhitungan.)
  • +41 byte untuk memperbaiki pembelahan dua ( batuk )
  • -7 byte secara langsung dan -16 secara tidak langsung terinspirasi oleh kode @ ETHproductions´
  • -3 byte dengan mengganti strtrdengan salah satu dari juggling bit saya

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;

Ini secara resmi pertama kalinya saya menggunakan operator penggabungan nol. Jalankan dengan -r.

PHP 7.1

Offset string negatif dalam versi PHP yang akan datang akan menghemat 12 byte:
Ganti strlen($s=$argv[1])dengan 0dan $sdengan $argv[1].


Bita gratis untuk (hampir) semua orang:

  • Menghitung dengan 0,1,2,3 bukannya 0,90.180.270 dan mengalikan hasil akhir dengan 90 akan menghemat dua byte dan mungkin memungkinkan golf lebih lanjut.
  • Ada beberapa pola dalam kode ASCII dari karakter. Coba salah satu dari ini dalam bahasa Anda:
    • (a/2%6+2)%5
    • a<87?a/2&3^3:3 atau a/2&3^3*(a<87)
    • a&1?a&2|a/4&1:0
    • a/.8-1&3
Titus
sumber
5

Python 3, 133 113 byte

Hanya meningkatkan jawaban @ L3viathan karena saya baru saja membuat akun ini dan karena itu belum dapat memberikan komentar.

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
Moonocababa
sumber
Selamat datang di Programming Puzzles & Code Golf, dan peningkatan yang bagus ...
trichoplax
Saya tidak melihat jawaban Anda, tetapi Titus punya ide yang sama, ditambah saya punya yang lain, saya turun ke 98 sekarang :)
L3viathan
5

05AB1E ,48 42 37 32 byte

Disimpan 6 byte berkat Emigna. Disimpan 5 byte berkat ide Titus untuk bekerja pada kisaran [0,4 [dan kalikan dengan 90 di akhir. Disimpan 5 byte berkat penguasaan Adnan terhadap metamorfosis xor / modulo kuno.

Jadi setiap sudut dikurangi dari kisaran [0,360 [hingga kisaran [0,4 [selama eksekusi]. Hasilnya kemudian dikalikan dengan 90 dan ditampilkan.

Ç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

Cobalah online!

Sumbu potensial golf:

  • Tidak yakin apakah mod 4 itu diperlukan (ini akan menghemat 2 byte). Semua test case berfungsi tanpanya, tapi mungkin ada case yang rumit. Bukti matematis untuk memvalidasi atau membatalkannya akan menjadi yang terbaik.
  • Tidak ada hal yang tersirat selain menampilkan hasilnya (tanda kutip penutup, tanda kurung tutup).
Osable
sumber
1
Tampaknya tidak memberikan hasil yang diminta pada NNNNNNNNNNNNNNNNNNNNNNNEdan SNNNNNNNNNNNNNNNNNNNNNNNEmenguji kasus.
Emigna
2
Aneh. Sekarang saya juga melakukannya. Saya pasti telah menyisipkan kesalahan atau sesuatu, maaf. Anda dapat mempersingkat kode menjadi v"NESW"yk90*})R¬U¦vXy+;DX-Ä89›180*+360%U}X.
Emigna
1
Penjelasan hebat! Mungkin bernilai termasuk catatan yang 89›sebenarnya berarti bagian bilangan bulat lebih besar dari 89, yang setara dengan mengatakan angka lengkap lebih besar atau sama dengan 90 (yang masih berfungsi dengan baik karena tepat 90 seharusnya tidak pernah terjadi). Saat ini komentar dalam kode yang dijelaskan membuatnya terdengar seperti memeriksa lebih besar dari 89, sedangkan kode Anda melewati kasus uji sehingga jelas memeriksa dengan benar lebih besar dari 90.
trichoplax
1
Saya mengedit penjelasannya, namun saya menulis "cast to integer" karena saya tidak yakin bagaimana operator harus bersikap terhadap nilai-nilai floating point negatif. Tidak ada masalah di sini karena ini bekerja pada nilai absolut, tetapi saya lebih suka tidak membuat asumsi terlalu kuat pada operator.
Osable
1
Anda dapat mengganti v"NESW"yk})dengan Ç30^5%:)
Adnan
5

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

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

Panggil fdengan string.

L3viathan
sumber
Anda tidak dapat memiliki keduanya yang ...0elsemereka lemparkan SyntaxErrors.
Jonathan Allan
@ JonathanAllan Versi Python apa yang Anda gunakan? Saya menggunakan 3.5.2 dan berhasil.
L3viathan
Saya menjalankannya di 3.3.3 - dapatkah Anda menghapus ruang di antara elsedan -juga? (bisa dalam 3.3.3)
Jonathan Allan
@ Jonathan Allan Ya saya bisa! Terima kasih, itu menyelamatkan saya byte lain.
L3viathan
2
@Itus d.findbisa, saya punya ide yang tepat semenit yang lalu; lihat jawaban yang diperbarui.
L3viathan
5

C, 184 byte

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

Tidak disatukan

// 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;
}
Eyal Lev
sumber
Tampaknya menggunakan float, tidak memberikan Anda presisi yang dibutuhkan.
Eyal Lev
4
Selamat datang di PPCG! : D
mbomb007
Bukankah nama-nama fungsi tersebut saling bertentangan (karena keduanya sama-sama d)?
clismique
@qwerp, tanda tangan berbeda (satu mengambil char *, lainnya hanya char)
Eyal Lev
2
Nama fungsi bukan nama yang dicoret dalam C, karena mereka dalam C ++, jadi Anda perlu mengganti nama salah satu dari mereka jika Anda ingin menjadi C.
Klas Lindbäck
3

R, 172 146 byte

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)

Tidak disatukan

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

Dijelaskan

  1. Baca input dari stdin
    • Cocokkan input dengan indeks ke c("N","E","S","W")
    • Dari indeks yang cocok: cocok dengan vektor derajat 0:3*90(alih-alih c(0,90,180,270))
    • Balikkan dan simpan sebagai z
  2. Inisialisasi pke tingkat yang setara dengan input karakter terakhir
  3. Simpan panjang input sebagai l
  4. Pada dasarnya, hitung yang terdekat dari dua bantalan yang mungkin membagi dua.
  5. Jika hanya satu input yang diberikan, setel pkez
  6. Memformat dan mencetak

Coba uji kasus pada R-fiddle (perhatikan bahwa ini adalah fungsi karena scantidak bekerja pada R-fiddle)

Billywob
sumber
Asalkan outputnya benar ke 5 tempat desimal, Anda tidak perlu melakukan pembulatan. Dari tantangan: Outputs 0.00001 and 0.000005 are both correct.Jadi Anda harus dapat menghemat beberapa byte dengan tidak membulatkannya
trichoplax
@trichoplax saya mengerti. Bisakah input juga berupa vektor karakter string seperti. c("N","N","E")bukan "NNE"? Ini setara dengan daftar python yang tidak bersarang ["N","N","E"].
Billywob
Iya nih. Saya bermaksud "urutan" menjadi istilah umum untuk memasukkan hal-hal seperti array, vektor, daftar, tupel.
trichoplax
1
Saya pikir Anda dapat menyimpan 4 byte jika Anda membagi semuanya dengan 90 dan printf (p * 90).
Titus
3

Haskell, 109 105 103 byte

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

Terima kasih untuk -2 byte @xnor!

cacat
sumber
Daftar lengkap untuk fterlihat panjang, tapi saya kesulitan menemukan sesuatu yang lebih pendek. Yang paling dekat saya dapatkan adalah f c=90*until(\i->"NESW"!!i==c)(+1)0(35). Saya pikir Anda bisa menggantinya 'W'dengan _.
xnor
Ya saya juga berharap akan ada sesuatu yang lebih pendek, tetapi tidak menemukan apa pun. Terima kasih untuk _!
flawr
3

Dyalog APL , 55 45 38 byte

Larutan

Membutuhkan ⎕IO←0, yang merupakan standar pada banyak sistem. Meminta arahan.

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

Penjelasan

Mengatasi masalah dengan mengubah setiap huruf menjadi angka kompleks 1∠ θa + b · i , kemudian melakukan pengurangan jumlah dari kanan-ke-kiri (forte APL) sambil menormalisasi pada setiap langkah. Θ akhir kemudian dikonversi ke derajat dan dinormalisasi menjadi dalam [0, 360):

'NES'⍳⍞indeks setiap huruf input dalam "NES"; N → 0, E → 1, S → 2, apa pun → 3

○2÷⍨dikonversi ke sudut dalam radian; θ = π · x2

¯12○konversikan ke bilangan kompleks pada lingkaran unit; e i · θ

(... )/kurangi daftar dengan ... (mis. menyisipkan fungsi antara elemen-elemen ...)

+÷(|+)... jumlah yang dinormalisasi; x n - 1 + x n| x n - 1 + x n |

12○mengkonversi ke sudut; θ

÷○÷180×dikonversi ke derajat; 1π · 1180 · x

360| pembagian divisi ketika dibagi 360

TryAPL online!

Anekdot

Jika input dan output adalah unit kompleks ortogonal, seluruh solusi akan menjadi hanya:

(+÷(|+))/

Sisa kode mem-parsing input dan memformat output.

Adm
sumber
Saya perhatikan output tes tidak cocok dengan yang ada di tantangan ke 5 tempat desimal, membuat ini tidak valid. Apakah Dyalog APL memiliki opsi untuk menggunakan presisi ganda?
trichoplax
@trichoplax Ya, ⎕FR←1287menggunakan floats 128 bit, tetapi TryAPL tidak mengizinkannya.
Adám
Saya pikir sesuatu yang lebih besar dari atau sama dengan floats 64 bit harus bekerja (saya hanya diuji dengan Python). Apakah ini berarti Anda dapat membuat kode tersebut valid tetapi hanya akan bekerja untuk orang yang telah menginstal bahasa? Mungkin Anda dapat menunjukkan kode yang valid untuk skor, dan menyertakan versi online yang tidak memiliki akurasi yang diperlukan sehingga orang dapat melihat bahwa algoritme tersebut benar.
trichoplax
@trichoplax Sebenarnya, TryAPL menggunakan presisi ganda, tetapi test case Anda mengakumulasi kesalahan di luar 53 bit.
Adám
Jika dapat ditunjukkan bahwa perbedaan tersebut disebabkan oleh perbedaan interpretasi standar IEEE 754, yang masih memenuhi standar, maka saya akan menyesuaikan kasus uji untuk memastikan kedua interpretasi memberikan hasil yang sama ke 5 tempat desimal. Saya memilih kasus uji sedemikian rupa sehingga mereka memberikan hasil yang sama ke 5 tempat desimal di Python untuk float (presisi ganda) dan desimal presisi acak. Saya akan memeriksanya.
trichoplax
2

Common Lisp, 347 327 byte

Terima kasih kepada @Titus untuk melepas beberapa

Ini mungkin bisa bermain golf lebih banyak, tetapi setidaknya itu berfungsi (saya pikir):

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

Pemakaian:

* (f "WNE")
337.50000
NIL

Fungsi dmengambil karakter N, E, W, atau Sdan kembali tingkat yang sesuai. Fungsi mmendapat tingkat gabungan yang tepat dari dua arah yang diberikan. Berfungsi fmelalui string yang disediakan, menghitung derajat yang sesuai, dan mencetaknya sebagai titik mengambang.

artificialnull
sumber
LISP saya berkarat, tetapi dapat membagi semuanya dengan 90 menghemat 6 byte?
Titus
@Itus saya pikir akan. Saya telah menyadari beberapa perbaikan lain jadi saya akan menambahkan ini ketika saya berada di komputer saya
artificialnull
2

Befunge, 183 181 175 byte

>~#+:#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_$$$,,,".">:#,_@

Cobalah online!

Penjelasan

Ini mengikuti algoritma yang mirip dengan banyak jawaban lainnya, hanya saja menggunakan perhitungan titik tetap yang ditiru dengan bilangan bulat karena Befunge tidak mendukung floating point.

Terima kasih kepada @Titus untuk rutin ASCII-to-int.

 ~ : 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
James Holderness
sumber
Apakah itu hanya berarti Anda perlu meniru tipe titik tetap yang lebih besar (lebih banyak tempat desimal)? Kasing uji dirancang untuk membutuhkan ketelitian ganda, yang tidak lebih dari 17 angka signifikan (maksimal 16 tempat desimal), dan 14 tempat desimal mungkin cukup.
trichoplax