4

問題 I の特定のインスタンスに
は、1 ~ 100 の範囲の int があります。この範囲内で、できるだけ均等に分散され、最初と最後の値を含むn 個の合計数を生成したいと考えています。

start = 1, end = 100, n = 5   
Output: [1, 25, 50, 75, 100]

start = 1, end = 100, n = 4   
Output: [1, 33, 66, 100]

start = 1, end = 100, n = 2   
Output: [1, 100]

私が現在持っているもの
実際に機能するアプローチがありますが、これを考えすぎて、もっと単純なものを見逃していると感じ続けていますか? これは最も効率的なアプローチですか、それとも改善できますか?

def steps(start, end, n):
    n = min(end, max(n, 2) - 1)
    mult = end / float(n)
    yield start
    for scale in xrange(1, n+1):
        val = int(mult * scale)
        if val != start:
            yield val

この関数が少なくとも範囲の下限値と上限値を常に返すことを保証していることに注意してください。だから、私は強制しますn >= 2

検索の参考のために、これを使用して、レンダリングされたシーケンスから画像フレームをサンプリングします。通常、最初、中間、最後が必要です。しかし、非常に長い画像シーケンスを処理し、より良いカバレッジを得るために、もう少しうまくスケーリングできるようにしたかったのです。

解決済み: 選択した回答から

@vartecの回答のこのわずかに変更されたバージョンをジェネレーターとして使用し、n安全のために値を制限することになりました。

def steps(start,end,n):
    n = min(end, max(n, 2))
    step = (end-start)/float(n-1)
    return (int(round(start+x*step)) for x in xrange(n))
4

5 に答える 5

5

適切な丸めが必要です。

def steps(start,end,n):
    if n<2:
        raise Exception("behaviour not defined for n<2")
    step = (end-start)/float(n-1)
    return [int(round(start+x*step)) for x in range(n)]
于 2012-04-10T09:16:52.150 に答える
4

余分な依存関係があり、やり過ぎかもしれませんが、短く、テストされており、正しい結果が得られるはずです: numpy.linspace

>>> numpy.linspace(1, 100, 4).astype(int).tolist()
[1, 34, 67, 100]
于 2012-04-10T09:00:24.973 に答える
3

を使用する際の問題rangeは、ステップが整数でなければならないため、 などの丸めの問題が発生することですsteps(1,100,4) == [1, 33, 66, 100]。整数出力が必要であるが、できるだけ均一なステップが必要な場合は、float をステップとして使用します。

>>> def steps(start,end,n):
...    step = (end-start)/float(n-1)
...    return [int(round(start+i*step)) for i in range(n)]

>>> steps(1,100,5)
>>> [1, 26, 51, 75, 100]
>>> steps(1,100,4)
>>> [1, 34, 67, 100]
>>> steps(1,100,2)
>>> [1, 100]
>>>
于 2012-04-10T08:46:45.647 に答える
1
>>> from itertools import count
>>> def steps(start,end,n):
        yield start
        begin = start if start>1 else 0
        c = count(begin,(end-begin)/(n-1))
        next(c)
        for _ in range(n-2):
            yield next(c)
        yield end


>>> list(steps(1,100,2))
[1, 100]
>>> list(steps(1,100,5))
[1, 25, 50, 75, 100]
>>> list(steps(1,100,4))
[1, 33, 66, 100]
>>> list(steps(50,100,3))
[50, 75, 100]
>>> list(steps(10,100,10))
[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

に短縮できます

>>> from itertools import islice, count
>>> def steps(start,end,n):
        yield start
        begin = start if start>1 else 0
        c = islice(count(begin,(end-begin)/(n-1)),1,None)
        for _ in range(n-2):
            yield next(c)
        yield end
于 2012-04-10T07:28:28.847 に答える
0

rangeを使用することの何が問題になっていますか? 使用方法は次のとおりです

>>> def steps(start,end,n):
    return [start]+range(start-1,end,end/(n-1))[1:]+[end]

>>> steps(1,100,5)
[1, 25, 50, 75, 100]
>>> steps(1,100,2)
[1, 100]
>>> 
于 2012-04-10T07:12:16.477 に答える