经典递归算法之排列,组合,集合和换零钱, Python yield实现.

来源:互联网 发布:gis矢量数据融合 编辑:程序博客网 时间:2024/05/22 12:01

对于每个函数名'f',还有个非递归的版本'xf',例如 perm和xperm, comb和xcomb等.

全部是以生成器的形式实现.例如:perm((1,2,3))返回(1,2,3)的全排列生成器.

def subsets(s):    if not s:        yield ()    else:        head, rest = s[:1], s[1:]        for se in subsets(rest):            yield se            yield head + sedef xsubsets(s):    stk = [(s, ())]    while stk:        s, head = stk.pop()        if not s:            yield head         else:            stk.append((s[1:], head + s[:1]))            stk.append((s[1:], head))def comb(s,k=None):    n = len(s)    if k is None:        k = n    if k < 0:        raise ValueError("k must be non-negative")    if k > n:        return ()    def recur(s, k, n):        if k == n:            yield s        elif k == 0:            yield ()        else:            head, rest = s[:1], s[1:]            yield from recur(rest, k, n-1)            yield from (head + x for x in recur(rest, k-1, n-1))    return recur(s, k, n)def xcomb(s,k=None):    n = len(s)    if k is None:        k = n    if k < 0:        raise ValueError("k must be non-negative")    if k > n:        return ()    def recur(s, k, n):        stk = [(s, k, n, ())]        while stk:            s, k, n, head = stk.pop()            if k == n:                yield head + s            elif k == 0:                yield head            else:                stk.append((s[1:], k-1, n-1, head + s[:1]))                stk.append((s[1:], k, n-1, head))    return recur(s, k, n)            def wperm(s):    if not s:        yield ()    else:        head, rest = s[:1], s[1:]        rest_n = len(rest) + 1        for ele in wperm(rest):            for i in range(rest_n):                yield ele[:i] + head + ele[i:]def xwperm(s):    stk = [(s, ())]    while stk:        s, head = stk.pop()        if not s:            yield head        else:            h = s[:1]            n = len(head) + 1            for i in range(n):                stk.append((s[1:], head[:i] + h + head[i:]))def perm(s,k=None):    for cs in comb(s,k):        yield from wperm(cs)def xperm(s,k=None):    for cs in xcomb(s,k):        yield from xwperm(cs)def exch(my,arr):            if my < 0 or not arr:        pass    elif not arr[1:]:        c = arr[0]        div, mod = divmod(my, c)        if mod == 0:            yield tuple(c for _ in range(div))    else:        head, rest = arr[:1], arr[1:]        yield from exch(my, rest)        yield from (head + x for x in exch(my-arr[0], arr))def xexch(my,arr):    stk = [(my, arr, ())]    while stk:        my, arr, head = stk.pop()        if my < 0 or not arr:            continue        if not arr[1:]:            c = arr[0]            div, mod = divmod(my, c)            if mod == 0:                yield head + tuple(c for _ in range(div))        else:            stk.append((my-arr[0], arr, head + arr[:1]))            stk.append((my, arr[1:], head))            import itertoolss = tuple(range(5))arr=tuple(range(1,6000))def test():    for i in range(len(s)+1):        assert(set(itertools.combinations(s,i))==set(comb(s,i)))def test2():    for i in range(len(s)+1):        assert(set(itertools.permutations(s,i))==set(perm(s,i)))        def test3():    for x in xexch(10,arr):        print(x)    #assert(set(xexch(10,arr))==set(exch(10,arr)))def test4():    for i in range(len(s)+1):        assert(set(xcomb(s,i))==set(comb(s,i)))    for x in xcomb(s, 2):        print(x)def test5():    for ss in subsets(arr):        print(ss)    print('---')    for ss in xsubsets(arr):        print(ss)    assert(set(subsets(arr))==set(xsubsets(arr)))def test6():    #assert(set(perm(arr,3))==set(xperm(arr,3)))    for x in xperm(arr,3):        print(x)        if __name__=='__main__':        test6()


0 0
原创粉丝点击