Reversing a number's digits using modular division - python

My homework is to find the "emirp numbers" (pairs of primes like 13 ⇆ 31) up to 10,000. I can reverse the digits using [::-1], but I must do it with % instead.
Here's my code. It works, but how can I reverse the digits using % instead of [::-1]?
counter=0;
prime_counter=0;
emirp_counter=0;
for N in range(13,9968):
i=2;
controlq=1;
while i < N/2+1 and controlq==1:
counter+=1;
if N % i == 0:
controlq=0;
i+=1;
if controlq==1:
x=int(str(N)[::-1]); # Here's the problem.
a=2;
controlw=1
while a < x/2+1 and controlw==1:
emirp_counter+=1
if x % a == 0:
controlw=0;
a+=1
if controlw==1 and (N!=x):
prime_counter+=1;
print(N,'<-- is an emirp number -->',x,);
print('TOTAL PRIME NUMBERS', prime_counter);
print('TOTAL PROCESS', emirp_counter+counter);
I just started learning Python (and programming) 1 month ago.

reverse a number using mod? from the top of my head I get this
def reverse_number(n):
digit=[]
while n!=0:
n,d = divmod(n,10) # n//10 , n%10
digit.insert(0,d)
result=0
for i,d in enumerate(digit):
result += d*10**i
return result
because n mod 10 give my the last digit of the number, then I just have to save it and then do a interger division of the number by 10, and repeat until my number is zero, Python let my do both at the same time with divmod, finally a make the new reversed number adding power of 10 as needed.
>>> reverse_number(45682)
28654

Short answer:
def reverse(x):
def reverse_int_(n, r):
return reverse_int_(n / 10, n % 10 + r * 10) if n else r
return reverse_int_(x, 0)
There you have your % operator.

Related

Python : Primes in numbers

Given a positive number n > 1 find the prime factor decomposition of n. The result will be a string with the following form :
"(p1**n1)(p2**n2)...(pk**nk)"
with the p(i) in increasing order and n(i) empty if n(i) is 1.
Example: n = 86240 should return "(2**5)(5)(7**2)(11)"
This is my code , but i have problem with time for n>250000
def primeFactors(n):
a=""
i=2
while i<=n:
#part of identifying if number i is prime
w1=5
w2=2
gg=0
while w1*w1<=i:
if i%w1==0:
gg=1
break
w1+=w2
w2=6-w2
#checking if previous loop has been broken
if gg:
i+=1
continue
#countig how many thimes we can divide n on i
c=0
for j in range(1,n):
if n%i!=0: break
c+=1
n=n//i
#if we can divide n on i only once
if c==1:
a+="("+str(i)+")"
elif c>1:
a+="("+str(i)+"**"+str(c)+")"
i+=1
return a
is there a way to fix this problem?
The problem isn't prime factorization, which the program does, it's getting Python to do it for very large numbers in a very small amount of time. Specifically, my understanding is we need to be able to calculate:
for n in range(10 ** 9, 10 ** 9 + 10):
print(n, '=', primeFactors(n))
in <= 120ms or less, i.e. <= 12ms per number. The OP's code doesn't get past 10 ** 9 + 4 before milliseconds turn into seconds, seconds into minutes. My first impression of your code is you need to separate your prime logic from the rest of the code, to make it understandable, and then clean up and optimize both parts of the code. My rewrite of your program:
def generate_primes(n):
""" generate real primes """
yield(2)
primes = [(2, 4)]
for m in range(3, n, 2):
for prime, square in primes:
if square > m:
yield(m)
primes.append((m, m * m))
break
if m % prime == 0:
break
def primeFactors(n):
string = ""
i = 2
for i in generate_primes(int(n ** 0.5) + 1):
# counting how many times we can divide n on i
c = 0
while True:
product, remainder = divmod(n, i)
if remainder != 0:
break
n = product
c += 1
# if we can divide n on i only once
if c == 1:
string += f"({i})"
elif c > 1:
string += f"({i}**{c})"
if n > 1: # final prime factor greater than square root
string += f"({n})"
return string
I swapped in a prime generator to avoid redundant calculations. This optimized version can achieve 32ms per large number factored in the above test. Still not good enough. So let's try #JamesKPolk's suggestion and use pseudoprimes:
def generate_primes(n):
""" generate 5-rough pseudoprimes """
if n >= 2:
yield(2)
if n >= 3:
yield(3)
if n >= 5:
m = 1
x = 4
while m < n:
m += x
yield(m)
x = 6 - x
The tradeoff here is that we will test more divisors than we really need, but we can generate these divisors much faster. This change achieves our goal of <= 12ms per large number factored, on my machine anyway.
OUTPUT
> time python3 test.py
1000000000 = (2**9)(5**9)
1000000001 = (7)(11)(13)(19)(52579)
1000000002 = (2)(3)(43)(983)(3943)
1000000003 = (23)(307)(141623)
1000000004 = (2**2)(41**2)(148721)
1000000005 = (3)(5)(66666667)
1000000006 = (2)(500000003)
1000000007 = (1000000007)
1000000008 = (2**3)(3**2)(7)(109**2)(167)
1000000009 = (1000000009)
0.106u 0.010s 0:00.11 100.0% 0+0k 0+0io 0pf+0w
>

