mgmg 1.5.6 → 1.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ae7f8d4f1a701c2f96a4fddbcabdda81fad3355276a368cf7b987ee47e6bfa3
4
- data.tar.gz: 26ee4b16fa9e8a97db0245ddc1019f94b8bbb166dac3fb1812a573cfc9920538
3
+ metadata.gz: 959345a0547c379e6ea2cc55e56283b580429c6b25d2a50df0c3ac9c7b02f8db
4
+ data.tar.gz: 8832f8ad1f54c1f06c77a2c72b25631fbfa9e9f98b5fe0d48ae15c7dd15568da
5
5
  SHA512:
6
- metadata.gz: e973d0aed431aa65d45b479a3017a78c04e1d7403d8cebacc3337065c4111b382294e51d472a240a80bfea1ed9281860aaf3597225fb5da0088d50758632842c
7
- data.tar.gz: d0ea591eaa7fe9418191289468592d1b207a434fc367a0e0a8811550a7104a7b2dfc9b75df60a929c83ceeda0c4e41915451718a3a25662dd93abe8b7b500986
6
+ metadata.gz: d22e5011de865ee5a40550ca1341ae7f5c4ea696f086c95e9ce7be273cd2c4d1acbd6b676c1e87371fc1af05bfd90c1dc796d2b3076a3f5f7a01c1336bed7856
7
+ data.tar.gz: a70bd19a98d4212ff63d535be59b528d054dc4cbf981eda4bed20ef9e4dce065bc48f7aa4a15e9e6b90542872dde0c3537558557ce3ad1e4129ab174ceb84b8b
data/CHANGELOG.md CHANGED
@@ -158,6 +158,10 @@
158
158
  - `String#min_level`において,正しい答えを返さなくなったバグを修正.
159
159
 
160
160
  ## 1.5.6 2022/07/17
161
- - `String#find_lowerbound`,`String#find_upperbound`における探索刻み幅を1から1/8に変更し,コーナーケースでの精度を上昇させた.
161
+ - `Mgmg.#find_lowerbound`,`Mgmg.#find_upperbound`における探索刻み幅を1から1/8に変更し,コーナーケースでの精度を上昇させた.
162
162
  - `Enumerable#min_level`が,原料☆によるレベル制限を無視した値を返すことがあったバグを修正.
163
- - `String#find_lowerbound`や`Mgmg::IR#atk_sd` などにおいて,返り値が,分母が1の`Rational`である場合,代わりに`Integer`を返すように修正.
163
+ - `Mgmg.#find_lowerbound`や`Mgmg::IR#atk_sd` などにおいて,返り値が,分母が1の`Rational`である場合,代わりに`Integer`を返すように修正.
164
+
165
+ ## 1.5.7 2022/10/15
166
+ - 経験値上限を指定して,目標パラメータを最大化する製作Lvを返す`Mgmg::Recipe#find_max`を追加.
167
+ - `Mgmg::Recipe#search`において,解の経験値が`cut_exp`ちょうどの場合に例外となっていたバグを修正.
data/lib/mgmg/recipe.rb CHANGED
@@ -93,6 +93,10 @@ module Mgmg
93
93
  opt = temp_opt(**kw)
94
94
  @recipe.search(para, target, opt:)
95
95
  end
96
+ def find_max(max_exp, para: @para, **kw)
97
+ opt = temp_opt(**kw)
98
+ @recipe.find_max(para, max_exp, opt:)
99
+ end
96
100
  private def correct_level(s, ac, x, opt)
97
101
  if s.nil?
98
102
  if x.equal?(false)
data/lib/mgmg/search.rb CHANGED
@@ -1,3 +1,4 @@
1
+ using Mgmg::Refiner
1
2
  class String
2
3
  def smith_search(para, target, comp, opt: Mgmg::Option.new)
3
4
  opt = opt.dup.set_default(self)
@@ -55,9 +56,9 @@ class String
55
56
  opt.comp_max = comp_search(para, target, opt.smith_min, opt:)
