Bắc theo Bắc bởi Bắc của Đông Nam


30

Cho một chuỗi N, S, E và W, xuất ra một ổ trục (góc theo chiều kim đồng hồ từ Bắc tính theo độ), chính xác đến 5 chữ số thập phân.

Trong ký hiệu la bàn truyền thống , một chuỗi chỉ gồm 2 ký tự này (như NNW hoặc ESE). Tại đây, bạn cũng phải chấp nhận các chuỗi chứa cả 4 (như WNNNSE) . Chỉ sử dụng 2 biểu tượng cho phép con người hiểu trực giác về ý nghĩa. Cho phép 4 biểu tượng làm cho nó thật kinh khủng khi đọc, nhưng cho phép các cách ngắn hơn để mô tả một ổ trục với độ chính xác nhất định.

(Như đã chỉ ra trong ý kiến của user2357112 , nó quay ra bạn có thể chứng minh rằng đối với bất kỳ mang nhất định, chuỗi 4 biểu tượng sẽ được chính xác độ dài tương tự như chuỗi 2 biểu tượng, vì vậy tôi đã dựa thách thức này trên một giả định sai. Hy vọng rằng việc thiếu mục đích thực tế này sẽ không làm giảm sự thích thú của bạn đối với thử thách ...)

Phương pháp chính xác được mô tả dưới đây và tương đương với ký hiệu truyền thống (nó mở rộng trên đó thay vì thay đổi nó).

Đầu vào

  • Đầu vào là một chuỗi duy nhất chỉ chứa các ký tự NESW.
  • Đầu vào có thể là một chuỗi các ký tự nếu bạn thích, miễn là điều này không bao gồm bất kỳ quá trình tiền xử lý nào. Ví dụ: [N, [E, [S, [W]]]]không được phép lấy danh sách lồng nhau để giúp xử lý thứ tự xử lý.
  • Lấy các ký tự khác nhau là không được phép. Bạn có thể không lấy một chuỗi 1234thay vì NESW.

Đầu ra

  • Đầu ra phải là số thập phân hoặc biểu diễn chuỗi của một (không phải là số hữu tỷ / phần).
  • Số không lưu trữ không cần phải được hiển thị. Nếu ổ trục là 9.00000, thì đầu ra 9cũng được tính là chính xác đến 5 chữ số thập phân.
  • Đầu ra nằm trong phạm vi [0, 360). Đó là, bao gồm 0 nhưng không bao gồm 360.
  • Độ chính xác được kiểm tra bằng cách làm tròn đầu ra đến 5 chữ số thập phân. Nếu ổ trục là 0,000005, vòng này đến 0,00001. Đầu ra 0,00001 và 0,000005 đều đúng.
  • Đầu ra trong ký hiệu khoa học cho một số đầu vào là chấp nhận được. Ví dụ, 1e-5thay vì 0.00001.

Chuyển đổi

  • Các ký tự đơn la bàn điểm N, E, S, và Wtương ứng với 0, 90, 180, và 270 độ tương ứng.
  • Chuẩn bị một trong những thứ này cho một chuỗi dẫn đến ổ trục chia đôi ổ đỡ của ký tự đơn và ổ trục của chuỗi gốc.
  • Gần nhất trong hai vòng bi chia đôi có thể được chọn, sao cho NE đại diện cho 45 độ, không phải 225 độ.
  • Điều này không rõ ràng trừ trường hợp góc bị cắt là 180 độ. Do đó NS, SN, WE, và EWtương ứng với ổ trục undefined, và đầu vào sẽ không bao giờ kết thúc trong bất kỳ trong số này. Tuy nhiên, chúng có thể xuất hiện ở bất kỳ nơi nào khác trong chuỗi đầu vào, vì điều này không gây ra sự mơ hồ.
  • Nếu hai ký tự cuối cùng giống hệt nhau, ký tự cuối cùng sẽ là dự phòng vì phép chia sẽ trả về cùng một mang. Vì điều này không thêm gì vào ký hiệu, mã của bạn không cần xử lý việc này. Do đó NN, EE, SS, và WWtương ứng với ổ trục undefined, và đầu vào sẽ không bao giờ kết thúc trong bất kỳ trong số này. Tuy nhiên, chúng có thể xuất hiện ở bất kỳ nơi nào khác trong chuỗi đầu vào.

