mastermind_ruby 0.0.4 → 0.0.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 26d01f387e4fb94d8102ab2a0f6e2ed6a2d898ef
4
- data.tar.gz: bee194613ef7e7df4a2bad11920a5fe8ed6e9f72
3
+ metadata.gz: bbcb52ce824fef8cce1bce5461618f53133a32a3
4
+ data.tar.gz: b708ecc974c04d200f814460b896844badcaa40c
5
5
  SHA512:
6
- metadata.gz: fac781566dc456a832bb6834a5f928f200a943e5eece7ee821b2fb8c0fd76f93c6355c361db9d81d3fffa15964e55ac60d503e458621d8f41d10373294044aec
7
- data.tar.gz: 2f9646f64a4a0b5d9ff49c18e3936a6527afa370a354465c4159636c02e4a8911a37a66a6a40456f7f0809d6b13c52bb3df3d17c104e4d036489e6072f7f6992
6
+ metadata.gz: 13ccf32aa18f9e82191c6293a6258f3b2e3f640f655d4ebb8a6476543c0c4c129f986dbdfe9715353d5e914567dd460c602d49042468278a2def6169162e300f
7
+ data.tar.gz: f44a9251273c8efb78049c44eb86898c7155fc1503941c1b72580e133b658b587d736a78f4a40e9e72ba8c951206398c4418dde6412b222ee128b752f81a623d
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mastermind_ruby (0.0.4)
4
+ mastermind_ruby (0.0.5)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/Rakefile CHANGED
@@ -2,9 +2,26 @@ require "bundler/gem_tasks"
2
2
 
3
3
  task :default => :test
4
4
 
5
+ desc 'Run all solvers'
6
+ task :solve => ["solve:intelligent_brute_force", "solve:brute_force"]
7
+
5
8
  desc 'Run all tests'
6
9
  task :test => ["test:unit", "test:integration"]
7
10
 
11
+ namespace :solve do
12
+ desc 'Brute force solve'
13
+ task :brute_force do
14
+ puts "----------- Running brute force solve ------------"
15
+ require_relative 'lib/mastermind_ruby/solver/brute_force_solver.rb'
16
+ end
17
+
18
+ desc 'Intelligent brute force solve'
19
+ task :intelligent_brute_force do
20
+ puts "----------- Intelligent brute force solve ------------"
21
+ require_relative 'lib/mastermind_ruby/solver/intelligent_brute_force_solver.rb'
22
+ end
23
+ end
24
+
8
25
  namespace :test do
9
26
  desc 'Run all unit tests'
10
27
  task :unit do
@@ -21,6 +38,10 @@ namespace :test do
21
38
  end
22
39
  end
23
40
 
41
+ task :statistics do
42
+ trap(0) { system "bin/statistics" }
43
+ end
44
+
24
45
  task :run do
25
46
  trap(0) { system "exe/mastermind" }
