Khoảng cách giữa hai điểm trên Mặt trăng


11

Cho vĩ độ / kinh độ của hai điểm trên Mặt trăng (lat1, lon1)(lat2, lon2)tính khoảng cách giữa hai điểm tính bằng km, bằng cách sử dụng bất kỳ công thức nào cho kết quả tương tự như công thức haversine.

Đầu vào

  • Bốn giá trị nguyên lat1, lon1, lat2, lon2theo độ (góc) hoặc
  • bốn giá trị thập phân ϕ1, λ1, ϕ2, λ2tính bằng radian.

Đầu ra

Khoảng cách tính bằng km giữa hai điểm (số thập phân với bất kỳ số nguyên chính xác hoặc làm tròn).

Công thức Haversine

d = 2 r \ arcsin \ left (\ sqrt {\ sin ^ 2 \ left (\ frac {\ phi_2 - \ phi_1} {2} \ phải) + \ cos (\ phi_1) \ cos (\ phi_2) \ sin ^ 2 \ trái (\ frac {\ lambda_2 - \ lambda_1} {2} \ phải)} \ phải)

Ở đâu

  • r là bán kính của hình cầu (giả sử bán kính của Mặt trăng là 1737 km),
  • ϕ1 vĩ độ của điểm 1 tính bằng radian
  • ϕ2 vĩ độ của điểm 2 tính bằng radian
  • λ1 kinh độ của điểm 1 tính bằng radian
  • λ2 kinh độ của điểm 2 tính bằng radian
  • d là khoảng cách tròn giữa hai điểm

