## 2020年5月5日火曜日

### Go - 状態と振る舞い - Goにはクラスがないけれど - 惑星、体積による平均半径、火星、地球、着地点、2点間の距離、メソッド

コード

package main

import (
"fmt"
"math"
)

type coordinate struct {
d, m, s float64
h       rune
}

func (c coordinate) decimal() float64 {
sign := 1.0
switch c.h {
case 'S', 'W', 's', 'w':
sign = -1
}
return sign * (c.d + c.m/60 + c.s/3600)
}

type location struct {
lat, long float64
}

func newLocation(lat, long coordinate) location {
return location{lat.decimal(), long.decimal()}
}

type world struct {
}

func (w world) distance(p1, p2 location) float64 {
s1, s2 := math.Sincos(rad(p1.lat))
c1, c2 := math.Sincos(rad(p2.lat))
clong := math.Cos(rad(p1.long - p2.long))
return w.radius * math.Acos(s1*s2+c1*c2*clong)
}
func rad(f float64) float64 {
return f * math.Pi / 180
}

type landingPoint struct {
name string
loc  location
}

func main() {
mars := world{radius: 3389.5}
landingPoints := []landingPoint{
landingPoint{
"Columbia Memorial Station",
newLocation(
coordinate{14, 34, 6.2, 's'},
coordinate{175, 28, 21.5, 'e'},
),
},
landingPoint{
"Challenger Memorial Station",
newLocation(
coordinate{1, 56, 46.3, 's'},
coordinate{354, 28, 24.2, 'e'},
),
},
landingPoint{
newLocation(
coordinate{4, 35, 22.2, 's'},
coordinate{137, 26, 30.1, 'e'},
),
},
landingPoint{
"Elysium Planitia",
newLocation(
coordinate{4, 30, 0, 'n'},
coordinate{135, 54, 0, 'e'},
),
},
}
var (
minDist, maxDist   float64
minNames, maxNames [2]string
)
for i, lp1 := range landingPoints {
for j := i + 1; j < len(landingPoints); j++ {
lp2 := landingPoints[j]
distance := mars.distance(lp1.loc, lp2.loc)
fmt.Printf("%v - %v 距離 %.2fkm\n",
lp1.name, lp2.name, distance)
if minDist == 0 || distance < minDist {
minDist = distance
minNames[0] = lp1.name
minNames[1] = lp2.name
} else if distance > maxDist {
maxDist = distance
maxNames[0] = lp1.name
maxNames[1] = lp2.name
}
}
}
fmt.Printf("最も近接している着地点は%vと%v。\n", minNames[0], minNames[1])
fmt.Printf("最も離れている2点は%vと%v。\n", maxNames[0], maxNames[1])

earth := world{6371.0008}
london := newLocation(
coordinate{51, 30, 0, 'n'},
coordinate{0, 8, 0, 'w'},
)
paris := newLocation(
coordinate{48, 51, 0, 'n'},
coordinate{2, 21, 0, 'e'},
)
fmt.Printf("英国のロンドンからフランスのパリまでの距離は%.2fkm。\n",
earth.distance(london, paris))
mountSharp := newLocation(
coordinate{5, 4, 48, 's'},
coordinate{137, 51, 0, 'e'},
)
olympusMons := newLocation(
coordinate{18, 39, 0, 'n'},
coordinate{226, 12, 0, 'e'},
)
fmt.Printf("火星のシャープ山(アイオリス山)からオリンポス山までの距離は%.2fkm。\n",
mars.distance(mountSharp, olympusMons))
}

% go run ./distance.go
Columbia Memorial Station - Challenger Memorial Station 距離 6039.66km
Columbia Memorial Station - Bradbury Landing 距離 6379.28km
Columbia Memorial Station - Elysium Planitia 距離 5948.55km
Challenger Memorial Station - Bradbury Landing 距離 5223.43km
Challenger Memorial Station - Elysium Planitia 距離 5647.02km
Bradbury Landing - Elysium Planitia 距離 5329.54km

%