numeron 1.0.0 → 1.1.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/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: