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.
@@ -0,0 +1,365 @@
1
+ class String
2
+ def smith_search(para, target, comp, smith_min=nil, smith_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil)
3
+ irep = ir(left_associative: left_associative) if irep.nil?
4
+ if smith_min.nil?
5
+ if min_smith
6
+ smith_min = self.min_smith.min_smith
7
+ else
8
+ smith_min = build(-1, -1, left_associative: left_associative).min_level
9
+ end
10
+ end
11
+ if smith_max < smith_min
12
+ raise ArgumentError, "smith_min <= smith_max is needed, (smith_min, smith_max) = (#{smith_min}, #{smith_max}) are given"
13
+ elsif cut_exp < Float::INFINITY
14
+ begin
15
+ smith_max = [smith_max, Mgmg.invexp2(cut_exp, comp)].min
16
+ rescue
17
+ raise Mgmg::SearchCutException
18
+ end
19
+ end
20
+ if target <= irep.para_call(para, smith_min, comp)
21
+ return smith_min
22
+ elsif irep.para_call(para, smith_max, comp) < target
23
+ raise Mgmg::SearchCutException
24
+ end
25
+ while 1 < smith_max - smith_min do
26
+ smith = (smith_max - smith_min).div(2) + smith_min
27
+ if irep.para_call(para, smith, comp) < target
28
+ smith_min = smith
29
+ else
30
+ smith_max = smith
31
+ end
32
+ end
33
+ smith_max
34
+ end
35
+ def comp_search(para, target, smith, comp_min=nil, comp_max=10000, left_associative: true, irep: nil)
36
+ irep = ir(left_associative: left_associative) if irep.nil?
37
+ comp_min = min_comp(left_associative: left_associative)
38
+ if comp_max < comp_min
39
+ raise ArgumentError, "comp_min <= comp_max is needed, (comp_min, comp_max) = (#{comp_min}, #{comp_max}) are given"
40
+ end
41
+ if target <= irep.para_call(para, smith, comp_min)
42
+ return comp_min
43
+ elsif irep.para_call(para, smith, comp_max) < target
44
+ raise Mgmg::SearchCutException
45
+ end
46
+ while 1 < comp_max - comp_min do
47
+ comp = (comp_max - comp_min).div(2) + comp_min
48
+ if irep.para_call(para, smith, comp) < target
49
+ comp_min = comp
50
+ else
51
+ comp_max = comp
52
+ end
53
+ end
54
+ comp_max
55
+ end
56
+ def search(para, target, smith_min=nil, comp_min=nil, smith_max=10000, comp_max=10000, left_associative: true, step: 1, cut_exp: Float::INFINITY, min_smith: false, irep: nil)
57
+ irep = ir(left_associative: left_associative) if irep.nil?
58
+ if smith_min.nil?
59
+ if min_smith
60
+ smith_min = self.min_smith
61
+ else
62
+ smith_min = build(-1, -1, left_associative: left_associative).min_level
63
+ end
64
+ end
65
+ comp_min = min_comp(left_associative: left_associative) if comp_min.nil?
66
+ comp_min = comp_search(para, target, smith_max, comp_min, comp_max, left_associative: left_associative, irep: irep)
67
+ smith_max = smith_search(para, target, comp_min, smith_min, smith_max, left_associative: left_associative, irep: irep)
68
+ smith_min = smith_search(para, target, comp_max, smith_min, smith_max, left_associative: left_associative, irep: irep)
69
+ raise Mgmg::SearchCutException if cut_exp < Mgmg.exp(smith_min, comp_min)
70
+ comp_max = comp_search(para, target, smith_min, comp_min, comp_max, left_associative: left_associative, irep: irep)
71
+ minex, ret = Mgmg.exp(smith_min, comp_max), [smith_min, comp_max]
72
+ exp = Mgmg.exp(smith_max, comp_min)
73
+ minex, ret = exp, [smith_max, comp_min] if exp < minex
74
+ (comp_min+step).step(comp_max-1, step) do |comp|
75
+ break if minex < Mgmg.exp(smith_min, comp)
76
+ smith = smith_search(para, target, comp, smith_min, smith_max, left_associative: left_associative, cut_exp: [minex, cut_exp].min)
77
+ exp = Mgmg.exp(smith, comp)
78
+ if exp < minex
79
+ minex, ret = exp, [smith, comp]
80
+ elsif exp == minex
81
+ if irep.para_call(para, *ret) < irep.para_call(para, smith, comp)
82
+ ret = [smith, comp]
83
+ end
84
+ end
85
+ rescue Mgmg::SearchCutException
86
+ end
87
+ raise Mgmg::SearchCutException, "the result exceeds given cut_exp=#{cut_exp}" if cut_exp < minex
88
+ ret
89
+ end
90
+ end
91
+ module Enumerable
92
+ def smith_search(para, target, armor, comp, smith_min=nil, smith_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil)
93
+ irep = ir(left_associative: left_associative) if irep.nil?
94
+ if smith_min.nil?
95
+ if min_smith
96
+ smith_min = self.min_smith[0]
97
+ else
98
+ smith_min = build(-1, -1, -1, left_associative: left_associative).min_level[0]
99
+ end
100
+ end
101
+ if smith_max < smith_min
102
+ raise ArgumentError, "smith_min <= smith_max is needed, (smith_min, smith_max) = (#{smith_min}, #{smith_max}) are given"
103
+ elsif cut_exp < Float::INFINITY
104
+ begin
105
+ smith_max = [smith_max, Mgmg.invexp3(cut_exp, armor, comp)].min
106
+ rescue
107
+ raise Mgmg::SearchCutException
108
+ end
109
+ end
110
+ if irep.para_call(para, smith_max, armor, comp) < target
111
+ raise Mgmg::SearchCutException
112
+ elsif target <= irep.para_call(para, smith_min, armor, comp)
113
+ return smith_min
114
+ end
115
+ while 1 < smith_max - smith_min do
116
+ smith = (smith_max - smith_min).div(2) + smith_min
117
+ if irep.para_call(para, smith, armor, comp) < target
118
+ smith_min = smith
119
+ else
120
+ smith_max = smith
121
+ end
122
+ end
123
+ smith_max
124
+ end
125
+ def armor_search(para, target, smith, comp, armor_min=nil, armor_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil)
126
+ irep = ir(left_associative: left_associative) if irep.nil?
127
+ if armor_min.nil?
128
+ if min_smith
129
+ armor_min = self.min_smith[1]
130
+ else
131
+ armor_min = build(-1, -1, -1, left_associative: left_associative).min_level[1]
132
+ end
133
+ end
134
+ if armor_max < armor_min
135
+ raise ArgumentError, "armor_min <= armor_max is needed, (armor_min, armor_max) = (#{armor_min}, #{armor_max}) are given"
136
+ elsif cut_exp < Float::INFINITY
137
+ begin
138
+ armor_max = [armor_max, Mgmg.invexp3(cut_exp, smith, comp)].min
139
+ rescue
140
+ raise Mgmg::SearchCutException
141
+ end
142
+ end
143
+ if irep.para_call(para, smith, armor_max, comp) < target
144
+ raise Mgmg::SearchCutException
145
+ elsif target <= irep.para_call(para, smith, armor_min, comp)
146
+ return armor_min
147
+ end
148
+ while 1 < armor_max - armor_min do
149
+ armor = (armor_max - armor_min).div(2) + armor_min
150
+ if irep.para_call(para, smith, armor, comp) < target
151
+ armor_min = armor
152
+ else
153
+ armor_max = armor
154
+ end
155
+ end
156
+ armor_max
157
+ end
158
+ def sa_search(para, target, comp, smith_min=nil, armor_min=nil, smith_max=10000, armor_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil)
159
+ irep = ir(left_associative: left_associative) if irep.nil?
160
+ if min_smith
161
+ s, a = self.min_smith
162
+ else
163
+ s, a = build(-1, -1, -1, left_associative: left_associative).min_level
164
+ end
165
+ smith_min = s if smith_min.nil?
166
+ armor_min = a if armor_min.nil?
167
+ smith_min = smith_search(para, target, armor_max, comp, smith_min, smith_max, left_associative: true, irep: irep)
168
+ armor_min = armor_search(para, target, smith_max, comp, armor_min, armor_max, left_associative: true, irep: irep)
169
+ raise Mgmg::SearchCutException if cut_exp < Mgmg.exp(smith_min, armor_min, comp)
170
+ smith_max = smith_search(para, target, armor_min, comp, smith_min, smith_max, left_associative: true, irep: irep)
171
+ armor_max = armor_search(para, target, smith_min, comp, armor_min, armor_max, left_associative: true, irep: irep)
172
+ minex, ret = Mgmg.exp(smith_min, armor_max, comp), [smith_min, armor_max]
173
+ exp = Mgmg.exp(smith_max, armor_min, comp)
174
+ if exp < minex
175
+ minex, ret = exp, [smith_max, armor_min]
176
+ (armor_min+1).upto(armor_max-1) do |armor|
177
+ break if minex < Mgmg.exp(smith_min, armor, comp)
178
+ smith = smith_search(para, target, armor, comp, smith_min, smith_max, left_associative: left_associative, cut_exp: [minex, cut_exp].min, irep: irep)
179
+ exp = Mgmg.exp(smith, armor, comp)
180
+ if exp < minex
181
+ minex, ret = exp, [smith, armor]
182
+ elsif exp == minex
183
+ if irep.para_call(para, *ret, comp) < irep.para_call(para, smith, armor, comp)
184
+ ret = [smith, armor]
185
+ end
186
+ end
187
+ rescue Mgmg::SearchCutException
188
+ end
189
+ else
190
+ (smith_min+1).upto(smith_max-1) do |smith|
191
+ break if minex < Mgmg.exp(smith, armor_min, comp)
192
+ armor = armor_search(para, target, smith, comp, armor_min, armor_max, left_associative: left_associative, cut_exp: [minex, cut_exp].min, irep: irep)
193
+ exp = Mgmg.exp(smith, armor, comp)
194
+ if exp < minex
195
+ minex, ret = exp, [smith, armor]
196
+ elsif exp == minex
197
+ if irep.para_call(para, *ret, comp) < irep.para_call(para, smith, armor, comp)
198
+ ret = [smith, armor]
199
+ end
200
+ end
201
+ rescue Mgmg::SearchCutException
202
+ end
203
+ end
204
+ raise Mgmg::SearchCutException if cut_exp < minex
205
+ ret
206
+ end
207
+ def comp_search(para, target, smith, armor, comp_min=nil, comp_max=10000, left_associative: true, irep: nil)
208
+ irep = ir(left_associative: left_associative) if irep.nil?
209
+ comp_min = min_comp(left_associative: left_associative)
210
+ if comp_max < comp_min
211
+ raise ArgumentError, "comp_min <= comp_max is needed, (comp_min, comp_max) = (#{comp_min}, #{comp_max}) are given"
212
+ end
213
+ if target <= irep.para_call(para, smith, armor, comp_min)
214
+ return comp_min
215
+ elsif irep.para_call(para, smith, armor, comp_max) < target
216
+ raise ArgumentError, "given comp_max=#{comp_max} does not satisfies the target"
217
+ end
218
+ while 1 < comp_max - comp_min do
219
+ comp = (comp_max - comp_min).div(2) + comp_min
220
+ if irep.para_call(para, smith, armor, comp) < target
221
+ comp_min = comp
222
+ else
223
+ comp_max = comp
224
+ end
225
+ end
226
+ comp_max
227
+ end
228
+ def search(para, target, smith_min=nil, armor_min=nil, comp_min=nil, smith_max=10000, armor_max=10000, comp_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil)
229
+ irep = ir(left_associative: left_associative) if irep.nil?
230
+ if min_smith
231
+ s, a = self.min_smith
232
+ else
233
+ s, a = build(-1, -1, -1, left_associative: left_associative).min_level
234
+ end
235
+ smith_min = s if smith_min.nil?
236
+ armor_min = a if armor_min.nil?
237
+ comp_min = min_comp(left_associative: left_associative) if comp_min.nil?
238
+ comp_min = comp_search(para, target, smith_max, armor_max, comp_min, comp_max, left_associative: left_associative, irep: irep)
239
+ smith_max, armor_max = sa_search(para, target, comp_min, smith_min, armor_min, smith_max, armor_max, left_associative: left_associative, irep: irep)
240
+ smith_min, armor_min = sa_search(para, target, comp_max, smith_min, armor_min, smith_max, armor_max, left_associative: left_associative, irep: irep)
241
+ raise Mgmg::SearchCutException if cut_exp < Mgmg.exp(smith_min, armor_min, comp_min)
242
+ comp_max = comp_search(para, target, smith_min, armor_min, comp_min, comp_max, left_associative: left_associative, irep: irep)
243
+ minex, ret = Mgmg.exp(smith_min, armor_min, comp_max), [smith_min, armor_min, comp_max]
244
+ exp = Mgmg.exp(smith_max, armor_max, comp_min)
245
+ minex, ret = exp, [smith_max, armor_max, comp_min] if exp < minex
246
+ (comp_min+1).upto(comp_max-1) do |comp|
247
+ break if minex < Mgmg.exp(smith_min, armor_min, comp)
248
+ 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, irep: irep)
249
+ exp = Mgmg.exp(smith, armor, comp)
250
+ if exp < minex
251
+ minex, ret = exp, [smith, armor, comp]
252
+ elsif exp == minex
253
+ if irep.para_call(para, *ret) < irep.para_call(para, smith, armor, comp)
254
+ ret = [smith, armor, comp]
255
+ end
256
+ end
257
+ rescue Mgmg::SearchCutException
258
+ end
259
+ raise Mgmg::SearchCutException, "the result exceeds given cut_exp=#{cut_exp}" if cut_exp < minex
260
+ ret
261
+ end
262
+ end
263
+
264
+ module Mgmg
265
+ module_function def find_lowerbound(a, b, para, start, term, smith_min_a: nil, smith_min_b: nil, armor_min_a: nil, armor_min_b: nil, min_smith: false)
266
+ if term <= start
267
+ raise ArgumentError, "start < term is needed, (start, term) = (#{start}, #{term}) are given"
268
+ end
269
+ ira, irb = a.ir, b.ir
270
+ sca, scb = a.search(para, start, smith_min_a, armor_min_a, min_smith: min_smith, irep: ira), b.search(para, start, smith_min_b, armor_min_b, min_smith: min_smith, irep: irb)
271
+ ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
272
+ if eb < ea || ( ea == eb && ira.para_call(para, *sca) < irb.para_call(para, *scb) )
273
+ a, b, ira, irb, sca, scb, ea, eb = b, a, irb, ira, scb, sca, eb, ea
274
+ smith_min_a, smith_min_b, armor_min_a, armor_min_b = smith_min_b, smith_min_a, armor_min_b, armor_min_a
275
+ end
276
+ tag = ira.para_call(para, *sca) + 1
277
+ sca, scb = a.search(para, term, smith_min_a, armor_min_a, min_smith: min_smith, irep: ira), b.search(para, term, smith_min_b, armor_min_b, min_smith: min_smith, irep: irb)
278
+ ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
279
+ if ea < eb || ( ea == eb && irb.para_call(para, *scb) < ira.para_call(para, *sca) )
280
+ raise Mgmg::SearchCutException
281
+ end
282
+ while tag < term
283
+ sca, scb = a.search(para, tag, smith_min_a, armor_min_a, min_smith: min_smith, irep: ira), b.search(para, tag, smith_min_b, armor_min_b, min_smith: min_smith, irep: irb)
284
+ ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
285
+ pa, pb = ira.para_call(para, *sca), irb.para_call(para, *scb)
286
+ if eb < ea
287
+ return [tag-1, pb]
288
+ elsif ea == eb
289
+ if pa < pb
290
+ return [tag-1, pa]
291
+ else
292
+ tag = pb + 1
293
+ end
294
+ else
295
+ tag = pa + 1
296
+ end
297
+ end
298
+ raise UnexpectedError
299
+ end
300
+
301
+ module_function def find_upperbound(a, b, para, start, term, smith_min_a: nil, smith_min_b: nil, armor_min_a: nil, armor_min_b: nil, min_smith: false)
302
+ if start <= term
303
+ raise ArgumentError, "term < start is needed, (start, term) = (#{start}, #{term}) are given"
304
+ end
305
+ ira, irb = a.ir, b.ir
306
+ sca, scb = a.search(para, start, smith_min_a, armor_min_a, min_smith: min_smith, irep: ira), b.search(para, start, smith_min_b, armor_min_b, min_smith: min_smith, irep: irb)
307
+ ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
308
+ if ea < eb || ( ea == eb && irb.para_call(para, *scb) < ira.para_call(para, *sca) )
309
+ a, b, ira, irb, sca, scb, ea, eb = b, a, irb, ira, scb, sca, eb, ea
310
+ smith_min_a, smith_min_b, armor_min_a, armor_min_b = smith_min_b, smith_min_a, armor_min_b, armor_min_a
311
+ end
312
+ tagu = ira.para_call(para, *sca)
313
+ sca[-1] -= 2
314
+ tagl = ira.para_call(para, *sca)
315
+ sca, scb = a.search(para, term, smith_min_a, armor_min_a, min_smith: min_smith, irep: ira), b.search(para, term, smith_min_b, armor_min_b, min_smith: min_smith, irep: irb)
316
+ ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
317
+ if eb < ea || ( ea == eb && ira.para_call(para, *sca) < irb.para_call(para, *scb) )
318
+ raise Mgmg::SearchCutException
319
+ end
320
+ while term < tagu
321
+ ret = nil
322
+ sca = a.search(para, tagl, smith_min_a, armor_min_a, min_smith: min_smith, irep: ira)
323
+ next_tagu, next_sca = tagl, sca
324
+ scb = b.search(para, tagl, smith_min_b, armor_min_b, min_smith: min_smith, irep: irb)
325
+ while tagl < tagu
326
+ ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
327
+ pa, pb = ira.para_call(para, *sca), irb.para_call(para, *scb)
328
+ if ea < eb
329
+ ret = tagl
330
+ sca = a.search(para, pa + 1, smith_min_a, armor_min_a, min_smith: min_smith, irep: ira)
331
+ tagl = ira.para_call(para, *sca)
332
+ scb = b.search(para, tagl, smith_min_b, armor_min_b, min_smith: min_smith, irep: irb)
333
+ elsif ea == eb
334
+ if pb < pa
335
+ ret = tagl
336
+ sca = a.search(para, pa + 1, smith_min_a, armor_min_a, min_smith: min_smith, irep: ira)
337
+ tagl = ira.para_call(para, *sca)
338
+ scb = b.search(para, tagl, smith_min_b, armor_min_b, min_smith: min_smith, irep: irb)
339
+ else
340
+ scb = b.search(para, pb + 1, smith_min_b, armor_min_b, min_smith: min_smith, irep: irb)
341
+ tagl = irb.para_call(para, *scb)
342
+ sca = a.search(para, tagl, smith_min_a, armor_min_a, min_smith: min_smith, irep: ira)
343
+ end
344
+ else
345
+ sca = a.search(para, pa + 1, smith_min_a, armor_min_a, min_smith: min_smith, irep: ira)
346
+ tagl = ira.para_call(para, *sca)
347
+ scb = b.search(para, tagl, smith_min_b, armor_min_b, min_smith: min_smith, irep: irb)
348
+ end
349
+ end
350
+ if ret.nil?
351
+ tagu = next_tagu
352
+ next_sca[-1] -= 2
353
+ tagl = ira.para_call(para, *next_sca)
354
+ if tagl == tagu
355
+ tagl = term
356
+ end
357
+ else
358
+ pa = ira.para_call(para, *a.search(para, ret+1, smith_min_a, armor_min_a, min_smith: min_smith, irep: ira))
359
+ pb = irb.para_call(para, *b.search(para, ret+1, smith_min_b, armor_min_b, min_smith: min_smith, irep: irb))
360
+ return [ret, [pa, pb].min]
361
+ end
362
+ end
363
+ raise UnexpectedError
364
+ end
365
+ end
data/lib/mgmg/utils.rb CHANGED
@@ -46,9 +46,49 @@ module Mgmg
46
46
  end
47
47
  attr_accessor :equip
48
48
  end
49
+ class SearchCutException < StandardError; end
50
+ class UnexpectedError < StandardError
51
+ def initialize()
52
+ super("There is a bug in `mgmg' gem. Please report to https://github.com/cycloawaodorin/mgmg/issues .")
53
+ end
54
+ end
49
55
 
50
- module_function def exp(smith, comp)
51
- ((smith-1)**2) + (2*((comp-1)**2)) + 3
56
+ module_function def exp(smith, armor, comp=armor.tap{armor=0})
57
+ if armor <= 0
58
+ if smith <= 0
59
+ if comp <= 0
60
+ 0
61
+ else
62
+ (2*((comp-1)**2)) + 2
63
+ end
64
+ else
65
+ if comp <= 0
66
+ ((smith-1)**2) + 1
67
+ else
68
+ ((smith-1)**2) + (2*((comp-1)**2)) + 3
69
+ end
70
+ end
71
+ else
72
+ if smith <= 0
73
+ if comp <= 0
74
+ ((armor-1)**2) + 1
75
+ else
76
+ ((armor-1)**2) + (2*((comp-1)**2)) + 3
77
+ end
78
+ else
79
+ if comp <= 0
80
+ ((smith-1)**2) + ((armor-1)**2) + 2
81
+ else
82
+ ((smith-1)**2) + ((armor-1)**2) + (2*((comp-1)**2)) + 4
83
+ end
84
+ end
85
+ end
86
+ end
87
+ module_function def invexp2(exp, comp)
88
+ Math.sqrt(exp - (2*((comp-1)**2)) - 3).round + 1
89
+ end
90
+ module_function def invexp3(exp, sa, comp)
91
+ Math.sqrt(exp - ((sa-1)**2) - (2*((comp-1)**2)) - 4).round + 1
52
92
  end
53
93
 
54
94
  CharacterList = /[^\(\)\+0123456789\[\]あきくしすたてなねのびりるイウガクグサジスタダチツデトドニノフブペボムラリルロンヴー一万二光兜典刀剣劣匠双古名吹咆品哮地大天太子安宝小帽弓弩当息悪戦手指斧書服木本杖業樹歴殺水氷法火炎牙物玉王産用界異的皮盾短石砕竜紫綿耳聖脛腕腿般良色衣袋覇質軍軽輝輪重量金鉄鎧闇陽靴額飾首骨鬼龍]/
@@ -94,6 +134,15 @@ module Mgmg
94
134
  end
95
135
  str
96
136
  end
137
+
138
+ module_function def parse_material(str)
139
+ m = /\A.+?(\d+)\Z/.match(str)
140
+ mat = MaterialIndex[str.to_sym]
141
+ if m.nil? || mat.nil?
142
+ raise InvalidMaterialError.new(str)
143
+ end
144
+ [mat, m[1].to_i, mat<90 ? mat.div(10) : 9]
145
+ end
97
146
 
98
147
  class Vec < Array
99
148
  def add!(other)
@@ -186,6 +235,9 @@ module Mgmg
186
235
  def col_size
187
236
  @body[0].length
188
237
  end
238
+ def shape
239
+ [row_size(), col_size()]
240
+ end
189
241
  def each_with_index
190
242
  @body.each.with_index do |row, i|
191
243
  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.0"
2
+ VERSION = "1.4.1"
3
3
  end
data/lib/mgmg.rb CHANGED
@@ -3,14 +3,17 @@ require_relative './mgmg/utils'
3
3
  require_relative './mgmg/const'
4
4
  require_relative './mgmg/equip'
5
5
  require_relative './mgmg/poly'
6
+ require_relative './mgmg/ir'
6
7
  require_relative './mgmg/system_equip'
8
+ require_relative './mgmg/search'
9
+ require_relative './mgmg/optimize'
7
10
 
8
11
  class String
9
12
  def min_level(w=1)
10
13
  Mgmg::Equip.min_level(self, w)
11
14
  end
12
- def min_levels(left_associative: true)
13
- build(-1, -1, left_associative: left_associative).min_levels
15
+ def min_levels(w=1, left_associative: true)
16
+ build(-1, -1, left_associative: left_associative).min_levels(w)
14
17
  end
15
18
  def min_smith(left_associative: true)
16
19
  Mgmg::Equip.min_smith(self, left_associative: left_associative)
@@ -21,37 +24,45 @@ class String
21
24
  def build(smith=-1, comp=smith, left_associative: true)
22
25
  Mgmg::Equip.build(self, smith, comp, left_associative: left_associative)
23
26
  end
27
+ def ir(left_associative: true)
28
+ Mgmg::IR.build(self, left_associative: left_associative)
29
+ end
24
30
  def poly(para=:cost, left_associative: true)
31
+ la = left_associative
25
32
  case para
26
33
  when :atkstr
27
- self.poly(:attack) + self.poly(:str)
34
+ self.poly(:attack, left_associative: la) + self.poly(:str, left_associative: la)
28
35
  when :atk_sd
29
- self.poly(:attack) + self.poly(:str).quo(2) + self.poly(:dex).quo(2)
36
+ self.poly(:attack, left_associative: la) + self.poly(:str, left_associative: la).quo(2) + self.poly(:dex, left_associative: la).quo(2)
30
37
  when :dex_as
31
- self.poly(:dex) + self.poly(:attack).quo(2) + self.poly(:str).quo(2)
38
+ self.poly(:dex, left_associative: la) + self.poly(:attack, left_associative: la).quo(2) + self.poly(:str, left_associative: la).quo(2)
32
39
  when :mag_das
33
- self.poly(:magic) + self.poly(:dex_as).quo(2)
40
+ self.poly(:magic, left_associative: la) + self.poly(:dex_as, left_associative: la).quo(2)
34
41
  when :magmag
35
- self.poly(:magdef) + self.poly(:magic).quo(2)
42
+ self.poly(:magdef, left_associative: la) + self.poly(:magic, left_associative: la).quo(2)
43
+ when :pmdef
44
+ pd = self.poly(:phydef, left_associative: la)
45
+ md = self.poly(:magmag, left_associative: la)
46
+ pd <= md ? pd : md
36
47
  when :cost
37
48
  if Mgmg::SystemEquip.keys.include?(self)
38
49
  return Mgmg::TPolynomial.new(Mgmg::Mat.new(1, 1, 0.quo(1)), 28, 0, 12, 12)
39
50
  end
40
51
  built = self.build(-1)
41
52
  const = (built.star**2) * ( /\+/.match(self) ? 5 : ( built.kind < 8 ? 2 : 1 ) )
42
- ret = poly(:attack) + poly(:phydef) + poly(:magdef)
43
- ret += poly(:hp).quo(4) + poly(:mp).quo(4)
44
- ret += poly(:str) + poly(:dex) + poly(:speed) + poly(:magic)
53
+ ret = poly(:attack, left_associative: la) + poly(:phydef, left_associative: la) + poly(:magdef, left_associative: la)
54
+ ret += poly(:hp, left_associative: la).quo(4) + poly(:mp, left_associative: la).quo(4)
55
+ ret += poly(:str, left_associative: la) + poly(:dex, left_associative: la) + poly(:speed, left_associative: la) + poly(:magic, left_associative: la)
45
56
  ret.mat.body[0][0] += const
