mgmg 1.3.1 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ae250ef7035838c1f0598c419e66259c1cde7ab692e5b5ffefcd78ab845207d
4
- data.tar.gz: 0fd5f62e8c3ac85ba990010bca631e08111b50d69fad11d782fcadfe075781fd
3
+ metadata.gz: d35a19c90c58e70a8410540581af727523ea22584580bbf5ccf3b50fd19cbe4c
4
+ data.tar.gz: ca9c6122b4d7d84389787a10ac7073e5f3f633d1c1fffab58be1ad693e3613d4
5
5
  SHA512:
6
- metadata.gz: 40bdd74efb69a024d87d265340caefd48ee90f4d3fd9d74d2a7a46fd78c6a553bc931798636b1ebc8bed8e95cfa8c6501a554c073897ac0ae9be3fdd37298466
7
- data.tar.gz: 9c32dfaf9a0d1027afd33e70562e813f7cce5a0378e0e81f806e77e3d4415ee4d779a09b7d3b122d523d9a0f8cc10af1a97da0ee3e3464440777b82efee35c48
6
+ metadata.gz: ab690d14c5d159646fa354b551eefe5a2afb7ab8c227769cdd5397262c5b810776611c3171c88af3143a96b18eac10050348c80c9b9801fc809544ec7291414d
7
+ data.tar.gz: a17fafc6c8eefdca6a137b0311f2e8ca1e44c71a8ea8a6341359ab6929d6b25228b8d0be96ef06ee29be514e0abfaa93cbc1a0f45ae1cb746175d39ad7a3207d
data/CHANGELOG.md CHANGED
@@ -30,7 +30,7 @@
30
30
  - マニュアル等の不備を修正.
31
31
 
32
32
  ## 1.0.9 2019/05/30
33
- - 丸めを無視した多項式近似(変数は製作レベル)を表す `Mgmg::TPolynomial`およびこれを生成するメソッド String#poly を追加.
33
+ - 丸めを無視した多項式近似(変数は製作レベル)を表す`Mgmg::TPolynomial`およびこれを生成するメソッド`String#poly`を追加.
34
34
 
35
35
  ## 1.0.10 2019/06/29
36
36
  - 消費エレメント量を返す`Mgmg::Equip#total_cost`を追加.
@@ -93,3 +93,9 @@
93
93
  - `Mgmg.#exp`に3引数を与えられるように修正.
94
94
  - `String#search`,`Enumerable#search`を追加.
95
95
  - `Enumerable#min_levels`,`Enumerable#min_level`,`Enumerable#min_smith`,`Enumerable#min_comp`を追加.
96
+
97
+ ## 1.3.2 2021/05/18
98
+ - `Mgmg::TPolynomial`に比較演算子を追加.
99
+ - `String#phydef_optimize`,`String#buster_optimize`を追加.
100
+ - (`Enumerable#search`から呼び出される)`Enumerable#comp_search`における最大道具製作レベルチェックが間違っていたバグを修正.
101
+ - `String#search`および`Enumerable#search`において,総経験値量が等しい組み合わせの場合,目標パラメータが大きくなる製作Lvの組み合わせを返すように修正.
data/README.md CHANGED
@@ -174,6 +174,15 @@ puts '小竜咆哮'.build
174
174
  ### `String#peff(para, smith, comp=smith, left_associative: true)`
175
175
  近似多項式における偏微分値を使用した場合の,`String#eff`と同様の値を返します.`self.poly(para, left_associative: left_associative).eff(smith, comp)`と等価です.
176
176
 
