numeron 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,32 +1,27 @@
1
1
  # Numeron
2
2
 
3
- ヌメロンの解の探索プログラム (Ruby)
3
+ ヌメロンの解の探索プログラム (Ruby版, 3桁Only)
4
+
5
+ 1. 解として可能性のある数値を自動計算
6
+ 2. Shuffle可能
7
+ 3. 次に出すべき1手を計算してくれるAnalyzer
8
+ 4. シミュレーター付き(要実装)
4
9
 
5
10
  Androidアプリ ... https://play.google.com/store/apps/details?id=com.jpn.gemstone.numer0n.android
6
11
 
7
12
  iPhoneアプリ ... https://itunes.apple.com/jp/app/numer0n-numeron/id512484171?mt=8
8
13
 
9
- ## Installation
10
-
11
- Add this line to your application's Gemfile:
12
-
13
- gem 'numeron'
14
-
15
- And then execute:
16
-
17
- $ bundle
14
+ ## インストール
18
15
 
19
- Or install it yourself as:
16
+ ruby 1.9以上が必要です
20
17
 
21
18
  $ gem install numeron
22
19
 
23
- ## Usage
20
+ ## Solverの使い方
24
21
 
25
- ```
26
- irb
27
- ```
22
+ irbで実行します
28
23
 
29
- ```
24
+ ```ruby
30
25
  > require 'numeron'
31
26
  true
32
27
  > Numeron::Solver.new.run
@@ -41,6 +36,29 @@ Possibilitiy list random: 798 # <= 答えの可能性の一覧からランダム
41
36
  finish? [yes|no] # <= yes or yで終了, noで続行
