numeron 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in numeron.gemspec
4
+ gemspec
5
+
6
+ group :development, :test do
7
+ gem 'tapp', :git => 'git://github.com/esminc/tapp.git'
8
+ gem 'guard'
9
+ gem 'guard-rspec'
10
+ gem 'fuubar'
11
+ gem 'libnotify', :require => false
12
+ gem 'rb-inotify', :require => false
13
+ gem 'rb-fsevent', :require => false
14
+ gem 'growl', :require => false
15
+ end
@@ -0,0 +1,5 @@
1
+ guard 'rspec' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 kengos
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,109 @@
1
+ # Numeron
2
+
3
+ ヌメロンの解の探索プログラム (Ruby版)
4
+
5
+ Androidアプリ ... https://play.google.com/store/apps/details?id=com.jpn.gemstone.numer0n.android
6
+
7
+ iPhoneアプリ ... https://itunes.apple.com/jp/app/numer0n-numeron/id512484171?mt=8
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'numeron'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install numeron
22
+
23
+ ## Usage
24
+
25
+ ```
26
+ irb
27
+ ```
28
+
29
+ ```
30
+ > require 'numeron'
31
+ true
32
+ > Numeron::Solver.new.run
33
+ Attack number: 123 # <= callした数値を入力
34
+ Eat number: 0 # <= callした結果 eatの数を入力
35
+ Bite number: 0 # <= callした結果 biteの数を入力
36
+ ... thinking
37
+ possibilities: 210 # <= 計算した結果、答えとして可能性がある数値の個数
38
+ Analyzer Answer: 372 # <= Analyzerがおすすめの答えとして選んだ数
39
+ Possibilitiy list random: 798 # <= 答えの可能性の一覧からランダムで選んだ数
40
+
41
+ finish? [yes|no] # <= yes or yで終了, noで続行
42
+ ```
43
+
44
+ ## Numeron::Calculator
45
+
46
+ ヌメロンの解の可能性として考えられるものを計算する部分。
47
+
48
+
49
+ 基本
50
+
51
+ ```ruby
52
+ calc = Numeron::Calculator.new
53
+ calc.input('123', 0, 1) # callした番号, Eatの数, Biteの数
54
+ p calc.possibilities # 答えの可能性の一覧がでてくる
55
+
56
+ # 続いて以下のように245をcallして 2Eat, 0Biteだった場合 11個に絞りこまれる
57
+ calc.input('245', 2, 0)
58
+ p calc.possibilities
59
+ # => ["240", "246", "247", "248", "249", "205", "265", "275", "285", "295", "345"]
60
+ ```
61
+
62
+ Shuffle対応(ほとんどテストはしていない)
63
+
64
+ ```ruby
65
+ calc = Numeron::Calculator.new
66
+ calc.input('123', 0, 3)
67
+ calc.shuffle # シャッフルされた
68
+ p calc.possibilities.size
69
+ # => 6
70
+
71
+ calc = Numeron::Calculator.new
72
+ calc.input('123', 1, 1)
73
+ p calc.possibilities.size
74
+ # => 42
75
+ calc.shuffle
76
+ p calc.possibilities.size
77
+ # => 126
78
+ ```
79
+
80
+ 以下の2つの変数を用いている
81
+
82
+ `@mays`
83
+
84
+ @mays[0]が左側の数値の可能性リスト(初期値0-9)<br>
85
+ @mays[1]が真ん中の数値の可能性リスト(初期値0-9)<br>
86
+ @mays[2]が右側の数値の可能性リスト(初期値0-9)<br>
87
+
88
+ `@possibilities`
89
+
90
+ 解の可能性リスト
91
+
92
+ ## Numeron::Analyzer
93
+
94
+ 案がなかったので、以下3つの分析方法を適当に実装。<br>
95
+ 計算量はまったく考慮していない
96
+
97
+ 0e1bを最悪ケースとして、このケースが出た場合に、最も可能性リストが少なくなる数値を計算する機能
98
+
99
+ 0e1b, 1e0bを最悪ケースとして、これらのケースが出た場合に、最も可能性リストの平均値が少なくなる数値を計算する機能
100
+
101
+ 可能性リスト中から、最も可能性リストが少なくなる数値を計算する機能
102
+
103
+ ## Contributing
104
+
105
+ 1. Fork it
106
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
107
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
108
+ 4. Push to the branch (`git push origin my-new-feature`)
109
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,9 @@
1
+ # coding: utf-8
2
+
3
+ require 'numeron/version'
4
+ require 'numeron/calculator'
5
+ require 'numeron/solver'
6
+ require 'numeron/analyzer'
7
+
8
+ module Numeron
9
+ end
@@ -0,0 +1,140 @@
1
+ # coding: utf-8
2
+
3
+ module Numeron
4
+ class Analyzer
5
+ attr_accessor :calculator
6
+ def initialize(calculator)
7
+ @calculator = calculator
8
+ end
9
+
10
+ # 次の1手の計算
11
+ # @param [Symbol] mode :average or :worst
12
+ # @return [Hash] {recommend: [Array], size: Number}
13
+ def run(mode = :average, options = {})
14
+ case mode
15
+ when :average
16
+ run_average_mode(options[:cases])
17
+ when :worst
18
+ run_worstcase_mode(options[:worst_case])
19
+ when :possibilities
20
+ run_possibilities
21
+ end
22
+ end
23
+
24
+ # 最悪のケースを0e1b, 1e0bと想定し、それぞれの結果が出た際に可能性の平均値が最も少なくなるケースを推定する
25
+ def run_average_mode(cases = nil)
26
+ cases ||= [
27
+ {eat: 0, bite: 1},
28
+ {eat: 1, bite: 0}
29
+ ]
30
+ recommend = []
31
+ min_size = 10000
32
+ all_list.each do |f|
33
+ average = calc_average(f, cases)
34
+ if min_size == average
35
+ recommend << f
36
+ elsif min_size > average
37
+ recommend = [f]
38
+ min_size = average
39
+ end
40
+ end
41
+
42
+ { recommend: recommend, size: min_size }
43
+ end
44
+
45
+ # 最悪のケースを0e1bと推定し、その結果として最も可能性の数が最も少なくなるケースを推定する
46
+ def run_worstcase_mode(worst_case = {})
47
+ worst_case = {eat: 0, bite: 1}.merge(worst_case)
48
+ min_size = 10000
49
+ recommend = []
50
+ all_list.each do |f|
51
+ _calculator = build_calculator
52
+ _calculator.input(f, worst_case[:eat], worst_case[:bite])
53
+ if min_size == _calculator.possibilities.size
54
+ recommend << f
55
+ elsif min_size > _calculator.possibilities.size
56
+ recommend = [f]
57
+ min_size = _calculator.possibilities.size
58
+ end
59
+ end
60
+
61
+ { recommend: recommend, size: min_size }
62
+ end
63
+
64
+ def run_possibilities
65
+ possibilities = @calculator.possibilities.clone
66
+
67
+ recommend = []
68
+ min_size = 10000
69
+ cases = [
70
+ {eat: 0, bite: 0},
71
+ {eat: 0, bite: 1},
72
+ {eat: 0, bite: 2},
73
+ {eat: 1, bite: 0},
74
+ {eat: 1, bite: 1},
75
+ {eat: 2, bite: 0}
76
+ ]
77
+ possibilities.each do |f|
78
+ average = calc_average(f, cases, true)
79
+ if min_size == average
80
+ recommend << f
81
+ elsif min_size > average
82
+ recommend = [f]
83
+ min_size = average
84
+ end
85
+ end
86
+
87
+ { recommend: recommend, size: min_size }
88
+ end
89
+
90
+ # attackの結果、推定される結果に対する可能性の数の平均を計算する
91
+ # @example
92
+ # [10, 20, 10, 0, 5, 0, 5]の場合は ( 10 + 20 + 10 + 5 + 5 ) / 5 = 10
93
+ def calc_average(attack, cases, can_zero = false)
94
+ result = []
95
+ cases.each do |pattern|
96
+ _calculator = build_calculator
97
+ _calculator.input(attack, pattern[:eat], pattern[:bite])
98
+ result << _calculator.possibilities.size
99
+ end
100
+
101
+ n = 0
102
+ sum = 0
103
+ result.each do |f|
104
+ sum = sum + f
105
+ n = n + 1 if f > 0
106
+ end
107
+
108
+ if n > 0
109
+ return sum.to_f / n.to_f
110
+ elsif can_zero
111
+ return 0
112
+ else
113
+ return 10000
114
+ end
115
+ end
116
+
117
+ def build_calculator
118
+ _calculator = Numeron::Calculator.new
119
+ _calculator.possibilities = @calculator.possibilities.clone
120
+ _calculator.mays = @calculator.mays.clone
121
+ _calculator.histories = @calculator.histories.clone
122
+ return _calculator
123
+ end
124
+
125
+ def all_list
126
+ [].tap do |f|
127
+ (0..9).to_a.each { |i|
128
+ (0..9).to_a.each { |j|
129
+ next if i == j
130
+ (0..9).to_a.each { |k|
131
+ next if i == k || j == k
132
+ f << i.to_s + j.to_s + k.to_s
133
+ }
134
+ }
135
+ }
136
+ end
137
+ end
138
+
139
+ end
140
+ end
@@ -0,0 +1,320 @@
1
+ # coding: utf-8
2
+
3
+ module Numeron
4
+ class Calculator
5
+ attr_accessor :histories, :possibilities, :mays
6
+
7
+ def initialize(card_size = 3)
8
+ @histories = []
9
+ @mays = [(0..9).to_a, (0..9).to_a, (0..9).to_a]
10
+ @possibilities = nil
11
+ end
12
+
13
+ def input(attack, eat, bite)
14
+ attack = attack.split(//).map(&:to_i)
15
+ eat = eat.to_i
16
+ bite = bite.to_i
17
+ @histories << {attack: attack, eat: eat, bite: bite}
18
+
19
+ if eat == 0 && bite == 0
20
+ zero_eat_zero_bite(attack)
21
+ elsif eat == 0 && bite == 3
22
+ zero_eat_three_bite(attack)
23
+ elsif eat == 0 && bite == 2
24
+ zero_eat_two_bite(attack)
25
+ elsif eat == 0 && bite == 1
26
+ zero_eat_one_bite(attack)
27
+ elsif eat == 1 && bite == 2
28
+ one_eat_two_bite(attack)
29
+ elsif eat == 1 && bite == 1
30
+ one_eat_one_bite(attack)
31
+ elsif eat == 1 && bite == 0
32
+ one_eat_zero_bite(attack)
33
+ elsif eat == 2 && bite == 0
34
+ two_eat_zero_bite(attack)
35
+ else
36
+ return false
37
+ end
38
+ return true
39
+ end
40
+
41
+ def zero_eat_zero_bite(attack)
42
+ @mays[0] = @mays[0] - attack
43
+ @mays[1] = @mays[1] - attack
44
+ @mays[2] = @mays[2] - attack
45
+
46
+ list = []
47
+ @mays[0].each do |i|
48
+ @mays[1].each do |j|
49
+ next if i == j
50
+ @mays[2].each do |k|
51
+ next if i == k || j == k
52
+ list << validation(i, j, k)
53
+ end
54
+ end
55
+ end
56
+ update_possibilities(list)
57
+ end
58
+
59
+ def zero_eat_one_bite(attack)
60
+ # 各桁のeatの可能性がなくなる
61
+ @mays[0] = @mays[0] - [attack[0]]
62
+ @mays[1] = @mays[1] - [attack[1]]
63
+ @mays[2] = @mays[2] - [attack[2]]
64
+
65
+ list = []
66
+ (@mays[0] - attack).each do |i|
67
+ (@mays[1] - attack).each do |j|
68
+ next if i == j
69
+ list << validation(i, j, attack[0]) if attack[0] != i || attack[0] != j
70
+ list << validation(i, j, attack[1]) if attack[1] != i || attack[1] != j
71
+ end
72
+ end
73
+
74
+ (@mays[0] - attack).each do |i|
75
+ (@mays[2] - attack).each do |k|
76
+ next if i == k
77
+ list << validation(i, attack[0], k) if attack[0] != i || attack[0] != j
78
+ list << validation(i, attack[2], k) if attack[1] != i || attack[1] != j
79
+ end
80
+ end
81
+
82
+ (@mays[1] - attack).each do |j|
83
+ (@mays[2] - attack).each do |k|
84
+ next if j == k
85
+ list << validation(attack[1], j, k) if attack[1] != j || attack[1] != k
86
+ list << validation(attack[2], j, k) if attack[2] != j || attack[2] != k
87
+ end
88
+ end
89
+ update_possibilities(list)
90
+ end
91
+
92
+ def zero_eat_two_bite(attack)
93
+ @mays[0] = @mays[0] - [attack[0]]
94
+ @mays[1] = @mays[1] - [attack[1]]
95
+ @mays[2] = @mays[2] - [attack[2]]
96
+ list = []
97
+
98
+ # 先頭不明
99
+ (@mays[0] - attack).each do |f|
100
+ list << validation(f, attack[0], attack[1])
101
+ list << validation(f, attack[2], attack[0])
102
+ list << validation(f, attack[2], attack[1])
103
+ end
104
+
105
+ # 中央不明
106
+ (@mays[1] - attack).each do |f|
107
+ list << validation(attack[1], f, attack[0])
108
+ list << validation(attack[2], f, attack[0])
109
+ list << validation(attack[2], f, attack[1])
110
+ end
111
+
112
+ # 末尾不明
113
+ (@mays[2] - attack).each do |f|
114
+ list << validation(attack[1], attack[0], f)
115
+ list << validation(attack[1], attack[2], f)
116
+ list << validation(attack[2], attack[0], f)
117
+ end
118
+ update_possibilities(list)
119
+ end
120
+
121
+ def zero_eat_three_bite(attack)
122
+ # 各桁の可能性が2つに絞られる
123
+ @mays[0] = @mays[0] & [attack[1], attack[2]]
124
+ @mays[1] = @mays[1] & [attack[0], attack[2]]
125
+ @mays[2] = @mays[2] & [attack[0], attack[1]]
126
+ list = [
127
+ validation(attack[1], attack[2], attack[0]),
128
+ validation(attack[2], attack[0], attack[1])
129
+ ].compact
130
+ update_possibilities(list)
131
+ end
132
+
133
+ def one_eat_zero_bite(attack)
134
+ list = []
135
+ # 先頭eat
136
+ (@mays[1] - attack).each do |j|
137
+ (@mays[2] - attack).each do |k|
138
+ next if j == k
139
+ list << validation(attack[0], j, k)
140
+ end
141
+ end
142
+
143
+ # 真ん中eat
144
+ (@mays[0] - attack).each do |i|
145
+ (@mays[2] - attack).each do |k|
146
+ next if i == k
147
+ list << validation(i, attack[1], k)
148
+ end
149
+ end
150
+
151
+ # 末尾eat
152
+ (@mays[0] - attack).each do |i|
153
+ (@mays[1] - attack).each do |j|
154
+ next if i == j
155
+ list << validation(i, j, attack[2])
156
+ end
157
+ end
158
+ update_possibilities(list)
159
+ end
160
+
161
+ def one_eat_one_bite(attack)
162
+ list = []
163
+ (@mays[2] - attack).each do |f|
164
+ list << validation(attack[0], attack[2], f)
165
+ end
166
+ (@mays[1] - attack).each do |f|
167
+ list << validation(attack[0], f, attack[1])
168
+ end
169
+ # 2桁目があっている
170
+ (@mays[2] - attack).each do |f|
171
+ list << validation(attack[2], attack[1], f)
172
+ end
173
+ (@mays[0] - attack).each do |f|
174
+ list << validation(f, attack[1], attack[0])
175
+ end
176
+ # 3桁目があっている
177
+ (@mays[0] - attack).each do |f|
178
+ list << validation(f, attack[0], attack[2])
179
+ end
180
+ (@mays[1] - attack).each do |f|
181
+ list << validation(attack[1], f, attack[2])
182
+ end
183
+ update_possibilities(list)
184
+ end
185
+
186
+ def one_eat_two_bite(attack)
187
+ # attack以外の可能性がなくなるので、積
188
+ @mays[0] = @mays[0] & attack
189
+ @mays[1] = @mays[1] & attack
190
+ @mays[2] = @mays[2] & attack
191
+ list = [
192
+ validation(attack[0], attack[2], attack[1]),
193
+ validation(attack[2], attack[1], attack[0]),
194
+ validation(attack[1], attack[0], attack[2])
195
+ ].compact
196
+ update_possibilities(list)
197
+ end
198
+
199
+ def two_eat_zero_bite(attack)
200
+ # 先頭2つがeat
201
+ list = []
202
+ (@mays[2] - attack).each do |k|
203
+ list << validation(attack[0], attack[1], k)
204
+ end
205
+ # 先頭、末尾がeat
206
+ (@mays[1] - attack).each do |j|
207
+ list << validation(attack[0], j, attack[2])
208
+ end
209
+ # 真ん中、末尾がeat
210
+ (@mays[0] - attack).each do |i|
211
+ list << validation(i ,attack[1], attack[2])
212
+ end
213
+ update_possibilities(list)
214
+ end
215
+
216
+ def validation(i, j, k)
217
+ return nil if i == j || i == k || j == k
218
+ if @mays[0].include?(i) && @mays[1].include?(j) && @mays[2].include?(k)
219
+ return i.to_s + j.to_s + k.to_s
220
+ else
221
+ return nil
222
+ end
223
+ end
224
+
225
+ # シャッフル
226
+ def shuffle
227
+ @mays[0] = @mays[0] | @mays[1] | @mays[2]
228
+ @mays[1] = @mays[0] | @mays[1] | @mays[2]
229
+ @mays[2] = @mays[0] | @mays[1] | @mays[2]
230
+ list = []
231
+ @mays[0].each do |i|
232
+ @mays[1].each do |j|
233
+ next if i == j
234
+ @mays[2].each do |k|
235
+ next if i == k || j == k
236
+ list << validation(i, j, k)
237
+ end
238
+ end
239
+ end
240
+ @possibilities = list.compact
241
+ @histories.each do |history|
242
+ eat_and_bite = history[:eat] + history[:bite]
243
+ if eat_and_bite == 1
244
+ one_eat_or_one_bite(history[:attack])
245
+ elsif eat_and_bite == 2
246
+ two_eat_or_two_bite(history[:attack])
247
+ end
248
+ end
249
+ end
250
+
251
+ def one_eat_or_one_bite(attack)
252
+ list = []
253
+ # attack[0] - attack[3]が一桁目に含まれている
254
+ (@mays[1] - attack).each do |j|
255
+ (@mays[2] - attack).each do |k|
256
+ next if j == k
257
+ list << validation(attack[0], j, k)
258
+ list << validation(attack[1], j, k)
259
+ list << validation(attack[2], j, k)
260
+ end
261
+ end
262
+ (@mays[0] - attack).each do |i|
263
+ # attack[0..3]が2桁目に含まれている
264
+ (@mays[2] - attack).each do |k|
265
+ next if i == k
266
+ list << validation(i, attack[0], k)
267
+ list << validation(i, attack[1], k)
268
+ list << validation(i, attack[2], k)
269
+ end
270
+ # attack[0..3]が3桁目に含まれている
271
+ (@mays[1] - attack).each do |j|
272
+ next if i == j
273
+ list << validation(i, j, attack[0])
274
+ list << validation(i, j, attack[1])
275
+ list << validation(i, j, attack[2])
276
+ end
277
+ end
278
+ update_possibilities(list)
279
+ end
280
+
281
+ def two_eat_or_two_bite(attack)
282
+ list = []
283
+ # 末尾が不明
284
+ (@mays[2] - attack).each do |k|
285
+ list << validation(attack[0], attack[1], k)
286
+ list << validation(attack[0], attack[2], k)
287
+ list << validation(attack[1], attack[0], k)
288
+ list << validation(attack[1], attack[2], k)
289
+ list << validation(attack[2], attack[0], k)
290
+ list << validation(attack[2], attack[1], k)
291
+ end
292
+
293
+ # 真ん中が不明
294
+ (@mays[1] - attack).each do |j|
295
+ list << validation(attack[0], j, attack[1])
296
+ list << validation(attack[0], j, attack[2])
297
+ list << validation(attack[1], j, attack[0])
298
+ list << validation(attack[1], j, attack[2])
299
+ list << validation(attack[2], j, attack[0])
300
+ list << validation(attack[2], j, attack[1])
301
+ end
302
+
303
+ # 先頭が不明
304
+ (@mays[0] - attack).each do |i|
305
+ list << validation(i, attack[0], attack[1])
306
+ list << validation(i, attack[0], attack[2])
307
+ list << validation(i, attack[1], attack[0])
308
+ list << validation(i, attack[1], attack[2])
309
+ list << validation(i, attack[2], attack[0])
310
+ list << validation(i, attack[2], attack[1])
311
+ end
312
+ update_possibilities(list)
313
+ end
314
+
315
+ def update_possibilities(possibilities)
316
+ possibilities.compact!
317
+ @possibilities = @possibilities.nil? ? possibilities : possibilities & @possibilities
318
+ end
319
+ end
320
+ end
@@ -0,0 +1,88 @@
1
+ # coding: utf-8
2
+
3
+ module Numeron
4
+ class Solver
5
+ attr_accessor :calc, :card_size
6
+ def initialize
7
+ @calc = Numeron::Calculator.new
8
+ @card_size = 3
9
+ end
10
+
11
+ def run
12
+ while 1
13
+ next unless question
14
+ think
15
+ finish
16
+ end
17
+ end
18
+
19
+ def question
20
+ attack_number = nil
21
+ eat = 0
22
+ bite = 0
23
+ while 1
24
+ print "Attack number: "
25
+ attack_number = STDIN.gets.chomp
26
+ if @card_size == attack_number.split(//).size
27
+ break
28
+ else
29
+ puts 'Required ' + @card_size.to_s + ' digits.'
30
+ end
31
+ end
32
+
33
+ while 1
34
+ while 1
35
+ print "Eat number: "
36
+ eat = STDIN.gets.chomp.to_i
37
+ if @card_size > eat
38
+ break
39
+ else
40
+ puts 'Required less than ' + @card_size.to_s + ' digits.'
41
+ end
42
+ end
43
+
44
+ while 1
45
+ print "Bite number: "
46
+ bite = STDIN.gets.chomp.to_i
47
+ if @card_size >= bite
48
+ break
49
+ else
50
+ print 'Required ' + @card_size.to_s + ' digits or less'
51
+ end
52
+ end
53
+ if eat + bite <= @card_size
54
+ break
55
+ else
56
+ puts "Error, Eat + Bite > " + @card_size.to_s
57
+ end
58
+ end
59
+
60
+ @calc.input(attack_number, eat, bite)
61
+ end
62
+
63
+ def think
64
+ puts "... thinking"
65
+ puts "possibilities: " + @calc.possibilities.size.to_s
66
+ analyzer = Numeron::Analyzer.new(@calc)
67
+ result = @calc.possibilities.size <= 64 ? analyzer.run(:possibilities) : analyzer.run(:average)
68
+ if result[:recommend].size > 0
69
+ puts "Analyzer Answer: " + result[:recommend].sample.to_s
70
+ else
71
+ puts "Calculator Error."
72
+ end
73
+ puts "Possibilitiy list random: " + @calc.possibilities.sample.to_s
74
+ end
75
+
76
+ def finish
77
+ while 1
78
+ print "\nfinish? [yes|no] "
79
+ f = STDIN.gets.chomp
80
+ if(f == 'yes' || f == 'y')
81
+ exit
82
+ elsif f == 'no' || f == 'n'
83
+ break
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,3 @@
1
+ module Numeron
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'numeron/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "numeron"
8
+ gem.version = Numeron::VERSION
9
+ gem.authors = ["kengos"]
10
+ gem.email = ["kengo@kengos.jp"]
11
+ gem.description = %q{numer0nの解を計算します。}
12
+ gem.summary = %q{numer0n solver}
13
+ gem.homepage = "https://github.com/kengos/numeron"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Numeron::Analyzer do
6
+ let(:analyzer) { Numeron::Analyzer.new(calc) }
7
+ describe '#run_average_mode' do
8
+ context '0e1b' do
9
+ let(:calc) { Numeron::Calculator.new.tap{|f| f.input('123', 0, 1) } }
10
+ it do
11
+ result = analyzer.run_average_mode
12
+ result[:recommend].should have(378).items
13
+ result[:size].should == 60.0
14
+ end
15
+ end
16
+ end
17
+
18
+ describe '#run_worstcase_mode' do
19
+ let(:calc) { Numeron::Calculator.new.tap{|f| f.input('123', 0, 1) } }
20
+ it do
21
+ result = analyzer.run_worstcase_mode
22
+ result[:recommend].should have(21).items
23
+ result[:size].should == 72
24
+ end
25
+ end
26
+
27
+ describe '#run_possibilities' do
28
+ let(:calc) { Numeron::Calculator.new.tap{|f| f.input('123', 0, 3) } }
29
+ it do
30
+ result = analyzer.run_possibilities
31
+ result[:recommend].should =~ %w(312 231)
32
+ result[:size].should == 0
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,136 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Numeron::Calculator do
6
+ let(:calc) { Numeron::Calculator.new }
7
+ describe '#input' do
8
+ it "0e0b" do
9
+ calc.input('123', 0, 0)
10
+ calc.possibilities.should have(7 * 6 * 5).items
11
+ end
12
+
13
+ it "0e1b" do
14
+ calc.input('123', 0, 1)
15
+ calc.possibilities.should have(252).items
16
+ end
17
+
18
+ it "0e2b" do
19
+ calc.input('123', 0, 2)
20
+ calc.possibilities.should have(63).items
21
+ calc.input('231', 0, 2)
22
+ calc.possibilities.should have(21).items
23
+ end
24
+
25
+ it "0e3b" do
26
+ calc.input('123', 0, 3)
27
+ calc.possibilities.should =~ %w(231 312)
28
+ calc.input('231', 0, 3)
29
+ calc.possibilities.should =~ %w(312)
30
+ end
31
+
32
+ it "1e0b" do
33
+ calc.input('123', 1, 0)
34
+ calc.possibilities.should have(126).items
35
+ end
36
+
37
+ it "1e1b" do
38
+ calc.input('123', 1, 1)
39
+ calc.possibilities.should have(42).items
40
+ end
41
+
42
+ it "1e2b" do
43
+ calc.input('123', 1, 2)
44
+ calc.possibilities.should =~ %w(132 321 213)
45
+ end
46
+
47
+ it "2e0b" do
48
+ calc.input('123', 2, 0)
49
+ calc.possibilities.should have(21).items
50
+ end
51
+ end
52
+
53
+ describe "#shuffle" do
54
+ it "0e3b" do
55
+ calc.input('123', 0, 3)
56
+ calc.shuffle
57
+ calc.possibilities.should =~ %w(123 132 213 231 312 321)
58
+ end
59
+
60
+ it "2e0b" do
61
+ calc.input('123', 2, 0)
62
+ calc.shuffle
63
+ # 12?, 13?, 21?, 23?, 31?, 32? が3パターン, ? = [0, 4, 5, 6, 7, 8, 9]
64
+ # => 6 * 3 * 7= 126
65
+ calc.possibilities.should have(126).items
66
+ end
67
+
68
+ it "1e1b" do
69
+ calc.input('123', 1, 1)
70
+ calc.shuffle
71
+ calc.possibilities.should have(126).items
72
+ end
73
+
74
+ it "1e0b" do
75
+ calc.input('123', 1, 0)
76
+ calc.shuffle
77
+ calc.possibilities.should have(378).items
78
+ end
79
+ end
80
+
81
+ describe "scenario" do
82
+ it "1e0b, 1e2b" do
83
+ calc.input('348', 1, 0)
84
+ calc.input('123', 1, 2)
85
+ calc.possibilities.should == ['321']
86
+ end
87
+
88
+ it "0e1b, 0e1b 0e0b 1e0b 1e2b" do
89
+ calc.input('123', 0, 1)
90
+ calc.input('210', 0, 1)
91
+ calc.input('340', 0, 0)
92
+ calc.input('562', 1, 0)
93
+ calc.input('892', 1, 2)
94
+ calc.possibilities.should == %w(982)
95
+ end
96
+
97
+ it "3eat is 571" do
98
+ calc.input('123', 0, 1)
99
+ calc.input('245', 0, 1)
100
+ calc.input('367', 0, 1)
101
+ calc.input('890', 0, 0)
102
+ calc.input('416', 0, 1)
103
+ calc.possibilities.should =~ ['571', '751']
104
+ end
105
+
106
+ it "0e1b, 0e1b" do
107
+ calc.input('123', 0, 1)
108
+ calc.input('245', 0, 1)
109
+ calc.possibilities.should have(75).items
110
+ end
111
+
112
+ it "0e1b, 0e1b 2" do
113
+ calc.input('123', 0, 1)
114
+ calc.input('235', 0, 1)
115
+ calc.possibilities.should have(78).items
116
+ end
117
+
118
+ it "0e1b, 0e1b 3" do
119
+ calc.input('123', 0, 1)
120
+ calc.input('145', 0, 1)
121
+ calc.possibilities.should have(90).items
122
+ end
123
+
124
+ it "0e1b, 0e1b 4" do
125
+ calc.input('123', 0, 1)
126
+ calc.input('456', 0, 1)
127
+ calc.possibilities.should have(96).items
128
+ end
129
+
130
+ it "0e1b, 2e0b" do
131
+ calc.input('123', 0, 1)
132
+ calc.input('245', 2, 0)
133
+ calc.possibilities.should have(11).items
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,6 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Numeron do
6
+ end
@@ -0,0 +1,14 @@
1
+ begin
2
+ require 'tapp'
3
+ rescue Exception
4
+ end
5
+
6
+ require 'rspec'
7
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/numeron')
8
+
9
+ RSpec.configure do |config|
10
+ config.mock_with :rspec
11
+ config.treat_symbols_as_metadata_keys_with_true_values = true
12
+ config.filter_run focus: true
13
+ config.run_all_when_everything_filtered = true
14
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: numeron
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - kengos
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-18 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: numer0nの解を計算します。
15
+ email:
16
+ - kengo@kengos.jp
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - Guardfile
24
+ - LICENSE.txt
25
+ - README.md
26
+ - Rakefile
27
+ - lib/numeron.rb
28
+ - lib/numeron/analyzer.rb
29
+ - lib/numeron/calculator.rb
30
+ - lib/numeron/solver.rb
31
+ - lib/numeron/version.rb
32
+ - numeron.gemspec
33
+ - spec/lib/numeron/analyzer_spec.rb
34
+ - spec/lib/numeron/calculator_spec.rb
35
+ - spec/lib/numeron_spec.rb
36
+ - spec/spec_helper.rb
37
+ homepage: https://github.com/kengos/numeron
38
+ licenses: []
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubyforge_project:
57
+ rubygems_version: 1.8.24
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: numer0n solver
61
+ test_files:
62
+ - spec/lib/numeron/analyzer_spec.rb
63
+ - spec/lib/numeron/calculator_spec.rb
64
+ - spec/lib/numeron_spec.rb
65
+ - spec/spec_helper.rb
66
+ has_rdoc: