import numpy as np

def count1(x):
    """stefan-2: Improved memory footprint.

    """
    sort_idx = np.argsort(x)
    x_sorted = x[sort_idx]

    jumps = np.hstack([[0], np.where(np.diff(x_sorted) > 0)[0] + 1])
    count = np.ones(len(x))
    count[jumps] -= np.hstack([jumps[0] + 1, np.diff(jumps)])

    out = np.empty(len(x))
    out[sort_idx] = np.cumsum(count)
    return out

def count2(x):
    """stefan-1: Broadcasting.

    """
    return np.diag(np.cumsum(x == x[:, None], axis=1)) - 1

def count3(x):
    """david-wf-1: for-loop.

    """
    c = np.empty(len(x), dtype=int)
    for idx in np.unique(x):
        v = (x == idx)
        c[v] = np.arange(len(v))

    return c

if __name__ == "__main__":
    x = np.array([0, 1, 0, 2, 0, 1, 4])
    print "Input: ", x
    print "Output: ", count1(x)
    print

    x = np.random.randint(10, size=(10,))
    assert np.all(count1(x) == count2(x))
    assert np.all(count1(x) == count3(x))

    print "Input: ", x
    print "Output: ", count1(x)

