Skip to content

Commit d74aad3

Browse files
committed
Template Method Pattern
1 parent 19587c4 commit d74aad3

10 files changed

+240
-0
lines changed

TemplateMethod/TemplateMethod.pdf

100 KB
Binary file not shown.

TemplateMethod/binary.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
class Binary < Participant
3+
4+
def init_limits(lower, upper)
5+
num = (lower+upper)/2
6+
end
7+
8+
def do_play(lower, num, upper)
9+
while ((result = @oracle.is_this_the_number?(num)) != :correct) && (@num_attempts <= @max_num_attempts) do
10+
if result == :less_than
11+
upper = num-1
12+
elsif result == :greater_than
13+
lower = num+1
14+
end
15+
num=init_limits(lower, upper)
16+
@num_attempts+=1
17+
end
18+
end
19+
20+
end

TemplateMethod/linear.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
class Linear < Participant
3+
4+
def init_limits(lower, upper)
5+
num = lower
6+
end
7+
8+
def do_play(lower, num, upper)
9+
while @oracle.is_this_the_number?(num)!=:correct && (@num_attempts <= @max_num_attempts) do
10+
num+=1
11+
@num_attempts+=1
12+
end
13+
end
14+
end

TemplateMethod/main.rb

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
2+
# Evaluate the performance of participants using different guessing strategies
3+
4+
require_relative 'oracle.rb'
5+
require_relative 'participant.rb'
6+
require_relative 'random_.rb'
7+
require_relative 'linear.rb'
8+
require_relative 'smart_random.rb'
9+
require_relative 'binary.rb'
10+
require_relative 'play_game.rb'
11+
12+
NUM_OF_RUNS = 8
13+
14+
oracle = Oracle.new
15+
16+
total_num_attempts = 0
17+
total_num_failures = 0
18+
19+
20+
players = Array.new
21+
22+
players.push(PlayGame.new(Random_.new(1,NUM_OF_RUNS, oracle, max_num_attempts: NUM_OF_RUNS*2)))
23+
players.push(PlayGame.new(Linear.new(1,NUM_OF_RUNS, oracle, max_num_attempts:NUM_OF_RUNS*2)))
24+
players.push(PlayGame.new(SmartRandom.new(1,NUM_OF_RUNS, oracle, max_num_attempts:NUM_OF_RUNS*5)))
25+
players.push(PlayGame.new(Binary.new(1,NUM_OF_RUNS, oracle, max_num_attempts:NUM_OF_RUNS*5)))
26+
27+
player = Binary.new(1,NUM_OF_RUNS, oracle, max_num_attempts:NUM_OF_RUNS*5)
28+
player.play
29+
30+
players.each { |player|
31+
total_num_attempts = 0
32+
total_num_failures = 0
33+
1.upto(NUM_OF_RUNS) do |i|
34+
oracle.secret_number = i
35+
player.reset
36+
if player.play==:success
37+
total_num_attempts += player.num_attempts
38+
else
39+
total_num_failures += 1
40+
end
41+
end
42+
puts "play #{player.player_name} took on average #{total_num_attempts/(NUM_OF_RUNS-total_num_failures)} attempts to succeed"
43+
}
44+
45+
46+

TemplateMethod/oracle.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
# Knows the number the participants are trying to guess
3+
class Oracle
4+
attr_writer :secret_number
5+
6+
def initialize(secret_num:0)
7+
@secret_number = secret_num
8+
end
9+
10+
def is_this_the_number? num
11+
if num == @secret_number
12+
:correct
13+
elsif num > @secret_number
14+
:less_than
15+
elsif num < @secret_number
16+
:greater_than
17+
end
18+
end
19+
20+
end

