diff --git a/FindSlice.py b/FindSlice.py new file mode 100644 index 0000000..ecd14ea --- /dev/null +++ b/FindSlice.py @@ -0,0 +1,65 @@ +import LeastCommonMultiple +from itertools import combinations + +def findSlice(minSlice = 180, step=60, maxLCM = 43200): + """计算分片组合 + + :param minSlice:最小分片数 + :param step: 分片增量 + :param maxLCM: 最大的最小公倍数,超出这个数即停止运算————预期的在这个数值内保证分片不重复 + :return: + 1/0 : 1表示达到maxLCM退出得出的结果;0表示未达到maxLCM退出得到的结果,即完美结果 + subSliceList:得到的分片组合 + lcm:实际的最小公倍数,即实际的在这个数值内保证分片不重复 + """ + #初始化分片组合列表 + sliceList = [] + sliceList.append(minSlice) + #初始化下一个分片数 + nextSlice = minSlice + #初始化已经计算过的分片组合 + usedSliceList = [] + #初始化已经计算过的最小公倍数 + usedLCM = [] + + while 1: #无线循环 + #按照分片增量增加下一个分片数 + nextSlice = nextSlice + step + sliceList.append(nextSlice) + #初始化组合长度 + i = 2 + while i < len(sliceList): # 当组合长度小于分片组合列表长度 + allSubSliceList = list(combinations(sliceList, i)) # 将分片列表按长度进行全量组合(排列组合中的组合) + for subSliceList in allSubSliceList: # 遍历每一个分片组合 + if subSliceList not in usedSliceList and minSlice in subSliceList: #如果当前组合没有计算过 并且 最小分片数在当前分片组合中(为了提升程序效率) + lcm = LeastCommonMultiple.getLCM(subSliceList) #计算当前组合的最小公倍数 + if lcm not in usedLCM: #如何当前组合的最小公倍数没有被计算过 + numSuccess = False # 初始化完美计算成功为False + for num in range(lcm, minSlice - 1, -1): #从大到小遍历最小公倍数 + numSuccess = False # 重置完美计算成功为False + for slice in reversed(subSliceList): #遍历每一个分片数 + if slice / minSlice > 1 and slice % minSlice == 0: #如果当前分片数是最小分片数的倍数 + continue #跳过该分片数 + remainder = num % slice #计算当前分片数的余数 + if remainder == 0 or remainder >= minSlice: #如果能除仅 或者 余数大于最小分片数 + numSuccess = True #当前分片数满足需求,计算成功 + break #不用再计算其他分片数,退出变量分片数循环 + else: + numSuccess = False #当前分片数不满足需求,计算失败 + if numSuccess == False: #如果每一个分片数都计算失败 + break #当前分片组合计算失败,退出当前分片组合计算 + usedLCM.append(lcm) #将当前组合的最小公倍数加入到已计算过的最小公倍数列表(为了提升程序效率) + if numSuccess == True: #当前分片组合的每一个分片数均计算成功,即完美计算 + return 0, subSliceList, lcm #返回完美计算结果 + else: #未完美计算成功 + if lcm > maxLCM: #如果当前计算的最小公倍数已满足我们的最大的最小公倍数要求 + return 1, subSliceList, lcm #返回非完美计算结果,但该结果已能满足要求 + #print(subSliceList) + usedSliceList.append(subSliceList) #将当前分片组合加入已计算过的分片组合列表 + i += 1 #组合长度加1 + + return 2 #非正常退出 + +if __name__ == '__main__': + print(findSlice()) # 找最小分片为3的分片组合 + diff --git a/LeastCommonMultiple.py b/LeastCommonMultiple.py new file mode 100644 index 0000000..fddb9d6 --- /dev/null +++ b/LeastCommonMultiple.py @@ -0,0 +1,103 @@ +import math + +""" + 获得多个数的最小公倍数 + isPrime(n) + getMutiPrime(n) + getLeastCommonMutible(numList) +""" + + +def isPrime(n): + """ + 判断一个数是否是质数 + """ + if n == 2: + return True + if n == 1 or n % 2 == 0: + return False + p = int(math.sqrt(n)) + 1 + i = 3 + while i < p: + if n % i == 0: + return False + i += 2 + return True + + +def getMutiPrime(n): + """get muti num of n + n=num1*num2...*numx for num1...numx are all prime numbers + 将数n进行质因数分解 prime factorization + """ + if n == 2: + resultlist = [2] + else: + list1 = [i for i in range(2, int(math.sqrt(n)) + 1) if isPrime(i)] + # print(list1) + resultlist = [] + tmp = n + while not isPrime(tmp) and tmp != 1: + for i in list1: + if tmp % i == 0: + resultlist.append(i) + tmp = tmp // i + # print(tmp) + # print(resultlist) + if tmp != 1: + resultlist.append(tmp) + return resultlist + + +def isMutillistFill(mutilLsit): + """ + 判断一个二维列表中的每一个列表是否都为空 + mutilLsit=[[],[],[]] 返回False + mutilLsit=[[1],[],[]] 返回True + """ + for row in mutilLsit: + if len(row) > 0: + return True + return False + + +def getLeastCommonMutible(numList): + """ + numList 待求数的列表, + 返回它们的最小公倍数的质因数列表 + """ + primelists = [] + set1 = set({}) + mutilResult = [] + for i in numList: + primelists.append(getMutiPrime(i)) + set1.update(set(i1 for i1 in getMutiPrime(i))) + # print(primelists) + flag = True + flag1 = False + while flag: + for i in set1: + for row in primelists: + if i in row: + row.remove(i) + flag1 = True + if flag1: + mutilResult.append(i) + flag1 = False + flag = isMutillistFill(primelists) + # print(mutilResult) + return mutilResult + + +def getMutil(numList): + result = 1 + for i in numList: + result *= i + return result + +def getLCM(numList): + return getMutil(getLeastCommonMutible(numList)) + +if __name__ == '__main__': + print(getLCM([3, 4, 5]))# 获取8,12,20的最小公倍数 + print(getLCM([i for i in range(2, 21)])) # 获取1到20的所有数的最小公倍数 \ No newline at end of file diff --git a/MaximumCommonDivisor.py b/MaximumCommonDivisor.py new file mode 100644 index 0000000..b1fa251 --- /dev/null +++ b/MaximumCommonDivisor.py @@ -0,0 +1,39 @@ +# 欧几里德定理求2个数的最大公约数 +def gcd(a, b): + if b == 0: + return a + else: + return gcd(b, a % b) + + +def mgcd(s): + # 两两求最大公约数,会得到1个数组,在这个数组里再两两求公约数,如此递归,最终会得到1个只有1个数的数组,就是最大公约数 + if len(s) == 1: + return s[0] + elif len(s) == 2: + return gcd(s[0], s[1]) + else: + cd = [] + for i in s: + # 不求自己与自己的最大公约数 + if i != s[0]: + cd.append(gcd(s[0], i)) + # 去除数组中的重复数据 + cd = list(set(cd)) + return mgcd(cd) + + +def greatest_common_divisor(*args): + """ + Find the greatest common divisor + """ + # 两两求最大公约数,会得到1个数组,在这个数组里再两两求公约数,如此递归,最终会得到1个只有1个数的数组,就是最大公约数 + return mgcd(args) + + +if __name__ == '__main__': + # These "asserts" using only for self-checking and not necessary for auto-testing + print(greatest_common_divisor(3, 4)) + print(greatest_common_divisor(3, 4, 5)) + print(greatest_common_divisor(3, 4, 5, 6)) + print(greatest_common_divisor(3, 4, 5, 6, 7)) \ No newline at end of file