42
37
  ```
43
38
 
39
+ ## Simulatorの使い方
40
+
41
+ コンピューターが何手で解にたどり着くかのシミュレーションをすることができます。
42
+
43
+ ```ruby
44
+ require 'numeron'
45
+
46
+ simulator = Numeron::Simulator.new
47
+ # 最初にコールする番号
48
+ first_attack = '123'
49
+ # シミュレーションする答えのリスト
50
+ answers = ['403', '256']
51
+
52
+ result = simulator.run(answers, first_attack) do |calculator|
53
+ # ここにシミュレーションしたいコードを書く
54
+ # calculatorはNumeron::Calculatorオブジェクト
55
+ end
56
+
57
+ p result
58
+ ```
59
+
60
+ 詳細は https://github.com/kengos/numeron/blob/master/examples/simulator_example.rb を参照
61
+
44
62
  ## Numeron::Calculator
45
63
 
46
64
  ヌメロンの解の可能性として考えられるものを計算する部分。
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: utf-8
3
+
4
+ require 'numeron'
5
+
6
+ simulator = Numeron::Simulator.new
7
+ # 結果を標準出力
8
+ simulator.verbose = true
9
+
10
+ # 適当に検証用の答えの一覧を作る()内の数値は作成する答えの数
11
+ answers = Numeron::Simulator.build_sample_answers(100)
12
+
13
+ # 最初の攻撃文字列
14
+ first_attack = '123'
15
+
16
+ result = simulator.run(answers, first_attack) do |calculator|
17
+ ## ここにシミュレーションしたいものを記述する(引数はNumeron::Calculator)
18
+ ## 下は計算結果において、正解の可能性のリストから1つランダムで選択するパターン
19
+ ## ちなみに10000件回してみたところ上記の可能性があるリストから1つ抜き出す方法の平均手数は 5.213 であった。
20
+ # calculator.possibilities.sample
21
+
22
+ ## Analyzerを使うパターン
23
+ ## max: 8, min: 2, median: 6, average: 5.74 (n=100)
24
+ # if calculator.possibilities.size > 21
25
+ # analyzer = Numeron::Analyzer.new(calculator)
26
+ # recommend = analyzer.run_worstcase_mode[:recommend]
27
+ # if recommend.size > 0
28
+ # recommend.sample
29
+ # else
30
+ # calculator.possibilities.sample
31
+ # end
32
+ # else
33
+ # calculator.possibilities.sample
34
+ # end
35
+
36
+ ## max: 8, min: 3, median: 6, average: 5.9
37
+ analyzer = Numeron::Analyzer.new(calculator)
38
+ if calculator.possibilities.size > 21
39
+ recommend = analyzer.run_worstcase_mode[:recommend]
40
+ if recommend.size > 0
41
+ recommend.sample
42
+ else
43
+ calculator.possibilities.sample
44
+ end
45
+ else
46
+ recommend = analyzer.run_possibilities[:recommend]
47
+ if recommend.size > 0
48
+ recommend.sample
49
+ else
50
+ calculator.possibilities.sample
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ Numeron::Simulator.calc_statistics(result).each do |k, v|
57
+ puts k.to_s + ': ' + v.to_s
58
+ end
@@ -4,6 +4,7 @@ require 'numeron/version'
4
4
  require 'numeron/calculator'
5
5
  require 'numeron/solver'
6
6
  require 'numeron/analyzer'
7
+ require 'numeron/simulator'
7
8
 
8
9
  module Numeron
9
10
  end
@@ -52,7 +52,7 @@ module Numeron
52
52
  _calculator.input(f, worst_case[:eat], worst_case[:bite])
53
53
  if min_size == _calculator.possibilities.size
54
54
  recommend << f
55
- elsif min_size > _calculator.possibilities.size
55
+ elsif _calculator.possibilities.size > 0 && min_size > _calculator.possibilities.size
56
56
  recommend = [f]
57
57
  min_size = _calculator.possibilities.size
58
58
  end
@@ -67,12 +67,10 @@ module Numeron
67
67
  recommend = []
68
68
  min_size = 10000
69
69
  cases = [
70
- {eat: 0, bite: 0},
71
70
  {eat: 0, bite: 1},
72
71
  {eat: 0, bite: 2},
73
72
  {eat: 1, bite: 0},
74
- {eat: 1, bite: 1},
75
- {eat: 2, bite: 0}
73
+ {eat: 1, bite: 1}
76
74
  ]
77
75
  possibilities.each do |f|
78
76
  average = calc_average(f, cases, true)
@@ -0,0 +1,93 @@
1
+ # coding: utf-8
2
+
3
+ module Numeron
4
+ class Simulator
5
+ attr_accessor :verbose
6
+ def initialize
7
+ @verbose = false
8
+ end
9
+
10
+ def run(answers, first_attack, &block)
11
+ [].tap do |result|
12
+ answers.each {|answer|
13
+ result << {answer: answer, times: calc_answer(answer, first_attack, &block)}
14
+ }
15
+ end
16
+ end
17
+
18
+ # 答えが見つかる回数を計算する
19
+ def calc_answer(answer, first_attack, &block)
20
+ calculator = Numeron::Calculator.new
21
+ times = 1
22
+ result = eat_and_bite(answer, first_attack)
23
+ return times if result[:eat] == 3
24
+ calculator.input(first_attack, result[:eat], result[:bite])
25
+ output(times, first_attack, result[:eat], result[:bite], calculator.possibilities.size)
26
+
27
+ while times <= 20 # 計算機不具合での無限ループ回避
28
+ times += 1
29
+ input = block.call(calculator)
30
+ result = eat_and_bite(answer, input)
31
+ if result[:eat] == 3
32
+ output(times, input, result[:eat], result[:bite], 0)
33
+ break if result[:eat] == 3
34
+ else
35
+ calculator.input(input, result[:eat], result[:bite])
36
+ output(times, input, result[:eat], result[:bite], calculator.possibilities.size)
37
+ end
38
+ end
39
+ times
40
+ end
41
+
42
+ def output(*args)
43
+ if @verbose
44
+ puts args.join(',')
45
+ end
46
+ end
47
+
48
+ def eat_and_bite(answer, input)
49
+ inputs = input.split(//).map(&:to_i)
50
+ answers = answer.split(//).map(&:to_i)
51
+
52
+ # eatの計算
53
+ { eat: 0, bite: 0 }.tap do |result|
54
+ inputs.each_with_index{|f, i|
55
+ if answers[i] == f
56
+ result[:eat] = result[:eat] + 1
57
+ elsif answers.include?(f)
58
+ result[:bite] = result[:bite] + 1
59
+ end
60
+ }
61
+ end
62
+ end
63
+
64
+ def self.build_sample_answers(num = 10)
65
+ lists = []
66
+ (0..9).to_a.each do |i|
67
+ (0..9).to_a.each do |j|
68
+ next if i == j
69
+ (0..9).to_a.each do |k|
70
+ next if i == k || j == k
71
+ lists << i.to_s + j.to_s + k.to_s
72
+ end
73
+ end
74
+ end
75
+
76
+ [].tap do |result|
77
+ num.times { result << lists.sample }
78
+ end
79
+ end
80
+
81
+ def self.calc_statistics(result)
82
+ sum = 0
83
+ _result = []
84
+ result.each do |f|
85
+ sum += f[:times]
86
+ _result << f[:times]
87
+ end
88
+ _result.sort!
89
+
90
+ { max: _result.max, min: _result.min, median: _result[_result.size / 2], average: (sum.to_f / result.size.to_f) }
91
+ end
92
+ end
93
+ end
@@ -64,22 +64,39 @@ module Numeron
64
64
  puts "... thinking"
65
65
  puts "possibilities: " + @calc.possibilities.size.to_s
66
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."
67
+ if @calc.possibilities.size > 2
68
+ result = {recommend: 0}
69
+ if @calc.possibilities.size > 64
70
+ result = analyzer.run_average_mode
71
+ elsif @calc.possibilities.size > 21
72
+ result = analyzer.run_possibilities
73
+ else
74
+ cases = [
75
+ {eat: 0, bite: 0},
76
+ {eat: 0, bite: 1},
77
+ {eat: 0, bite: 2},
78
+ {eat: 1, bite: 0},
79
+ {eat: 1, bite: 1},
80
+ {eat: 2, bite: 0}
81
+ ]
82
+ result = analyzer.run_average_mode(cases)
83
+ end
84
+ if result[:recommend].size > 0
85
+ puts "Analyzer Answer: " + result[:recommend].sample.to_s
86
+ else
87
+ puts "Calculator Error."
88
+ end
72
89
  end
73
90
  puts "Possibilitiy list random: " + @calc.possibilities.sample.to_s
74
91
  end
75
92
 
76
93
  def finish
77
94
  while 1
78
- print "\nfinish? [yes|no] "
95
+ print "\nfinish? [yes] "
79
96
  f = STDIN.gets.chomp
80
97
  if(f == 'yes' || f == 'y')
81
98
  exit
82
- elsif f == 'no' || f == 'n'
99
+ else
83
100
  break
84
101
  end
85
102
  end
@@ -1,3 +1,3 @@
1
1
  module Numeron
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -8,7 +8,7 @@ Gem::Specification.new do |gem|
8
8
  gem.version = Numeron::VERSION
9
9
  gem.authors = ["kengos"]
10
10
  gem.email = ["kengo@kengos.jp"]
11
- gem.description = %q{numer0nの解を計算します。}
11
+ gem.description = %q{numer0nの解を計算します。(Shuffle対応,シミュレーター付き,Analyzer未完成)}
12
12
  gem.summary = %q{numer0n solver}
13
13
  gem.homepage = "https://github.com/kengos/numeron"
14
14
 
@@ -0,0 +1,92 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Numeron::Simulator do
6
+
7
+ describe '#run' do
8
+ let(:simulator) { Numeron::Simulator.new }
9
+ it 'should give a block' do
10
+ result = simulator.run(['308', '259'], '123') do |calculator|
11
+ calculator.possibilities.sample
12
+ end
13
+ result.should have(2).items
14
+ result[0][:answer].should eql '308'
15
+ result[0][:times].should > 0
16
+ result[1][:answer].should eql '259'
17
+ result[1][:times].should > 0
18
+ end
19
+ end
20
+
21
+ describe '#calc_answer' do
22
+ let(:simulator) { Numeron::Simulator.new }
23
+ it 'should give a block' do
24
+ simulator.calc_answer('630', '123') do |calculator|
25
+ calculator.possibilities.sample
26
+ end.should >= 1
27
+ end
28
+ end
29
+
30
+ describe '.build_sample_answers' do
31
+ it { Numeron::Simulator::build_sample_answers(5).should have(5).items }
32
+ end
33
+
34
+ describe '.calc_statistics' do
35
+ let(:result) {
36
+ [
37
+ {times: 4}, {times: 2}, {times: 5}, {times: 4}, {times: 3}
38
+ ]
39
+ }
40
+ it { Numeron::Simulator::calc_statistics(result).should == {max: 5, min: 2, median: 4, average: 3.6} }
41
+ end
42
+
43
+ describe '#eat_and_bite' do
44
+ let(:answer) { '987' }
45
+ subject { Numeron::Simulator.new.eat_and_bite(answer, input) }
46
+
47
+ context '123' do
48
+ let(:input) { '123' }
49
+ it { should == {eat: 0, bite: 0} }
50
+ end
51
+
52
+ context '812' do
53
+ let(:input) { '812' }
54
+ it { should == {eat: 0, bite: 1} }
55
+ end
56
+
57
+ context '871' do
58
+ let(:input) { '871' }
59
+ it { should == {eat: 0, bite: 2} }
60
+ end
61
+
62
+ context '879' do
63
+ let(:input) { '879' }
64
+ it { should == {eat: 0, bite: 3} }
65
+ end
66
+
67
+ context '912' do
68
+ let(:input) { '912' }
69
+ it { should == {eat: 1, bite: 0} }
70
+ end
71
+
72
+ context '971' do
73
+ let(:input) { '971' }
74
+ it { should == {eat: 1, bite: 1} }
75
+ end
76
+
77
+ context '978' do
78
+ let(:input) { '978' }
79
+ it { should == {eat: 1, bite: 2} }
80
+ end
81
+
82
+ context '981' do
83
+ let(:input) { '981' }
84
+ it { should == {eat: 2, bite: 0} }
85
+ end
86
+
87
+ context '987' do
88
+ let(:input) { '987' }
89
+ it { should == {eat: 3, bite: 0} }
90
+ end
91
+ end
92
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: numeron
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ bindir: bin
11
11
  cert_chain: []
12
12
  date: 2012-11-18 00:00:00.000000000 Z
13
13
  dependencies: []
14
- description: numer0nの解を計算します。
14
+ description: numer0nの解を計算します。(Shuffle対応,シミュレーター付き,Analyzer未完成)
15
15
  email:
16
16
  - kengo@kengos.jp
17
17
  executables: []
@@ -24,14 +24,17 @@ files:
24
24
  - LICENSE.txt
25
25
  - README.md
26
26
  - Rakefile
27
+ - examples/simulator_example.rb
27
28
  - lib/numeron.rb
28
29
  - lib/numeron/analyzer.rb
29
30
  - lib/numeron/calculator.rb
31
+ - lib/numeron/simulator.rb
30
32
  - lib/numeron/solver.rb
31
33
  - lib/numeron/version.rb
32
34
  - numeron.gemspec
33
35
  - spec/lib/numeron/analyzer_spec.rb
34
36
  - spec/lib/numeron/calculator_spec.rb
37
+ - spec/lib/numeron/simulator_spec.rb
35
38
  - spec/lib/numeron_spec.rb
36
39
  - spec/spec_helper.rb
37
40
  homepage: https://github.com/kengos/numeron
@@ -61,6 +64,7 @@ summary: numer0n solver
61
64
  test_files:
62
65
  - spec/lib/numeron/analyzer_spec.rb
63
66
  - spec/lib/numeron/calculator_spec.rb
67
+ - spec/lib/numeron/simulator_spec.rb
64
68
  - spec/lib/numeron_spec.rb
65
69
  - spec/spec_helper.rb
66
70
  has_rdoc: