Skip to content

Commit 7db19db

Browse files
committed
initialize array with empty strings
- use @cursor to determine Ring#full? - update test to match
1 parent 32f23d1 commit 7db19db

File tree

3 files changed

+48
-51
lines changed

3 files changed

+48
-51
lines changed

examples/oracle.rb

+6-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
include CompSci
55

6-
model = Oracle::Model.new
6+
model = Oracle::Model.new(3)
77

88
quit = false
99

@@ -16,16 +16,17 @@
1616
line.each_char { |c|
1717
pred = model.prediction
1818
if pred
19-
puts format("Predicted: %s %.2f\tGot: %s\t%s\t%.2f%% CORRECT",
19+
puts model
20+
puts format("Predicted: %s %.2f\tGot: %s\t%s",
2021
pred[:best_key],
2122
pred[:best_pct] * 100,
2223
c,
23-
pred[:best_key] == c ? 'CORRECT ' : 'INCORRECT',
24-
model.correct_pct * 100)
24+
pred[:best_key] == c ? 'CORRECT ' : 'INCORRECT')
25+
2526
end
2627
model.update(c)
2728
}
28-
puts model
29+
# puts model
2930
end
3031
puts
3132
end

lib/compsci/oracle.rb

+40-43
Original file line numberDiff line numberDiff line change
@@ -9,37 +9,29 @@ module Oracle
99
# We use a cursor and modulo to pick where to insert.
1010
# The last 5 chars are not BBAAA but AAABB.
1111
class Ring
12-
attr_reader :count, :cursor, :storage
12+
attr_reader :limit, :cursor, :storage
1313

14-
def initialize(count = 5)
15-
@count = count
14+
def initialize(limit = 5)
15+
@limit = limit
1616
@cursor = 0
17-
@storage = Array.new
17+
@storage = Array.new(@limit, '')
1818
end
1919

2020
def update(val)
21-
@storage[@cursor % @count] = val
21+
@storage[@cursor % @limit] = val
2222
@cursor += 1
2323
self
2424
end
2525

2626
def to_s
27-
if @cursor < @count
28-
@storage
29-
else
30-
cursor = @cursor % @count
31-
@storage[cursor, @count - cursor] + @storage[0, cursor]
32-
end.join
27+
cursor = @cursor % @limit
28+
# steep:ignore:start
29+
(@storage[cursor, @limit - cursor] + @storage[0, cursor]).join
30+
# steep:ignore:end
3331
end
3432

3533
def full?
36-
if @storage.count < @count
37-
false
38-
elsif @storage.count == @count
39-
true
40-
else
41-
raise("@storage.count too large: #{@storage.inspect}")
42-
end
34+
@cursor >= @limit
4335
end
4436
end
4537

@@ -50,7 +42,7 @@ class Model
5042
def self.summarize(hsh)
5143
best_key = nil
5244
best_val = 0
53-
best_pct = 0
45+
best_pct = 0.0
5446

5547
total = hsh.values.sum
5648
pct = {}
@@ -72,36 +64,48 @@ def self.summarize(hsh)
7264

7365
attr_reader :ring, :freq, :pred
7466

75-
def initialize(count = 5)
76-
@ring = Ring.new(count)
67+
def initialize(limit = 5)
68+
@ring = Ring.new(limit)
7769
@freq = Hash.new
7870
@pred = Hash.new(0)
7971
end
8072

8173
def to_s
82-
format("%s\t%s", @ring, self.prediction)
74+
format("%s\t%.1f%%", @ring, self.percentage)
75+
end
76+
77+
# Rational 0..1, correct / total
78+
def ratio
79+
return 1r if @pred.empty?
80+
Rational(@pred[:correct], @pred[:correct] + @pred[:incorrect])
81+
end
82+
83+
# Float 0.0..100.0 based on ratio
84+
def percentage
85+
(self.ratio * 100.0).round(1).to_f # convince steep it's a Float
8386
end
8487

85-
# [0..1]
86-
def correct_pct
87-
return 1 if @pred.empty?
88-
@pred[:correct] / (@pred[:correct] + @pred[:incorrect]).to_f
88+
def prediction
89+
h = @freq[@ring.to_s] and Model.summarize(h)
8990
end
9091

9192
def update(val)
93+
# only make predictions once the ring is full
9294
if @ring.full?
93-
key = @ring.to_s
94-
@freq[key] ||= Hash.new(0)
95-
@freq[key][val] += 1
96-
end
97-
pred = self.prediction
98-
if pred
99-
if val == pred[:best_key]
100-
@pred[:correct] += 1
101-
else
102-
@pred[:incorrect] += 1
95+
buf = @ring.to_s
96+
97+
# update @pred if we've seen this sequence before
98+
if (h = @freq[buf])
99+
pred = Model.summarize(h)
100+
@pred[(val == pred[:best_key]) ? :correct : :incorrect] += 1
103101
end
102+
103+
# update @freq
104+
@freq[buf] ||= Hash.new(0)
105+
@freq[buf][val] += 1
104106
end
107+
108+
# update @ring
105109
@ring.update(val)
106110
self
107111
end
@@ -111,13 +115,6 @@ def accept(str)
111115
str.each_char { |c| self.update(c) }
112116
self
113117
end
114-
115-
def prediction
116-
if @ring.full?
117-
h = @freq[@ring.to_s]
118-
Model.summarize(h) if h and !h.empty?
119-
end
120-
end
121118
end
122119
end
123120
end

test/oracle.rb

+2-3
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@
99
describe Ring do
1010
it "has a limited number of slots" do
1111
r = Ring.new(3)
12-
expect(r.count).must_equal 3
13-
expect(r.storage.count).wont_equal 3
14-
expect(r.storage.count).must_equal 0
12+
expect(r.limit).must_equal 3
13+
expect(r.storage.count).must_equal 3
1514

1615
r.update(1)
1716
r.update(2)

0 commit comments

Comments
 (0)