mastermind_ruby 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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