Permalink
Browse files

add ArrayBsearch module

  • Loading branch information...
1 parent b0e178b commit d072e867527276eb531e606bf5c1a995bcc52e25 @seki committed Mar 30, 2013
Showing with 163 additions and 153 deletions.
  1. +144 −134 lib/drip.rb
  2. +19 −19 test/basic.rb
View
@@ -8,140 +8,6 @@ class Drip
INF = 1.0/0.0
def inspect; to_s; end
-
- class ImmutableDrip
- class Generator
- def initialize(pool=[], tag=[])
- @pool = pool
- @tag = tag
- @shared = Hash.new {|h, k| h[k] = k; k}
- @tag.each {|pair| @shared[pair[0]]}
- end
- attr_reader :pool, :tag
-
- def add(key, value, *tag)
- @pool << [key, value]
- idx = @pool.size - 1
- tag.uniq.each do |t|
- @tag << [[@shared[t], key]]
- end
- end
-
- def generate
- tag = @tag.sort
- tag.inject(nil) do |last, kv|
- k = kv[0]
- k[0] = last if k[0] == last
- k[0]
- end
- ImmutableDrip.new(@pool.sort, tag)
- end
- end
-
- def initialize(pool=[], tag=[])
- @pool = pool
- @tag = tag
- end
-
- def fetch(key)
- idx = lower_boundary(@pool, key)
- k, v = @pool[idx]
- k == key ? v.to_a : nil
- end
-
- def read(key, n=1)
- idx = lower_boundary(@pool, key + 1)
- return [] unless idx
- @pool[idx, n].collect {|kv|
- [kv[0], *kv[1].to_a]
- }
- end
-
- def read_tag(key, tag, n=1)
- idx = lower_boundary(@tag, [tag, key + 1])
- return [] unless idx
- @tag[idx, n].find_all {|kv| kv[0][0] == tag}.collect {|kv|
- [kv[0][1], *fetch(kv[0][1])]
- }
- end
-
- def latest?(key, tag)
- return false if @pool.empty?
- if tag
- lower = lower_boundary(@tag, [tag, key])
- upper = upper_boundary(@tag, [tag, INF])
- return lower == upper - 1
- else
- return @pool[-1][0] == key
- end
- end
-
- def head_tag(n, tag)
- lower = lower_boundary(@tag, [tag, 0])
- upper = upper_boundary(@tag, [tag, INF])
- lower = [lower, upper - n].max
- @tag[lower ... upper].collect {|kv|
- [kv[0][1], *fetch(kv[0][1])]
- }
- end
-
- def head(n=1, tag=nil)
- return head_tag(n, tag) if tag
- n = @pool.size < n ? @pool.size : n
- @pool[-n, n].collect {|kv|
- [kv[0], *kv[1].to_a]
- }
- end
-
- def older_tag(key, tag)
- idx = upper_boundary(@tag, [tag, key-1])
- k, v = @tag[idx - 1]
- k && k[0] == tag ? [k[1], *fetch(k[1])] : nil
- end
-
- def older(key, tag=nil)
- return nil if @pool.empty?
- key = @pool[-1][0] + 1 unless key
- return older_tag(key, tag) if tag
- idx = upper_boundary(@pool, key - 1)
- k, v = @pool[idx - 1]
- k && k < key ? [k, *v.to_a] : nil
- end
-
- def newer(key, tag=nil)
- return read(key, 1)[0] unless tag
- read_tag(key, tag, 1)[0]
- end
-
- def lower_boundary(ary, key)
- lower = -1
- upper = ary.size
- while lower + 1 != upper
- mid = (lower + upper).div(2)
- if (ary[mid][0] <=> key) < 0
- lower = mid
- else
- upper = mid
- end
- end
- return upper
- end
-
- def upper_boundary(ary, key)
- lower = -1
- upper = ary.size
- while lower + 1 != upper
- mid = (lower + upper).div(2)
- if (ary[mid][0] <=> key) <= 0
- lower = mid
- else
- upper = mid
- end
- end
- return lower + 1
- end
- end
-
def initialize(dir, option={})
@past = prepare_store(dir, option)
@fence = (@past.head[0][0] rescue 0) || 0
@@ -503,6 +369,150 @@ def renew
end
end
+class Drip
+ module ArrayBsearch
+ module_function
+ def lower_boundary(ary, key)
+ lower = -1
+ upper = ary.size
+ while lower + 1 != upper
+ mid = (lower + upper).div(2)
+ if (ary[mid][0] <=> key) < 0
+ lower = mid
+ else
+ upper = mid
+ end
+ end
+ return upper
+ end
+
+ def upper_boundary(ary, key)
+ lower = -1
+ upper = ary.size
+ while lower + 1 != upper
+ mid = (lower + upper).div(2)
+ if (ary[mid][0] <=> key) <= 0
+ lower = mid
+ else
+ upper = mid
+ end
+ end
+ return lower + 1
+ end
+ end
+end
+
+class Drip
+ class ImmutableDrip
+ include Drip::ArrayBsearch
+
+ class Generator
+ def initialize(pool=[], tag=[])
+ @pool = pool
+ @tag = tag
+ @shared = Hash.new {|h, k| h[k] = k; k}
+ @tag.each {|pair| @shared[pair[0]]}
+ end
+ attr_reader :pool, :tag
+
+ def add(key, value, *tag)
+ @pool << [key, value]
+ idx = @pool.size - 1
+ tag.uniq.each do |t|
+ @tag << [[@shared[t], key]]
+ end
+ end
+
+ def generate
+ tag = @tag.sort
+ tag.inject(nil) do |last, kv|
+ k = kv[0]
+ k[0] = last if k[0] == last
+ k[0]
+ end
+ ImmutableDrip.new(@pool.sort, tag)
+ end
+ end
+
+ def initialize(pool=[], tag=[])
+ @pool = pool
+ @tag = tag
+ end
+
+ def fetch(key)
+ idx = lower_boundary(@pool, key)
+ k, v = @pool[idx]
+ k == key ? v.to_a : nil
+ end
+
+ def read(key, n=1)
+ idx = lower_boundary(@pool, key + 1)
+ return [] unless idx
+ @pool[idx, n].collect {|kv|
+ [kv[0], *kv[1].to_a]
+ }
+ end
+
+ def read_tag(key, tag, n=1)
+ idx = lower_boundary(@tag, [tag, key + 1])
+ return [] unless idx
+ @tag[idx, n].find_all {|kv| kv[0][0] == tag}.collect {|kv|
+ [kv[0][1], *fetch(kv[0][1])]
+ }
+ end
+
+ def latest?(key, tag)
+ return false if @pool.empty?
+ if tag
+ lower = lower_boundary(@tag, [tag, key])
+ upper = upper_boundary(@tag, [tag, INF])
+ return lower == upper - 1
+ else
+ return @pool[-1][0] == key
+ end
+ end
+
+ def head_tag(n, tag)
+ lower = lower_boundary(@tag, [tag, 0])
+ upper = upper_boundary(@tag, [tag, INF])
+ lower = [lower, upper - n].max
+ @tag[lower ... upper].collect {|kv|
+ [kv[0][1], *fetch(kv[0][1])]
+ }
+ end
+
+ def head(n=1, tag=nil)
+ return head_tag(n, tag) if tag
+ n = @pool.size < n ? @pool.size : n
+ @pool[-n, n].collect {|kv|
+ [kv[0], *kv[1].to_a]
+ }
+ end
+
+ def older_tag(key, tag)
+ idx = upper_boundary(@tag, [tag, key-1])
+ k, v = @tag[idx - 1]
+ k && k[0] == tag ? [k[1], *fetch(k[1])] : nil
+ end
+
+ def older(key, tag=nil)
+ return nil if @pool.empty?
+ key = @pool[-1][0] + 1 unless key
+ return older_tag(key, tag) if tag
+ idx = upper_boundary(@pool, key - 1)
+ k, v = @pool[idx - 1]
+ k && k < key ? [k, *v.to_a] : nil
+ end
+
+ def newer(key, tag=nil)
+ return read(key, 1)[0] unless tag
+ read_tag(key, tag, 1)[0]
+ end
+
+ end
+end
+
+
if __FILE__ == $0
require 'my_drip'
MyDrip.invoke
View
@@ -220,30 +220,30 @@ def ignore_test_huge
class TestImmutableDrip < Test::Unit::TestCase
def test_bsearch
- im = Drip::ImmutableDrip.new
+ ab = Drip::ArrayBsearch
- assert_equal(0, im.lower_boundary([], 'c'))
- assert_equal(0, im.upper_boundary([], 'c'))
+ assert_equal(0, ab.lower_boundary([], 'c'))
+ assert_equal(0, ab.upper_boundary([], 'c'))
ary = %w(a b c c c d e f).collect {|x| [x]}
- assert_equal(0, im.lower_boundary(ary, ''))
- assert_equal(0, im.lower_boundary(ary, 'a'))
- assert_equal(1, im.lower_boundary(ary, 'b'))
- assert_equal(2, im.lower_boundary(ary, 'c'))
- assert_equal(5, im.lower_boundary(ary, 'd'))
- assert_equal(6, im.lower_boundary(ary, 'e'))
- assert_equal(7, im.lower_boundary(ary, 'f'))
- assert_equal(8, im.lower_boundary(ary, 'g'))
+ assert_equal(0, ab.lower_boundary(ary, ''))
+ assert_equal(0, ab.lower_boundary(ary, 'a'))
+ assert_equal(1, ab.lower_boundary(ary, 'b'))
+ assert_equal(2, ab.lower_boundary(ary, 'c'))
+ assert_equal(5, ab.lower_boundary(ary, 'd'))
+ assert_equal(6, ab.lower_boundary(ary, 'e'))
+ assert_equal(7, ab.lower_boundary(ary, 'f'))
+ assert_equal(8, ab.lower_boundary(ary, 'g'))
- assert_equal(0, im.upper_boundary(ary, ''))
- assert_equal(1, im.upper_boundary(ary, 'a'))
- assert_equal(2, im.upper_boundary(ary, 'b'))
- assert_equal(5, im.upper_boundary(ary, 'c'))
- assert_equal(6, im.upper_boundary(ary, 'd'))
- assert_equal(7, im.upper_boundary(ary, 'e'))
- assert_equal(8, im.upper_boundary(ary, 'f'))
- assert_equal(8, im.upper_boundary(ary, 'g'))
+ assert_equal(0, ab.upper_boundary(ary, ''))
+ assert_equal(1, ab.upper_boundary(ary, 'a'))
+ assert_equal(2, ab.upper_boundary(ary, 'b'))
+ assert_equal(5, ab.upper_boundary(ary, 'c'))
+ assert_equal(6, ab.upper_boundary(ary, 'd'))
+ assert_equal(7, ab.upper_boundary(ary, 'e'))
+ assert_equal(8, ab.upper_boundary(ary, 'f'))
+ assert_equal(8, ab.upper_boundary(ary, 'g'))
end
def add_to_gen(gen, key, value, *tag)

0 comments on commit d072e86

Please sign in to comment.