Most efficient way to filter prime numbers from a list of random numbers in Python

I have a list filled with random numbers and I want to return the prime numbers from this list. So I created these functions:
def is_prime(number):
for i in range(2, int(sqrt(number)) + 1):
if number % i == 0:
return False
return number > 1
And
def filter_primes(general_list):
return set(filter(is_prime, general_list))
But I want to improve performance, so how can I achieve this?
Sieve of Eratosthenes, taking about 0.17 seconds for primes under 10 million on PyPy 3.5 on my device:
from array import array
from math import isqrt
def primes(upper):
numbers = array('B', [1]) * (upper + 1)
for i in range(2, isqrt(upper) + 1):
if numbers[i]:
low_multiple = i * i
numbers[low_multiple:upper + 1:i] = array('B', [0]) * ((upper - low_multiple) // i + 1)
return {i for i, x in enumerate(numbers) if i >= 2 and x}
and the filter function:
filter_primes = primes(10_000_000).intersection
3 rounds of the the Miller-Rabin test ( https://en.wikipedia.org/wiki/Miller%2dRabin_primality_test ) using bases 2, 7, and 61, is known to accurately detect all primes <= 32 bit, i.e., anything that fits into a python int.
This is much, much faster than trial division or sieving if the numbers can be large.
If the numbers cannot be large (i.e., < 10,000,000 as you suggest in comments), then you may want to precompute the set of all primes < 10,000,000, but there are over 600,000 of those.
How about this? I think It's a little better:
def filter_primes(general_list):
return filter(is_prime, set(general_list))
This way we don't call is_prime() for same number multiple times.
The Sieve of Eratosthenes is more efficient than Trial Division, the method you are using.
Your trial division loop can be made more efficient, taking about half the time. Two is the only even prime number, so treat two as a special case and only deal with odd numbers thereafter, which will halve the work.
My Python is non-existent, but this pseudocode should make things clear:
def isPrime(num)
// Low numbers.
if (num <= 1)
return false
end if
// Even numbers
if (num % 2 == 0)
return (num == 2) // 2 is the only even prime.
end if
// Odd numbers
for (i = 3 to sqrt(num) + 1 step 2)
if (num % i == 0)
return false
end if
end for
// If we reach here, num is prime.
return true;
end def
That step 2 in the for loop is what halves the work. Having earlier eliminated all even numbers you only need to test with odd trial divisors: 3, 5, 7, ...
def primes_list(num_list):
divs = [2,3,5,7]
primes = [x for x in set(num_list) if 0 not in {1 if ((x%i != 0) | (x in divs)) & (x > 0) else 0 for i in divs}]
return primes
For this function, it takes a list, num_list, as a parameter. divs is a predefined, or rather hard coded, list of prime numbers less than 10 excluding 1. Then we use list comprehension to filter num_list for prime numbers as the variable primes.
This is one more flavour of code to find the prime no of the range. The simple and easy way.
def find_prime(n):
if n <=1:
return False
else:
for i in range(2, n):
if n % i == 0:
return False
return True
n = 10
x = filter(find_prime, range(n)) #you can give random no list too
print(list(x))
def is_prime(n):
if n>1:
for i in range(2,int(n**0.5)+1):
if n%i==0:
return False
return True
else: return False
print([x for x in general_list if is_prime(x)])
would you try this... There is no need for the filter at all and you could simply apply set() to the general_list if there are duplicate elements in the list to optimize more.

Recursive function to know if a number is divisible by 3

I need to create a recursive function which return me true if the input number it's divisible by 3. I know that it's more simple without recursion, but I need to create a function of this type.
I've created a function, but i want to know if it's possible to create a better one, 'cause whit a big 'num', the function doesn't work. I think that I should use this fact: a natural number is divisible by 3 if the sum of its digits is divisible by 3.
This is my code:
def divThree(num):
if num==3:
return true
else:
divThree(num-3)
EDIT: I created a better function, but i don't understand why doesn't return me true if the number is divisible by three. Instead, if it isn't, goes on maximum recursion error.
def recursiveThree(num):
if num==3 or num==6 or num==9:
return true
else:
sum=0
sNum=str(num)
for i in range(0,len(sNum)):
sum=sum+int(sNum[i])
recursiveThree(sum)
The most straightforward solution is to use modulo 3 to check for
divisibility, but that's not going to be recursive.
An alternate solution is to recursively keep dividing by 3 until you get down to 1, but that will stack overflow for large values.
A third solution, which lends itself to recursion, is to leverage the property that if the sum of the digits of a number is divisible by 3, then the number is divisible by 3.
Here's an implementation of the third option that avoids modulo arithmetic and copes with very large numbers:
def divThree(num):
if num < 10:
return (num in [3, 6, 9])
else:
return divThree(sum([int(digit) for digit in str(num)]))
You can add 0 to the list in the first return if you want to consider it divisible by 3 as well.
If you want to accommodate both positive and negative values, prepend:
if num < 0:
return divThree(-num)
as the first check to be performed.
You need to check if the number has zero remainder when using 3 as the divisor.
Use the % operator to check for a remainder. So if you want to see if something is evenly divisible by 3 then use num % 3 == 0 If the remainder is zero then the number is divisible by 3.
This returns true:
print (6 % 3 == 0)
returns True
This returns False:
print (5 % 3 == 0)
returns False
Here is a simple function to check True of False:
def divThree(numb):
return numb % 3 == 0
print (divThree(99))
Edit:
I am not sure how big a number you are trying to check but I tested this function with what I think is a big number and it worked. I could be just not understanding what it is you need thought.
def divThree(numb):
return numb % 3 == 0
print (divThree(4325609549876542987503216540321540104986213754901245217346214390735402153407213540213457183254098263487053214132754073254921534987053245321454))
Returned True
You enlarge recursively the factor to subtract:
def divisible_by_tree(num, factor=3):
if factor < num:
num = divi(num, factor * 2)
if num >= factor:
num -= factor
if factor > 3:
return num
return num == 0
This is kind of an obscure method, and there are several better answers, but implementing a theorem of congruences, you could say:
from random import randint # For test trials
def isDivisByThree(n):
sN = str(n)
if(len(sN) == 1):
bIsProductOfThree=True if(n==3 or n==6 or n==9) else False
return bIsProductOfThree
else:
sumOfDigits = 0
for x in sN:
sumOfDigits += int(x)
# end for
return isDivisByThree(sumOfDigits)
# end if
# end isDivisByThree(...)
def main():
for testTrialCount in range(1, 35+1):
testSubject = randint(1, 2147483647)
result = isDivisByThree(testSubject)
if(result):
print("Test Trial #" + str(testTrialCount) + ": " + str(testSubject) + " is divisble by 3!")
else:
print("Test Trial #" + str(testTrialCount) + ": " + str(testSubject) + " is NOT divisble by 3.")
# end if
# end for
# end main()
main()
This works because of a theorem related to the application of congruences which states: if d|(b-1) then n = (a_k * ... * a_1 * a_0) is divisible by d if and only if the sum of digits a_k + ... + a_1 + a_0 is divisible by d. (Where d is the divisor (3 for this example) and b is the base in which the number is expressed (10 for this example).)
Example output for the first 10 trials:
Test Trial #1: 458327921 is NOT divisble by 3.
Test Trial #2: 23787660 is divisble by 3!
Test Trial #3: 820562190 is divisble by 3!
Test Trial #4: 1466915534 is NOT divisble by 3.
Test Trial #5: 1395854683 is NOT divisble by 3.
Test Trial #6: 1844052852 is divisble by 3!
Test Trial #7: 261731131 is NOT divisble by 3.
Test Trial #8: 624183104 is NOT divisble by 3.
Test Trial #9: 788686237 is NOT divisble by 3.
Test Trial #10: 1075010016 is divisble by 3!
...
Edit:
Ah, I see pjs beat me to this with a similar solution.
You could find out what it would take for the number to become divisible by 3 using the modulo and then subtracting that to num
def divThree(num):
if num % 3 == 0:
return True
a = num % 3
return divThree(num-a)
In C (easy to translate)
bool divisible_by_three (int x) {
if (x < 0) return divisible_by_three (-x);
else if (x >= 3) return divisible_by_three (x % 3);
else return (x == 0);
}
Yes, it's recursive. Exercise for your instructor: Find the bug.

Divisors of a number: How can I improve this code to find the number of divisors of big numbers?

My code is very slow when it comes to very large numbers.
def divisors(num):
divs = 1
if num == 1:
return 1
for i in range(1, int(num/2)):
if num % i == 0:
divs += 1
elif int(num/2) == i:
break
else:
pass
return divs
For 10^9 i get a run time of 381.63s.
Here is an approach that determines the multiplicities of the various distinct prime factors of n. Each such power, k, contributes a factor of k+1 to the total number of divisors.
import math
def smallest_divisor(p,n):
#returns the smallest divisor of n which is greater than p
for d in range(p+1,1+math.ceil(math.sqrt(n))):
if n % d == 0:
return d
return n
def divisors(n):
divs = 1
p = 1
while p < n:
p = smallest_divisor(p,n)
k = 0
while n % p == 0:
k += 1
n //= p
divs *= (k+1)
return divs - 1
It returns the number of proper divisors (so not counting the number itself). If you want to count the number itself, don't subtract 1 from the result.
It works rapidly with numbers of the size 10**9, though will slow down dramatically with even larger numbers.
Division is expensive, multiplication is cheap.
Factorize the number into primes. (Download the list of primes, keep dividing from the <= sqrt(num).)
Then count all the permutations.
If your number is a power of exactly one prime, p^n, you obvioulsy have n divisors for it, excluding 1; 8 = 2^3 has 3 divisors: 8, 4, 2.
In general case, your number factors into k primes: p0^n0 * p1^n1 * ... * pk^nk. It has (n0 + 1) * (n1 + 1) * .. * (nk + 1) divisors. The "+1" term counts for the case when all other powers are 0, that is, contribute a 1 to the multiplication.
Alternatively, you could just google and RTFM.
Here is an improved version of my code in the question. The running time is better, 0.008s for 10^9 now.
def divisors(num):
ceiling = int(sqrt(num))
divs = []
if num == 1:
return [1]
for i in range(1, ceiling + 1):
if num % i == 0:
divs.append(num / i)
if i != num // i:
divs.append(i)
return divs
It is important for me to also keep the divisors, so if this can still
be improved I'd be glad.
Consider this:
import math
def num_of_divisors(n):
ct = 1
rest = n
for i in range(2, int(math.ceil(math.sqrt(n)))+1):
while rest%i==0:
ct += 1
rest /= i
print i # the factors
if rest == 1:
break
if rest != 1:
print rest # the last factor
ct += 1
return ct
def main():
number = 2**31 * 3**13
print '{} divisors in {}'.format(num_of_divisors(number), number)
if __name__ == '__main__':
main()
We can stop searching for factors at the square root of n. Multiple factors are found in the while loop. And when a factor is found we divide it out from the number.
edit:
#Mark Ransom is right, the factor count was 1 too small for numbers where one factor was greater than the square root of the number, for instance 3*47*149*6991. The last check for rest != 1 accounts for that.
The number of factors is indeed correct then - you don't have to check beyond sqrt(n) for this.
Both statements where a number is printed can be used to append this number to the number of factors, if desired.

Designing a recursive function that uses digit_sum to calculate sum of digits

def digit_sum(n):
if n==0 or n==1:
return n
else:
return n+digit_sum(n-1)
def digital_root(n):
if n<10:
return n
else:
return digit_sum((n // 10) + n % 10)
I am trying to use digit_sum to calculate the sum of digits of digital_root can someone help me please. I am trying to use a recursive function for digital_root.
Running the file in Python shell:
digital_root(1969)
This should calculate 1+9+6+9=25 then since 25 is greater than 10 it should then calculate the sum of its digits 2+5 so that the final answer is 7.
To get the last digit of a (positive integer) number you can calculate the modulo:
last_digit = n % 10
The remainder of the number (excluding the last place) is:
rest = (n - last_digit) / 10
This should in theory be enough to split a number and add the digits:
def sum_digits(n):
if n < 10:
return n
else:
last_digit = n % 10
rest = n // 10
# or using divmod (thanks #warvariuc):
# rest, last_digit = divmod(n, 10)
return last_digit + sum_digits(rest)
sum_digits(1969) # 25
If you want to apply this recursivly until you have a value smaller than 10 you just need to call this function as long as that condition is not fulfilled:
def sum_sum_digit(n):
sum_ = sum_digit(n)
if sum_ < 10:
return sum_
else:
return sum_sum_digit(sum_)
sum_sum_digit(1969) # 7
Just if you're interested another way to calculate the sum of the digits is by converting the number to a string and then adding each character of the string:
def sum_digit(n):
return sum(map(int, str(n)))
# or as generator expression:
# return sum(int(digit) for digit in str(n))
If you really require a recursive solution without using any loops (for, while) then you can always recurse again to ensure a single digit:
def digital_root(n):
if n < 10:
return n
a, b = divmod(n, 10)
b += digital_root(a)
return digital_root(b)
>>> digital_root(1969)
7
Or you could just not recurse at all:
def digital_root(n): # n > 0
return 1+(n-1)%9
>>> digital_root(1969)
7
try this...
digitSum = 0
solution = 0
S = raw_input()
S = list(map(int, S.split()))
#print S
for i in S:
digitSum += i
#print digitSum
singleDigit = len(str(digitSum)) == 1
if singleDigit == True: solution = digitSum
while singleDigit == False:
solution = sum( [ int(str(digitSum)[i]) for i in range( 0, len(str(digitSum))) ] )
digitSum = solution
singleDigit = len(str(solution)) == 1
print(solution)

Categories

Resources