Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 数字的有序对_Python_Algorithm_Python 3.x_Math_Optimization - Fatal编程技术网

Python 数字的有序对

Python 数字的有序对,python,algorithm,python-3.x,math,optimization,Python,Algorithm,Python 3.x,Math,Optimization,对于给定的数N求总的可能有序对(x,y),使x和y小于或等于N,且x的位数之和小于y的位数之和 例如,n=6:存在21个可能的有序对,它们是[(0,1)、(0,2)、(0,3)、(0,4)、(0,5)、(0,6)、(1,2)、(1,3)、(1,4)、(1,5)、(1,6)、(2,3)、(2,4)、(2,5)、(2,6)、(3,4)、(3,5)、(3,6)、(4,5)、(5,6)] 这里x总是小于y,x的位数之和也小于y的位数之和,并且x和y都等于或小于N。这是我的简单方法,但这非常缓慢,在N=1

对于给定的数
N
求总的可能有序对(x,y),使x和y小于或等于N,且x的位数之和小于y的位数之和

例如,n=6:存在
21个
可能的有序对,它们是
[(0,1)、(0,2)、(0,3)、(0,4)、(0,5)、(0,6)、(1,2)、(1,3)、(1,4)、(1,5)、(1,6)、(2,3)、(2,4)、(2,5)、(2,6)、(3,4)、(3,5)、(3,6)、(4,5)、(5,6)]

这里x总是小于y,x的位数之和也小于y的位数之和,并且x和y都等于或小于N。这是我的简单方法,但这非常缓慢,在N=10000之前效果很好,之后表现很差

