mgmg 1.2.4 → 1.4.0

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.
data/lib/mgmg/equip.rb ADDED
@@ -0,0 +1,392 @@
1
+ module Mgmg
2
+ using Refiner
3
+ class Equip
4
+ ParamList = %w|攻撃 物防 魔防 HP MP 腕力 器用 素早 魔力|
5
+ ElementList = %w|火 地 水|
6
+ EqPosList = %w|武 頭 胴 腕 足 飾|
7
+ def initialize(kind, weight, star, main_m, sub_m, para, element)
8
+ @kind, @weight, @star, @main, @sub, @para, @element = kind, weight, star, main_m, sub_m, para, element
9
+ @total_cost = Vec[0, 0, 0]
10
+ @history, @min_levels = [self], Hash.new
11
+ end
12
+ attr_accessor :kind, :weight, :star, :main, :sub, :para, :element, :total_cost, :history, :min_levels
13
+ def initialize_copy(other)
14
+ @kind = other.kind
15
+ @weight = other.weight
16
+ @star = other.star
17
+ @main = other.main
18
+ @sub = other.sub
19
+ @para = other.para.dup
20
+ @element = other.element.dup
21
+ @total_cost = other.total_cost.dup
22
+ @history = other.history.dup
23
+ @min_levels = other.min_levels.dup
24
+ end
25
+
26
+ def compose(other, level, outsourcing=false)
27
+ self.class.compose(self, other, level, outsourcing)
28
+ end
29
+
30
+ def to_s
31
+ par = @para.map.with_index{|e, i| e==0 ? nil : "#{ParamList[i]}:#{e.comma3}"}.compact
32
+ elm = @element.map.with_index{|e, i| e==0 ? nil : "#{ElementList[i]}#{e}"}.compact
33
+ unless elm.empty?
34
+ par << "EL:#{elm.join('')}"
35
+ end
36
+ if @kind == 28
37
+ ep = @star.map.with_index{|e, i| e==0 ? nil : "#{EqPosList[i]}:#{e}"}.compact
38
+ "複数装備#{@weight}(#{ep.join(', ')})[#{par.join(', ')}]"
39
+ else
40
+ "#{EquipName[@kind]}#{@weight}☆#{@star}(#{MaterialClass[@main]}#{MaterialClass[@sub]})[#{par.join(', ')}]"
41
+ end
42
+ end
43
+ def inspect
44
+ par = @para.map.with_index{|e, i| "#{ParamList[i]}:#{e}"}
45
+ par << ( "EL:" + @element.map.with_index{|e, i| "#{ElementList[i]}#{e}"}.join('') )
46
+ tc = "<コスト:" + @total_cost.map.with_index{|e, i| "#{ElementList[i]}#{e}"}.join('') + '>'
47
+ if @kind == 28
48
+ ep = @star.map.with_index{|e, i| "#{EqPosList[i]}:#{e}"}
49
+ "複数装備#{@weight}(#{ep.join(', ')})[#{par.join(', ')}]#{tc}"
50
+ else
51
+ "#{EquipName[@kind]}#{@weight}☆#{@star}(#{MaterialClass[@main]}#{MaterialClass[@sub]})[#{par.join(', ')}]#{tc}"
52
+ end
53
+ end
54
+
55
+ def min_level
56
+ if @kind == 28
57
+ ret = [0, 0]
58
+ @min_levels.each do |str, ml|
59
+ if str.build(-1).kind < 8
60
+ if ret[0] < ml
61
+ ret[0] = ml
62
+ end
63
+ else
64
+ if ret[1] < ml
65
+ ret[1] = ml
66
+ end
67
+ end
68
+ end
69
+ ret
70
+ else
71
+ @min_levels.values.append(0).max
72
+ end
73
+ end
74
+
75
+ def para_call(para)
76
+ method(para).call
77
+ end
78
+
79
+ %i|attack phydef magdef hp mp str dex speed magic|.each.with_index do |s, i|
80
+ define_method(s){ @para[i] }
81
+ end
82
+ def atkstr
83
+ attack()+str()
84
+ end
85
+ def atk_sd
86
+ attack()+str().quo(2)+dex().quo(2)
87
+ end
88
+ def dex_as
89
+ attack().quo(2)+str().quo(2)+dex()
90
+ end
91
+ def mag_das
92
+ magic()+dex_as().quo(2)
93
+ end
94
+ [:fire, :earth, :water].each.with_index do |s, i|
95
+ define_method(s){ @element[i] }
96
+ end
97
+
98
+ def power
99
+ case @kind
100
+ when 0, 1
101
+ atk_sd()
102
+ when 2, 3
103
+ atkstr()
104
+ when 4
105
+ [dex_as(), mag_das()].max
106
+ when 5
107
+ dex_as()
108
+ when 6, 7
109
+ [magic()*2, atkstr()].max
110
+ when 28
111
+ @para.sum-((hp()+mp())*3.quo(4))
112
+ else
113
+ ret = @para.max
114
+ if ret == magdef()
115
+ ret+magic().quo(2)
116
+ else
117
+ ret
118
+ end
119
+ end
120
+ end
121
+ def magmag
122
+ magdef()+magic().quo(2)
123
+ end
124
+ def fpower
125
+ power().to_f
126
+ end
127
+ def pmdef
128
+ [phydef(), magmag()].min
129
+ end
130
+
131
+ def smith_cost(outsourcing=false)
132
+ if outsourcing
133
+ if @kind < 8
134
+ (@star**2)*2+@para.sum+hp().cdiv(4)-hp()+mp().cdiv(4)-mp()
135
+ else
136
+ (@star**2)+@para.sum+hp().cdiv(4)-hp()+mp().cdiv(4)-mp()
137
+ end
138
+ else
139
+ if @kind < 8
140
+ ((@star**2)*2+@para.sum+hp().cdiv(4)-hp()+mp().cdiv(4)-mp()).div(2)
141
+ else
142
+ ((@star**2)+@para.sum+hp().cdiv(4)-hp()+mp().cdiv(4)-mp()).div(2)
143
+ end
144
+ end
145
+ end
146
+ def comp_cost(outsourcing=false)
147
+ if outsourcing
148
+ [(@star**2)*5+@para.sum+hp().cdiv(4)-hp()+mp().cdiv(4)-mp(), 0].max.div(2)
149
+ else
150
+ [((@star**2)*5+@para.sum+hp().cdiv(4)-hp()+mp().cdiv(4)-mp()).div(2), 0].max.div(2)
151
+ end
152
+ end
153
+ alias :cost :comp_cost
154
+
155
+ def add!(other)
156
+ if @kind == 28
157
+ if other.kind == 28
158
+ @star.add!(other.star)
159
+ else
160
+ @star[EquipPosition[other.kind]] += 1
161
+ end
162
+ else
163
+ @star = Vec.new(6, 0)
164
+ @star[EquipPosition[@kind]] = 1
165
+ @kind = 28
166
+ if other.kind == 28
167
+ @star.add!(other.star)
168
+ else
169
+ @star[EquipPosition[other.kind]] += 1
170
+ end
171
+ end
172
+ @weight += other.weight
173
+ @main, @sub = 12, 12
174
+ @para.add!(other.para)
175
+ @element.add!(other.element)
176
+ @total_cost.add!(other.total_cost)
177
+ @history.concat(other.history)
178
+ @min_levels.merge!(other.min_levels)
179
+ self
180
+ end
181
+ def +(other)
182
+ self.dup.add!(other)
183
+ end
184
+ def coerce(other)
185
+ if other == 0
186
+ zero = self.class.new(28, 0, Vec.new(6, 0), 12, 12, Vec.new(9, 0), Vec.new(3, 0))
187
+ zero.history.clear
188
+ [zero, self]
189
+ else
190
+ raise TypeError, "Mgmg::Equip can't be coerced into other than 0"
191
+ end
192
+ end
193
+ end
194
+
195
+ class << Equip
196
+ def build(str, s_level, c_level, left_associative: true)
197
+ str = Mgmg.check_string(str)
198
+ stack, str = build_sub0([], str)
199
+ build_sub(stack, str, s_level, c_level, left_associative)
200
+ end
201
+ private def build_sub0(stack, str)
202
+ SystemEquip.each do |k, v|
203
+ if Regexp.compile(k).match(str)
204
+ stack << v
205
+ str = str.gsub(k, "<#{stack.length-1}>")
206
+ end
207
+ end
208
+ [stack, str]
209
+ end
210
+ private def build_sub(stack, str, s_level, c_level, lassoc)
211
+ if m = /\A(.*\+?)\[([^\[\]]+)\](\+?[^\[]*)\Z/.match(str)
212
+ stack << build_sub(stack, m[2], s_level, c_level, lassoc)
213
+ build_sub(stack, "#{m[1]}<#{stack.length-1}>#{m[3]}", s_level, c_level, lassoc)
214
+ elsif m = ( lassoc ? /\A(.+)\+(.+?)\Z/ : /\A(.+?)\+(.+)\Z/ ).match(str)
215
+ if c_level < 0
216
+ compose(build_sub(stack, m[1], s_level, c_level, lassoc), build_sub(stack, m[2], s_level, c_level, lassoc), 0, true)
217
+ else
218
+ compose(build_sub(stack, m[1], s_level, c_level, lassoc), build_sub(stack, m[2], s_level, c_level, lassoc), c_level, false)
219
+ end
220
+ elsif m = /\A\<(\d+)\>\Z/.match(str)
221
+ stack[m[1].to_i]
222
+ else
223
+ if s_level < 0
224
+ smith(str, 0, true)
225
+ else
226
+ smith(str, s_level, false)
227
+ end
228
+ end
229
+ end
230
+
231
+ def compose(main, sub, level, outsourcing)
232
+ main_k, sub_k = main.kind, sub.kind
233
+ main_s, sub_s = main.star, sub.star
234
+ main_main, sub_main = main.main, sub.main
235
+ main_sub, sub_sub = main.sub, sub.sub
236
+ para = Vec.new(9, 0)
237
+ ele = Vec.new(3, 0)
238
+
239
+ # 9パラメータ
240
+ coef = Equip9[main_k].dup
241
+ para[] = coef
242
+ para.add!(level).e_div!(2)
243
+ para.e_mul!(sub.para).e_div!(100)
244
+ coef.sub!(Equip9[sub_k])
245
+ coef.add!( 100 + (main_s-sub_s)*5 - ( ( main_main==sub_main && main_main != 9 ) ? 30 : 0 ) )
246
+ coef.add!(Material9[main_main]).sub!(Material9[sub_main])
247
+ coef.e_mul!(EquipFilter[main_k])
248
+ para.e_mul!(coef).e_div!( main_k==sub_k ? 200 : 100 )
249
+ para.add!(main.para)
250
+
251
+ # エレメント
252
+ ele[] = sub.element
253
+ ele.e_mul!([75, level].min).e_div!( main_k==sub_k ? 200 : 100 )
254
+ ele.add!(main.element)
255
+
256
+ ret = new(main_k, main.weight+sub.weight, main_s+sub_s, main_sub, sub_main, para, ele)
257
+ ret.total_cost.add!(main.total_cost).add!(sub.total_cost)
258
+ cc = ret.comp_cost(outsourcing)
259
+ ret.total_cost[1] += cc
260
+ ret.total_cost[main_k < 8 ? 0 : 2] += cc
261
+ ret.min_levels.merge!(main.min_levels, sub.min_levels)
262
+ ret.history = [*main.history, *sub.history, ret]
263
+ ret
264
+ end
265
+
266
+ def smith(str, level, outsourcing)
267
+ str = Mgmg.check_string(str)
268
+ unless m = /\A(.+)\((.+\d+),?(.+\d+)\)\Z/.match(str)
269
+ raise InvalidSmithError.new(str)
270
+ end
271
+ kind = EquipIndex[m[1].to_sym]
272
+ unless kind
273
+ raise InvalidEquipClassError.new(m[1])
274
+ end
275
+ main_m, main_s, main_mc = parse_material(m[2])
276
+ sub_m, sub_s, sub_mc = parse_material(m[3])
277
+ para = Vec.new(9, 0)
278
+ ele = Vec.new(3, 0)
279
+
280
+ # 9パラメータ
281
+ para[] = Equip9[kind]
282
+ para.e_mul!(Main9[main_m]).e_div!(100)
283
+ coef = Sub9[sub_m].dup
284
+ coef.add!(level)
285
+ para.e_mul!(coef).e_div!( main_mc==sub_mc ? 200 : 100 )
286
+
287
+ # エレメント
288
+ ele[] = MainEL[main_m]
289
+ ele.e_mul!(SubEL[sub_m]).e_div!(6)
290
+
291
+ # 重量
292
+ weight = ( ( EquipWeight[kind] + SubWeight[sub_m] - level.div(2) ) * ( MainWeight[main_m] ) ).div(10000)
293
+
294
+ ret = new(kind, ( weight<1 ? 1 : weight ), (main_s+sub_s).div(2), main_mc, sub_mc, para, ele)
295
+ ret.total_cost[kind < 8 ? 0 : 2] += ret.smith_cost(outsourcing)
296
+ ret.min_levels.store(str, str.min_level)
297
+ ret
298
+ end
299
+
300
+ def min_level(str, weight=1)
301
+ str = Mgmg.check_string(str)
302
+ unless m = /\A(.+)\((.+\d+),?(.+\d+)\)\Z/.match(str)
303
+ raise InvalidSmithError.new(str)
304
+ end
305
+ kind = EquipIndex[m[1].to_sym]
306
+ main_m, main_s, = parse_material(m[2])
307
+ sub_m, sub_s, = parse_material(m[3])
308
+
309
+ q, r = ((weight+1)*10000).divmod(MainWeight[main_m])
310
+ l = ( EquipWeight[kind] + SubWeight[sub_m] - q + ( r==0 ? 1 : 0 ) )*2
311
+ [(main_s-1)*3, (sub_s-1)*3, l].max
312
+ end
313
+
314
+ private def parse_material(str)
315
+ m = /\A.+?(\d+)\Z/.match(str)
316
+ mat = MaterialIndex[str.to_sym]
317
+ if m.nil? || mat.nil?
318
+ raise InvalidMaterialError.new(str)
319
+ end
320
+ [mat, m[1].to_i, mat<90 ? mat.div(10) : 9]
321
+ end
322
+
323
+ def min_comp(str, left_associative: true)
324
+ str = Mgmg.check_string(str)
325
+ stack, str = minc_sub0([], str)
326
+ (minc_sub(stack, str, left_associative)[1]-1)*3
327
+ end
328
+ private def minc_sub0(stack, str)
329
+ SystemEquip.each do |k, v|
330
+ if Regexp.compile(k).match(str)
331
+ stack << v.star
332
+ str = str.gsub(k, "<#{stack.length-1}>")
333
+ end
334
+ end
335
+ [stack, str]
336
+ end
337
+ private def minc_sub(stack, str, lassoc)
338
+ if m = /\A(.*\+?)\[([^\[\]]+)\](\+?[^\[]*)\Z/.match(str)
339
+ stack << minc_sub(stack, m[2], lassoc)[0]
340
+ minc_sub(stack, "#{m[1]}<#{stack.length-1}>#{m[3]}", lassoc)
341
+ elsif m = ( lassoc ? /\A(.+)\+(.+?)\Z/ : /\A(.+?)\+(.+)\Z/ ).match(str)
342
+ a, _ = minc_sub(stack, m[1], lassoc)
343
+ b, _ = minc_sub(stack, m[2], lassoc)
344
+ [a+b, [a, b].max]
345
+ elsif m = /\A\<(\d+)\>\Z/.match(str)
346
+ [stack[m[1].to_i], 1]
347
+ else
348
+ [smith(str, 0, true).star, 1]
349
+ end
350
+ end
351
+
352
+ def min_smith(str, left_associative: true)
353
+ str = Mgmg.check_string(str)
354
+ stack, str = mins_sub0([], str)
355
+ (([mins_sub(stack, str, left_associative)]+stack).max-1)*3
356
+ end
357
+ private def mins_sub0(stack, str)
358
+ SystemEquip.each do |k, v|
359
+ if Regexp.compile(k).match(str)
360
+ stack << 0
361
+ str = str.gsub(k, "<#{stack.length-1}>")
362
+ end
363
+ end
364
+ [stack, str]
365
+ end
366
+ private def mins_sub(stack, str, lassoc)
367
+ if m = /\A(.*\+?)\[([^\[\]]+)\](\+?[^\[]*)\Z/.match(str)
368
+ stack << mins_sub(stack, m[2], lassoc)
369
+ mins_sub(stack, "#{m[1]}<#{stack.length-1}>#{m[3]}", lassoc)
370
+ elsif m = ( lassoc ? /\A(.+)\+(.+?)\Z/ : /\A(.+?)\+(.+)\Z/ ).match(str)
371
+ [mins_sub(stack, m[1], lassoc), mins_sub(stack, m[2], lassoc)].max
372
+ elsif m = /\A\<(\d+)\>\Z/.match(str)
373
+ 1
374
+ else
375
+ mins_sub2(str)
376
+ end
377
+ end
378
+ private def mins_sub2(str)
379
+ str = Mgmg.check_string(str)
380
+ unless m = /\A(.+)\((.+\d+),?(.+\d+)\)\Z/.match(str)
381
+ raise InvalidSmithError.new(str)
382
+ end
383
+ kind = EquipIndex[m[1].to_sym]
384
+ unless kind
385
+ raise InvalidEquipClassError.new(m[1])
386
+ end
387
+ main_m, main_s, main_mc = parse_material(m[2])
388
+ sub_m, sub_s, sub_mc = parse_material(m[3])
389
+ [main_s, sub_s].max
390
+ end
391
+ end
392
+ 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