月の2点間の距離


11

(lat1, lon1)と上の2つのポイントの緯度/経度を指定して、haversineの式と同じ結果を与える(lat2, lon2)使用して、2つのポイント間の距離をキロメートルで計算します。

入力

  • lat1, lon1, lat2, lon2度(角度)の4つの整数値または
  • ϕ1, λ1, ϕ2, λ2ラジアン単位の4つの10進数値。

出力

2つのポイント間の距離(キロメートル単位、精度または丸められた整数)。

ハーバーシン式

d = 2 r \ arcsin \ left(\ sqrt {\ sin ^ 2 \ left(\ frac {\ phi_2-\ phi_1} {2} \ right)+ \ cos(\ phi_1)\ cos(\ phi_2)\ sin ^ 2 \ left(\ frac {\ lambda_2-\ lambda_1} {2} \ right)} \ right)

どこ

  • r は球体の半径です(月の半径が1737 kmであると仮定)、
  • ϕ1 ラジアン単位のポイント1の緯度
  • ϕ2 ラジアン単位のポイント2の緯度
  • λ1 ラジアン単位のポイント1の経度
  • λ2 ラジアン単位のポイント2の経度
  • d 2点間の循環距離

(ソース:https : //en.wikipedia.org/wiki/Haversine_formula

他の可能な式

  • d = r * acos(sin ϕ1 sin ϕ2 + cos ϕ1 cos ϕ2 cos(λ2 - λ1)) @milesの式
  • d = r * acos(cos(ϕ1 - ϕ2) + cos ϕ1 cos ϕ2 (cos(λ2 - λ1) - 1)) @Neilの式

入力が度であり、出力が丸められた整数である例

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

ルール

  • 入力と出力は、任意の便利な形式で指定できます
  • 入力が単位ラジアン単位かを回答で指定します。
  • 無効な緯度/経度値を処理する必要はありません
  • 完全なプログラムまたは機能のいずれかが受け入れられます。関数の場合、出力する代わりに出力を返すことができます。
  • 可能であれば、他の人があなたのコードを試すことができるように、オンラインテスト環境へのリンクを含めてください!
  • 標準的な抜け穴は禁止されています。
  • これはので、通常のゴルフルールがすべて適用され、最短のコード(バイト単位)が勝ちます。

7
その特定の式を使用することは観察できない要件です。その式与えるのと同じ結果を与えるのに十分ではありませんか?
アダム

1
入力をラジアンで取得できますか?
アダム

1
@mdahmoune OK、書くのを簡単にするために度数でリストしました、入力をラジアンにする必要がありますか?それ以外の場合、この課題は角度変換と主な課題のコンボ(これは悪い)です。
アダム

5
「誰の言語がこのフォーミュラを最も多くゴルフできるか」というように思われるため、私はこの質問を支持しました。

2
ほとんどの言語のための短い式は次のようになりますd = r * acos( sin ϕ1 sin ϕ2 + cos ϕ1 cos ϕ2 cos(λ2 - λ1) )どこr = 1737
マイル

回答:



6

R + 地球圏54 47バイト

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

オンラインでお試しください!

入力をlongitude,latitude度単位の2要素ベクトルとして受け取ります。TIOにはgeosphereパッケージがありませんが、以下の関数と同じ結果を返すことを保証します。

7バイトを削ってくれたJonathan Allanに感謝します。

R、64バイト

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

オンラインでお試しください!

テストケースのように4つの入力を受け取りますが、度ではなくラジアン単位です。


あるe3/1000本当に必要?
ジョナサンアラン

1
@JonathanAllanいいえ、そうではありません。それは私の愚かなことですが、半径のデフォルトの引数はメートル単位の地球ですので、当時は論理的でした、笑
ジュゼッペ

余弦の球面法則は、特に短い距離では数値的に安定していないことに注意してください。おそらくMathematicaでは問題ありませんが、Rや他のほとんどの言語では、「haversine式と同じ結果を与える式」の基準が満たされるかどうかは議論の余地があります。
反時計回りを回すの

@ceasedtoturncounterclockwisほとんどをベースRに含めるために含めました。任意の精度の浮動小数点ライブラリを使用すると効果が軽減されると思います。
ジュゼッペ

はい、または...半正矢式、言う、のような安定した式を使用して
ターンに中止することcounterclockwis


5

JavaScript(ES7)、90バイト

注:はるかに短いソリューションについては、@OlivierGrégoireの投稿を参照してください

TFeldの答えの直接の移植。ラジアン単位で入力します。

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

オンラインでお試しください!

悪名高いwith()85バイトを使用して

6バイトを節約してくれた@ l4m2に感謝

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

オンラインでお試しください!


2
できることwith(Math)f=(a,b,c,d)=>3474*asin((sin((c-a)/2)**2+cos(c)*cos(a)*sin((d-b)/2)**2)**.5)
l4m2

@milesの短いアルゴリズムを使用した77バイト(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
@Neilの短いアルゴリズムを使用した74バイト(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バイト(a,b,c,d,C=Math.cos)=>1737*Math.acos(C(a-c)+C(a)*C(c)*(C(d-b)-1))
オリヴィエグレゴワール

@OlivierGrégoireとても素敵です。おそらく新しい回答として投稿する必要があります。
アーナウルド

5

APL(Dyalog Unicode)40 35 バイトSBCS

匿名の暗黙関数。左引数として{ϕ₁、λ₁}を、右引数として{ϕ₂、λ₂}を取ります。

式2 r√(sin²((ϕ₁-ϕ₂)2)+ cos ϕ₁ cos ϕ₂sin²((λ₁–λ₂)2))を使用します。

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

オンラインでお試しください!r関数は度をラジアンに変換します)


 対応する要素を連結します。{{ϕ₁、ϕ₂}、{λ{、λ₂}}

 最初のものを選んでください。{ϕ₁、ϕ₂}

 それから

2×.○ それらの余弦の積; cos ϕ₁ cos ϕ₂
点灯。ドット「積」ですが、乗算の代わりにトリガー関数セレクター(2はコサイン)、プラスの代わりに時間

1, その前に1を追加します。{1、cos ϕ₁ cos ϕ₂}

( 次の関数を{ϕ₁、λϕ}および{ϕ₂、λ₂}に適用した結果を乗算します。

- それらの違い; {ϕ₁-ϕ₂、λ₁-λ₂}

2÷⍨ それを2で割ります。{ (ϕ₁-ϕ₂)2(λ₁-λ₂)2 }

1○ そのサイン; {sin((ϕ₁-ϕ₂)2)、sin((λ₁-λ₂)2)}

×⍨ それを二乗する(点灯。自己乗算)。{sin²((ϕ₁-ϕ₂)2)、sin²((λ₁-λ₂)2)}

{sin²((ϕ₁-ϕ₂)2)、cos ϕ₁ cos ϕ₂sin²((λ₁-λ₂)2)}

1⊥ その合計(lit. base-1で評価); sin²((ϕ₁-ϕ₂)2)+ cos ϕ₁ cos ϕ₂sin²((λ₁-λ₂)2

.5*⍨ その平方根(それを半分のべき乗する)

¯1○ その逆正弦

3474× これを掛けます


度単位の入力を許可する関数は次のとおりです。

○÷∘180

÷180 引数を180で割った値

 πを掛ける


4

Python 2、95バイト

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*

オンラインでお試しください!

ラジアン単位で入力します。


I / Oがスラックされる前の古いバージョン:入力を整数度として受け取り、丸められたdistを返します

Python 2、135バイト

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

オンラインでお試しください!


あなたがドロップすることができますintし、round小数が出力として許可されているので、ラジアンなどの入力も許可されているので、あなたはまた、ラジアンへの変換を回避することができます
mdahmoune

@mdahmoune、ありがとう、更新
TFeld

3

Java 8、113 92 88 82バイト

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

入力a,b,c,dϕ1,λ1,ϕ2,λ2ラジアン単位です。

@milesの短い式を使用して-21バイト。@OlivierGrégoreの
おかげで-4バイトになりました。なぜなら、とを直接使用する代わりに、すべてのas でまだ使用しているからです。@Neilの短い式 を使用して-6バイト。{Math m=null;return ...;}Math.m.returnMath

オンラインでお試しください。

説明:

(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
「早すぎる最適化はすべての悪の根源です」!88バイト:(a,b,c,d)->1737*Math.acos(Math.sin(a)*Math.sin(c)+Math.cos(a)*Math.cos(c)*Math.cos(d-b))
オリビエグレゴワール

時期尚早の最適化はすべての悪の根源です」私はあなたが本当に正しいと思います。.ありがとう!
ケビンCruijssen

1
私はより短い定式化を見つけました:(a,b,c,d)->1737*Math.acos(Math.cos(a-c)+Math.cos(a)*Math.cos(c)*(Math.cos(d-b)-1))
ニール

(ただし、その定式化は元のWolfram言語では短くありません。)
ニール

3

Japt55 50バイト

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

必ずしも他の回答ほど正確ではありませんが、少年はこの回答を楽しんでいます。詳しく説明させてください。
ほとんどの言語では、この課題は非常に簡単ですが、Japtには、アークサインもアークコサインも組み込まれていないという不幸な性質があります。もちろん、JavascriptをJaptに埋め込むことができますが、それはFeng Shuiの反対です。

このマイナーな迷惑を克服するために私たちがしなければならないのは、おおよそのアークコサインであり、私たちは行ってもいいです!

最初の部分は、アークコサインに供給されるすべてのものです。

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.

結果は暗黙的に保存され、U後で使用されます。

その後、アークコサインの適切な近似値を見つける必要があります。私は怠け者で、数学が苦手なので、明らかにそれをブルートフォースするだけです。

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.

ジェネレーターの解像度に任意の数を使用できた可能性があり、手動テストで7!は十分に大きいが、かなり高速であることが示されました。

入力をラジアンとして受け取り、丸められていない数値を出力します。

おかげで5バイト削られた Oliverの

オンラインでお試しください!


あなたは削除することができます(ではMc(X-V。の文字コード1737はISO-8859-1ではないため、UTF-8に切り替わります。代わりに、173+に文字コードを使用でき7ます。ethproductions.github.io/japt/?v=1.4.5&code=I603&input=
オリバー

あなたはまた、削除することができ,た後ToMP:-)
オリバー

@Oliverありがとう また、エンコーディングのことも知りませんでした。それについても感謝します。
NIT

1
JavaScriptのルートに進みたい場合は、すべてをshocoで実行できることに留意してください。
オリバー



2

ゼリー 23 22  18 バイト

-4マイルのおかげで(の使用バイト{}使用しながら、それらの式を

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

結果を(浮動小数点として)返すラジアン単位の[ϕ1, ϕ2,]左と[λ1, λ2]右を受け入れる2項関数。

オンラインでお試しください!


Mine ...(aを使用して1バイトも保存しました{

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

オンラインで試す


おもしろいことに、ページを再度更新し、編集内容を表示しました。変更を表示するために新しい回答をクリックするだけでは、編集内容が更新されません。18バイトの代替は;I}ÆẠP+ÆSP${ÆA×⁽£ġ
マイル

使い方を理解したことは{あり}ませんし、彼らは私が期待することを決してしません。それは私が17で他の方法でできることを意味しませんか?!
ジョナサンアラン

多分。{そして}ちょうどモナドからダイアドを作成します。同様のビューがありますP{ -> ḷP¥。同様の状況で1バイトまたは2バイトを節約できるような何かを素早く行うために、コンポーズ(Jから)を追加するとよいかもしれませんx (P+$) y -> (P x) + (P y)
マイル

2

Mapping Toolboxを備えたMATLAB、26バイト

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

チャレンジで説明したのと同じ順序で、セル配列として4つの入力を受け取る匿名関数。

1737/180等しいため、これにより正確な結果が得られることに注意してください(月の半径が1737 kmであると仮定)9.65

Matlab R2017bでの実行例:

ここに画像の説明を入力してください


1

Python 3、79バイト

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

TIOにはgeopy.pyがありません


2
@Nit、私の理解では、質問の前に公開されているライブラリを使用することは公正なゲームであるということです。それは、MATLABのマッピングツールを使用する、または数学ライブラリを使用する他の言語を使用するようなものだと思います。
RootTwo

1

APL(Dyalog Unicode)、29 バイトSBCS

完全なプログラム。stdinに{ϕ₁、st₂}を要求し、次に{λ₁、λ₂}を要求します。標準出力に出力します。

式r acos(sin ϕ₁ sin ϕ₂ + cos(λ₂–λ₁)cos ϕ₁ cos ϕ₂)を使用します。

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

オンラインでお試しください!r関数は度をラジアンに変換します)


 {ϕ₁、ϕ₂}のプロンプト

1 2∘.○ デカルトトリガ関数アプリケーション。{{sin ϕ₁、sin ϕ₂}、{cos ϕ₁、cos ϕ₂}}

×/ 行ごとの製品。{sin ϕ₁ sin ϕ₂、cos ϕ₁ cos ϕ₂}

()×@2 2番目の要素で、次の要素を乗算します。

 {λ₁、λ₂}のプロンプト

-/ それらの違い; λ₁–λ₂

2○ その余弦。cos(λ₁–λ₂)

{sin ϕ₁ sin ϕ₂、cos(λ₁–λ₂)cos ϕ₁ cos ϕ₂}

+/ 和; sin ϕ₁ sin ϕ₂ + cos(λ₁–λ₂)cos ϕ₁ cos ϕ₂

¯2○ その余弦。cos(sin ϕ₁ sin ϕ₂ + cos(λ₁–λ₂)cos ϕ₁ cos ϕ₂)

1737× それにrを掛けます。1737 cos(sin ϕ₁ sin ϕ₂ + cos(λ₁–λ₂)cos ϕ₁ cos ϕ₂)


度単位の入力を許可する関数は次のとおりです。

○÷∘180

÷180 引数を180で割った値

 πを掛ける


1

C(gcc)100 88 65 64バイト

88→65 @ マイルの式を使用
65→64 @ マイルの式を使用

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

オンラインでお試しください!


-lmコンパイラフラグに2バイトを追加する必要があると思います。
OOBalance

@OOBalance:フラグの存在は必ずしも必要ではありません。コンパイラがシステムにインストールされた方法に依存します。
jxh

わかった。これは、私の答えであるcodegolf.stackexchange.com/a/161452/79343ありがとう。
OOBalance

@OOBalance:答えを支持しました。私も自分の解決策を提出しました。
jxh

いいね あなたのものも支持しました。
OOBalance

1

Excel、53バイト

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

@Neilの式を使用します。ラジアンで入力します。


1

ロブスター、66バイト

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

マイルの式を使用しますが、入力は度単位です。これにより、半径を乗算する前にラジアンに変換する追加のステップが追加されます。




1

SmileBASIC、60バイト

INPUT X,Y,S,T?1737*ACOS(COS(X-S)+COS(X)*COS(S)*(COS(T-Y)-1))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.