ac-library-rb 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/unittest.yml +16 -0
- data/.gitignore +11 -0
- data/.rubocop.yml +198 -0
- data/Gemfile +3 -0
- data/LICENSE +116 -0
- data/README.ja.md +56 -0
- data/README.md +41 -0
- data/Rakefile +11 -0
- data/ac-library-rb.gemspec +32 -0
- data/bin/console +8 -0
- data/bin/lock_lib.rb +27 -0
- data/bin/setup +8 -0
- data/document_en/binary_index_tree.md +3 -0
- data/document_en/convolution.md +67 -0
- data/document_en/dsu.md +132 -0
- data/document_en/fenwick_tree.md +99 -0
- data/document_en/index.md +79 -0
- data/document_en/lazy_segtree.md +141 -0
- data/document_en/math.md +104 -0
- data/document_en/max_flow.md +165 -0
- data/document_en/min_cost_flow.md +132 -0
- data/document_en/modint.md +263 -0
- data/document_en/priority_queue.md +119 -0
- data/document_en/segtree.md +134 -0
- data/document_en/string.md +106 -0
- data/document_en/two_sat.md +91 -0
- data/document_en/union_find.md +3 -0
- data/document_ja/convolution.md +64 -0
- data/document_ja/dsu.md +183 -0
- data/document_ja/fenwick_tree.md +83 -0
- data/document_ja/index.md +89 -0
- data/document_ja/lazy_segtree.md +135 -0
- data/document_ja/math.md +116 -0
- data/document_ja/max_flow.md +129 -0
- data/document_ja/min_cost_flow.md +105 -0
- data/document_ja/modint.md +349 -0
- data/document_ja/priority_queue.md +103 -0
- data/document_ja/scc.md +65 -0
- data/document_ja/segtree.md +145 -0
- data/document_ja/string.md +105 -0
- data/document_ja/two_sat.md +87 -0
- data/lib/ac-library-rb/version.rb +3 -0
- data/lib/convolution.rb +124 -0
- data/lib/core_ext/modint.rb +19 -0
- data/lib/crt.rb +52 -0
- data/lib/dsu.rb +44 -0
- data/lib/fenwick_tree.rb +48 -0
- data/lib/floor_sum.rb +21 -0
- data/lib/inv_mod.rb +26 -0
- data/lib/lazy_segtree.rb +149 -0
- data/lib/lcp_array.rb +23 -0
- data/lib/max_flow.rb +137 -0
- data/lib/min_cost_flow.rb +143 -0
- data/lib/modint.rb +170 -0
- data/lib/pow_mod.rb +13 -0
- data/lib/priority_queue.rb +89 -0
- data/lib/scc.rb +77 -0
- data/lib/segtree.rb +140 -0
- data/lib/suffix_array.rb +128 -0
- data/lib/two_sat.rb +34 -0
- data/lib/z_algorithm.rb +32 -0
- data/lib_helpers/ac-library-rb/all.rb +22 -0
- data/lib_lock/ac-library-rb.rb +22 -0
- data/lib_lock/ac-library-rb/convolution.rb +126 -0
- data/lib_lock/ac-library-rb/core_ext/modint.rb +19 -0
- data/lib_lock/ac-library-rb/crt.rb +54 -0
- data/lib_lock/ac-library-rb/dsu.rb +46 -0
- data/lib_lock/ac-library-rb/fenwick_tree.rb +50 -0
- data/lib_lock/ac-library-rb/floor_sum.rb +23 -0
- data/lib_lock/ac-library-rb/inv_mod.rb +28 -0
- data/lib_lock/ac-library-rb/lazy_segtree.rb +151 -0
- data/lib_lock/ac-library-rb/lcp_array.rb +25 -0
- data/lib_lock/ac-library-rb/max_flow.rb +139 -0
- data/lib_lock/ac-library-rb/min_cost_flow.rb +145 -0
- data/lib_lock/ac-library-rb/modint.rb +172 -0
- data/lib_lock/ac-library-rb/pow_mod.rb +15 -0
- data/lib_lock/ac-library-rb/priority_queue.rb +91 -0
- data/lib_lock/ac-library-rb/scc.rb +79 -0
- data/lib_lock/ac-library-rb/segtree.rb +142 -0
- data/lib_lock/ac-library-rb/suffix_array.rb +130 -0
- data/lib_lock/ac-library-rb/two_sat.rb +36 -0
- data/lib_lock/ac-library-rb/z_algorithm.rb +34 -0
- metadata +158 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
# MinCostFlow
|
2
|
+
|
3
|
+
最小費用流問題を扱うライブラリです。
|
4
|
+
|
5
|
+
## 特異メソッド
|
6
|
+
|
7
|
+
### new(n = 0) -> MinCostFlow
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
graph = MinCostFlow.new(10)
|
11
|
+
```
|
12
|
+
|
13
|
+
n頂点0辺のグラフを作ります。
|
14
|
+
|
15
|
+
頂点の番号は、0-based indexです。
|
16
|
+
|
17
|
+
## インスタンスメソッド
|
18
|
+
|
19
|
+
### add_edge(from, to, cap, cost) -> Integer
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
graph.add_edge(0, 1, 5)
|
23
|
+
```
|
24
|
+
|
25
|
+
頂点`from`から頂点`to`への最大容量`cap`, 流量`0`の辺を追加します。
|
26
|
+
|
27
|
+
返り値は、0-based indexで何番目に追加された辺かを返します。
|
28
|
+
|
29
|
+
### flow(start, to, flow_limit = Float::MAX) -> [flow, cost]
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
(1) graph.flow(0, 3)
|
33
|
+
(2) graph.flow(0, 3, flow_limit)
|
34
|
+
```
|
35
|
+
|
36
|
+
内部はほぼ`slope`メソッドで、`slop`メソッドの返り値の最後の要素を取得しているだけ。制約・計算量は`slope`メソッドと同じ。
|
37
|
+
|
38
|
+
**エイリアス** `flow`, `min_cost_max_flow`
|
39
|
+
|
40
|
+
### slope(s, t, flow_limit = Float::MAX) -> [[flow, cost]]
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
graph.slop(0, 3)
|
44
|
+
```
|
45
|
+
|
46
|
+
**計算量** `O(F(n + m) log n)` ※ Fは流量、mは辺数
|
47
|
+
|
48
|
+
**エイリアス** `slope`, `min_cost_slope`
|
49
|
+
|
50
|
+
### get_edge(i) -> [from, to, cap, flow, cost]
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
graph.get_edge(i)
|
54
|
+
graph.edge(i)
|
55
|
+
graph[i]
|
56
|
+
```
|
57
|
+
|
58
|
+
辺の状態を返します。
|
59
|
+
|
60
|
+
**制約** `0 ≦ i < m`
|
61
|
+
|
62
|
+
**計算量** `O(1)`
|
63
|
+
|
64
|
+
### edges -> Array([from, to, cap, flow, cost])
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
graph.edges
|
68
|
+
```
|
69
|
+
|
70
|
+
全ての辺の情報を含む配列を返します。
|
71
|
+
|
72
|
+
**計算量** `O(m)` ※`m`は辺数です。
|
73
|
+
|
74
|
+
## Verified
|
75
|
+
|
76
|
+
[ALPC: E \- MinCostFlow](https://atcoder.jp/contests/practice2/tasks/practice2_e)
|
77
|
+
- [1213ms 2020/9/17](https://atcoder.jp/contests/practice2/submissions/16792967)
|
78
|
+
|
79
|
+
## 参考リンク
|
80
|
+
|
81
|
+
- 当ライブラリ
|
82
|
+
- [当ライブラリの実装コード min_cost_flow.rb](https://github.com/universato/ac-library-rb/blob/master/lib/min_cost_flow.rb)
|
83
|
+
- [当ライブラリのテストコード min_cost_flow_test.rb](https://github.com/universato/ac-library-rb/blob/master/test/min_cost_flow_test.rb)
|
84
|
+
- 本家ライブラリ
|
85
|
+
- [本家ライブラリのドキュメント mincostflow.md(GitHub)](https://github.com/atcoder/ac-library/blob/master/document_ja/mincostflow.md)
|
86
|
+
- [本家ライブラリの実装コード mincostflow.hpp(GitHub)](https://github.com/atcoder/ac-library/blob/master/atcoder/mincostflow.hpp)
|
87
|
+
- [本家ライブラリのテストコード mincostflow_test.cpp(GitHub)](https://github.com/atcoder/ac-library/blob/master/test/unittest/mincostflow_test.cpp)
|
88
|
+
|
89
|
+
## Q&A
|
90
|
+
|
91
|
+
### エイリアスの意図は
|
92
|
+
|
93
|
+
本家ライブラリの最小費用流の方のメソッド名が長いので、エイリアスを持たせています。本家ライブラリの最大流の方のメソッド名は短いので、不思議です。
|
94
|
+
|
95
|
+
### `Float::INFINITY`ではなく、`Float::MAX`を使う意図とは
|
96
|
+
|
97
|
+
特に検証してないので、何の数値がいいのか検証したいです。
|
98
|
+
|
99
|
+
`Integer`クラスでも良いよいな気がしました。
|
100
|
+
|
101
|
+
### 辺にStructは使わないの
|
102
|
+
|
103
|
+
Structを使った方がコードがスリムになって上級者ぽくもあり見栄えは良いです。
|
104
|
+
|
105
|
+
しかし、計測した結果、Strucだと遅かったので使用していません。
|
@@ -0,0 +1,349 @@
|
|
1
|
+
# ModInt
|
2
|
+
|
3
|
+
答えをある数で割ったあまりを出力する問題で使えるライブラリです。
|
4
|
+
|
5
|
+
計算の際に自動であまりを取るため、ミスを減らすことができます。
|
6
|
+
|
7
|
+
## 注意
|
8
|
+
|
9
|
+
本ライブラリModIntの使用により、**実行時間が遅く**なる可能性があります。
|
10
|
+
|
11
|
+
使用にあたり注意してください。
|
12
|
+
|
13
|
+
## 使用例
|
14
|
+
|
15
|
+
最初に`ModInt.set_mod`か`ModInt.mod =`で、剰余の法を設定して下さい。
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
ModInt.set_mod(11)
|
19
|
+
ModInt.mod #=> 11
|
20
|
+
|
21
|
+
a = ModInt(10)
|
22
|
+
b = 3.to_m
|
23
|
+
|
24
|
+
p -b # 8 mod 11
|
25
|
+
|
26
|
+
p a + b # 2 mod 11
|
27
|
+
p 1 + a # 0 mod 11
|
28
|
+
p a - b # 7 mod 11
|
29
|
+
p b - a # 4 mod 11
|
30
|
+
|
31
|
+
p a * b # 8 mod 11
|
32
|
+
p b.inv # 4 mod 11
|
33
|
+
|
34
|
+
p a / b # 7 mod 11
|
35
|
+
|
36
|
+
a += b
|
37
|
+
p a # 2 mod 11
|
38
|
+
a -= b
|
39
|
+
p a # 10 mod 11
|
40
|
+
a *= b
|
41
|
+
p a # 8 mod 11
|
42
|
+
a /= b
|
43
|
+
p a # 10 mod 11
|
44
|
+
|
45
|
+
p ModInt(2)**4 # 5 mod 11
|
46
|
+
|
47
|
+
puts a #=> 10
|
48
|
+
|
49
|
+
p ModInt.raw(3) #=> 3 mod 11
|
50
|
+
```
|
51
|
+
|
52
|
+
## putsとpによる出力
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
ModInt.mod = 11
|
56
|
+
a = 12.to_m
|
57
|
+
|
58
|
+
puts a #=> 1
|
59
|
+
p a #=> 1 mod 11
|
60
|
+
```
|
61
|
+
|
62
|
+
`ModInt`は、`to_s`, `inspect`を定義しています。
|
63
|
+
|
64
|
+
これにより、`puts`は`to_s`, `p`は`inspect`を内部で使っているため、出力が変更されています。
|
65
|
+
|
66
|
+
`puts`メソッドは、`Integer`の出力と変わらない振る舞いで便利ですが、逆にいえば見分けはつかないので注意して下さい。
|
67
|
+
|
68
|
+
## 特異メソッド
|
69
|
+
|
70
|
+
### new(val = 0) -> ModInt
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
a = ModInt.new(10)
|
74
|
+
b = ModInt(3)
|
75
|
+
```
|
76
|
+
|
77
|
+
`new`を使わないシンタックスシュガー`Kernel#ModInt`を用意しています。
|
78
|
+
|
79
|
+
#### 【参考】Integer#to_m, String#to_m
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
5.to_m
|
83
|
+
'2'.to_m
|
84
|
+
```
|
85
|
+
|
86
|
+
`Integer`、`String`インスタンスを`ModInt`に変換します。
|
87
|
+
|
88
|
+
**エイリアス** `to_modint`, `to_m`
|
89
|
+
|
90
|
+
### set_mod(mod)
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
ModInt.set_mod(10**9 + 7)
|
94
|
+
ModInt.mod = 10**9 + 7
|
95
|
+
```
|
96
|
+
|
97
|
+
最初にこのメソッドを用い、modを設定して下さい。
|
98
|
+
|
99
|
+
これは、内部の実装として、グローバル変数`$_mod`に設定しています。
|
100
|
+
|
101
|
+
また、内部では`$_mod`が素数かどうかを判定して, グローバル変数`$_mod_is_prime`に真偽値を代入します。
|
102
|
+
|
103
|
+
なお、このメソッドの返り値を使う機会は少ないと思いますが、`mod=`の方は、代入した引数をそのまま返すのに対し、`set_mod`は`[mod, mod.prime?]`を返します。
|
104
|
+
|
105
|
+
**エイリアス** `set_mod`, `mod=`
|
106
|
+
|
107
|
+
### mod -> Integer
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
ModInt.mod
|
111
|
+
```
|
112
|
+
modを返します。
|
113
|
+
|
114
|
+
これは、内部の実装として、グローバル変数`$_mod`を返します。
|
115
|
+
|
116
|
+
### raw(val) -> ModInt
|
117
|
+
|
118
|
+
```ruby
|
119
|
+
ModInt.raw(2, 11) # 2 mod 11
|
120
|
+
```
|
121
|
+
|
122
|
+
`val`に対してmodを取らずに、ModIntを返します。
|
123
|
+
|
124
|
+
定数倍高速化のための、コンストラクタです。
|
125
|
+
|
126
|
+
`val`が`0`以上で`mod`を超えないことが保証される場合、こちらで`ModInt`を生成した方が高速です。
|
127
|
+
|
128
|
+
## インスタンスメソッド
|
129
|
+
|
130
|
+
### val -> Integer
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
ModInt.mod = 11
|
134
|
+
m = 12.to_m # 1 mod 11
|
135
|
+
n = -1.to_m # 10 mod 11
|
136
|
+
|
137
|
+
p i = m.val #=> 1
|
138
|
+
p j = n.to_i #=> 10
|
139
|
+
```
|
140
|
+
|
141
|
+
ModIntクラスのインスタンスから、本体の値を返します。
|
142
|
+
|
143
|
+
内部の実装として、`@val`を返しています。
|
144
|
+
|
145
|
+
`integer`に変換するときに、使用してください。
|
146
|
+
|
147
|
+
**エイリアス** `val`, `to_i`
|
148
|
+
|
149
|
+
#### エイリアスについての補足
|
150
|
+
|
151
|
+
`val`と`to_i`は、`ModInt`のインスタンスメソッドとしてはエイリアスで違いはありません。しかし、`Integer`クラスにも`to_i`メソッドがあるため`to_i`の方が柔軟性がありRubyらしいです。内部実装でもどちらが引数であってもいいように`to_i`が使われています。なお、`val`は、本家の関数名であり、内部実装のインスタンス変数名`@val`です。
|
152
|
+
|
153
|
+
### inv -> ModInt
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
ModInt.mod = 11
|
157
|
+
m = 3.to_m
|
158
|
+
|
159
|
+
p m.inv #=> 4 mod 11
|
160
|
+
```
|
161
|
+
|
162
|
+
`xy ≡ 1`なる`y`を返します。
|
163
|
+
|
164
|
+
つまり、モジュラ逆数を返します。
|
165
|
+
|
166
|
+
### pow(other) -> ModInt
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
ModInt.mod = 11
|
170
|
+
m = 2.to_m
|
171
|
+
|
172
|
+
p m**4 #=> 5 mod 11
|
173
|
+
p m.pow(4) #=> 5 mod 11
|
174
|
+
```
|
175
|
+
|
176
|
+
引数は`Integer`のみです。
|
177
|
+
|
178
|
+
### 各種演算
|
179
|
+
|
180
|
+
`Integer`クラスと同じように、`ModInt`同士、`Integer`と`ModInt`で四則演算などができます。
|
181
|
+
詳しくは、使用例のところを見てください。
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
ModInt.mod = 11
|
185
|
+
|
186
|
+
p 5.to_m + 7.to_m #=> 1 mod 11
|
187
|
+
p 0 + -1.to_m #=> 10 mod 11
|
188
|
+
p -1.to_m + 0 #=> 10 mod 11
|
189
|
+
|
190
|
+
p 12.to_m == 23.to_m #=> true
|
191
|
+
p 12.to_m == 1 #=> true
|
192
|
+
```
|
193
|
+
|
194
|
+
#### 【注意】IntegerとModIntの比較方法
|
195
|
+
|
196
|
+
`Integer`と`ModInt`は`==`, `!=`による比較ができますが、本家ACLと一部の挙動が異なっています。
|
197
|
+
|
198
|
+
比較する`Integer`は[0, mod)の範囲では真偽値を返しますが、それ以外の範囲の場合は必ず`false`を返します。本ライブラリは[0, mod)の範囲で制約がありますが、本家ライブラリは制約がないので、この点で異なります。
|
199
|
+
|
200
|
+
## Verified
|
201
|
+
|
202
|
+
- [ABC156: D \- Bouquet](https://atcoder.jp/contests/abc156/tasks/abc156_d) 2020/2/22開催
|
203
|
+
- [ACコード 138ms 2020/10/5](https://atcoder.jp/contests/abc156/submissions/17205940)
|
204
|
+
- [ARC009: C \- 高橋君、24歳](https://atcoder.jp/contests/arc009/tasks/arc009_3) 2012/10/20開催
|
205
|
+
- [ACコード 1075ms 2020/10/5](https://atcoder.jp/contests/arc009/submissions/17206081)
|
206
|
+
- [ACコード 901ms 2020/10/5](https://atcoder.jp/contests/arc009/submissions/17208378)
|
207
|
+
|
208
|
+
## 高速化Tips
|
209
|
+
|
210
|
+
`+`, `-`, `*`, `/`のメソッドは、それぞれ内部で`dup`で複製させたものに対して`add!`, `sub!`, `mul!`, `div!`のメソッドを用いています。レシーバの`ModInt`を破壊的に変更してもいいときは、こちらのメソッドを用いた方が定数倍ベースで速いかもしれません。
|
211
|
+
|
212
|
+
## 参考リンク
|
213
|
+
|
214
|
+
- 当ライブラリ
|
215
|
+
- [当ライブラリのコード modint.rb(GitHub)](https://github.com/universato/ac-library-rb/blob/master/lib/modint.rb)
|
216
|
+
- [当ライブラリのコード modint_test.rb(GitHub)](https://github.com/universato/ac-library-rb/blob/master/lib/modint.rb)
|
217
|
+
- 本家ライブラリ
|
218
|
+
- [本家の実装コード modint.hpp(GitHub)](https://github.com/atcoder/ac-library/blob/master/atcoder/modint.hpp)
|
219
|
+
- [本家のテストコード modint_test.cpp(GitHub)](https://github.com/atcoder/ac-library/blob/master/atcoder/modint.hpp)
|
220
|
+
- [本家のドキュメント modint.md(GitHub)](https://github.com/atcoder/ac-library/blob/master/document_ja/modint.md)
|
221
|
+
- Rubyリファレンスマニュアル
|
222
|
+
- [class Numeric \(Ruby 2\.7\.0 リファレンスマニュアル\)](https://docs.ruby-lang.org/ja/latest/class/Numeric.html)
|
223
|
+
- その他
|
224
|
+
- [modint 構造体を使ってみませんか? \(C\+\+\) \- noshi91のメモ](https://noshi91.hatenablog.com/entry/2019/03/31/174006)(2019/3/31)
|
225
|
+
- [Pythonでmodintを実装してみた \- Qiita](https://qiita.com/wotsushi/items/c936838df992b706084c)(2019/4/1)
|
226
|
+
- [C#版のModIntのドキュメント](https://github.com/key-moon/ac-library-cs/blob/master/document_ja/modint.md)
|
227
|
+
|
228
|
+
|
229
|
+
## Q&A
|
230
|
+
|
231
|
+
### 実行時間が遅くなる可能性があるのに、何故入れるのか
|
232
|
+
|
233
|
+
- 本家ライブラリの再現。
|
234
|
+
- コードの本質的な部分への再現
|
235
|
+
- 実際どれぐらい遅いのか計測するため。ベンチマークとして。
|
236
|
+
- 利用者を増やして需要を確かめ、Ruby本体に入れるように訴えたい。
|
237
|
+
|
238
|
+
### ModIntのメリット
|
239
|
+
|
240
|
+
Rubyは、C言語/C++と異なり、次のような特徴があります。
|
241
|
+
|
242
|
+
- 負数を正数で割っても正数を返す定義
|
243
|
+
- 多倍長整数で、オーバーフローしない(※数が大きすぎると計算は遅くなります)
|
244
|
+
|
245
|
+
そのため、C言語/C++に比べるとModIntを使うメリットは薄れる部分もありますが、
|
246
|
+
|
247
|
+
- 可読性の向上
|
248
|
+
- Modの取り忘れを気にする必要がなくなる
|
249
|
+
|
250
|
+
などのメリットがあります。
|
251
|
+
|
252
|
+
### グローバル変数を使う意図は
|
253
|
+
|
254
|
+
`$_mod`や`$_mod_is_prime`というグローバル変数を使用しています。
|
255
|
+
|
256
|
+
特に実務などで、グローバル変数は忌避すべきものとされています。
|
257
|
+
|
258
|
+
しかし、クラス変数は、インスタンス変数に比べアクセスするのに時間がかかるようで、全てのそれぞれのModIntインスタンス変数`@mod`を持たせるよりも遅くなることがありました。
|
259
|
+
|
260
|
+
そのため、総合的に1番実行時間が速かったグローバル変数を使用しています。
|
261
|
+
|
262
|
+
インスタンス変数、クラス変数、クラスインスタンス変数、グローバル変数、定数など色々ありますが、どれがどこで遅いのか・速いのか、何が最善なのかわかっていないので、実装を変える可能性があります。
|
263
|
+
|
264
|
+
### グローバル変数が、アンダースコア始まりな理由
|
265
|
+
|
266
|
+
`$mod`はコードで書きたい人もいたので、名前衝突しないよう`$_mod`としました。
|
267
|
+
|
268
|
+
### Numericクラスから継承する意図は
|
269
|
+
|
270
|
+
Rubyの数値クラスは、`Numeric`クラスから継承する仕様で、それに合わせています。
|
271
|
+
|
272
|
+
継承してると、少しだけいいことがあります。
|
273
|
+
- `==`を定義すると、`!=`, `zero?`, `nonzero?`などのメソッドも定義される。
|
274
|
+
- ここ重要です。`==`を定義しているので、`!=`を定義しなくて済んでいます。
|
275
|
+
- `*`を定義すると、`abs2`メソッドも定義される。
|
276
|
+
- `finite?`, `real`, `real?`,`imag`, が使えるようになる。
|
277
|
+
- `is_a?(Numeric)`で`true`を返し数値のクラスだとわかる。
|
278
|
+
|
279
|
+
### Integerクラスから継承しない理由
|
280
|
+
|
281
|
+
`Integer`などの数値クラスでは`Integer.new(i)`のように書けないように`new`メソッドが封じられていて、うまい継承方法がわかりませんでした。
|
282
|
+
また、そもそも`Integer`と割り算などの挙動が違うため、`Integer`から継承すべきではないという意見もありました。`ModInt`は大小の比較などもすべきではないです。。
|
283
|
+
|
284
|
+
### add!と!がついている理由
|
285
|
+
|
286
|
+
Rubyだと!付きメソッドが破壊的メソッドが多いから、本ライブラリでもそうしました。`+`に`add`のエイリアスをつけるという案もありましたが、そのようなエイリアスがあっても使う人はほぼいないと考え保留にしました。
|
287
|
+
|
288
|
+
### primeライブラリのprime?を使わない理由
|
289
|
+
|
290
|
+
Ruby本体の`prime`ライブラリにある`prime?`を使用せず、本家ライブラリの`is_prime`関数に合わせて`ModInt.prime?(k)`を実装しています。こちらの方が速いようです。「Ruby本体の`prime`ライブラリは計測などの目的であり高速化する必要はない」旨をRubyコミッターの方がruby-jpで発言していた記憶です。
|
291
|
+
|
292
|
+
### powメソッドの引数がIntegerで、ModIntが取れない理由
|
293
|
+
|
294
|
+
`ModInt#pow`の引数は、`Integer`のみとしています。
|
295
|
+
|
296
|
+
しかし、`ModInt`も許容すれば、コードがスッキリする可能性もあると思いますが、理論的に`Integer`のみが来るはずと考えるためです。間違った形で`ModInt`を引数にとれてしまうとバグが起きたときに気がつきにくいため、封印しています。
|
297
|
+
|
298
|
+
### ModIntの大小比較やRangeが取れない理由
|
299
|
+
|
300
|
+
コードがスッキリする可能性もあると思いますが、理論的に正しくないと考えるためです。間違った形で`ModInt`が大小比較できてしまうと、バグが起きたときに気がつきにくいため、封印しています。
|
301
|
+
|
302
|
+
### RubyならRefinementsでModIntを作れるのでは
|
303
|
+
|
304
|
+
それもいいかもしれないです。
|
305
|
+
|
306
|
+
### ModIntのコンストラクタまわりの由来など
|
307
|
+
|
308
|
+
#### ModInt(val) -> ModInt
|
309
|
+
|
310
|
+
`Kernel#Integer`, `Kernel#Float`, `Kernel#Rational`に準じて、`Kernel#ModInt`を作っています。
|
311
|
+
|
312
|
+
```ruby
|
313
|
+
ModInt.mod = 11
|
314
|
+
|
315
|
+
m = ModInt(5)
|
316
|
+
```
|
317
|
+
|
318
|
+
#### ModInt.raw(val)
|
319
|
+
|
320
|
+
`raw`の由来は本家がそうしてたからです。
|
321
|
+
|
322
|
+
#### to_m
|
323
|
+
|
324
|
+
Rubyの`to_i`, `to_f`などに準じています。
|
325
|
+
|
326
|
+
|
327
|
+
## 本家ライブラリとの違い
|
328
|
+
|
329
|
+
### rhsという変数名
|
330
|
+
|
331
|
+
右辺(right-hand side)の意味で`rhs`という変数名が使われていましたが、馴染みがなくRubyでは`other`が一般的であるため`other`に変更しています。
|
332
|
+
|
333
|
+
```ruby
|
334
|
+
def ==(other)
|
335
|
+
@val == other.to_i
|
336
|
+
end
|
337
|
+
```
|
338
|
+
|
339
|
+
### コンストラクタは、true/false未対応
|
340
|
+
|
341
|
+
本家C++ライブラリの実装では、真偽値からmodint型の0, 1を作れるらしいです。
|
342
|
+
|
343
|
+
しかし、本ライブラリは、下記の理由から、対応しません。
|
344
|
+
|
345
|
+
- 定数倍高速化
|
346
|
+
- Rubyの他の数値型は、true/falseから直接変換できない。
|
347
|
+
- Rubyの偽扱いのfaltyはfalse/nilのみであり、コンストラクタだけ対応しても変な印象を受ける。
|
348
|
+
- Ruby中心に使っている人には馴染みがなく使う人が少なそう。
|
349
|
+
- 使う機会もあまりなさそう。
|