趣味问题之趣味整数

# -*- coding: utf-8 -*-
"""
Created on Thu Nov 17 16:52:17 2016


@author: alis
"""


'''趣味百题之趣味整数'''






# 求一个数的所有因子
def factors(num):
    p = 1
    q = num
    a = []
    while p < q:
        if num % p == 0:
            a.append(p);a.append(q)
        p += 1
        q = num/p
    a.sort()
    return a    
z = factors(1054) 




#1、0-9这10个数字可以组成多少不重复的3位数?
count = 0
for i in range(1,10):
    for j in range(10):
        if (i == j):continue                      # 如果 i==j ,过滤
        for k in range(10):
            if (i != k) and (j != k):
                print i,j,k
                count  += 1
print count










'''2 水仙花数是指一个n位数(n≥3),它的每个位上的数字的n次幂之和等于它本身。
例如:1^3+5^3+3^3=153。


求100~999之间所有的水仙花数。'''
for i in range(100,1000):
    num2str = str(i)
    mat = list(num2str)
    z  = (int(mat[0]))**3  + (int(mat[1]))**3 + (int(mat[2]))**3
    if z == i:
        print "%d 是水仙花数!" %i
  
      
'''3.  完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。它所有的真因子
(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。例如,第一个完全数是6,
它有约数1、2、3、6,除去它本身6外,其余3个数相加,1+2+3=6。第二个完全数是28,
它有约数1、2、4、7、14、28,除去它本身28外,其余5个数相加,1+2+4+7+14=28。


编程求10000以内的完全数。 '''
# 方法1


from numpy import *
import time
begin_time = time.clock()
for i in range(2,50000):
    z = int(sqrt(i))
    vector = []
    for j in range(1,z+1):
        if mod(i,j) == 0:
            temp = i/j
            vector.append(j)
            vector.append(temp)
    vector.sort()
    del vector[-1]
    if sum(vector) == i:
        print "%d 是完全数" %i
end_time = time.clock()
print "运行时间为%f"%(end_time - begin_time)








#方法2
begin_time = time.clock()
for i in range(2,500000):
    z = factors(i)
    del z[-1]
    if sum(z) == i:
        print "%d 是完全数" %i
end_time = time.clock()
print "运行时间为%f"%(end_time - begin_time)






'''4. 220的真因数之和为1+2+4+5+10+11+20+22+44+55+110=284
284的真因数之和为1+2+4+71+142=220
毕达哥拉斯把这样的数对A、B称为相亲数:A的真因数之和为B,而B的真因数之和为A。


求100000以内的相亲数。'''
#方法一:
begin_time = time.clock()
def find_num(num):
    sqi = int(sqrt(num))
    mat = []
    for j in range(1,sqi+1):
        if mod(num,j) == 0:
            temp = num/j
            mat.append(j)
            mat.append(temp)
    mat.sort()
    del mat[-1]
    sum_mat = sum(mat)
    return sum_mat


for i  in range(2,100000):
    sum1 = find_num(i)
    sum2 = find_num(sum1)
    if i == sum2:
          print "%d 与 %d 是相亲数" %(sum1,sum2)
end_time = time.clock()
print (end_time - begin_time)        
        
#方法2  
begin_time = time.time()


def sumOfFactors(k):
    p = 1 
    q = k 
    s = 0
    a = []
    while p < q:
        if k % p == 0:
            s += p + q
            a.append(p);a.append(q)
        p += 1
        q = k / p 


    if k == p * q and p == q:
        s += p


    return s - k 


def fun(start, end):
    for x in range(start, end):
        y = sumOfFactors(x)
        if x < y and sumOfFactors(y) == x:
            print x, y
    
fun(2, 100000)
end_time = time.time()
print (end_time - begin_time)










'''5.
黑洞数又称陷阱数,是类具有奇特转换特性的整数。任何一个数字不全相同的整数,经有
限“重排求差”操作,总会得到某一个或一些数,这些数即为黑洞数。“重排求差”操作即把组成
该数的数字重排后得到的最大数减去重排后得到的最小数。
举个例子,3位数的黑洞数为495.
简易推导过程:随便找个数,如297,3个位上的数从小到大和从大到小各排一次,为972和279,
相减得693。按上面做法再做一次,得到594,再做一次,得到495,之后反复都得到495。


验证4位数的黑洞数为6174。'''


def diff_str(n):
    num2str = str(n)
    num = list(num2str)
    num.sort()
    small = '';big = ''
    for i in range(len(num)):
        small = small + str(num[i])
        big = big + str(num[len(num)-i-1])
    diff = int(big) - int(small)
    print "%d -  %d  = %d"%(int(big),int(small),diff)
    if diff == 6174:
        print "计算结束,6174是黑洞数"
    else:
        diff_str(diff)


diff_str(8260)
    
    
# 6. 求1000以内的勾股数。
import math
for i in range(1,1000):
    for j in range(i+1,1000):
        c = i**2 + j**2
        if c > 1000:break
        else:
            print"1000以内勾股数为%d,%d,%d" %(i,j,c)
            
'''7.
如果某个数的平方的末尾几位等于这个数,那么就称这个数为自守数。显然,5和6是一位自守数
(5*5=25,6*6=36)。 25*25=625,76*76=5776,所以25和76是两位自守数。求10000以内的自守数。'''            
for i in range(1,100000):
    len_i = len(str(i))
    temp = list(str(i**2))
    a = ''
    for j in range(len(temp)-len_i,len(temp)):
        a = a + str(temp[j])
    if i == int(a):
        print "%d 是自守数!"%i
    else:continue








'''8.
所谓反序数,即有这样成对的数,其特点是其中一个数的数字排列顺序完全颠倒过来,就变成另一个
数,如102和201,36和63等,简单的理解就是顺序相反的两个数,我们把这种成对的数互称为反序数。
反序数唯一不可能出现以0结尾的数。一个3位数各位上的数字都不相同,
它和它的反序数的乘积是280021,这个3位数应是多少?'''
for i in range(100,1000):
    a = i/100
    b = mod(i,100)/10
    c = mod(i,10)
    re_num = c*100 + b*10 + a
    if re_num * i == 280021:
        print "这个三位数是%d"%i
        break
    else:
        continue
    
    
    
    
    
            
                
    
    
    
    
    
    
    
    














   
        
        
        
            
            
       




                
                
                

你可能感兴趣的:(趣味算法)