Ví dụ

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

Các trường hợp thử nghiệm

Một đệ trình chỉ có hiệu lực nếu nó cung cấp đầu ra chính xác cho tất cả các trường hợp thử nghiệm. Lưu ý rằng các trường hợp thử nghiệm đẩy đến giới hạn của những gì có thể được xử lý với độ chính xác gấp đôi. Đối với các ngôn ngữ mặc định với độ chính xác đơn, có lẽ bạn sẽ cần phải sử dụng các byte để chỉ định độ chính xác kép để có được đầu ra chính xác.

Kết quả đầu ra của trường hợp thử nghiệm được hiển thị làm tròn đến 5 chữ số thập phân và độ chính xác tùy ý. Cả hai đều là đầu ra hợp lệ.

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

Chấm điểm

Đây là . Điểm số là độ dài của mã nguồn tính bằng byte và chiến thắng ngắn nhất.


Nhà sư phạm

Tôi đã phạm sai lầm khi nghĩ rằng "North by North West" là một hướng la bàn hợp lệ. Một sai lầm hạnh phúc, vì nó đã dẫn đến một ý tưởng thách thức, nhưng sau đó tôi đã phát hiện ra từ trang Wikipedia :

"Tiêu đề của bộ phim Alfred Hitchcock 1959, North by Northwest, thực sự không phải là một hướng trên la bàn 32 gió, mà là bộ phim có liên quan đến hãng hàng không Tây Bắc. "

Nó cũng chỉ ra rằng phương pháp được sử dụng cho thử thách này chỉ phù hợp với các điểm la bàn truyền thống lên đến và bao gồm cả la bàn 16 điểm. La bàn 32 gió được mô tả trên trang đó rất khác biệt và tôi đã thuận tiện bỏ qua sự tồn tại của nó cho thử thách này.

Cuối cùng, đối với bất cứ ai nghĩ rằng tôi nên sử dụng "Đông Nam" thay vì "Đông Nam",.


WNNNSE<= Điều gì sẽ là đầu ra cho mục nhập ví dụ này khi bắt đầu bài viết của bạn? Nghe có vẻ không hợp lệ đối với tôi, nhưng thật khó để nói.
Tensibai

@Tensibai Đối với đầu vào WNNNSE, đầu ra sẽ là 323.4375. Xem phần ví dụ để biết hướng dẫn sẽ áp dụng theo cách tương tự cho trường hợp này.
trichoplax

Đầu vào như thế có f(N,N,N,S,E)ổn không?
Karl Napf

@KarlNapf Tôi đã mở rộng phần đầu vào để làm rõ. Nếu tôi hiểu chính xác, ví dụ đầu vào của bạn với nhiều đối số có vẻ tương đương với một chuỗi các ký tự, vì vậy nó có thể được chấp nhận.
trichoplax

2
"Cho phép 4 biểu tượng làm cho nó thật kinh khủng khi đọc, nhưng cho phép các cách ngắn hơn để mô tả một ổ trục với độ chính xác nhất định." - bạn có chắc chắn về điều đó không? Có vẻ như tất cả các yếu tố đầu vào mô tả cùng một ổ trục có cùng độ dài, vì nếu bạn chỉ định mỗi ổ trục có tỷ lệ nhị phân từ 0 đến 1, chuỗi N có độ dài N> 1 luôn tương ứng với một tỷ lệ nhị phân có mẫu số 2 ^ (N +1) ở mức thấp nhất. Ngoài ra, cho phép nhiều hơn 2 chữ cái riêng biệt trong một ổ trục không thêm sức mạnh biểu cảm; bất kỳ ổ trục nào được thể hiện bằng 3 hoặc 4 chữ cái có thể được thể hiện bằng 2.
user2357112 hỗ trợ Monica

Câu trả lời:


13

JavaScript (ES6), 84 80 78 74 72 byte

Đã lưu một byte nhờ @Titus, 1 nhờ @Neil

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

Mất một lúc, nhưng tôi nghĩ cuối cùng tôi cũng đã hoàn thiện công thức ...

Kiểm tra đoạn

Giải trình

Hãy bắt đầu với trường hợp đơn giản nhất: một chuỗi char đơn. Kết quả chỉ đơn giản là vị trí (được lập chỉ mục 0) của nó trong chuỗi NESW, nhân với 90.

Đối với chuỗi hai char, kết quả nằm ở giữa kết quả của char thứ nhất và kết quả của chuỗi thứ hai. Tuy nhiên, có một nhược điểm: nếu chênh lệch tuyệt đối giữa hai giá trị lớn hơn 180 (ví dụ NWhoặc WN), chúng ta phải 180 theo góc để nó không chỉ hướng ngược lại.

Đối với bất kỳ chuỗi nào dài hơn, kết quả nằm ở giữa kết quả của char đầu tiên và kết quả của phần còn lại của chuỗi. Điều này có thể được khái quát theo cách sau:

  • Nếu đầu vào là một char duy nhất, hãy trả về chỉ mục của nó trong chuỗi NESWlần 90.
  • Mặt khác, trả về chỉ mục của char đầu tiên trong chuỗi NESWlần 45, cộng với một nửa kết quả của phần còn lại của chuỗi; thêm 180 nếu chênh lệch tuyệt đối giữa hai lớn hơn 90.

Cách tuyệt vời để cắt ký tự đầu tiên ra khỏi chuỗi! Bạn có thể lưu một byte nếu bạn tính toán với các giá trị chia cho 45.
Tít

@Titus Tôi có thể lưu 2 byte với kỹ thuật đó, cảm ơn!
Sản phẩm ETH

1
searchthay vì indexOfđể tiết kiệm cho bạn một byte.
Neil

@Neil Cảm ơn một lần nữa! Tôi đã xoay sở để đánh gôn thêm ba lần nữa bằng cách sắp xếp lại hoàn toàn phương trình.
Sản phẩm 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);

Chỉnh sửa: -10 byte bằng cách "mượn" ý tưởng từ đệ trình của ETHproductions
-22 byte nhờ @Titus

Ung dung

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

Tôi nghĩ rằng bạn có thể điều chỉnh phạm vi của mình trở lại [0,360) ngắn hơn bằng cách sử dụng%
trichoplax

@trichoplax Thắng bá mà cắt số thập phân?
Tít


1
Lưu 10 byte với b=(b+360)%360;thay vì b+=b>360?-360:b<0?360:0;. Lưu thêm 12 byte với việc chia mọi thứ cho 90 và return b*90;.
Tít

1
Dưới đây là 10 byte nữa: hợp nhất hai bài tập và xóa dấu ngoặc: b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0)+8)/2%4;sau đó phân phối +8đến kết quả tạm thờib=(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 với toán tử hợp nhất null
  • -2 byte bằng cách không thay thế N(và hơn thế nữa, vì điều đó cho phép đặt bản dịch vào đầu vòng lặp: Nlà trung thực, nhưng 0được ước tính trong tính toán.)
  • +41 byte để sửa lỗi chia đôi ( ho )
  • -7 byte trực tiếp và -16 được lấy cảm hứng gián tiếp từ mã @ ETHproductions
  • -3 byte bằng cách thay thế strtrbằng một trong những trò tung hứng bit của tôi

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;

Đây chính thức là lần đầu tiên tôi sử dụng toán tử hợp nhất null. Chạy với -r.

PHP 7.1

Việc bù chuỗi âm trong phiên bản PHP sắp tới sẽ tiết kiệm được 12 byte:
Thay thế strlen($s=$argv[1])bằng 0$sbằng $argv[1].


Byte miễn phí cho (hầu hết) mọi người:

  • Tính toán với 0,1,2,3 thay vì 0,90,180,270 và nhân kết quả cuối cùng với 90 sẽ tiết kiệm được hai byte có thể cho phép chơi gôn thêm.
  • Có một số mẫu trong mã ASCII của các ký tự. Hãy thử một trong những thứ này bằng ngôn ngữ của bạn:
    • (a/2%6+2)%5
    • a<87?a/2&3^3:3 hoặc là a/2&3^3*(a<87)
    • a&1?a&2|a/4&1:0
    • a/.8-1&3

5

Python 3, 133 113 byte

Chỉ cần cải thiện câu trả lời của @ L3viathan vì tôi mới tạo tài khoản này và do đó chưa thể đưa ra nhận xét nào.

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

Chào mừng bạn đến với Câu đố lập trình & Golf Code, và cải tiến tốt đẹp ...
trichoplax

Tôi không thấy câu trả lời của bạn, nhưng Titus cũng có một ý tưởng tương tự, cộng với tôi đã có một câu trả lời khác, giờ tôi đã xuống 98 rồi :)
L3viathan

5

05AB1E ,48 42 37 32 byte

Đã lưu 6 byte nhờ Emigna. Đã lưu 5 byte nhờ ý tưởng của Titus để hoạt động trên phạm vi [0,4 [và nhân với 90 ở cuối. Đã lưu 5 byte nhờ sự thông thạo của biến thái xor / modulo cổ đại của Adnan.

Vì vậy, mọi góc được giảm từ phạm vi [0,360 [xuống phạm vi [0,4 [trong suốt quá trình thực hiện. Kết quả sau đó được nhân với 90 và hiển thị.

Ç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

Hãy thử trực tuyến!

Các trục tiềm năng của việc chơi golf:

  • Không chắc chắn nếu mod 4 được yêu cầu (nó sẽ tiết kiệm 2 byte). Tất cả các trường hợp thử nghiệm hoạt động mà không có nó, nhưng có thể tồn tại một trường hợp khó khăn. Một bằng chứng toán học để xác nhận nó hoặc vô hiệu hóa nó sẽ là đỉnh cao.
  • Không có nội dung ngầm ngoài việc hiển thị kết quả (đóng dấu ngoặc kép, đóng ngoặc).

1
Dường như không đưa ra kết quả được yêu cầu trong các trường hợp NNNNNNNNNNNNNNNNNNNNNNNESNNNNNNNNNNNNNNNNNNNNNNNEthử nghiệm.
Emigna

2
Kỳ dị. Bây giờ tôi cũng làm như vậy. Tôi phải dán sai hoặc một cái gì đó, xin lỗi. Bạn có thể rút ngắn mã xuống v"NESW"yk90*})R¬U¦vXy+;DX-Ä89›180*+360%U}X.
Emigna

1
Giải thích tuyệt vời! Có thể có giá trị bao gồm một ghi chú 89›thực sự có nghĩa là phần nguyên lớn hơn 89, tương đương với việc nói số hoàn thành lớn hơn hoặc bằng 90 (vẫn hoạt động tốt vì chính xác 90 không bao giờ xảy ra). Hiện tại nhận xét trong mã được giải thích có vẻ như nó đang kiểm tra lớn hơn 89, trong khi mã của bạn vượt qua các trường hợp kiểm tra vì vậy rõ ràng là kiểm tra chính xác cho hơn 90.
trichoplax

1
Tôi đã chỉnh sửa lời giải thích, tuy nhiên tôi đã viết "chuyển thành số nguyên" vì tôi không chắc người vận hành nên hành xử như thế nào đối với các giá trị dấu phẩy động âm. Không có vấn đề gì ở đây vì nó hoạt động dựa trên giá trị tuyệt đối, nhưng tôi không muốn đưa ra các giả định quá mạnh về toán tử.
Osable

1
Bạn có thể thay thế v"NESW"yk})bằng Ç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

Gọi fvới chuỗi.


Bạn không thể có hai người ...0elsehọ ném SyntaxErrors.
Jonathan Allan

@Jonathan ALLan Bạn đang sử dụng phiên bản Python nào? Tôi đang trên 3.5.2 và nó hoạt động.
L3viathan

Tôi đã chạy nó vào ngày 3.3.3 - bạn có thể xóa khoảng trống giữa else-không? (có thể trong 3.3.3)
Jonathan Allan

@Jonathan ALLan Có tôi có thể! Cảm ơn, điều đó giúp tôi tiết kiệm một byte khác.
L3viathan

2
@Titus d.findcó thể, tôi đã có ý tưởng chính xác một phút trước; xem câu trả lời cập nhật.
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;}

Ung dung

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

dường như sử dụng float, không cung cấp cho bạn độ chính xác cần thiết.
Eyal Lev

4
Chào mừng đến với PPCG! : D
mbomb007

Tên của các hàm có xung đột với nhau không (vì cả hai tên đều là d)?
clismique

@qwerp, chữ ký khác nhau (một mất char *, khác chỉ mất char)
Eyal Lev

2
Tên hàm không được đặt tên trong C, vì chúng có trong C ++, vì vậy bạn cần đổi tên một trong số chúng nếu bạn muốn nó là 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)

Ung dung

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

Giải thích

  1. Đọc đầu vào từ stdin
    • Khớp đầu vào theo chỉ mục với c("N","E","S","W")
    • Từ các chỉ số phù hợp: khớp với vectơ độ 0:3*90(thay vì c(0,90,180,270))
    • Đảo ngược và lưu trữ như z
  2. Khởi tạo pmức độ tương đương với char cuối cùng trong đầu vào
  3. Lưu trữ thời lượng đầu vào như l
  4. Lặp lại, tính toán gần nhất của hai vòng bi chia đôi có thể.
  5. Nếu chỉ có một đầu vào được đặt, đặt pthànhz
  6. Định dạng và in

Hãy thử các trường hợp thử nghiệm trên R-fiddle (lưu ý rằng đây là chức năng do scankhông hoạt động trên R-fiddle)


Với điều kiện đầu ra đúng đến 5 chữ số thập phân, bạn không cần thực hiện làm tròn số. Từ thử thách: Outputs 0.00001 and 0.000005 are both correct.Vì vậy, bạn sẽ có thể lưu một số byte bằng cách không làm tròn
trichoplax

@trichoplax Tôi hiểu. Đầu vào cũng có thể là một vectơ của các ký tự chuỗi như thế nào. c("N","N","E")thay vì "NNE"? Điều này tương đương với một danh sách trăn không lồng nhau ["N","N","E"].
Billywob

Vâng. Tôi dự định "trình tự" là một thuật ngữ chung để bao gồm những thứ như mảng, vectơ, danh sách, bộ dữ liệu.
trichoplax

1
Tôi nghĩ bạn có thể tiết kiệm 4 byte nếu bạn chia mọi thứ cho 90 và printf (p * 90).
Tít

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

Cảm ơn -2 byte @xnor!


Danh sách đầy đủ cho fvẻ ngoài dài, nhưng tôi gặp khó khăn trong việc tìm kiếm bất cứ điều gì ngắn hơn. Gần nhất tôi nhận được là f c=90*until(\i->"NESW"!!i==c)(+1)0(35). Tôi nghĩ bạn có thể thay thế 'W'bằng _.
xnor

Vâng tôi cũng dự kiến ​​sẽ có một cái gì đó ngắn hơn, nhưng không tìm thấy bất cứ điều gì. Cảm ơn vì _!
flawr

3

APL Dyalog , 55 45 38 byte

Dung dịch

Yêu cầu ⎕IO←0, được mặc định trên nhiều hệ thống. Hỏi hướng.

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

Giải trình

Đi xung quanh vấn đề bằng cách chuyển đổi mỗi bức thư cho một số phức tạp 1∠ qmột + b · i , sau đó làm giảm tổng từ phải sang trái (sở trường của APL) trong khi bình thường hóa tại mỗi bước. Trận chung kết θ sau đó được chuyển đổi sang độ và bình thường là trong vòng [0, 360):

'NES'⍳⍞các chỉ số của từng chữ cái đầu vào trong "NES"; N → 0, E → 1, S → 2, bất cứ điều gì khác → 3

○2÷⍨chuyển đổi thành các góc theo radian; θ = π · x2

¯12○chuyển đổi thành số phức trên vòng tròn đơn vị; e i ·

(... )/giảm danh sách bằng ... (tức là chèn hàm giữa các thành phần của ...)

+÷(|+)... tổng bình thường; x n - 1 + x n| x n - 1 + x n |

12○chuyển đổi thành góc; θ

÷○÷180×chuyển đổi sang độ; 1π · 1180 · x

360| phần còn lại khi chia cho 360

Dùng thử trực tuyến!

Giai thoại

Nếu đầu vào và đầu ra là các đơn vị phức tạp trực giao, toàn bộ giải pháp sẽ chỉ là:

(+÷(|+))/

Phần còn lại của mã là phân tích cú pháp đầu vào và định dạng đầu ra.


Tôi nhận thấy các đầu ra thử nghiệm không khớp với các thử thách trong 5 vị trí thập phân, khiến điều này không hợp lệ. Dyalog APL có tùy chọn sử dụng độ chính xác kép không?
trichoplax

@trichoplax Có, ⎕FR←1287sử dụng số float 128 bit, nhưng TryAPL không cho phép.
Adám

Tôi nghĩ rằng mọi thứ lớn hơn hoặc bằng 64 bit float đều hoạt động (mặc dù tôi chỉ thử nghiệm bằng Python). Điều này có nghĩa là bạn có thể làm cho mã hợp lệ nhưng sau đó nó sẽ chỉ hoạt động cho những người đã cài đặt ngôn ngữ? Có lẽ bạn có thể hiển thị mã hợp lệ đầy đủ cho điểm số và bao gồm phiên bản trực tuyến không có độ chính xác cần thiết để mọi người có thể thấy rằng thuật toán là chính xác.
trichoplax

@trichoplax Trên thực tế, TryAPL sử dụng độ chính xác gấp đôi, nhưng các trường hợp thử nghiệm của bạn tích lũy các lỗi vượt quá 53 bit.
Adám

Nếu có thể chỉ ra rằng sự khác biệt là do sự khác biệt trong cách giải thích của tiêu chuẩn IEEE 754, vẫn tuân thủ tiêu chuẩn, thì tôi sẽ điều chỉnh các trường hợp thử nghiệm để đảm bảo cả hai cách hiểu đều cho kết quả giống nhau đến 5 chữ số thập phân. Tôi đã chọn các trường hợp thử nghiệm sao cho chúng cho cùng một kết quả đến 5 vị trí thập phân trong Python cho cả số thập phân (độ chính xác kép) và số thập phân chính xác tùy ý. Tôi sẽ xem xét nó.
trichoplax

2

Lisp thường gặp, 347 327 byte

Cảm ơn @Titus đã cất cánh

Điều này có thể có thể được đánh gôn nhiều hơn, nhưng ít nhất nó hoạt động (tôi nghĩ):

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

Sử dụng:

* (f "WNE")
337.50000
NIL

Chức năng dmất một nhân vật N, E, W, hay Svà trả về mức độ thích hợp. Hàm mđược mức độ kết hợp chính xác của hai hướng cho trước. Hàm flặp qua chuỗi được cung cấp, tính toán mức độ phù hợp và in nó dưới dạng dấu phẩy động.


LISP của tôi bị gỉ, nhưng có thể chia mọi thứ cho 90 lưu 6 byte không?
Tít

@Titus Tôi nghĩ nó sẽ. Tôi đã nhận ra một số cải tiến khác vì vậy tôi sẽ thêm nó khi tôi ở máy tính của mình
nhân tạo vào

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

Hãy thử trực tuyến!

Giải trình

Điều này tuân theo một thuật toán tương tự với nhiều câu trả lời khác, chỉ có điều nó sử dụng các phép tính điểm cố định được mô phỏng bằng các số nguyên do Befunge không hỗ trợ dấu phẩy động.

Cảm ơn @Titus về thói quen 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

Điều đó chỉ có nghĩa là bạn cần mô phỏng một loại điểm cố định lớn hơn (số thập phân nhiều hơn)? Các trường hợp thử nghiệm được thiết kế để yêu cầu độ chính xác gấp đôi, không quá 17 con số có ý nghĩa (tối đa là 16 chữ số thập phân) và 14 vị trí thập phân có thể là đủ.
trichoplax

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.