TemplateMethod/participant.rb

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
2+
require_relative 'oracle.rb'
3+
4+
# Tries to guess the 'secret' number using several different strategies
5+
class Participant
6+
attr_accessor :num_attempts, :oracle
7+
attr_reader :lower, :upper
8+
9+
def initialize(lower, upper, oracle, max_num_attempts:10)
10+
@oracle, @max_num_attempts, @lower, @upper = oracle, max_num_attempts, lower, upper
11+
@num_attempts = 0
12+
end
13+
14+
#Template method
15+
def play
16+
num = init_limits(@lower, @upper)
17+
@num_attempts+=1
18+
do_play(@lower, num, @upper)
19+
compare
20+
end
21+
22+
def init_limits(lower, upper)
23+
raise "Abstract method called"
24+
end
25+
26+
def do_play(lower, num, upper)
27+
raise "Abstract method called"
28+
end
29+
30+
def compare
31+
if (@num_attempts <= @max_num_attempts)
32+
:success
33+
else
34+
fail
35+
end
36+
end
37+
38+
def reset
39+
@num_attempts = 0
40+
end
41+
42+
private
43+
def fail
44+
:fail
45+
end
46+
47+
end

TemplateMethod/participant_spec.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
require 'rspec'
2+
require_relative 'participant'
3+
require_relative 'oracle'
4+
5+
rand_values = [10, 7, 4, 9, 6, 5, 2, 8, 1, 3, 0] # for rand
6+
7+
describe 'participant behaviour' do
8+
9+
before do
10+
@oracle = Oracle.new(secret_num:4)
11+
@participant = Participant.new(@oracle, max_num_attempts:5)
12+
allow(Kernel).to receive(:rand).and_return(*rand_values) # mocking Kernel.rand
13+
end
14+
15+
it 'guesses the number 4 in 3 attempts using play_randomly' do
16+
expect(@participant.play(0, 10)).to eq(:success)
17+
expect(@participant.num_attempts).to eq(3)
18+
end
19+
20+
it 'guesses the number 4 in 5 attempts using play_linear' do
21+
expect(@participant.play(0, 0)).to eq(:success)
22+
expect(@participant.num_attempts).to eq(5)
23+
end
24+
25+
it 'guesses the number 4 in 3 attempts using play_smart_random' do
26+
expect(@participant.play(0, 10)).to eq(:success)
27+
expect(@participant.num_attempts).to eq(3)
28+
end
29+
30+
it 'guesses the number 4 in 4 attempts using play_binary_search' do
31+
expect(@participant.play(0, 10)).to eq(:success)
32+
expect(@participant.num_attempts).to eq(4)
33+
end
34+
35+
end

TemplateMethod/play_game.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
class PlayGame
3+
4+
5+
def initialize(player)
6+
@player = player
7+
end
8+
9+
def play
10+
@player.play
11+
end
12+
13+
def reset
14+
@player.reset
15+
end
16+
17+
def num_attempts
18+
@player.num_attempts
19+
end
20+
21+
def player_name
22+
@player.class.name
23+
end
24+
end

TemplateMethod/random_.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
class Random_ < Participant
3+
4+
def init_limits(lower, upper)
5+
num = Kernel.rand(lower..upper)
6+
end
7+
8+
def do_play(lower, num, upper)
9+
while @oracle.is_this_the_number?(num)!=:correct && (@num_attempts <= @max_num_attempts) do
10+
num = init_limits(lower, upper)
11+
@num_attempts+=1
12+
end
13+
end
14+
15+
end

TemplateMethod/smart_random.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
class SmartRandom < Participant
3+
4+
def init_limits(lower, upper)
5+
num = Kernel.rand(lower..upper)
6+
end
7+
8+
def do_play(lower, num, upper)
9+
while ((result = @oracle.is_this_the_number?(num)) != :correct) && (@num_attempts <= @max_num_attempts) do
10+
if result == :less_than
11+
upper = num-1
12+
elsif result == :greater_than
13+
lower = num+1
14+
end
15+
num = init_limits(lower, upper)
16+
@num_attempts+=1
17+
end
18+
end
19+
end

0 commit comments

Comments
 (0)