Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import math
- import sys
- import gmpy2
- from sympy import factorint
- from functools import reduce
- # This terrible python code is provided by Kaelygon
- #
- # Find divisibility rule by prime P: P * N = a * 10^b + c
- # such that an integer can be split in two parts A and B
- # and reduced to a smaller number by simulating 10^b division and modulus
- # using string manipulation and addition: B*a-A*c
- # Matt Parker explanation https://youtu.be/6pLz8wEQYkA
- #Find divisibility rules P * N = a * 10^b + c
- def findDivRules(P, aRange, bRange, cRange):
- rules = []
- bMin=int(math.log10(abs(P))+1)+(bRange[0]-1)
- for b in range(bMin, bRange[1]):
- bPowTen=10**b # 10^b
- for a in range(aRange[0], aRange[1]):
- ab = a*bPowTen # a*b^10
- if ab<P: continue
- for c in range(cRange[0], cRange[1]):
- PN = ab + c # P * N = a * 10^b + c
- if PN<=P or PN%P!=0 or c==0: continue # skip trivial solutions
- N = PN//P
- rules.append((P, N, a, b, c))
- if not rules: return (P, 0, 0, 0, 0)
- # Sort by smallest b and c
- bestRule = min(rules, key=lambda x: (x[3], abs(x[4])))
- return bestRule
- def printParkerStyle(isPrime,rule):
- if isPrime:
- P, N, a, b, c = rule
- aSign=""
- cSign=""
- if c<0 and a >0:
- cSing="add to"
- aSing="add"
- else:
- if c>0: cSing="add to"
- else: cSing="subtract from"
- if a<0: aSing="add"
- else: aSing="subtract"
- print(f"{P} is a prime and has the tests:")
- print(f"Take the {(10**b):,}s, ",end="")
- if(abs(c)>1): print(f"multiply by {c},")
- print(f"and {cSing} the rest. ",end="")
- print(f"Multiply the units by {a} and ",end="")
- print(f"{aSing}.",end="")
- else:
- if len(rule)<2: return
- P=rule[0]
- print(f"{P}: test for ",end="")
- print(f"{rule[1]} ",end="")
- for factor in rule[2:]:
- print(f"and {factor} ",end="")
- print("")
- #Output formatting
- def printRuleTable(isPrime,rule):
- if isPrime:
- P, N, a, b, c = rule
- row = f"P:{P:<6} N:{N:<6} a:{a:<6} b:{b:<6} c:{c:<6} P*N:{P * N:<6}"
- print(row,end="")
- else:
- if len(rule)<1: return
- print(f"P:{rule[0]} Factors {rule[1:]}",end="")
- parkerPrinter()
- #79662*94-1*16
- def extendRuleSearch(P,aMax,bMax,cMax):
- inc=0
- while(True):
- inc+=1
- aStart=inc*aMax
- bStart=inc+bMax #Extending exponent is not that useful
- cStart=inc*cMax
- rule=[]
- aRange = [1+aStart,2*aStart]
- bRange = [1,bStart]
- cRange = [-2*cStart,-cStart]
- rule.extend(findDivRules(P, aRange, bRange, cRange)) #extend negative c search
- if rule[2]:
- return rule, 2*inc-1
- break
- rule=[]
- cRange = [cStart,2*cStart]
- rule.extend(findDivRules(P, aRange, bRange, cRange)) #extend positive c search
- if rule[2]:
- return rule, 2*inc
- break
- def main():
- printComposites=True
- parkerPrinting=True
- if not parkerPrinting:
- print("Test number 'num' divisibility by P")
- print("using iterative formula B*a-A*c")
- print("where A=num/&10^b B=num%10^b.")
- print("a, b and c are constants listed below.\n")
- aMax=10
- printFunc = [printRuleTable,printParkerStyle]
- for P in range(1,30000+1,1):
- if(P==0):continue
- digitCount=int(math.log10(abs(P))+1)
- bMax=digitCount*2+1
- cMax=abs(P//20)
- #minimums
- if bMax<5 : bMax=5
- if cMax<16 : cMax=16
- if not gmpy2.is_prime(P):
- if not printComposites: continue
- composite=[P]
- factors = factorint(P)
- for prime, exponent in factors.items():
- composite.append(int(prime ** exponent))
- printFunc[parkerPrinting](False,composite)
- print("")
- continue
- aRange = [1,aMax] # Second split 'B' multiplier
- bRange = [1,bMax] # 'b' sets the tested number split right to left
- cRange = [-cMax,cMax] # First split 'A' multiplier
- rule=[]
- rule.extend(findDivRules(P, aRange, bRange, cRange))
- if rule[2]: #if results found
- printFunc[parkerPrinting](True,rule)
- print("")
- else: #extend range if not
- rule,inc=extendRuleSearch(P,aMax,bMax,cMax)
- printFunc[parkerPrinting](True,rule)
- if not parkerPrinting:
- print(f" Extended search ",end="")
- if inc==1:
- print("once.")
- else:
- print(f"{inc} times.")
- print("")
- if __name__=="__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement