Passed
Push — master ( faf331...f878c5 )
by Ken M.
01:54
created

earth_distances.distance()   A

Complexity

Conditions 4

Size

Total Lines 18
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 15
nop 2
dl 0
loc 18
rs 9.65
c 0
b 0
f 0
1
import re
2
from math import acos, cos, pi, radians, sin
3
4
5
R = 6371
6
7
8
def extract_position(position_str):
9
    items = re.search('(\d+)\D(\d+)\D(\d+)\D(\w)', position_str).groups()
10
    if 'W' in position_str or 'S' in position_str:
11
        return radians(
12
            -(int(items[0]) * 3600 + int(items[1]) * 60 + int(items[2])) / 3600.0
13
        )
14
    return radians((int(items[0]) * 3600 + int(items[1]) * 60 + int(items[2])) / 3600.0)
15
16
17
def distance(first, second):
18
    if len(first.split()) == 2:
19
        first = first.split()
20
    else:
21
        first = first.split(',')
22
    if len(second.split()) == 2:
23
        second = second.split()
24
    else:
25
        second = second.split(',')
26
    first_latitude, first_longitude, second_latitude, second_longitude = map(
27
        extract_position, first + second
28
    )
29
    direct_distance = sin(first_latitude) * sin(second_latitude) + cos(
30
        first_latitude
31
    ) * cos(second_latitude) * cos(first_longitude - second_longitude)
32
    if acos(direct_distance) == 0:
33
        return pi * R
34
    return round(R * acos(direct_distance), 1)
35
36
37
if __name__ == '__main__':
38
    # These "asserts" using only for self-checking and not necessary for
39
    # auto-testing
40
    def almost_equal(checked, correct, significant_digits=1):
41
        precision = 0.1 ** significant_digits
42
        return correct - precision < checked < correct + precision
43
44
    assert almost_equal(
45
        distance(u"51°28′48″N 0°0′0″E", u"46°12′0″N, 6°9′0″E"), 739.2
46
    ), "From Greenwich to Geneva"
47
    assert almost_equal(
48
        distance(u"90°0′0″N 0°0′0″E", u"90°0′0″S, 0°0′0″W"), 20015.1
49
    ), "From South to North"
50
    assert almost_equal(
51
        distance(u"33°51′31″S, 151°12′51″E", u"40°46′22″N 73°59′3″W"), 15990.2
52
    ), "Opera Night"
53
    distance(u"48°27′0″N,34°59′0″E", u"15°47′56″S 47°52′0″W")
54