26
47
  end
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../lib/mastermind_ruby/solver/brute_force_solver'
3
+ require_relative '../lib/mastermind_ruby/solver/intelligent_brute_force_solver'
4
+ require 'benchmark'
5
+
6
+ def show_wait_spinner(fps=10)
7
+ chars = %w[| / - \\]
8
+ delay = 1.0/fps
9
+ iter = 0
10
+ spinner = Thread.new do
11
+ while iter do # Keep spinning until told otherwise
12
+ print chars[(iter+=1) % chars.length]
13
+ sleep delay
14
+ print "\b"
15
+ end
16
+ end
17
+ yield.tap{ # After yielding to the block, save the return value
18
+ iter = false # Tell the thread to exit, cleaning up after itself…
19
+ spinner.join # …and wait for it to do so.
20
+ } # Use the block's return value as the method's
21
+ end
22
+
23
+ def standard_devitation(arr)
24
+ avg = arr.inject(:+) / arr.length
25
+ devitations = arr.map do |item|
26
+ (item - avg)**2
27
+ end
28
+ Math.sqrt(devitations.inject(:+) / arr.length)
29
+ end
30
+
31
+ def median(arr)
32
+ sorted = arr.sort
33
+ len = sorted.length
34
+ (sorted[(len - 1) / 2] + sorted[len / 2]) / 2.0
35
+ end
36
+
37
+ # Game count input
38
+ games = 10
39
+ print 'How many games should the solvers solve: '
40
+ games_input = gets.strip.to_i
41
+ unless games_input == 0
42
+ games = games_input
43
+ end
44
+
45
+ # Code length input
46
+ code_length = 4
47
+ print 'Code length (Hit enter for default): '
48
+ code_length_input = gets.strip.to_i
49
+ unless code_length_input == 0
50
+ code_length = code_length_input
51
+ end
52
+
53
+ solvers = [IntelligentBruteForceSolver, BruteForceSolver]
54
+ counts = {}
55
+ benchmarks = {}
56
+
57
+ puts "Generating statistics..."
58
+
59
+ show_wait_spinner{
60
+ games.times do
61
+ generated_code = MastermindRuby::Code.random(code_length)
62
+ solvers.each do |solver_class|
63
+ counts[solver_class] ||= []
64
+ benchmarks[solver_class] ||= []
65
+ solver = solver_class.new(code_length: code_length)
66
+ ui = SolveInterface.new(solver)
67
+ game = MastermindRuby::Game.new(ui, solution: generated_code)
68
+ time = Benchmark.realtime do
69
+ game.start
70
+ end
71
+ benchmarks[solver_class] << time
72
+ counts[solver_class] << ui.current_try
73
+ end
74
+ end
75
+ }
76
+ puts "------------------ Statistics for #{games} games with code length #{code_length} ----------------"
77
+ puts ''
78
+ solvers.each do |solver|
79
+ tries = counts[solver].sort
80
+ puts "---------- #{solver} -----------"
81
+ puts "- Total time needed to solve \033[1m#{games}\033[0m games: \033[1m#{'%.4f' % benchmarks[solver].inject(:+)}\033[0m seconds"
82
+ puts "- Total: \033[1m#{tries.inject(:+)}\033[0m tries"
83
+ puts "- Average per game: \033[1m#{tries.inject(:+) / tries.length}\033[0m tries"
84
+ puts "- Standard devitation: \033[1m#{'%.4f' % standard_devitation(tries)}\033[0m"
85
+ puts "- Median: \033[1m#{median(tries)}\033[0m"
86
+ puts "- Best: \033[1m#{tries.first}\033[0m tries"
87
+ puts "- Worst: \033[1m#{tries.last}\033[0m tries"
88
+ end
@@ -83,6 +83,10 @@ module MastermindRuby
83
83
  end
84
84
  end
85
85
 
86
+ def count(obj)
87
+ @code.count(obj)
88
+ end
89
+
86
90
  def ===(other)
87
91
  other === to_s
88
92
  end
@@ -61,7 +61,7 @@ module MastermindRuby
61
61
  end
62
62
 
63
63
  # Method which is called when the guess was not a valid code
64
- def display_invalid_code
64
+ def display_invalid_code(code)
65
65
  puts 'Invalid code'
66
66
  end
67
67
 
@@ -49,7 +49,7 @@ module MastermindRuby
49
49
  @ui.display_assessment(result)
50
50
  end
51
51
  else
52
- @ui.display_invalid_code
52
+ @ui.display_invalid_code(guess)
53
53
  end
54
54
  end
55
55
  end
@@ -0,0 +1,23 @@
1
+ require_relative 'solve_interface'
2
+
3
+ class BruteForceSolver
4
+ attr_reader :code_length
5
+
6
+ def initialize(code_length: 4)
7
+ @code_length = code_length
8
+ @input = generate_start_codes
9
+ end
10
+
11
+ def request_quess(count)
12
+ MastermindRuby::Code.parse(@input[count])
13
+ end
14
+
15
+ def generate_start_codes
16
+ MastermindRuby::Code::AVAILABLE_CHARACTERS.repeated_permutation(@code_length).map &:join
17
+ end
18
+
19
+ def assessment_received(result)
20
+ # idiot solver ignores what assessment is received
21
+ end
22
+
23
+ end
@@ -0,0 +1,40 @@
1
+ require_relative 'solve_interface'
2
+
3
+ class IntelligentBruteForceSolver
4
+ attr_reader :code_length
5
+
6
+ def initialize(code_length: 4)
7
+ @code_length = code_length
8
+ @basic_codes = generate_start_codes
9
+ @basic_try = -1
10
+ @code_try = -1
11
+ @existing_chars = []
12
+ end
13
+
14
+ def request_quess(count)
15
+ if @basic_try < 5
16
+ @basic_try += 1
17
+ MastermindRuby::Code.parse(@basic_codes[@basic_try])
18
+ else
19
+ @code_try += 1
20
+ @tryable_codes ||= generate_codes
21
+ MastermindRuby::Code.new(@tryable_codes[@code_try])
22
+ end
23
+ end
24
+
25
+ def assessment_received(result)
26
+ unless result == @code_length.times.map { '-' }.join
27
+ result.count('B').times { @existing_chars << MastermindRuby::Code::AVAILABLE_CHARACTERS[@basic_try] }
28
+ end
29
+ end
30
+
31
+ def generate_start_codes
32
+ MastermindRuby::Code::AVAILABLE_CHARACTERS.map do |char|
33
+ char * @code_length
34
+ end
35
+ end
36
+
37
+ def generate_codes
38
+ @existing_chars.permutation.to_a.uniq
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ require_relative '../../mastermind_ruby'
2
+
3
+
4
+ class SolveInterface
5
+ attr_reader :current_try
6
+
7
+ def initialize(solver)
8
+ @solver = solver
9
+ @code_length = solver.code_length
10
+ @current_try = -1
11
+ end
12
+
13
+ def read_playername
14
+ @solver.class.name
15
+ end
16
+
17
+ def read_code_length
18
+ @code_length
19
+ end
20
+
21
+ def read_next_guess(try_count)
22
+ @current_try += 1
23
+ @solver.request_quess(try_count -1)
24
+ end
25
+
26
+ def display_welcome_message(playername)
27
+ end
28
+
29
+ def display_assessment(result)
30
+ @solver.assessment_received(result)
31
+ end
32
+
33
+ def display_invalid_code(code)
34
+ raise ArgumentError, "#{code.inspect} is not a valid code"
35
+ # raise ArgumentError.new('Please enter a valid code')
36
+ end
37
+
38
+ def display_end_game(try_count)
39
+ end
40
+ end
@@ -1,3 +1,3 @@
1
1
  module MastermindRuby
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -3,7 +3,7 @@ require_relative 'lib/mastermind_ruby/version'
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'mastermind_ruby'
5
5
  s.version = MastermindRuby::VERSION
6
- s.date = '2015-08-06'
6
+ s.date = '2015-08-10'
7
7
  s.summary = "A mastermind library"
8
8
  s.description = "Mastermind or Master Mind is a code-breaking game for two players.
9
9
  The modern game with pegs was invented in 1970 by Mordecai Meirowitz, an Israeli postmaster and telecommunications expert.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mastermind_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yves Siegrist
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2015-08-06 00:00:00.000000000 Z
12
+ date: 2015-08-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -58,11 +58,15 @@ files:
58
58
  - Rakefile
59
59
  - TODO.md
60
60
  - bin/rake
61
+ - bin/statistics
61
62
  - exe/mastermind
62
63
  - lib/mastermind_ruby.rb
63
64
  - lib/mastermind_ruby/code.rb
64
65
  - lib/mastermind_ruby/console_interface.rb
65
66
  - lib/mastermind_ruby/game.rb
67
+ - lib/mastermind_ruby/solver/brute_force_solver.rb
68
+ - lib/mastermind_ruby/solver/intelligent_brute_force_solver.rb
69
+ - lib/mastermind_ruby/solver/solve_interface.rb
66
70
  - lib/mastermind_ruby/version.rb
67
71
  - mastermind_ruby.gemspec
68
72
  homepage: https://github.com/Elektron1c97/Mastermind_ruby