from itertools import permutations
n=100
lis=list(range(n+1))
y=list(i for i in permutations(lis,2) if i[0]<i[1] and sum(list(map(int,
(list(str(i[0]))))))<sum(list(map(int,(list(str(i[1])))))))
print(len(y))
从itertools导入置换
n=100
lis=列表(范围(n+1))
y=列表(i表示置换中的i(lis,2),如果i[0]
这是家庭作业吗


闻起来像是家庭作业。

一个问题是,您仍然在生成所有排列,然后删除x大于或等于y的条目。另一个问题是,您正在为每次迭代重新计算y的位数之和,以便以后存储和比较。可能有一个更优雅的解决方案,您可以如果您知道将来的所有x条目都将不符合条件,那么实际上就是脱离嵌套循环

from itertools import permutations
from time import time

def time_profile(f):

    def time_func(*args, **kwargs):
        start_time = time()
        r = f(*args, **kwargs)
        end_time = time()
        print "{} Time: {}".format(f, end_time - start_time)
        return r

    return time_func

@time_profile
def calc1(n):
    lis=list(range(n+1))
    y=list(i for i in permutations(lis,2) if i[0]<i[1] and sum(list(map(int,
    (list(str(i[0]))))))<sum(list(map(int,(list(str(i[1])))))))
    return y

@time_profile
def calc2(n):
    l = []
    for y in xrange(n+1):
        y_sum = sum(map(int, str(y)))
        for x in xrange(y):
            # May be possible to use x_digits to break
            x_digits = map(int, str(x))
            if sum(x_digits) >= y_sum: continue
            l.append((x, y))

    return l

if __name__ == '__main__':
    N = 10000
    if len(calc1(N)) != len(calc2(N)): print 'fail'
从itertools导入置换
从时间导入时间
def时间_配置文件(f):
定义时间函数(*args,**kwargs):
开始时间=时间()
r=f(*args,**kwargs)
结束时间=时间()
打印“{}时间:{}”。格式(f,结束时间-开始时间)
返回r
返回时间函数
@时间剖面图
def calc1(n):
lis=列表(范围(n+1))
y=列表(i表示排列中的i(lis,2),如果i[0]时间:233.378999949

<0xfff2c09c时的函数计算C2>时间:84.967000076

与问题无关的其他几点。对list的一些调用是多余的。map函数已经返回了一个list。在Python 3中,range返回一个生成器,在您迭代时返回一个值。它的内存效率更高,工作原理也一样。

代码的工作原理 这几乎完全是对您的方法的算法改进。使用生成器或列表理解可能更快,但您必须对其进行分析以进行检查。该算法的工作原理如下:

  • 预计算1-N的数字和
  • 将数字1-N按其数字和进行分组。我们有一个类似这样的对象。因此,如果我们想要得到数字和大于2的数字,我们只需要计算第三行之后的数字
  • 1:1,10
    2:2,11,20
    3:3,12,21,30

  • 注意每行中的数字都是按顺序排列的。如果我们的数字是12,我们只需要查看12之后的数字。我们可以通过二进制搜索找到每行中的12
  • 总体而言,这比您的算法提高了约20倍,内存消耗为O(N)

    代码
    你的脚本产生了错误的输出,同时就像我说的那样,这对巨大的N不起作用,但我感谢你的努力:)嗯……如果你想要速度,数据库表可能是最好的方法。另外,你能在准确性方面添加更多细节吗?xfrom itertools import permutations for _ in range(int(input())): n=1000 lis=range(n+1) y=(i for i in permutations(lis,2) if i[0]<i[1] and sum(map(int,(str(i[0]))))<sum(map(int,(list(str(i[1])))))) print (sum(1 for _ in y))
    def find_total_possible(n):
        x = [i for i in range(n + 1)]
        y = [i + 1 for i in range(n + 1)
        z = list(zip(x,y))
        return z
    
    from itertools import permutations
    from time import time
    
    def time_profile(f):
    
        def time_func(*args, **kwargs):
            start_time = time()
            r = f(*args, **kwargs)
            end_time = time()
            print "{} Time: {}".format(f, end_time - start_time)
            return r
    
        return time_func
    
    @time_profile
    def calc1(n):
        lis=list(range(n+1))
        y=list(i for i in permutations(lis,2) if i[0]<i[1] and sum(list(map(int,
        (list(str(i[0]))))))<sum(list(map(int,(list(str(i[1])))))))
        return y
    
    @time_profile
    def calc2(n):
        l = []
        for y in xrange(n+1):
            y_sum = sum(map(int, str(y)))
            for x in xrange(y):
                # May be possible to use x_digits to break
                x_digits = map(int, str(x))
                if sum(x_digits) >= y_sum: continue
                l.append((x, y))
    
        return l
    
    if __name__ == '__main__':
        N = 10000
        if len(calc1(N)) != len(calc2(N)): print 'fail'
    
    import time
    import bisect
    import itertools
    
    N = 6
    
    def sum_digits(n):
        # stolen from here: https://stackoverflow.com/questions/14939953/sum-the-digits-of-a-number-python
        # there may be a faster way of doing this based on the fact that you're doing this over 1 .. N
        r = 0
        while n:
            r, n = r + n % 10, n // 10
        return r        
    
    t = time.time()
    # trick 1: precompute all of the digit sums. This cuts the time to ~0.3s on N = 1000
    digit_sums = [sum_digits(i) for i in range(N+1)]
    digit_sum_map = {}
    
    # trick 2: group the numbers by the digit sum, so we can iterate over all the numbers with a given digit sum very quickly
    for i, key in enumerate(digit_sums):
        try:
            digit_sum_map[key].append(i)
        except KeyError:
            digit_sum_map[key] = [i]
    max_digit_sum = max(digit_sum_map.keys())
    
    # trick 3: note that we insert elements into the digit_sum_map in order. thus we can binary search within the map to find
    # where to start counting from. 
    result = []
    for i in range(N):
        for ds in range(digit_sums[i] + 1, max_digit_sum + 1):
            result.extend(zip(itertools.repeat(i), digit_sum_map[ds][bisect.bisect_left(digit_sum_map[ds], i):]))
    
    print('took {} s, answer is {} for N = {}'.format(time.time() - t, len(result), N))
    # took 0.0 s, answer is 21 for N = 6
    # took 0.11658287048339844 s, answer is 348658 for N = 1000
    # took 8.137377977371216 s, answer is 33289081 for N = 10000
    
    # for reference, your last method takes 2.45 s on N = 1000 on my machine