頭と尻尾はくれてやる!

iOSアプリなどの開発日記です


最小二乗法で近似曲線/平面を得る(Swift)

以前(Objective-Cを使ってた頃)n次の近似曲線を得るためガウスジョルダン法で解く、というのをやったことがあった。

Swiftで最小二乗平面を得たいので調べてみた(※1)ら「あー、これもガウスジョルダン法でいい奴だよな?」と思い(実は思い違いだった)、Objective-Cの関数をSwiftに書き直した。

元はn次の近似曲線を得ていたので、それができているのを確認するサンプルが一つ。

もう一つは今回メインの、空間内の複数の点に対する最小二乗平面を得るというサンプル。

YamaguchiTatsuya/ApproximateCurveAndPlane: Sample code to calculate approximate curve and plane using Least squares method and Gauss-Jordan elimination in Swift, macOS
↑GitHubにアップしたそれらのサンプルコード。
macOSアプリで1つの画面に両方のを表示させてる(プロジェクト二つ作るほどでもないし?)。

近似曲線/平面を得た実行結果のスクショ
↑スクショはこんな感じ。左が近似曲線を描いたNSViewで右は最小二乗平面(を意味するたくさんの小さい点)を描いたSceneKitのview(なのでマウスで視点を動かせる)。


最小二乗平面はガウスジョルダン法でもいいけど、未知数3個に式が3つの連立方程式なので単に逆行列(simd_float4x4までは逆行列を得る関数がある)を作ってかけてやればいい、ということに後で気付きました、、、


※1 参考ページ
[数学] 最小二乗平面をプログラムで求める - Qiita



macOS 10.15.3 Catalina
Xcode 11.3.1
Swift 5.1.3
スポンサーサイト






ポケモンGOの相性表から見る有利/不利なわざのタイプ

ポケモンGOの相性表から見る有利/不利なポケモンのタイプ
↑この続き。

ポケモンのわざタイプ相性表
↑相性表(公式ページより)。

前記事と同じようにそれじゃあ有利/不利なわざのタイプだってあるんじゃないの?ということで計算してみました。

あるタイプのわざで、ポケモンのタイプ171パターン(18+18x17/2)に攻撃する場合、ダメージにかかる係数の平均を計算したものです。

結果は以下の通りです。

1) じめん 1.173
2) いわ 1.134
3) こおり 1.091
4) ほのお 1.091
5) みず 1.068
6) フェアリー 1.068
7) ひこう 1.068
8) かくとう 1.047
9) はがね 1.027
10) ゴースト 1.019
11) あく 1.005
12) エスパー 0.979
13) ドラゴン 0.957
14) でんき 0.940
15) くさ 0.909
16) むし 0.909
17) どく 0.902
18) ノーマル 0.860

複合タイプの場合、現在のところポケモンが1種も存在しない場合があるのでそれを抜いて再度計算してみると以下のようになりました。
計算時のデータ数はどれも108です(171-63 =108パターン)

1) こおり 1.120
2) いわ 1.119
3) ほのお 1.110
4) じめん 1.095
5) ひこう 1.074
6) フェアリー 1.057
7) みず 1.055
8) ゴースト 1.043
9) かくとう 1.038
10) あく 1.013
11) はがね 1.002
12) でんき 0.999
13) ドラゴン 0.956
14) むし 0.944
15) エスパー 0.943
16) くさ 0.934
17) どく 0.879
18) ノーマル 0.860

そういえば、前記事ではこおりタイプって守りが弱かった(単独ではワーストだし)けど、こおりわざはダメージ大きいということでバランスさせてるのでしょうか?

ノーマルわざに比べこおりわざを延々と使い続ければ与えるダメージは3割増!というのはあくまで計算上であり、相手も不利なら逃げますからね。


ポケモンGOの相性表から見る有利/不利なポケモンのタイプ

ポケモンGOで2つのタイプを持つポケモンが存在しないパターンはあるのか?
↑この続き。


ポケモンのわざタイプ相性表
↑相性表(公式ページより)。

相性表を眺めているとタイプの有利/不利、わざの有利/不利なんてのがあるのかな?と思いません?例えばでんきタイプはじめんわざに対してだけ不利ですよね。じゃあでんきタイプ使えばいいんじゃないの?!とか。
どれか二つのタイプには実はすごいお得なのがいるんじゃないの?!とか

そんなわけで計算してみました。

攻撃のわざタイプが均等に登場すると仮定すれば期待値のように係数を計算することができます。
先ほどのでんきタイプだと全18タイプのわざに対し、等倍(1.0)が14個、攻撃側が有利なのが1つ(1.6x1)、守備側が有利なのが3個(0.625x3)なので
(1.0x14 + 1.6x1 + 0.625x3)/18 = 0.971 となります。

ちなみにこの有利/不利の係数はダメージの計算式に登場する値で、じめんわざがでんきタイプに与えるダメージを計算する時に表ではマルになってますからx1.6とかかってきます。
つまり、ここではどのポケモンのタイプ(の組み合わせ)が守りが固いのか?ということなので値は小さい方がダメージが少なくなる=良い、というランキングになります。

計算結果(上位20個)は以下の通りです。前記事通り、あくまで今現在のものです。かっこ内に該当するタイプのポケモンを書いてます。-の場合は存在しません。

1) [はがね, フェアリー] 0.803 (クチート)
2) [ひこう, はがね] 0.819 (エアームド)
3) [ゴースト, はがね] 0.828 (-)
4) [みず, はがね] 0.832 (エンペルト)
5) [ドラゴン, はがね] 0.832 (ディアルガ)
6) [どく, はがね] 0.851 (-)
7) [はがね, -] 0.858 (-)
8) [でんき, はがね] 0.864 (レアコイル/ジバコイル/コイル)
9) [ほのお, はがね] 0.867 (ヒードラン)
10) [むし, はがね] 0.873 (アイアント/ミノマダム(ゴミのミノ)/ハッサム/フォレトス/シュバルゴ)
11) [かくとう, はがね] 0.873 (コバルオン/ルカリオ)
12) [ノーマル, はがね] 0.877 (-)
13) [じめん, はがね] 0.878 (ハガネール/アローラディグダ/ドリュウズ/アローラダグトリオ)
14) [あく, はがね] 0.890 (-)
15) [くさ, はがね] 0.899 (ナットレイ/テッシード)
16) [エスパー, はがね] 0.899 (メタグロス/メタング/ドーミラー/ドータクン/ジラーチ/ダンバル)
17) [ノーマル, ゴースト] 0.916 (-)
18) [ゴースト, フェアリー] 0.923 (-)
19) [ゴースト, あく] 0.924 (ヤミラミ/ミカルゲ)
20) [でんき, ゴースト] 0.928 (-)

↑エアームド、スーパーリーグでよく見ますね、ホントうざい(私のメンバーにはほんと厄介)。

長いので途中は省略して、ワースト20はこんな感じです。

152) [こおり, ドラゴン] 1.104 (-)
153) [かくとう, いわ] 1.108 (テラキオン)
154) [こおり, ひこう] 1.111 (フリーザー/デリバード)
155) [こおり, じめん] 1.112 (マンムー/ウリムー/イノムー)
156) [こおり, -] 1.112 (-)
157) [くさ, あく] 1.128 (ダーテング/ノクタス/コノハナ)
158) [いわ, あく] 1.128 (バンギラス)
159) [くさ, かくとう] 1.128 (ビリジオン/キノガッサ)
160) [エスパー, いわ] 1.129 (ソルロック/ルナトーン)
161) [くさ, ドラゴン] 1.131 (アローラナッシー)
162) [ノーマル, こおり] 1.132 (-)
163) [こおり, かくとう] 1.138 (-)
164) [じめん, いわ] 1.156 (ヨーギラス/イシツブテ/ゴローン/イワーク/ゴローニャ/サイドン/サナギラス/サイホーン/ドサイドン)
165) [こおり, あく] 1.157 (ニューラ/マニューラ)
166) [こおり, エスパー] 1.158 (ムチュール/ルージュラ)
167) [くさ, エスパー] 1.162 (ナッシー/セレビィ/タマタマ)
168) [くさ, むし] 1.176 (パラス/ミノマダム(くさきのミノ)/パラセクト)
169) [こおり, むし] 1.178 (-)
170) [くさ, こおり] 1.203 (ユキカブリ/ユキノオー)
171) [こおり, いわ] 1.223 (-)








ポケモンGOで2つのタイプを持つポケモンが存在しないパターンはあるのか?

ポケモンGOのGOバトルリーグをする時には印刷したわざタイプとポケモンのタイプの相性表を近くに置いてますが、、、難しいもんですねえ。時々iPhoneを放り投げたくなる時があります。

ポケモンのわざタイプ相性表
↑公式ページにある相性表。
Niantic サポート

ところでこの相性表を眺めててふと、2種類のタイプを持つポケモンの組み合わせって全てのパターンで存在してるのかな?と思い調べてみました。

ポケモンのタイプは18種類あって、そこから2種類持つ場合、全組み合わせのパターン数は18x17/2=153種類。

この組み合わせのうち存在しないパターンは63パターンでした(リストは最後に)。
あれだけポケモンがいるからほとんど網羅されてるのかと思ってたので意外に多いと感じました。

ちなみに使ったデータ内のポケモンの種類は624種類。
これは現時点(イッシュ地方のが時折追加されてる状態)での数だし、データの都合上例えばポワルンは4種、というように数えてたりもするので他の人が検証すると変わってくるかもしれないけど、まあざっくりこの程度の数。
このうち2種類のタイプを持つポケモンは296種類でした。







最後に、この2種類のタイプを持つポケモンは今のところいない、というリストを。
1) ノーマル, ほのお
2) ノーマル, くさ
3) ノーマル, でんき
4) ノーマル, こおり
5) ノーマル, かくとう
6) ノーマル, どく
7) ノーマル, じめん
8) ノーマル, むし
9) ノーマル, いわ
10) ノーマル, ゴースト
11) ノーマル, ドラゴン
12) ノーマル, はがね
13) ほのお, みず
14) ほのお, くさ
15) ほのお, でんき
16) ほのお, こおり
17) ほのお, どく
18) ほのお, エスパー
19) ほのお, むし
20) ほのお, ドラゴン
21) ほのお, フェアリー
22) みず, ゴースト
23) くさ, でんき
24) くさ, ゴースト
25) くさ, フェアリー
26) でんき, こおり
27) でんき, かくとう
28) でんき, どく
29) でんき, じめん
30) でんき, ゴースト
31) でんき, ドラゴン
32) でんき, あく
33) でんき, フェアリー
34) こおり, かくとう
35) こおり, どく
36) こおり, むし
37) こおり, いわ
38) こおり, ドラゴン
39) かくとう, じめん
40) かくとう, ひこう
41) かくとう, ゴースト
42) かくとう, ドラゴン
43) かくとう, フェアリー
44) どく, エスパー
45) どく, いわ
46) どく, ドラゴン
47) どく, はがね
48) じめん, あく
49) じめん, フェアリー
50) エスパー, むし
51) エスパー, ゴースト
52) エスパー, あく
53) むし, ドラゴン
54) むし, あく
55) むし, フェアリー
56) いわ, ゴースト
57) いわ, ドラゴン
58) いわ, フェアリー
59) ゴースト, はがね
60) ゴースト, フェアリー
61) ドラゴン, フェアリー
62) あく, はがね
63) あく, フェアリー


Swiftでarray.remove(value)と記述するextension

SwiftのArrayに入っている値を削除したい。

使えそうなメソッドは↓この辺りか。
mutating func remove(at i: Self.Index) -> Self.Element

これだと何番目のindexか自分で調べないといけない。
それは面倒なので、削除する値を直接指定して
array.remove(value)
なんて感じで記述したい。

SwiftのExtensionで実装した。
extension Array where Element: Hashable  {

mutating func remove(_ removingValue: Element) {

var removingIndex: Int? = nil

for (index, value) in self.enumerated() {
if value == removingValue {
removingIndex = index
break
}
}
if removingIndex != nil {
self.remove(at: removingIndex!)
}
}
}

funcの前にmutatingとあって返り値がない。なので
array = array.remove(value)
などと記述せずに
array.remove(value)
でOK。
ElementにHashableとすることでこれを満たす型に対して処理してくれる。

使う時はこんな感じで。
    // 1)NSColorの場合
var colors: [NSColor] = [.red, .green, .blue,]

print("---before---")
for color in colors {
print(String(describing: color))
}

colors.remove(.green)

print("---after---")
for color in colors {
print(String(describing: color))
}


// 2)整数の場合
var ints: [Int] = [2, 3, 5, 7, 11]
ints.remove(7)
print(ints)

実行した結果のスクショ

↑実行した結果。

なお、コードをたどればわかるが配列内に削除したい要素が複数あっても1つしか削除しない。自分の用途ではこれでOKだったので。



macOS 10.15.3 Catalina
Xcode 11.3.1
Swift 5.1.3




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.