46
57
  ret
47
58
  else
48
- Mgmg::TPolynomial.build(self, para, left_associative: left_associative)
59
+ Mgmg::TPolynomial.build(self, para, left_associative: la)
49
60
  end
50
61
  end
51
62
  def eff(para, smith, comp=smith, left_associative: true)
52
- a = build(smith, comp, left_associative: left_associative).method(para).call
53
- b = build(smith+1, comp, left_associative: left_associative).method(para).call
54
- c = build(smith, comp+2, left_associative: left_associative).method(para).call
63
+ a = build(smith, comp, left_associative: left_associative).para_call(para)
64
+ b = build(smith+1, comp, left_associative: left_associative).para_call(para)
65
+ c = build(smith, comp+2, left_associative: left_associative).para_call(para)
55
66
  sden = smith==0 ? 1 : 2*smith-1
56
67
  cden = comp==0 ? 4 : 8*comp
57
68
  [(b-a).quo(sden), (c-a).quo(cden)]
@@ -59,55 +70,21 @@ class String
59
70
  def peff(para, smith, comp=smith, left_associative: true)
60
71
  poly(para, left_associative: left_associative).eff(smith, comp)
61
72
  end
62
- def smith_search(para, target, comp, smith_min=nil, smith_max=10000, left_associative: true)
63
- smith_min = build(-1, -1, left_associative: left_associative).min_level if smith_min.nil?
64
- if smith_max < smith_min
65
- raise ArgumentError, "smith_min <= smith_max is needed, (smith_min, smith_max) = (#{smith_min}, #{smith_max}) are given"
66
- end
67
- if target <= build(smith_min, comp, left_associative: left_associative).method(para).call
68
- return smith_min
69
- elsif build(smith_max, comp, left_associative: left_associative).method(para).call < target
70
- raise ArgumentError, "given smith_max=#{smith_max} does not satisfies the target"
71
- end
72
- while 1 < smith_max - smith_min do
73
- smith = (smith_max - smith_min).div(2) + smith_min
74
- if build(smith, comp, left_associative: left_associative).method(para).call < target
75
- smith_min = smith
76
- else
77
- smith_max = smith
78
- end
79
- end
80
- smith_max
81
- end
82
- def comp_search(para, target, smith, comp_min=nil, comp_max=10000, left_associative: true)
83
- comp_min = min_comp(left_associative: left_associative)
84
- if comp_max < comp_min
85
- raise ArgumentError, "comp_min <= comp_max is needed, (comp_min, comp_max) = (#{comp_min}, #{comp_max}) are given"
86
- end
87
- if target <= build(smith, comp_min, left_associative: left_associative).method(para).call
88
- return comp_min
89
- elsif build(smith, comp_max, left_associative: left_associative).method(para).call < target
90
- raise ArgumentError, "given comp_max=#{comp_max} does not satisfies the target"
91
- end
92
- while 1 < comp_max - comp_min do
93
- comp = (comp_max - comp_min).div(2) + comp_min
94
- if build(smith, comp, left_associative: left_associative).method(para).call < target
95
- comp_min = comp
96
- else
97
- comp_max = comp
98
- end
99
- end
100
- comp_max
101
- end
102
- def show(smith=-1, comp=smith, left_associative: true)
73
+ def show(smith=-1, comp=smith, left_associative: true, para: :power)
103
74
  built = self.build(smith, comp, left_associative: left_associative)
104
- pstr = '%.3f' % built.fpower
75
+ pstr = '%.3f' % built.para_call(para)
105
76
  pstr.sub!(/\.?0+\Z/, '')
106
77
  puts "Building"
107
78
  puts " #{self}"
108
79
  puts "with levels (#{smith}, #{comp}) yields (#{pstr}, #{built.total_cost})"
109
80
  puts " #{built}"
110
81
  end
82
+ def phydef_optimize(smith=nil, comp=smith, left_associative: true, magdef_maximize: true)
83
+ Mgmg::Optimize.phydef_optimize(self, smith, comp, left_associative: left_associative, magdef_maximize: magdef_maximize)
84
+ end
85
+ def buster_optimize(smith=nil, comp=smith, left_associative: true)
86
+ Mgmg::Optimize.buster_optimize(self, smith, comp, left_associative: left_associative)
87
+ end
111
88
  end
112
89
  module Enumerable
113
90
  def build(smith=-1, armor=smith, comp=armor.tap{armor=smith}, left_associative: true)
@@ -120,4 +97,51 @@ module Enumerable
120
97
  end
121
98
  end.sum
122
99
  end
100
+ def ir(left_associative: true)
101
+ self.map do |str|
102
+ str.ir(left_associative: left_associative)
103
+ end.sum
104
+ end
105
+ def show(smith=-1, armor=smith, comp=armor.tap{armor=smith}, left_associative: true, para: :power)
106
+ built = self.build(smith, armor, comp, left_associative: left_associative)
107
+ pstr = '%.3f' % built.para_call(para)
108
+ pstr.sub!(/\.?0+\Z/, '')
109
+ puts "Building"
110
+ puts " #{self.join(', ')}"
111
+ puts "with levels (#{smith}, #{armor}, #{comp}) yields (#{pstr}, #{built.total_cost})"
112
+ puts " #{built}"
113
+ end
114
+ def min_levels(w=1, left_associative: true)
115
+ build(-1, -1, -1, left_associative: left_associative).min_levels(w)
116
+ end
117
+ def min_level(w=1, left_associative: true)
118
+ ret = [0, 0]
119
+ build(-1, -1, -1, left_associative: left_associative).min_levels(w).each do |str, level|
120
+ m = /\A\[*([^\+]+)/.match(str)
121
+ if Mgmg::EquipPosition[m[1].build(0).kind] == 0
122
+ ret[0] = [ret[0], level].max
123
+ else
124
+ ret[1] = [ret[1], level].max
125
+ end
126
+ end
127
+ ret
128
+ end
129
+ def min_smith(left_associative: true)
130
+ ret = [0, 0]
131
+ self.each do |str|
132
+ s = Mgmg::Equip.min_smith(str, left_associative: left_associative)
133
+ m = /\A\[*([^\+]+)/.match(str)
134
+ if Mgmg::EquipPosition[m[1].build(0).kind] == 0
135
+ ret[0] = [ret[0], s].max
136
+ else
137
+ ret[1] = [ret[1], s].max
138
+ end
139
+ end
140
+ ret
141
+ end
142
+ def min_comp(left_associative: true)
143
+ self.map do |str|
144
+ Mgmg::Equip.min_comp(str, left_associative: left_associative)
145
+ end.max
146
+ end
123
147
  end