177
+ ### `String#phydef_optimize(smith=nil, comp=smith, left_associative: true, magdef_maximize: true)`
178
+ 反転物防装備の反転材の種別,素材の最適化を行い,修正したレシピを返します.
179
+ `smith`,`comp`は探索を行う製作レベルを表し,`smith`が`nil`の場合,近似多項式で最適化を行います.近似多項式では,道具製作レベルの次数が高い項の係数を最適化します.
180
+ 物防を最大化するレシピのうち,`magdef_maximize`が真なら魔防を最大化する組み合わせ,偽ならコストを最小化(≒魔防を最小化)する組み合わせを探索します.
181
+ ある範囲での全数探索を行うため,段数の多いレシピでは計算量が膨大になるほか,厳密な最適化を保証するものではなく,今後のアップデートで解が変わるような変更が入る可能性があります.
182
+
183
+ ### `String#buster_optimize(smith=nil, comp=smith, left_associative: true)`
184
+ `String#phydef_optimize`の魔力弓版で,反転材の素材の最適化を行い,修正したレシピを返します.
185
+
177
186
  ### `Mgmg::Equip`
178
187
  前述の`String#build`によって生成される装備品のクラスです.複数装備の合計値を表す「複数装備」という種別の装備品の場合もあります.以下のようなインスタンスメソッドが定義されています.
179
188
 
data/lib/mgmg.rb CHANGED
@@ -5,6 +5,7 @@ require_relative './mgmg/equip'
5
5
  require_relative './mgmg/poly'
6
6
  require_relative './mgmg/system_equip'
7
7
  require_relative './mgmg/search'
8
+ require_relative './mgmg/optimize'
8
9
 
9
10
  class String
10
11
  def min_level(w=1)
@@ -70,6 +71,12 @@ class String
70
71
  puts "with levels (#{smith}, #{comp}) yields (#{pstr}, #{built.total_cost})"
71
72
  puts " #{built}"
72
73
  end
74
+ def phydef_optimize(smith=nil, comp=smith, left_associative: true, magdef_maximize: true)
75
+ Mgmg::Optimize.phydef_optimize(self, smith, comp, left_associative: left_associative, magdef_maximize: magdef_maximize)
76
+ end
77
+ def buster_optimize(smith=nil, comp=smith, left_associative: true)
78
+ Mgmg::Optimize.buster_optimize(self, smith, comp, left_associative: left_associative)
79
+ end
73
80
  end
74
81
  module Enumerable
75
82
  def build(smith=-1, armor=smith, comp=armor.tap{armor=smith}, left_associative: true)
@@ -0,0 +1,213 @@
1
+ module Mgmg
2
+ module Optimize; end
3
+ class << Optimize
4
+ InvList = [%w|帽子 フード サンダル|.freeze, %w|宝1 骨1 木1 木2 骨2|.freeze, %w|宝1 骨1 木1|.freeze].freeze
5
+ def phydef_optimize(str, smith, comp=smith, left_associative: true, magdef_maximize: true)
6
+ best = ( smith.nil? ? [str, str.poly(:phydef), str.poly(:magdef), str.poly(:cost)] : [str, str.build(smith, comp)] )
7
+ str = Mgmg.check_string(str)
8
+ ai = 0
9
+ while str.sub!(/(帽子|フード|サンダル)\([宝木骨][12][宝木骨]1\)/){
10
+ ai += 1
11
+ "<A#{ai}>"
12
+ }; end
13
+ bi = 0
14
+ while str.sub!(/[宝木骨]1\)/){
15
+ bi += 1
16
+ "<B#{bi}>)"
17
+ }; end
18
+ skin = false
19
+ m = /([^\+]*\([^\(]+[綿皮]1\))\]*\Z/.match(str)
20
+ if m
21
+ if smith
22
+ if m[1].sub(/綿1\)/, '皮1)').build(smith).weight == m[1].sub(/皮1\)/, '綿1)').build(smith).weight
23
+ skin = true
24
+ end
25
+ else
26
+ skin = true
27
+ end
28
+ str = str.sub(/皮(1\)\]*)\Z/) do
29
+ "綿#{$1}"
30
+ end
31
+ end
32
+ a = Array.new(ai){ [0, 0, 0] }
33
+ b0 = Array.new(bi){ 0 }
34
+ while a
35
+ b = b0
36
+ while b
37
+ r = pd_apply_idx(str, a, b)
38
+ best = pd_better(best, ( smith.nil? ? [r, r.poly(:phydef), r.poly(:magdef), r.poly(:cost)] : [r, r.build(smith, comp)] ), magdef_maximize)
39
+ b = pd_next_b(b)
40
+ end
41
+ a = pd_next_a(a)
42
+ end
43
+ if skin
44
+ str = str.sub(/綿(1\)\]*)\Z/) do
45
+ "皮#{$1}"
46
+ end
47
+ a = Array.new(ai){ [0, 0, 0] }
48
+ while a
49
+ b = b0
50
+ while b
51
+ r = pd_apply_idx(str, a, b)
52
+ best = pd_better(best, ( smith.nil? ? [r, r.poly(:phydef), r.poly(:magdef), r.poly(:cost)] : [r, r.build(smith, comp)] ), magdef_maximize)
53
+ b = pd_next_b(b)
54
+ end
55
+ a = pd_next_a(a)
56
+ end
57
+ end
58
+ best[0]
59
+ end
60
+ private def pd_better(pre, cur, mag)
61
+ case pre.size
62
+ when 2
63
+ if pre[1].phydef < cur[1].phydef
64
+ return cur
65
+ elsif pre[1].phydef == cur[1].phydef
66
+ if mag
67
+ if pre[1].magdef < cur[1].magdef
68
+ return cur
69
+ elsif pre[1].magdef == cur[1].magdef
70
+ if cur[1].total_cost.sum < pre[1].total_cost.sum
71
+ return cur
72
+ end
73
+ end
74
+ else
75
+ if cur[1].comp_cost < pre[1].comp_cost
76
+ return cur
77
+ elsif cur[1].comp_cost == pre[1].comp_cost
78
+ if cur[1].total_cost.sum < pre[1].total_cost.sum
79
+ return cur
80
+ end
81
+ end
82
+ end
83
+ end
84
+ return pre
85
+ when 4
86
+ if pre[1] < cur[1]
87
+ return cur
88
+ elsif pre[1] == cur[1]
89
+ if mag
90
+ if pre[2] < cur[2]
91
+ return cur
92
+ elsif pre[2] == cur[2]
93
+ if cur[3] < pre[3]
94
+ return cur
95
+ end
96
+ end
97
+ else
98
+ if cur[3] < pre[3]
99
+ return cur
100
+ end
101
+ end
102
+ end
103
+ return pre
104
+ else
105
+ raise "Unexpected Error"
106
+ end
107
+ end
108
+ private def pd_apply_idx(str, a, b)
109
+ a.each.with_index do |aa, i|
110
+ str = str.sub("<A#{i+1}>", "#{InvList[0][aa[0]]}(#{InvList[1][aa[1]]}#{InvList[2][aa[2]]})")
111
+ end
112
+ b.each.with_index do |bb, i|
113
+ str = str.sub("<B#{i+1}>", InvList[2][bb])
114
+ end
115
+ str
116
+ end
117
+ private def pd_next_b_full(b)
118
+ 0.upto(b.length-1) do |i|
119
+ b[i] += 1
120
+ if b[i] == InvList[2].size
121
+ b[i] = 0
122
+ else
123
+ return b
124
+ end
125
+ end
126
+ nil
127
+ end
128
+ private def pd_next_b(b)
129
+ if b[0] == 0
130
+ return Array.new(b.length, 1)
131
+ end
132
+ nil
133
+ end
134
+ private def pd_next_a(a)
135
+ 0.upto(a.length-1) do |i|
136
+ 0.upto(2) do |j|
137
+ a[i][j] += 1
138
+ if a[i][j] == InvList[j].size
139
+ a[i][j] = 0
140
+ else
141
+ return a
142
+ end
143
+ end
144
+ end
145
+ nil
146
+ end
147
+
148
+ MwList = %w|綿 皮 骨 木 水|.freeze
149
+ def buster_optimize(str, smith, comp=smith, left_associative: true)
150
+ best = ( smith.nil? ? [str, str.poly(:mag_das)] : [str, str.build(smith, comp)] )
151
+ str = Mgmg.check_string(str)
152
+ ai = -1
153
+ org = nil
154
+ while str.sub!(/弓\(([骨水綿皮木][12][骨水綿皮木]1)\)/){
155
+ ai += 1
156
+ if ai == 0
157
+ org = $1.dup
158
+ end
159
+ "弓(<A#{ai}>)"
160
+ }; end
161
+ str = str.sub(/<A0>/, org)
162
+ a = Array.new(ai){ [0, 0, 0] }
163
+ while a
164
+ r = bus_apply_idx(str, a)
165
+ best = bus_better(best, ( smith.nil? ? [r, r.poly(:mag_das)] : [r, r.build(smith, comp)] ))
166
+ a = bus_next_a(a)
167
+ end
168
+ best[0]
169
+ end
170
+ private def bus_apply_idx(str, a)
171
+ a.each.with_index do |aa, i|
172
+ str = str.sub("<A#{i+1}>", "#{MwList[aa[0]]}#{aa[1]+1}#{MwList[aa[2]]}1")
173
+ end
174
+ str
175
+ end
176
+ private def bus_better(pre, cur)
177
+ if pre[1].kind_of?(Mgmg::Equip)
178
+ if pre[1].mag_das < cur[1].mag_das
179
+ return cur
180
+ elsif pre[1].mag_das == cur[1].mag_das
181
+ if cur[1].total_cost.sum < pre[1].total_cost.sum
182
+ return cur
183
+ end
184
+ end
185
+ return pre
186
+ else
187
+ if pre[1] < cur[1]
188
+ return cur
189
+ end
190
+ return pre
191
+ end
192
+ end
193
+ private def bus_next_a(a)
194
+ 0.upto(a.length-1) do |i|
195
+ [0, 2].each do |j|
196
+ a[i][j] += 1
197
+ if a[i][j] == 5
198
+ a[i][j] = 0
199
+ else
200
+ return a
201
+ end
202
+ end
203
+ a[i][1] += 1
204
+ if a[i][1] == 2
205
+ a[i][1] = 0
206
+ else
207
+ return a
208
+ end
209
+ end
210
+ nil
211
+ end
212
+ end
213
+ end
data/lib/mgmg/poly.rb CHANGED
@@ -139,10 +139,12 @@ module Mgmg
139
139
  ret
