Doge log

Abby CTO 雑賀 力王のオフィシャルサイトです

bisect, bsearch

pythonから引っ張ってくる

class Array
  
  def insert_right(item, lo=0, hi=nil)

    if lo < 0
        raise IndexError.new('lo must be non-negative')
    end
    if hi == nil
        hi = self.length
    end
    while lo < hi
        mid = ((lo+hi)/2).truncate
        if item < self[mid]
          hi = mid
        else 
          lo = mid+1
        end
    end
    self.insert(lo, item)
  end

  def bsearch_right(item, lo=0, hi=nil)

    if lo < 0
        raise IndexError.new('lo must be non-negative')
    end
    if hi == nil
        hi = self.length
    end
    while lo < hi
        mid = ((lo+hi)/2).truncate
        if item < self[mid]
          hi = mid
        else
          lo = mid+1
        end
    end
    return lo
  end
  
  def insert_left(item, lo=0, hi=nil)

    if lo < 0
        raise IndexError.new('lo must be non-negative')
    end
    if hi == nil
        hi = self.length
    end
    while lo < hi
        mid = ((lo+hi)/2).truncate
        if self[mid] < item 
          lo = mid+1
        else
          hi = mid
        end
    end
    self.insert(lo, item)
  end

  def bsearch_left(item, lo=0, hi=nil)

    if lo < 0
        raise IndexError.new('lo must be non-negative')
    end
    if hi == nil
        hi = self.length
    end
    while lo < hi
        mid = ((lo+hi)/2).truncate
        if self[mid] < item
          lo = mid+1
        else
          hi = mid
        end
    end
    return lo
  end
end

先頭が小さくなる。逆も考えてComparetorみたいなの渡す方法のがいいのか。
bsearchはよく境界線(?)を引くのに使う

点数に応じてランク付けをするサンプル。

grades = "FEDCBA"
breakpoints = [30, 44, 66, 75, 85] 
grade = lambda do |total|
  return grades[breakpoints.bsearch_right(total)]
end 
        
p grade.call(66) #=> 'C'

p [33, 99, 77, 44, 12, 88].map{|x|
      grade.call(x)
} #=> ["E", "A", "B", "D", "F", "A"]   

以上、渋谷の駅前のマックからお届けしました!!
(今週は9時ぐらい〜10時ぐらいまで渋谷の駅前のマックでコードを書いてます)