56
57
  ret = nil
57
58
  exp = Mgmg.exp(opt.smith_min, opt.comp_max)
58
- opt.cut_exp, ret = exp, [opt.smith_min, opt.comp_max] if exp < opt.cut_exp
59
+ opt.cut_exp, ret = exp, [opt.smith_min, opt.comp_max] if exp <= opt.cut_exp
59
60
  exp = Mgmg.exp(opt.smith_max, opt.comp_min)
60
- opt.cut_exp, ret = exp, [opt.smith_max, opt.comp_min] if exp < opt.cut_exp
61
+ opt.cut_exp, ret = exp, [opt.smith_max, opt.comp_min] if ( exp < opt.cut_exp || (ret.nil? && exp==opt.cut_exp) )
61
62
  (opt.comp_min+opt.step).step(opt.comp_max-1, opt.step) do |comp|
62
63
  break if opt.cut_exp < Mgmg.exp(opt.smith_min, comp)
63
64
  smith = smith_search(para, target, comp, opt:)
@@ -71,7 +72,24 @@ class String
71
72
  end
72
73
  rescue Mgmg::SearchCutException
73
74
  end
74
- raise Mgmg::SearchCutException, "the result exceeds given cut_exp=#{opt.cut_exp}" if ret.nil?
75
+ if ret.nil?
76
+ max = opt.irep.para_call(para, *find_max(para, opt.cut_exp, opt:))
77
+ raise Mgmg::SearchCutException, "the maximum output with given cut_exp=#{opt.cut_exp.comma3} is #{max.comma3}, which does not reach given target=#{target.comma3}"
78
+ end
79
+ ret
80
+ end
81
+
82
+ def find_max(para, max_exp, opt: Mgmg::Option.new)
83
+ opt = opt.dup.set_default(self)
84
+ exp = Mgmg.exp(opt.smith_min, opt.comp_min)
85
+ raise Mgmg::SearchCutException, "the recipe requires #{exp.comma3} experiment points, which exceeds given max_exp=#{max_exp.comma3}" if max_exp < exp
86
+ ret = [Mgmg.invexp2(max_exp, opt.comp_min), opt.comp_min]
87
+ max = opt.irep.para_call(para, *ret)
88
+ (opt.comp_min+1).step(Mgmg.invexp2c(max_exp, opt.smith_min), opt.step) do |comp|
89
+ smith = Mgmg.invexp2(max_exp, comp)
90
+ cur = opt.irep.para_call(para, smith, comp)
91
+ ret, max = [smith, comp], cur if ( max < cur || ( max == cur && Mgmg.exp(smith, comp) < Mgmg.exp(*ret) ) )
92
+ end
75
93
  ret
76
94
  end
77
95
  end
@@ -138,10 +156,10 @@ module Enumerable
138
156
  opt.armor_max = armor_search(para, target, opt.smith_min, comp, opt: opt_nocut)
139
157
  ret = nil
140
158
  exp = Mgmg.exp(opt.smith_min, opt.armor_max, comp)
141
- opt.cut_exp, ret = exp, [opt.smith_min, opt.armor_max] if exp < opt.cut_exp
159
+ opt.cut_exp, ret = exp, [opt.smith_min, opt.armor_max] if exp <= opt.cut_exp
142
160
  exp2 = Mgmg.exp(opt.smith_max, opt.armor_min, comp)
143
161
  if exp2 < exp
144
- opt.cut_exp, ret = exp2, [opt.smith_max, opt.armor_min] if exp2 < opt.cut_exp
162
+ opt.cut_exp, ret = exp2, [opt.smith_max, opt.armor_min] if exp2 <= opt.cut_exp
145
163
  (opt.armor_min+1).upto(opt.armor_max-1) do |armor|
146
164
  break if opt.cut_exp < Mgmg.exp(opt.smith_min, armor, comp)
147
165
  smith = smith_search(para, target, armor, comp, opt:)
@@ -196,15 +214,16 @@ module Enumerable
196
214
  def search(para, target, opt: Mgmg::Option.new)
197
215
  opt = opt.dup.set_default(self)
198
216
  opt.comp_min = comp_search(para, target, opt.smith_max, opt.armor_max, opt:)
199
- opt.smith_max, opt.armor_max = sa_search(para, target, opt.comp_min, opt:)
200
- opt.smith_min, opt.armor_min = sa_search(para, target, opt.comp_max, opt:)
217
+ opt_nocut = opt.dup; opt_nocut.cut_exp = Float::INFINITY
218
+ opt.smith_max, opt.armor_max = sa_search(para, target, opt.comp_min, opt: opt_nocut)
219
+ opt.smith_min, opt.armor_min = sa_search(para, target, opt.comp_max, opt: opt_nocut)
201
220
  raise Mgmg::SearchCutException if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.armor_min, opt.comp_min)
202
221
  opt.comp_max = comp_search(para, target, opt.smith_min, opt.armor_min, opt:)
203
222
  ret = nil
204
223
  exp = Mgmg.exp(opt.smith_min, opt.armor_min, opt.comp_max)
205
- opt.cut_exp, ret = exp, [opt.smith_min, opt.armor_min,opt. comp_max] if exp < opt.cut_exp
224
+ opt.cut_exp, ret = exp, [opt.smith_min, opt.armor_min,opt. comp_max] if exp <= opt.cut_exp
206
225
  exp = Mgmg.exp(opt.smith_max, opt.armor_max, opt.comp_min)
207
- opt.cut_exp, ret = exp, [opt.smith_max, opt.armor_max, opt.comp_min] if exp < opt.cut_exp
226
+ opt.cut_exp, ret = exp, [opt.smith_max, opt.armor_max, opt.comp_min] if ( exp < opt.cut_exp || (ret.nil? && exp==opt.cut_exp) )
208
227
  (opt.comp_min+1).upto(opt.comp_max-1) do |comp|
209
228
  break if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.armor_min, comp)
210
229
  smith, armor = sa_search(para, target, comp, opt:)
@@ -218,14 +237,32 @@ module Enumerable
218
237
  end
219
238
  rescue Mgmg::SearchCutException
220
239
  end
221
- raise Mgmg::SearchCutException, "the result exceeds given cut_exp=#{opt.cut_exp}" if ret.nil?
240
+ if ret.nil?
241
+ max = opt.irep.para_call(para, *find_max(para, opt.cut_exp, opt:))
242
+ raise Mgmg::SearchCutException, "the maximum output with given cut_exp=#{opt.cut_exp.comma3} is #{max.comma3}, which does not reach given target=#{target.comma3}"
243
+ end
244
+ ret
245
+ end
246
+
247
+ def find_max(para, max_exp, opt: Mgmg::Option.new)
248
+ opt = opt.dup.set_default(self)
249
+ exp = Mgmg.exp(opt.smith_min, opt.armor_min, opt.comp_min)
250
+ raise Mgmg::SearchCutException, "the recipe requires #{exp.comma3} experiment points, which exceeds given max_exp=#{max_exp.comma3}" if max_exp < exp
251
+ ret = [Mgmg.invexp3(max_exp, opt.armor_min, opt.comp_min), opt.armor_min, opt.comp_min]
252
+ max = opt.irep.para_call(para, *ret)
253
+ (opt.comp_min+1).step(Mgmg.invexp3c(max_exp, opt.smith_min, opt.armor_min), opt.step) do |comp|
254
+ opt.armor_min.upto(Mgmg.invexp3(max_exp, opt.smith_min, comp)) do |armor|
255
+ smith = Mgmg.invexp3(max_exp, armor, comp)
256
+ cur = opt.irep.para_call(para, smith, armor, comp)
257
+ ret, max = [smith, armor, comp], cur if ( max < cur || ( max == cur && Mgmg.exp(smith, armor, comp) < Mgmg.exp(*ret) ) )
258
+ end
259
+ end
222
260
  ret
223
261
  end
224
262
  end
225
263
 
226
264
  module Mgmg
227
265
  Eighth = 1.quo(8)
228
- using Refiner
229
266
  module_function def find_lowerbound(a, b, para, start, term, opt_a: Option.new, opt_b: Option.new)
230
267
  if term <= start
231
268
  raise ArgumentError, "start < term is needed, (start, term) = (#{start}, #{term}) are given"
data/lib/mgmg/utils.rb CHANGED
@@ -158,10 +158,36 @@ module Mgmg
158
158
  end
159
159
  end
160
160
  module_function def invexp2(exp, comp)
161
- Math.sqrt(exp - (2*((comp-1)**2)) - 3).round + 1
161
+ ret = Math.sqrt(exp - (2*((comp-1)**2)) - 3).floor + 2
162
+ if Mgmg.exp(ret, comp) <= exp
163
+ ret
164
+ else
165
+ ret-1
166
+ end
167
+ end
168
+ module_function def invexp2c(exp, s)
169
+ ret = Math.sqrt((exp - (((s-1)**2)) - 3).quo(2)).floor + 2
170
+ if Mgmg.exp(s, ret) <= exp
171
+ ret
172
+ else
173
+ ret-1
174
+ end
162
175
  end
163
176
  module_function def invexp3(exp, sa, comp)
164
- Math.sqrt(exp - ((sa-1)**2) - (2*((comp-1)**2)) - 4).round + 1
177
+ ret = Math.sqrt(exp - ((sa-1)**2) - (2*((comp-1)**2)) - 4).floor + 2
178
+ if Mgmg.exp(ret, sa, comp) <= exp
179
+ ret
180
+ else
181
+ ret-1
182
+ end
183
+ end
184
+ module_function def invexp3c(exp, smith, armor)
185
+ ret = Math.sqrt((exp - ((smith-1)**2) - ((armor-1)**2) - 4).quo(2)).floor + 2
186
+ if Mgmg.exp(smith, armor, ret) <= exp
187
+ ret
188
+ else
189
+ ret-1
190
+ end
165
191
  end
166
192
  module_function def clear_cache
167
193
  CacheMLS.clear; Equip::Cache.clear; Equip::CacheML.clear; TPolynomial::Cache.clear; IR::Cache.clear
data/lib/mgmg/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mgmg
2
- VERSION = "1.5.6"
2
+ VERSION = "1.5.7"
3
3
  end
data/reference.md CHANGED
@@ -130,7 +130,7 @@
130
130
  `opt`は,`comp_min`,`comp_max`,`left_associative`,`reinforcement`,`irep`を使用します.
131
131
 
132
132
  ## `String#search(para, target, opt: Mgmg.option())`
133
- `c_min=comp_search(para, target, opt.smith_max, opt: opt)` から `c_max=comp_search(para, target, opt.smith_min, opt: opt)` まで,`opt.step`ずつ動かして,
133
+ 道具製作Lvを `c_min=comp_search(para, target, opt.smith_max, opt: opt)` から `c_max=comp_search(para, target, opt.smith_min, opt: opt)` まで,`opt.step`ずつ動かして,
134
134
  `smith_search`を行い,その過程で得られた最小経験値の鍛冶・防具製作Lvと道具製作Lvからなる配列を返します.
135
135
  レシピ中の,対象パラメータの種別値がすべて奇数,または全て偶数であるなら,`opt.step`を`2`にしても探索すべき範囲を網羅できます.
136
136
  その他は`String#smith_seach`と同様です.
@@ -139,12 +139,18 @@
139
139
 
140
140
  ## `Enumerable#search(para, target, opt: Mgmg.option())`
141
141
  複数装備の組について,`para`の値が`target`以上となる最小経験値の`[鍛冶Lv,防具製作Lv,道具製作Lv]`を返します.
142
- 武器のみなら防具製作Lvは`0`,防具のみなら鍛冶Lvは`0`,合成なしなら道具製作Lvは`0`となります.
142
+ 武器のみなら防具製作Lvは`-1`,防具のみなら鍛冶Lvは`-1`,合成なしなら道具製作Lvは`0`となります.
143
143
 
144
144
  `opt.smith_min`および`opt.armor_min`のデフォルト値は,武器・防具の各総重量を`opt.target_weight`で製作するのに必要な鍛冶・防具製作Lv (`self.min_level(*opt.target_weight)`)です.`opt.target_weight`には2要素からなる配列を指定しますが,整数が与えられた場合,それを2つ並べた配列と同等のものとして扱います.合計重量を指定することにはならないので注意してください.`opt.target_weight`のデフォルト値は`0`です.
145
145
 
146
146
  その他は,`String#smith_seach`と同様です.
147
147
 
148
+ ## `String#find_max(para, max_exp, opt: Mgmg.option())`
149
+ 経験値の合計が`max_exp`以下の範囲で,`para`の値が最大となる鍛冶・防具製作Lvと道具製作Lvからなる配列を返します.`para`の値が最大となる組が複数存在する場合,経験値が小さい方が優先されます.
150
+
151
+ ## `Enumerable#find_max(para, max_exp, opt: Mgmg.option())`
152
+ 複数装備の組について,経験値の合計が`max_exp`以下の範囲で,`para`の値が最大となる鍛冶Lv,防具製作Lv,道具製作Lvからなる配列を返します.`para`の値が最大となる組が複数存在する場合,経験値が小さい方が優先されます.
153
+
148
154
  ## `Mgmg.#find_lowerbound(a, b, para, start, term, opt_a: Mgmg.option(), opt_b: Mgmg.option())`
149
155
  レシピ`a`とレシピ`b`について,`para`の値を目標値以上にする最小経験値の組において,目標値`start`における優劣が逆転する目標値の下限を探索し,返します.
150
156
  返り値は`[逆転しない最大目標値, 逆転時の最小para値]`です.前者は逆転目標値の下限,後者は,目標値が前者よりも少しだけ大きいときの`para`値です.
@@ -482,6 +488,9 @@ alias として`*`があるほか`scalar(1.quo(value))`として`quo`,`/`,`s
482
488
  ## `Mgmg::Recipe#search(target, para: self.para, **kw)`
483
489
  `self.recipe.search`を呼び出して返します.注目パラメータはセットされたものを自動的に渡しますが,別のパラメータを使いたい場合,キーワード引数で指定します.その他のキーワード引数を与えた場合,オプションのうち,与えられたパラメータのみ一時的に上書きします.
484
490
 
491
+ ## `Mgmg::Recipe#find_max(max_exp, para: self.para, **kw)`
492
+ `self.recipe.find_max`を呼び出して返します.注目パラメータはセットされたものを自動的に渡しますが,別のパラメータを使いたい場合,キーワード引数で指定します.その他のキーワード引数を与えた場合,オプションのうち,与えられたパラメータのみ一時的に上書きします.
493
+
485
494
  ## `Mgmg::Recipe#min_level(w=self.option.target_weight, include_outsourcing=false)`
486
495
  `self.recipe.min_level(w, include_outsourcing)`を返します.`w`のデフォルトパラメータが`target_weight`になっている以外は`String#min_level`または`Enumerable#min_level`と同じです.
487
496
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mgmg
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.6
4
+ version: 1.5.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - KAZOON
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-07-17 00:00:00.000000000 Z
11
+ date: 2022-10-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -104,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
104
  - !ruby/object:Gem::Version
105
105
  version: '0'
106
106
  requirements: []
107
- rubygems_version: 3.3.18
107
+ rubygems_version: 3.3.23
108
108
  signing_key:
109
109
  specification_version: 4
110
110
  summary: Calculate specs of equipments of Megurimeguru, a game produced by Kou.