140
140
  end
141
141
  def +(other)
142
+ other = self.coerce(other)[0] unless other.kind_of?(self.class)
142
143
  mat = @mat.padd(other.mat)
143
144
  self.class.new(mat, 28, 0, 12, 12)
144
145
  end
145
146
  def -(other)
147
+ other = self.coerce(other)[0] unless other.kind_of?(self.class)
146
148
  mat = @mat.padd(other.mat.scalar(-1))
147
149
  self.class.new(mat, 28, 0, 12, 12)
148
150
  end
@@ -204,6 +206,76 @@ module Mgmg
204
206
  end
205
207
  ret.nil? ? 0 : ret
206
208
  end
209
+
210
+ def coerce(other)
211
+ [self.class.new(Mat.new(1, 1, other), 28, 0, 12, 12), self]
212
+ end
213
+ def <(other)
214
+ foo = self-other
215
+ (foo.mat.row_size-1).downto(0) do |s|
216
+ (foo.mat.col_size-1).downto(0) do |c|
217
+ bar = foo.mat.body[s][c]
218
+ if bar < 0
219
+ return true
220
+ elsif 0 < bar
221
+ return false
222
+ end
223
+ end
224
+ end
225
+ false
226
+ end
227
+ def <=(other)
228
+ foo = self-other
229
+ (foo.mat.row_size-1).downto(0) do |s|
230
+ (foo.mat.col_size-1).downto(0) do |c|
231
+ bar = foo.mat.body[s][c]
232
+ if bar < 0
233
+ return true
234
+ elsif 0 < bar
235
+ return false
236
+ end
237
+ end
238
+ end
239
+ true
240
+ end
241
+ def >(other)
242
+ foo = other-self
243
+ (foo.mat.row_size-1).downto(0) do |s|
244
+ (foo.mat.col_size-1).downto(0) do |c|
245
+ bar = foo.mat.body[s][c]
246
+ if bar < 0
247
+ return true
248
+ elsif 0 < bar
249
+ return false
250
+ end
251
+ end
252
+ end
253
+ false
254
+ end
255
+ def >=(other)
256
+ foo = other-self
257
+ (foo.mat.row_size-1).downto(0) do |s|
258
+ (foo.mat.col_size-1).downto(0) do |c|
259
+ bar = foo.mat.body[s][c]
260
+ if bar < 0
261
+ return true
262
+ elsif 0 < bar
263
+ return false
264
+ end
265
+ end
266
+ end
267
+ true
268
+ end
269
+ def ==(other)
270
+ foo = self-other
271
+ (foo.mat.row_size-1).downto(0) do |s|
272
+ (foo.mat.col_size-1).downto(0) do |c|
273
+ bar = foo.mat.body[s][c]
274
+ return false if bar != 0
275
+ end
276
+ end
277
+ true
278
+ end
207
279
  end
208
280
  class << TPolynomial
209
281
  ParamIndex = Hash.new
data/lib/mgmg/search.rb CHANGED
@@ -72,7 +72,13 @@ class String
72
72
  break if minex < Mgmg.exp(smith_min, comp)
73
73
  smith = smith_search(para, target, comp, smith_min, smith_max, left_associative: left_associative, cut_exp: [minex, cut_exp].min)
74
74
  exp = Mgmg.exp(smith, comp)
75
- minex, ret = exp, [smith, comp] if exp < minex
75
+ if exp < minex
76
+ minex, ret = exp, [smith, comp]
77
+ elsif exp == minex
78
+ if build(*ret).para_call(para) < build(smith, comp).para_call(para)
79
+ ret = [smith, comp]
80
+ end
81
+ end
76
82
  rescue Mgmg::SearchCutException
77
83
  end
78
84
  raise Mgmg::SearchCutException, "the result exceeds given cut_exp=#{cut_exp}" if cut_exp < minex
@@ -165,7 +171,13 @@ module Enumerable
165
171
  break if minex < Mgmg.exp(smith_min, armor, comp)
166
172
  smith = smith_search(para, target, armor, comp, smith_min, smith_max, left_associative: left_associative, cut_exp: [minex, cut_exp].min)
167
173
  exp = Mgmg.exp(smith, armor, comp)
168
- minex, ret = exp, [smith, armor] if exp < minex
174
+ if exp < minex
175
+ minex, ret = exp, [smith, armor]
176
+ elsif exp == minex
177
+ if build(*ret, comp).para_call(para) < build(smith, armor, comp).para_call(para)
178
+ ret = [smith, armor]
179
+ end
180
+ end
169
181
  rescue Mgmg::SearchCutException
170
182
  end
171
183
  else
@@ -173,7 +185,13 @@ module Enumerable
173
185
  break if minex < Mgmg.exp(smith, armor_min, comp)
174
186
  armor = armor_search(para, target, smith, comp, armor_min, armor_max, left_associative: left_associative, cut_exp: [minex, cut_exp].min)
175
187
  exp = Mgmg.exp(smith, armor, comp)
