mgmg 1.3.0 → 1.4.1
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 +4 -4
- data/CHANGELOG.md +29 -1
- data/README.md +31 -212
- data/lib/mgmg/const.rb +2 -1
- data/lib/mgmg/equip.rb +49 -46
- data/lib/mgmg/ir.rb +373 -0
- data/lib/mgmg/optimize.rb +213 -0
- data/lib/mgmg/poly.rb +81 -0
- data/lib/mgmg/search.rb +365 -0
- data/lib/mgmg/utils.rb +54 -2
- data/lib/mgmg/version.rb +1 -1
- data/lib/mgmg.rb +80 -56
- data/reference.md +289 -0
- metadata +11 -7
data/lib/mgmg/ir.rb
ADDED
@@ -0,0 +1,373 @@
|
|
1
|
+
module Mgmg
|
2
|
+
using Refiner
|
3
|
+
class IR
|
4
|
+
class Const
|
5
|
+
def initialize(value)
|
6
|
+
@value = value
|
7
|
+
end
|
8
|
+
attr_accessor :value
|
9
|
+
def initialize_copy(other)
|
10
|
+
@value = other.value
|
11
|
+
end
|
12
|
+
def evaluate(s, c)
|
13
|
+
@value
|
14
|
+
end
|
15
|
+
def evaluate3(s, a, c)
|
16
|
+
@value
|
17
|
+
end
|
18
|
+
def to_s
|
19
|
+
@value.to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
class Smith
|
23
|
+
def initialize(sub9, coef, den, sa=nil)
|
24
|
+
@sub9, @coef, @den, @sa = sub9, coef, den, sa
|
25
|
+
end
|
26
|
+
attr_accessor :sub9, :coef, :den, :sa
|
27
|
+
def initialize_copy(other)
|
28
|
+
@sub9, @coef, @den, @sa = other.sub9, other.coef, other.den, other.sa
|
29
|
+
end
|
30
|
+
def evaluate(s, c)
|
31
|
+
((s+@sub9)*@coef).div(@den)
|
32
|
+
end
|
33
|
+
def evaluate3(s, a, c)
|
34
|
+
if sa==:a
|
35
|
+
((a+@sub9)*@coef).div(@den)
|
36
|
+
else
|
37
|
+
((s+@sub9)*@coef).div(@den)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
def to_s
|
41
|
+
if sa==:a
|
42
|
+
"[#{@coef}(a+#{@sub9})/#{den}]"
|
43
|
+
else
|
44
|
+
"[#{@coef}(s+#{@sub9})/#{den}]"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
class Compose
|
49
|
+
def initialize(main, sub, equip9, coef, den)
|
50
|
+
@main, @sub, @equip9, @coef, @den = main, sub, equip9, coef, den
|
51
|
+
end
|
52
|
+
attr_accessor :main, :sub, :equip9, :coef, :den
|
53
|
+
def initialize_copy(other)
|
54
|
+
@main, @sub = other.main.dup, other.sub.dup
|
55
|
+
@equip9, @coef, @den = other.equip9, other.coef, other.den
|
56
|
+
end
|
57
|
+
def evaluate(s, c)
|
58
|
+
@main.evaluate(s, c) + ( ( @sub.evaluate(s, c) * (c+@equip9).div(2) ).cdiv(100) * @coef ).cdiv(@den)
|
59
|
+
end
|
60
|
+
def evaluate3(s, a, c)
|
61
|
+
@main.evaluate3(s, a, c) + ( ( @sub.evaluate3(s, a, c) * (c+@equip9).div(2) ).cdiv(100) * @coef ).cdiv(@den)
|
62
|
+
end
|
63
|
+
def to_s
|
64
|
+
ms, ss = @main.to_s, @sub.to_s
|
65
|
+
if ss == '0'
|
66
|
+
ms
|
67
|
+
else
|
68
|
+
if ms == '0'
|
69
|
+
"[[#{ss}[(c+#{@equip9})/2]/100]/#{@den}]"
|
70
|
+
else
|
71
|
+
"#{ms}+[[#{ss}[(c+#{@equip9})/2]/100]/#{@den}]"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
class Multi
|
77
|
+
def initialize(body)
|
78
|
+
@body = body
|
79
|
+
end
|
80
|
+
attr_accessor :body
|
81
|
+
def initialize_copy(other)
|
82
|
+
@body = other.body.dup
|
83
|
+
end
|
84
|
+
def evaluate(s, c)
|
85
|
+
@body.sum do |e|
|
86
|
+
e.evaluate(s, c)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
def evaluate3(s, a, c)
|
90
|
+
@body.sum do |e|
|
91
|
+
e.evaluate3(s, a, c)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
def to_s
|
95
|
+
@body.map(&:to_s).join('+')
|
96
|
+
end
|
97
|
+
end
|
98
|
+
class << Multi
|
99
|
+
def sum(a, b)
|
100
|
+
unconsts, const = [], Const.new(0)
|
101
|
+
case a
|
102
|
+
when Multi
|
103
|
+
if a.body[0].kind_of?(Const)
|
104
|
+
const.value += a.body[0].value
|
105
|
+
unconsts = a.body[1..(-1)]
|
106
|
+
else
|
107
|
+
unconsts = a.body.dup
|
108
|
+
end
|
109
|
+
when Const
|
110
|
+
const.value += a.value
|
111
|
+
else
|
112
|
+
unconsts << a
|
113
|
+
end
|
114
|
+
case b
|
115
|
+
when Multi
|
116
|
+
if b.body[0].kind_of?(Const)
|
117
|
+
const.value += b.body[0].value
|
118
|
+
unconsts.concat(b.body[1..(-1)])
|
119
|
+
else
|
120
|
+
unconsts.concat(b.body)
|
121
|
+
end
|
122
|
+
when Const
|
123
|
+
const.value += b.value
|
124
|
+
else
|
125
|
+
unconsts << b
|
126
|
+
end
|
127
|
+
body = ( const.value == 0 ? unconsts : [const, *unconsts] )
|
128
|
+
case body.size
|
129
|
+
when 0
|
130
|
+
const
|
131
|
+
when 1
|
132
|
+
body[0]
|
133
|
+
else
|
134
|
+
new(body)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
def initialize(kind, star, main_m, sub_m, para)
|
139
|
+
@kind, @star, @main, @sub, @para = kind, star, main_m, sub_m, para
|
140
|
+
end
|
141
|
+
attr_accessor :kind, :star, :main, :sub, :para
|
142
|
+
def initialize_copy(other)
|
143
|
+
@kind = other.kind
|
144
|
+
@star = other.star
|
145
|
+
@main = other.main
|
146
|
+
@sub = other.sub
|
147
|
+
@para = other.para.dup
|
148
|
+
end
|
149
|
+
|
150
|
+
def compose(other)
|
151
|
+
self.class.compose(self, other)
|
152
|
+
end
|
153
|
+
|
154
|
+
def to_s
|
155
|
+
par = @para.map.with_index{|e, i| e.to_s=='0' ? nil : "#{Mgmg::Equip::ParamList[i]}:#{e.to_s}"}.compact
|
156
|
+
if @kind == 28
|
157
|
+
ep = @star.map.with_index{|e, i| e==0 ? nil : "#{Mgmg::Equip::EqPosList[i]}:#{e}"}.compact
|
158
|
+
"複数装備(#{ep.join(', ')})<#{par.join(', ')}>"
|
159
|
+
else
|
160
|
+
"#{EquipName[@kind]}☆#{@star}(#{MaterialClass[@main]}#{MaterialClass[@sub]})<#{par.join(', ')}>"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def para_call(para, s, ac, x=nil)
|
165
|
+
if x.nil?
|
166
|
+
method(para).call(s, ac)
|
167
|
+
else
|
168
|
+
method(para).call(s, ac, x)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
%i|attack phydef magdef hp mp str dex speed magic|.each.with_index do |sym, i|
|
173
|
+
define_method(sym) do |s=nil, ac=s, x=nil|
|
174
|
+
if s.nil?
|
175
|
+
@para[i]
|
176
|
+
elsif x.nil?
|
177
|
+
@para[i].evaluate(s, ac)
|
178
|
+
else
|
179
|
+
@para[i].evaluate3(s, ac, x)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
def atkstr(s, ac, x=nil)
|
184
|
+
attack(s, ac, x)+str(s, ac, x)
|
185
|
+
end
|
186
|
+
def atk_sd(s, ac, x=nil)
|
187
|
+
attack(s, ac, x)+str(s, ac, x).quo(2)+dex(s, ac, x).quo(2)
|
188
|
+
end
|
189
|
+
def dex_as(s, ac, x=nil)
|
190
|
+
attack(s, ac, x).quo(2)+str(s, ac, x).quo(2)+dex(s, ac, x)
|
191
|
+
end
|
192
|
+
def mag_das(s, ac, x=nil)
|
193
|
+
magic(s, ac, x)+dex_as(s, ac, x).quo(2)
|
194
|
+
end
|
195
|
+
def magic2(s, ac, x=nil)
|
196
|
+
magic(s, ac, x)*2
|
197
|
+
end
|
198
|
+
def magmag(s, ac, x=nil)
|
199
|
+
magdef(s, ac, x)+magic(s, ac, x).quo(2)
|
200
|
+
end
|
201
|
+
def pmdef(s, ac, x=nil)
|
202
|
+
[phydef(s, ac, x), magmag(s, ac, x)].min
|
203
|
+
end
|
204
|
+
|
205
|
+
def power(s, a=s, c=a.tap{a=s})
|
206
|
+
case @kind
|
207
|
+
when 0, 1
|
208
|
+
atk_sd(s, c)
|
209
|
+
when 2, 3
|
210
|
+
atkstr(s, c)
|
211
|
+
when 4
|
212
|
+
[dex_as(s, c), mag_das(s, c)].max
|
213
|
+
when 5
|
214
|
+
dex_as(s, c)
|
215
|
+
when 6, 7
|
216
|
+
[magic(s, c)*2, atkstr(s, c)].max
|
217
|
+
when 28
|
218
|
+
@para.sum{|e| e.evaluate3(s, a, c)}-((hp(s, a, c)+mp(s, a, c))*3.quo(4))
|
219
|
+
else
|
220
|
+
ret = @para.map{|e| e.evaluate3(s, a, c)}.max
|
221
|
+
if ret == magdef(s, a, c)
|
222
|
+
ret+magic(s, a, c).quo(2)
|
223
|
+
else
|
224
|
+
ret
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
def fpower(s, a=s, c=a.tap{a=s})
|
229
|
+
power(s, a, c).to_f
|
230
|
+
end
|
231
|
+
|
232
|
+
def smith_cost(s, c=s, outsourcing=false)
|
233
|
+
if outsourcing
|
234
|
+
if @kind < 8
|
235
|
+
(@star**2)*2+@para.sum{|e| e.evaluate(s, c)}+hp(s, c).cdiv(4)-hp(s, c)+mp(s, c).cdiv(4)-mp(s, c)
|
236
|
+
else
|
237
|
+
(@star**2)+@para.sum{|e| e.evaluate(s, c)}+hp(s, c).cdiv(4)-hp(s, c)+mp(s, c).cdiv(4)-mp(s, c)
|
238
|
+
end
|
239
|
+
else
|
240
|
+
if @kind < 8
|
241
|
+
((@star**2)*2+@para.sum{|e| e.evaluate(s, c)}+hp(s, c).cdiv(4)-hp(s, c)+mp(s, c).cdiv(4)-mp(s, c)).div(2)
|
242
|
+
else
|
243
|
+
((@star**2)+@para.sum{|e| e.evaluate(s, c)}+hp(s, c).cdiv(4)-hp(s, c)+mp(s, c).cdiv(4)-mp(s, c)).div(2)
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
def comp_cost(s, c=s, outsourcing=false)
|
248
|
+
if outsourcing
|
249
|
+
[(@star**2)*5+@para.sum{|e| e.evaluate(s, c)}+hp().cdiv(4)-hp()+mp().cdiv(4)-mp(), 0].max.div(2)
|
250
|
+
else
|
251
|
+
[((@star**2)*5+@para.sum{|e| e.evaluate(s, c)}+hp().cdiv(4)-hp()+mp().cdiv(4)-mp()).div(2), 0].max.div(2)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
alias :cost :comp_cost
|
255
|
+
|
256
|
+
def add!(other)
|
257
|
+
if @kind == 28
|
258
|
+
if other.kind == 28
|
259
|
+
@star.add!(other.star)
|
260
|
+
else
|
261
|
+
@star[EquipPosition[other.kind]] += 1
|
262
|
+
end
|
263
|
+
else
|
264
|
+
@star = Vec.new(6, 0)
|
265
|
+
@star[EquipPosition[@kind]] = 1
|
266
|
+
@kind = 28
|
267
|
+
if other.kind == 28
|
268
|
+
@star.add!(other.star)
|
269
|
+
else
|
270
|
+
@star[EquipPosition[other.kind]] += 1
|
271
|
+
end
|
272
|
+
end
|
273
|
+
@main, @sub = 12, 12
|
274
|
+
@para = Array.new(9) do |i|
|
275
|
+
Multi.sum(self.para[i], other.para[i])
|
276
|
+
end
|
277
|
+
self
|
278
|
+
end
|
279
|
+
def +(other)
|
280
|
+
self.dup.add!(other)
|
281
|
+
end
|
282
|
+
def coerce(other)
|
283
|
+
if other == 0
|
284
|
+
zero = self.class.new(28, Vec.new(6, 0), 12, 12, Array.new(9){Const.new(0)})
|
285
|
+
[zero, self]
|
286
|
+
else
|
287
|
+
raise TypeError, "Mgmg::IR can't be coerced into other than 0"
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
class << IR
|
292
|
+
def build(str, left_associative: true)
|
293
|
+
str = Mgmg.check_string(str)
|
294
|
+
stack, str = build_sub0([], str)
|
295
|
+
build_sub(stack, str, left_associative)
|
296
|
+
end
|
297
|
+
private def build_sub0(stack, str)
|
298
|
+
SystemEquip.each do |k, v|
|
299
|
+
if Regexp.compile(k).match(str)
|
300
|
+
stack << from_equip(v)
|
301
|
+
str = str.gsub(k, "<#{stack.length-1}>")
|
302
|
+
end
|
303
|
+
end
|
304
|
+
[stack, str]
|
305
|
+
end
|
306
|
+
private def build_sub(stack, str, lassoc)
|
307
|
+
if m = /\A(.*\+?)\[([^\[\]]+)\](\+?[^\[]*)\Z/.match(str)
|
308
|
+
stack << build_sub(stack, m[2], lassoc)
|
309
|
+
build_sub(stack, "#{m[1]}<#{stack.length-1}>#{m[3]}", lassoc)
|
310
|
+
elsif m = ( lassoc ? /\A(.+)\+(.+?)\Z/ : /\A(.+?)\+(.+)\Z/ ).match(str)
|
311
|
+
compose(build_sub(stack, m[1], lassoc), build_sub(stack, m[2], lassoc))
|
312
|
+
elsif m = /\A\<(\d+)\>\Z/.match(str)
|
313
|
+
stack[m[1].to_i]
|
314
|
+
else
|
315
|
+
smith(str)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
def compose(main, sub)
|
320
|
+
main_k, sub_k = main.kind, sub.kind
|
321
|
+
main_s, sub_s = main.star, sub.star
|
322
|
+
main_main, sub_main = main.main, sub.main
|
323
|
+
main_sub, sub_sub = main.sub, sub.sub
|
324
|
+
|
325
|
+
coef = Equip9[main_k].dup
|
326
|
+
coef.sub!(Equip9[sub_k])
|
327
|
+
coef.add!( 100 + (main_s-sub_s)*5 - ( ( main_main==sub_main && main_main != 9 ) ? 30 : 0 ) )
|
328
|
+
coef.add!(Material9[main_main]).sub!(Material9[sub_main])
|
329
|
+
den = ( main_k==sub_k ? 200 : 100 )
|
330
|
+
para = Array.new(9) do |i|
|
331
|
+
if EquipFilter[main_k][i] == 0
|
332
|
+
main.para[i]
|
333
|
+
else
|
334
|
+
Mgmg::IR::Compose.new(main.para[i], sub.para[i], Equip9[main_k][i], coef[i], den)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
new(main_k, main_s+sub_s, main_sub, sub_main, para)
|
339
|
+
end
|
340
|
+
def smith(str)
|
341
|
+
str = Mgmg.check_string(str)
|
342
|
+
unless m = /\A(.+)\((.+\d+),?(.+\d+)\)\Z/.match(str)
|
343
|
+
raise InvalidSmithError.new(str)
|
344
|
+
end
|
345
|
+
kind = EquipIndex[m[1].to_sym]
|
346
|
+
unless kind
|
347
|
+
raise InvalidEquipClassError.new(m[1])
|
348
|
+
end
|
349
|
+
main_m, main_s, main_mc = Mgmg.parse_material(m[2])
|
350
|
+
sub_m, sub_s, sub_mc = Mgmg.parse_material(m[3])
|
351
|
+
sa = ( Mgmg::EquipPosition[kind] == 0 ? :s : :a )
|
352
|
+
|
353
|
+
coef = Equip9[kind].dup
|
354
|
+
coef.e_mul!(Main9[main_m]).e_div!(100)
|
355
|
+
den = ( main_mc==sub_mc ? 200 : 100 )
|
356
|
+
para = Array.new(9) do |i|
|
357
|
+
if coef[i] == 0
|
358
|
+
Mgmg::IR::Const.new(0)
|
359
|
+
else
|
360
|
+
Mgmg::IR::Smith.new(Sub9[sub_m][i], coef[i], den, sa)
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
new(kind, (main_s+sub_s).div(2), main_mc, sub_mc, para)
|
365
|
+
end
|
366
|
+
def from_equip(equip)
|
367
|
+
para = equip.para.map do |value|
|
368
|
+
Mgmg::IR::Const.new(value)
|
369
|
+
end
|
370
|
+
new(equip.kind, equip.star, equip.main, equip.sub, para)
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
@@ -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,85 @@ 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
|
279
|
+
def <=>(other)
|
280
|
+
if self == other
|
281
|
+
0
|
282
|
+
elsif self < other
|
283
|
+
-1
|
284
|
+
else
|
285
|
+
1
|
286
|
+
end
|
287
|
+
end
|
207
288
|
end
|
208
289
|
class << TPolynomial
|
209
290
|
ParamIndex = Hash.new
|