Haskell は分からない、という、はてブ指数を言い出した人がブックマークでコメントしていたので、同等の処理を Ruby と Python で。
余計なことにユニットテスト付き。
module Enumerable def take_while ret = [] each do |val| break unless yield val ret << val end return ret end end def hindex(array) len = array.size (1..len).zip(array.sort.reverse).take_while do |i, val| val >= i end.size end if $0 == __FILE__ require 'test/unit' class HIndexTest < Test::Unit::TestCase def test_hindex assert_hindex 4, [0, 10, 20, 30, 40] assert_hindex 4, [10, 20, 30, 40] assert_hindex 3, [20, 30, 40] assert_hindex 2, [30, 40] assert_hindex 1, [40] assert_hindex 2, [1, 2, 3] assert_hindex 3, [3, 3, 3] assert_hindex 2, [3, 3] assert_hindex 1, [3] assert_hindex 0, [0, 0] assert_hindex 0, [0] assert_hindex 0, [] end def assert_hindex(expected, input) assert_equal(expected, hindex(input)) end end end
理屈の上では take_while ではなく、select でもいい。
from itertools import count, izip, takewhile def iterlen(iterable): l = 0 for i in iterable: l += 1 return l def hindex(lst): """ >>> hindex([0, 10, 20, 30, 40]) 4 >>> hindex([10, 20, 30, 40]) 4 >>> hindex([20, 30, 40]) 3 >>> hindex([30, 40]) 2 >>> hindex([40]) 1 >>> hindex([1, 2, 3]) 2 >>> hindex([3, 3, 3]) 3 >>> hindex([3, 3]) 2 >>> hindex([3]) 1 >>> hindex([0, 0]) 0 >>> hindex([0]) 0 >>> hindex([]) 0 """ def pred((rank, val)): return val >= rank return iterlen(takewhile(pred, izip(count(1), reversed(sorted(lst))))) def _test(): import doctest doctest.testmod() if __name__ == '__main__': _test()
両者ともテストのコードが一番でかい。