(nguồn: https://en.wikipedia.org/wiki/Haversine_formula )

Các công thức có thể khác

Ví dụ trong đó đầu vào là độ và đầu ra là số nguyên tròn

42, 9, 50, 2  --> 284
50, 2, 42, 9  --> 284
4, -2, -2, 1  --> 203
77, 8, 77, 8  --> 0
10, 2, 88, 9  --> 2365

Quy tắc

  • Đầu vào và đầu ra có thể được đưa ra trong bất kỳ định dạng thuận tiện .
  • Chỉ định trong câu trả lời cho dù đầu vào là độ hoặc radian .
  • Không cần xử lý các giá trị vĩ độ / kinh độ không hợp lệ
  • Hoặc là một chương trình đầy đủ hoặc một chức năng được chấp nhận. Nếu một chức năng, bạn có thể trả lại đầu ra thay vì in nó.
  • Nếu có thể, vui lòng bao gồm một liên kết đến một môi trường thử nghiệm trực tuyến để người khác có thể thử mã của bạn!
  • Sơ hở tiêu chuẩn bị cấm.
  • Đây là vì vậy tất cả các quy tắc chơi gôn thông thường đều được áp dụng và mã ngắn nhất (tính bằng byte) sẽ thắng.

7
Sử dụng công thức cụ thể đó là một yêu cầu không thể quan sát được. Nó không đủ để đưa ra kết quả giống như công thức đó sẽ cho?
Adám

1
Chúng ta có thể lấy đầu vào bằng radian?
Adám

1
@mdahmoune OK, vì vậy bạn đã liệt kê theo độ để dễ viết, nhưng chúng tôi có thể yêu cầu đầu vào phải bằng radian không? Nếu không, thử thách này trở thành một kết hợp (rất tệ) về chuyển đổi góc và của thử thách chính.
Adám

5
Tôi đã đánh giá thấp câu hỏi này bởi vì dường như nhiều hơn là 'Ngôn ngữ của ai có thể chơi công thức này nhiều nhất', mà theo tôi, không đặc biệt thú vị.
caird coinheringaahing

2
Một công thức ngắn hơn cho hầu hết các ngôn ngữ sẽ là d = r * acos( sin ϕ1 sin ϕ2 + cos ϕ1 cos ϕ2 cos(λ2 - λ1) )nơir = 1737
dặm

Câu trả lời:



6

R + địa quyển , 54 47 byte

function(p,q)geosphere::distHaversine(p,q,1737)

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

Lấy đầu vào là vectơ 2 phần tử tính longitude,latitudebằng độ. TIO không có geospheregói nhưng yên tâm rằng nó trả về kết quả giống hệt với chức năng bên dưới.

Cảm ơn Jonathan Allan đã cạo sạch 7 byte.

R , 64 byte

function(p,l,q,k)1737*acos(sin(p)*sin(q)+cos(p)*cos(q)*cos(k-l))

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

Có 4 đầu vào như trong các trường hợp thử nghiệm, nhưng tính bằng radian chứ không phải độ.


e3/1000thực sự cần thiết?
Jonathan Allan

1
@Jonathan Allan không có họ. Điều đó khá ngu ngốc đối với tôi, nhưng đối số mặc định cho bán kính là trái đất tính bằng mét nên lúc đó nó hợp lý, lol
Giuseppe

Lưu ý rằng định luật hình cầu của cosin không ổn định về số lượng, đặc biệt đối với khoảng cách nhỏ. Điều đó có thể ổn trong Mathicala , nhưng trong R và hầu hết các ngôn ngữ khác, điều gây tranh cãi là liệu "bất kỳ công thức nào cho kết quả giống như tiêu chí của công thức haversine" đều được đáp ứng.
đã ngừng quay ngược chiều

@ceasetoturncountclockwis Tôi chủ yếu đưa nó vào mục đích để có nó trong cơ sở R. Tôi cho rằng sử dụng một thư viện dấu phẩy động chính xác tùy ý sẽ làm giảm hiệu ứng.
Giuseppe

Có, hoặc sử dụng một công thức ổn định như, giả sử, công thức haversine ...
đã ngừng quay ngược chiều


5

JavaScript (ES7), 90 byte

Lưu ý: xem bài đăng của @ OlivierGrégoire để biết giải pháp ngắn hơn nhiều

Một cổng trực tiếp của câu trả lời của TFeld . Đưa đầu vào bằng radian.

(a,b,c,d,M=Math)=>3474*M.asin((M.sin((c-a)/2)**2+M.cos(c)*M.cos(a)*M.sin((d-b)/2)**2)**.5)

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

Sử dụng khét tiếng with(), 85 byte

Cảm ơn @ l4m2 vì đã tiết kiệm 6 byte

with(Math)f=(a,b,c,d)=>3474*asin((sin((c-a)/2)**2+cos(c)*cos(a)*sin((d-b)/2)**2)**.5)

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


2
Bạn có thể làmwith(Math)f=(a,b,c,d)=>3474*asin((sin((c-a)/2)**2+cos(c)*cos(a)*sin((d-b)/2)**2)**.5)
l4m2

77 byte sử dụng thuật toán ngắn hơn của @miles :(a,b,c,d,M=Math)=>1737*M.acos(M.sin(a)*M.sin(c)+M.cos(a)*M.cos(c)*M.cos(d-b))
Kevin Cruijssen

1
74 byte sử dụng thuật toán ngắn hơn của @Neil :(a,b,c,d,M=Math)=>1737*M.acos(M.cos(a-c)+M.cos(a)*M.cos(c)*(M.cos(d-b)-1))
Kevin Cruijssen

3
65 byte tối ưu hóa câu trả lời của mọi người:(a,b,c,d,C=Math.cos)=>1737*Math.acos(C(a-c)+C(a)*C(c)*(C(d-b)-1))
Olivier Grégoire

@ OlivierGrégoire Rất đẹp. Bạn có lẽ nên đăng nó như một câu trả lời mới.
Arnauld

5

APL (Dyalog Unicode) , 40 35 byte SBCS

Chức năng ngầm ẩn danh. Lấy {ϕ₁,} làm đối số bên trái và {ϕ₂, λ₂} làm đối số bên phải.

Sử dụng công thức 2 r √ (sin² ( (φ₁-φ₂) / 2 ) + cos cos φ₁ φ₂ sin² ( (λ₁ - λ₂) / 2 ))

3474ׯ1○.5*⍨1⊥(×⍨12÷⍨-)×1,2×.○∘⊃,¨

Hãy thử trực tuyến! ( rhàm chuyển đổi độ thành radian)


 nối các phần tử tương ứng; {{ϕ₁, ϕ₂}, {λ₁, λ₂}}

 chọn cái đầu tiên; {ϕ₁, ϕ₂}

 sau đó

2×.○ sản phẩm của cosin của họ; cos ϕ₁ cos ϕ₂
lit. chấm "sản phẩm" nhưng với bộ chọn chức năng trig (2 là cosine) thay vì nhân và thời gian thay vì cộng

1, trả trước 1 cho điều đó; {1, cos ϕ₁ cos ϕ₂}

(Nhiều  nhân với kết quả của việc áp dụng hàm sau cho {ϕ₁, λ₁} và {ϕ₂, λ₂}:

- sự khác biệt của họ; {ϕ₁ - ϕ₂, λ₁ - λ₂}

2÷⍨ chia số đó cho 2; { (ϕ₁ - ϕ₂)2 , (λ₁ - λ₂)2 }

1○ sin của điều đó; {sin ( (φ₁ - φ₂) / 2 ), sin ( (λ₁ - λ₂) / 2 )}

×⍨ hình vuông đó (lit. tự nhân); {sin² ( (φ₁ - φ₂) / 2 ), sin² ( (λ₁-λ₂) / 2 )}

Bây giờ chúng ta có {sin² ( (φ₁ - φ₂) / 2 ), cos cos φ₁ φ₂ sin² ( (λ₁ - λ₂) / 2 )}

1⊥ tổng mà (đánh giá trong cơ sở-1); sin² ( (φ₁-φ₂) / 2 ) + cos cos φ₁ φ₂ sin² ( (λ₁ - λ₂) / 2 )

.5*⍨ căn bậc hai của điều đó (lit. nâng nó lên sức mạnh của một nửa)

¯1○ arcsine của điều đó

3474× nhân nó lên


Hàm cho phép nhập theo độ là:

○÷∘180

÷180 đối số chia cho 180

 nhân với số thập phân


4

Python 2 , 95 byte

lambda a,b,c,d:3474*asin((sin((c-a)/2)**2+cos(c)*cos(a)*sin((d-b)/2)**2)**.5)
from math import*

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

Đưa đầu vào bằng radian.


Phiên bản cũ, trước khi i / o bị chùng: Lấy đầu vào dưới dạng độ nguyên và trả về làm tròn dist

Python 2 , 135 byte

lambda a,b,c,d:int(round(3474*asin((sin((r(c)-r(a))/2)**2+cos(r(c))*cos(r(a))*sin((r(d)-r(b))/2)**2)**.5)))
from math import*
r=radians

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


bạn có thể bỏ introundvì số thập phân được phép làm đầu ra, bạn cũng có thể tránh chuyển đổi sang radian vì đầu vào là radian cũng được cho phép
mdahmoune

@mdahmoune, Cảm ơn, đã cập nhật
TFeld

3

Java 8, 113 92 88 82 byte

(a,b,c,d)->1737*Math.acos(Math.cos(a-c)+Math.cos(a)*Math.cos(c)*(Math.cos(d-b)-1))

Đầu vào a,b,c,dđược ϕ1,λ1,ϕ2,λ2tính bằng radian.

-21 byte sử dụng công thức ngắn hơn của @miles .
-4 byte nhờ @ OlivierGrégore vì tôi vẫn được sử dụng {Math m=null;return ...;}với tất cả Math.như m., thay vì thả returnvà sử dụng Mathtrực tiếp.
-6 byte sử dụng công thức ngắn hơn của @Neil .

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

Giải trình:

(a,b,c,d)->                  // Method with four double parameters and double return-type
  1737*Math.acos(            //  Return 1737 multiplied with the acos of:
   Math.cos(a-c)             //   the cos of `a` minus `c`,
   +Math.cos(a)*Math.cos(c)  //   plus the cos of `a` multiplied with the cos of `c`
   *(Math.cos(d-b)-1))       //   multiplied with the cos of `d` minus `b` minus 1

1
"Tối ưu hóa sớm là gốc rễ của mọi tội lỗi"! 88 byte:(a,b,c,d)->1737*Math.acos(Math.sin(a)*Math.sin(c)+Math.cos(a)*Math.cos(c)*Math.cos(d-b))
Olivier Grégoire

" Tối ưu hóa sớm là gốc rễ của mọi tội lỗi " Tôi đoán bạn thực sự đúng .. Cảm ơn!
Kevin Cruijssen

1
Tôi đã tìm thấy một công thức ngắn hơn:(a,b,c,d)->1737*Math.acos(Math.cos(a-c)+Math.cos(a)*Math.cos(c)*(Math.cos(d-b)-1))
Neil

(Công thức đó không ngắn hơn trong Ngôn ngữ Wolfram gốc.)
Neil

3

Japt , 55 50 byte

MsU *MsW +McU *McW *McX-V
ToMP1/7l¹ñ@McX aUÃv *#­7

Không nhất thiết phải hoàn toàn chính xác như các câu trả lời khác, nhưng cậu bé đã làm tôi vui với câu trả lời này. Cho phép tôi giải thích.
Mặc dù trong hầu hết các ngôn ngữ, thử thách này khá đơn giản, Japt có một đặc tính đáng tiếc là không có tích hợp cho cả arcsine và arccosine. Chắc chắn, bạn có thể nhúng Javascript vào Japt, nhưng đó sẽ là điều ngược lại với Phong thủy.

Tất cả những gì chúng ta phải làm để khắc phục sự phiền toái nhỏ này là xấp xỉ arccosine và chúng ta tốt để đi!

Phần đầu tiên là mọi thứ được đưa vào arccosine.

MsU *MsW +McU *McW *McX-V
MsU                        // Take the sine of the first input and
    *MsW...                // multiply by the cos of the second one etc.

Kết quả được lưu trữ ngầm Uđể sử dụng sau này.

Theo đó, chúng ta cần tìm một xấp xỉ tốt cho arccosine. Vì tôi lười biếng và không giỏi môn toán, rõ ràng chúng tôi sẽ chỉ bắt bẻ nó.

ToMP1/7l¹ñ@McX aUÃv *#­7
T                       // Take 0
 o                      // and create a range from it
  MP                    // to π
    1/7l¹               // with resolution 1/7!.
         ñ@             // Sort this range so that
           McX          // the cosine of a given value
               aU       // is closest to U, e.g. the whole trig lot
                        // we want to take arccosine of.
                 Ã      // When that's done,
                  v     // get the first element
                    *#­7 // and multiply it by 1737, returning implicitly.

Chúng tôi đã có thể sử dụng bất kỳ số lượng lớn nào cho độ phân giải của trình tạo, thử nghiệm thủ công cho thấy 7!đủ lớn trong khi có tốc độ khá nhanh.

Lấy đầu vào là radian, đầu ra số không có dấu.

Cạo sạch năm byte nhờ Oliver .

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


Bạn có thể loại bỏ (trong Mc(X-V. Vì mã char 1737không phải là ISO-8859-1, nên nó chuyển sang UTF-8, chi phí cao hơn. Thay vào đó, bạn có thể sử dụng mã char cho 173+ 7. ethproductions.github.io/japt/?v=1.4.5&code=I603&input=
Oliver

Bạn cũng có thể xóa ,sau ToMP:-)
Oliver

@Oliver Cảm ơn rất nhiều, dấu ngoặc đơn là cần thiết trong phiên bản gốc của tôi nhưng đã trở nên lỗi thời khi chơi golf xung quanh một chút, mặc dù vậy tôi hoàn toàn bỏ lỡ nó. Ngoài ra, tôi cũng không biết về điều mã hóa, cũng cảm ơn rất nhiều vì điều đó.
Nit

1
Nếu bạn muốn đi theo con đường JavaScript, hãy nhớ rằng bạn có thể chạy mọi thứ thông qua shoco.
Oliver



2

Thạch ,  23 22  18 byte

-4 byte nhờ dặm (sử dụng {}khi sử dụng công thức của họ .

;I}ÆẠP+ÆSP${ÆA×⁽£ġ

Hàm dyadic chấp nhận [ϕ1, ϕ2,]ở bên trái và [λ1, λ2]bên phải tính bằng radian trả về kết quả (dưới dạng dấu phẩy động).

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


Của tôi ... (cũng đã lưu một byte ở đây bằng cách sử dụng a {)

,IÆẠCH;ÆẠ{Ḣ+PƊ½ÆṢ×⁽µṣ

Dùng thử trực tuyến


Thật thú vị, tôi đã làm mới trang một lần nữa và nó hiển thị chỉnh sửa của bạn, chỉ cần nhấp vào câu trả lời mới để hiển thị thay đổi không cập nhật để hiển thị các chỉnh sửa của bạn. thay thế 18 byte là;I}ÆẠP+ÆSP${ÆA×⁽£ġ
dặm

Không bao giờ hiểu làm thế nào để sử dụng {}họ không bao giờ làm những gì tôi mong đợi. Điều đó không có nghĩa là tôi có thể làm theo cách khác trong 17?!
Jonathan Allan

Có lẽ. {}chỉ cần tạo ra một con đê từ một đơn nguyên. Một quan điểm tương tự có thể là P{ -> ḷP¥. Có thể là tốt để thêm một sáng tác (từ J) để làm một cái gì đó giống như x (P+$) y -> (P x) + (P y)có thể lưu một hoặc hai byte trong các tình huống tương tự.
dặm

2

MATLAB với Hộp công cụ ánh xạ, 26 byte

@(x)distance(x{:})*9.65*pi

Hàm ẩn danh lấy bốn đầu vào làm một mảng ô, theo cùng thứ tự như được mô tả trong thử thách.

Lưu ý rằng điều này cho kết quả chính xác (giả sử rằng bán kính Mặt trăng là 1737 km), vì 1737/180bằng nhau 9.65.

Ví dụ chạy trong Matlab R2017b:

nhập mô tả hình ảnh ở đây


1

Python 3, 79 byte

from geopy import*
lambda a,b:distance.great_circle(a,b,radius=1737).kilometers

TIO không có geopy.py


2
@Nit, sự hiểu biết của tôi là trò chơi công bằng để sử dụng một thư viện có sẵn công khai trước câu hỏi. Tôi nghĩ nó giống như sử dụng các công cụ lập bản đồ của MATLAB hoặc các ngôn ngữ khác bằng thư viện toán học.
RootTwo

1

APL (Dyalog Unicode) , 29 byte SBCS

Hoàn thành chương trình. Nhắc stdin cho {ϕ₁,} và sau đó cho {λ₁, λ₂}. In ra thiết bị xuất chuẩn.

Sử dụng công thức r acos (sin sin + cos (λ₂ - λ₁) cos cos ϕ₂)

1737ׯ2○+/(2○-/⎕)×@2×/1 2∘.○⎕

Hãy thử trực tuyến! ( rhàm chuyển đổi độ thành radian)


 lời nhắc cho {ϕ₁,}

1 2∘.○ Ứng dụng trig-chức năng của Cartesian; {{sin ϕ₁, sin ϕ₂}, {cos, cos ϕ₂}}

×/ sản phẩm hàng khôn ngoan; {sin sin, cos cos ϕ₂}

(Sai )×@2 ở phần tử thứ hai, nhân số sau:

 lời nhắc cho {λ₁,}

-/ sự khác biệt giữa những cái đó; λ₁ -

2○ cosin của điều đó; cos (λ₁ - λ₂)

Bây giờ chúng ta có {sin sin, cos (λ₁ - λ₂) cos cos ϕ₂}

+/ Tổng; tội lỗi ϕ₁ sin + cos (λ₁ - λ₂) cos cos

¯2○ cosin của điều đó; cos (sin sin + cos (λ₁ - λ₂) cos cos ϕ₂)

1737× nhân r với đó; 1737 cos (sin sin + cos (λ₁ - λ₂) cos cos ϕ₂)


Hàm cho phép nhập theo độ là:

○÷∘180

÷180 đối số chia cho 180

 nhân với số thập phân


1

C (gcc) , 100 88 65 64 byte

88 → 65 sử dụng công thức của @miles
65 → 64 bằng công thức của @ Neil

#define d(w,x,y,z)1737*acos(cos(w-y)+cos(w)*cos(y)*(cos(z-x)-1))

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


Tôi tin rằng bạn cần thêm hai byte cho -lmcờ trình biên dịch.
OOBalance

@OOBalance: Không phải lúc nào cũng có sự hiện diện của cờ. Nó phụ thuộc vào cách trình biên dịch được cài đặt trên hệ thống.
jxh

Ổn thỏa. Đoán điều này có nghĩa là tôi có thể trừ hai byte cho câu trả lời này của tôi: codegolf.stackexchange.com/a/161452/79343 Cảm ơn.
OOBalance

@OOBalance: Nâng cao câu trả lời. Tôi cũng đã gửi giải pháp của riêng tôi.
jxh

Đẹp. Nâng cao của bạn là tốt.
OOBalance

1

Excel, 53 byte

=1737*ACOS(COS(A1-C1)+COS(A1)*COS(C1)*(COS(D1-B1)-1))

Sử dụng công thức của @ Neil. Đầu vào bằng radian.


1

Tôm hùm , 66 byte

def h(a,c,b,d):1737*radians arccos a.sin*b.sin+a.cos*b.cos*cos d-c

Sử dụng công thức dặm, nhưng đầu vào là ở độ. Điều này thêm bước chuyển đổi sang radian trước khi nhân với bán kính.




1

SmileBASIC, 60 byte

INPUT X,Y,S,T?1737*ACOS(COS(X-S)+COS(X)*COS(S)*(COS(T-Y)-1))
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.