=begin O(1) -> key -> location -> bucket hash(x) -> int ------- | | [ [1, value], [4, value], [40, value] ] ------- | | [ [1, value] ] ------- | | ------- =end def assert_equals(x, y) raise [x, y].inspect unless x == y end class KV def initialize @items = Hash.new do |hash, key| hash[key] = [] end end def set(key, value) @items[key] << [Time.now.to_i, value] end def get(key, at = nil) if at @items[key].bsearch { |(timestamp, _value)| timestamp <= at }&.at(-1) else @items[key].last&.at(-1) end end end kv = KV.new kv.set('foo', 'bar') # challenge 1 assert_equals(kv.get('foo'), 'bar') kv.set(42, 'forty two') assert_equals(kv.get(42), 'forty two') assert_equals(kv.get('baz'), nil) # challenge 2 kv.set('foo', 'bar') now = Time.now.to_i sleep(3) kv.set('foo', 'bar2') assert_equals(kv.get('foo'), 'bar2') assert_equals(kv.get('foo', now), 'bar') # challenge 3 assert_equals(kv.get('foo', now + 1), 'bar') assert_equals(kv.get('foo', now + 2), 'bar') puts 'yay!'