176
- minex, ret = exp, [smith, armor] if exp < minex
188
+ if exp < minex
189
+ minex, ret = exp, [smith, armor]
190
+ elsif exp == minex
191
+ if build(*ret, comp).para_call(para) < build(smith, armor, comp).para_call(para)
192
+ ret = [smith, armor]
193
+ end
194
+ end
177
195
  rescue Mgmg::SearchCutException
178
196
  end
179
197
  end
@@ -187,7 +205,7 @@ module Enumerable
187
205
  end
188
206
  if target <= build(smith, armor, comp_min, left_associative: left_associative).para_call(para)
189
207
  return comp_min
190
- elsif build(smith, comp_max, left_associative: left_associative).para_call(para) < target
208
+ elsif build(smith, armor, comp_max, left_associative: left_associative).para_call(para) < target
191
209
  raise ArgumentError, "given comp_max=#{comp_max} does not satisfies the target"
192
210
  end
193
211
  while 1 < comp_max - comp_min do
@@ -221,7 +239,13 @@ module Enumerable
221
239
  break if minex < Mgmg.exp(smith_min, armor_min, comp)
222
240
  smith, armor = sa_search(para, target, comp, smith_min, armor_min, smith_max, armor_max, left_associative: left_associative, cut_exp: [minex, cut_exp].min)
223
241
  exp = Mgmg.exp(smith, armor, comp)
224
- minex, ret = exp, [smith, armor, comp] if exp < minex
242
+ if exp < minex
243
+ minex, ret = exp, [smith, armor, comp]
244
+ elsif exp == minex
245
+ if build(*ret).para_call(para) < build(smith, armor, comp).para_call(para)
246
+ ret = [smith, armor, comp]
247
+ end
248
+ end
225
249
  rescue Mgmg::SearchCutException
226
250
  end
227
251
  raise Mgmg::SearchCutException, "the result exceeds given cut_exp=#{cut_exp}" if cut_exp < minex
data/lib/mgmg/utils.rb CHANGED
@@ -221,6 +221,9 @@ module Mgmg
221
221
  def col_size
222
222
  @body[0].length
223
223
  end
224
+ def shape
225
+ [row_size(), col_size()]
226
+ end
224
227
  def each_with_index
225
228
  @body.each.with_index do |row, i|
226
229
  row.each.with_index do |e, j|
data/lib/mgmg/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mgmg
2
- VERSION = "1.3.1"
2
+ VERSION = "1.3.2"
3
3
  end
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.3.1
4
+ version: 1.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - KAZOON
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-31 00:00:00.000000000 Z
11
+ date: 2021-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,7 +52,7 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: 1.2.3
55
- description:
55
+ description:
56
56
  email:
57
57
  - cycloawaodorin+gem@gmail.com
58
58
  executables: []
@@ -70,6 +70,7 @@ files:
70
70
  - lib/mgmg.rb
71
71
  - lib/mgmg/const.rb
72
72
  - lib/mgmg/equip.rb
73
+ - lib/mgmg/optimize.rb
73
74
  - lib/mgmg/poly.rb
74
75
  - lib/mgmg/search.rb
75
76
  - lib/mgmg/system_equip.rb
@@ -82,7 +83,7 @@ metadata:
82
83
  homepage_uri: https://github.com/cycloawaodorin/
83
84
  source_code_uri: https://github.com/cycloawaodorin/mgmg
84
85
  changelog_uri: https://github.com/cycloawaodorin/mgmg/blob/master/CHANGELOG.md
85
- post_install_message:
86
+ post_install_message:
86
87
  rdoc_options: []
87
88
  require_paths:
88
89
  - lib
@@ -97,8 +98,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
97
98
  - !ruby/object:Gem::Version
98
99
  version: '0'
99
100
  requirements: []
100
- rubygems_version: 3.1.4
101
- signing_key:
101
+ rubygems_version: 3.2.17
102
+ signing_key:
102
103
  specification_version: 4
103
104
  summary: Calculate specs of equipments of Megurimeguru, a game produced by Kou.
104
105
  test_files: []