So I have a list of numbers that look like "3723311723" and "13617172343". As you can see these numbers can be split into prime numbers e.g "3723311723" could be split into 37, 23, 31 ect. How could I write a python program that takes a number like this as an input and returns a list of the primes inside it (in the order they are found)?
Thanks.
If you know that the numbers are definitely gonna be prime, then you just have to break up the string into substrings of length 2, right?
s = "37233141712331719337"
print([int(s[i:i+2]) for i in range(0, len(s), 2)])
Output:
[37, 23, 31, 41, 71, 23, 31, 71, 93, 37]
EDIT:
This does a recursive search to find non-overlapping primes. If there's no valid split, it returns False. The usual caveats of recursion apply: if the input is too long, you'll recurse too deep and the program will blow up. But you can use a stack instead of recursing if that's an issue.
def is_prime(n):
for k in range(2, n):
if n % k == 0:
return False
return True
def primesplit(s, i=0):
if i+1 >= len(s):
return []
if i+2 <= len(s):
two_digits = int(s[i:i+2])
if is_prime(two_digits):
remaining_digits = primesplit(s, i+2)
if isinstance(remaining_digits, list):
return [two_digits] + remaining_digits
one_digit = int(s[i:i+1])
if not is_prime(one_digit):
return False
remaining_digits = primesplit(s, i+1)
if isinstance(remaining_digits, list):
return [one_digit] + remaining_digits
return False
s = "37233141712331719337"
result = primesplit(s)
print(result)
print("".join(map(str, result)) == s)
Output:
[37, 23, 31, 41, 71, 23, 31, 7, 19, 3, 37]
True
It's a bit complicated what you are asking for, but here's what I thought you meant:
Given a number, look for any two digit prime within that number(I assume they ARE allowed to overlap)
A easy way to do that is like this:
def isPrime(number):
if number>1:
for i in range(2,number):
if (number%i)==0:
return False
return True
else:
return False
def getPrimes(number):
number=str(number)
retList=[]
for i in range(len(number)-1):
temp=int(number[i:i+2])
if isPrime(temp):
retList+=[temp]
return retList
This does NOT check for single digit primes, but that could easily be added if you needed it (simply check every digit in the original number if they are prime).
Is this what you wanted?
This is what you are looking for:
The loop finds both 1 and 2 digit prime numbers in the order they appear in the original number and there will be no duplicates too.
In [126]: n
Out[126]: '37233141712331719337'
In [127]: primes = []
...: for i in range(len(n)-1):
...: n1 = int(n[i])
...: n2 = int(n[i:i+2])
...: if isPrime(n1):
...: if n1 not in primes:
...: primes.append(n1)
...: if isPrime(n2):
...: if n2 not in primes:
...: primes.append(n2)
...:
In [128]: primes
Out[128]: [3, 37, 7, 2, 23, 31, 1, 41, 17, 71, 19]
Here is how you can use the isprime method from the sympy module, and zip:
from sympy import isprime
n = "37233141712331719337"
lst = [int(i + j) for i, j in zip(n, n[1:]) if isprime(int(i + j))]
print(lst)
Output:
[37, 23, 31, 41, 17, 71, 23, 31, 17, 71, 19, 37]
Related
I want to create a python function that accepts two integer parameters finds all prime numbers between them and returns these primes in a list.
I did a part of the code but I'm stuck in printing prime numbers and turning them into a list.
a,n = map(int,input("Enter a and n: ").split())
def isPrime(a,n):
if n <= 1:
return False
for i in range(a, n+1):
if n % i == 0:
return False;
return True
You can make your is_prime function shorter like that:
a,n = map(int,input("Enter a and n: ").split(" "))
def is_prime(a):
return all(a % i for i in range(2, a))
out = []
for i in range(a, n):
if is_prime(i):
out.append(i)
print(out)
The output for a = 0 and n = 90 would be:
[0, 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89]
I edited your solution so that you only check for numbers with a value of 2 or higher. Your solution allows negatives, which is not correct.
Also, your clause for checking for the primes is wrong, as you check if n has divisors. Instead, you want to check if every number in [a, n) interval has a divisor. The interval is [a, n) because a prime number has only 1 and itself as divisors.
My code does just that, so if the algorithm finds that a number in the [a, n) interval has no divisors, then it will append it in an empty list that I created before going through the loop, and return the list, then print it.
a, n = map(int, input("Enter a and n: ").split())
def isPrime(a, n):
lst = []
for i in range(a, n + 1):
if (i > 1):
for j in range(2, i):
if (i % j == 0):
break
else:
lst.append(i)
return lst
print(isPrime(a, n))
My output for a = 0 and n = 100 is:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
My code is a modified version of this.
So I'm trying to print all the prime numbers up to 100. Here's my code so far:
primes = []
for num in range(100):
if num > 1:
for i in range(2, num):
if num % i != 0:
primes += [num]
break
else:
break
print(primes)
However when i run the code, it only does the calculation (if num % i != 0) for the first iteration in the range (for i in range(2, num)). This is a problem in the case of numbers like 15, where the first iteration in for i in range is 2. 15 divided by 2 does not give a whole number, and so it runs primes += [num]. It has taken the first iteration and has not run the rest of them. Is there a way to run all the iterations in the range?
Try this:
primes = []
for num in range(100):
if num > 1:
for i in range(2, num):
if num % i == 0:
break
else:
primes.append(num)
print(primes)
The code will execute the else block only if the inner for loop is exhausted, i.e completes it's all iteration without breaking.
You got the logic somewhat wrong. Here's how you've to do it
primes = []
for num in range(2, 100): # 0 and 1 aren't primes
for i in range(2, num):
if num % i == 0:
break
else: # the else condition is for the for loop i.e. if it executes without break
primes.append(num)
print(primes)
The all function may be what you're looking for!
Here is my take on it.
>>> def primes(limit=100):
... for number in range(limit):
... is_prime = all([number % divisor != 0 for divisor in range(2, number)])
... if is_prime:
... yield number
...
>>> list(primes(10))
[0, 1, 2, 3, 5, 7]
>>> list(primes(100))
[0, 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
>>>
Is not complete, 0 and 1 are not primes. But I think you get the idea.
tried to adapt to your approach although, I think there should be better ways to solve this problem
>>> primes = []
>>> for num in range(2,100):
... p = True
... for i in range(2, num):
... if num % i == 0:
... p = False
... if p:
... primes += [num]
...
>>> primes
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Given the list:
n = [3, 6, 12, 24, 36, 48, 60]
I need to turn a random number divisible by 3, after by 6, after by 12, after by 24, after by 36, after by 48 and after by 60. One at each time, not the divisible for the seven numbers simultaneously.
But, to make the number divisible, I need to sum another number to reach the number divisible by 3, 6, 12, 24, 36, 48 or 60.
I don't know the random number neither the number to add to this random number in order to turn it divisible by 3, 6, 12, 24, 36, 48 or 60.
Can someone help me, please?
Using the map function list comprehension:
import random
n = [3, 6, 12, 24, 36, 48, 60]
a = random.randint(start, stop)
result = [a + x - a % x if a % x else a for x in n]
addition = [x - a for x in result]
print(a)
print(result)
print(addition)
start and stop are the limits for your random number.
Output for a = 311:
311
[312, 312, 312, 312, 324, 336, 360]
[1, 1, 1, 1, 13, 25, 49]
Begin of the old answer to the rather unclear question before the first edit by the author.
The following post answers the question: Which is the next number after a, which is a multiple of all numbers of the list n, if it is not a?
First the least common multiple lcm of the numbers from the list must be determined. For this purpose, the method least_common_multiple is executed for the complete list. The modulo operation then checks whether a is not already a multiple of the numbers. If this is the case, a is output. Otherwise, the next multiple of lcm is output.
from math import gcd
from functools import reduce
n = [3, 6, 12, 24, 36, 48, 60]
a = 311
def least_common_multiple(x, y):
return abs(x * y) // gcd(x, y)
lcm = reduce(least_common_multiple, n)
result = a if a > 0 else 1 # can be change if necessary, see edit
mod = result % lcm
if mod:
result += (lcm - mod)
print('Current number: ' + str(a))
print('The next number divisible by any number from the given list: ' + str(result))
print('Necessary addition: ' + str(result - a))
Output:
Current number: 311
The next number divisible by any number from the given list: 720
Necessary addition: 409
Edit: Changed the code so that 0 is no longer a valid result for a non-positive a.
However, if it is valid, you can change the code at the commented part with: result = a.
New answer for the clarified question:
import math
def f(x, a):
return math.ceil(a / x) * x - a
n = [3, 6, 12, 24, 36, 48, 60]
a = 311
result = [f(x, a) for x in n]
print(result)
Old answer:
I think you're looking for the LCM (lowest common multiple) of all numbers in n. We can get the LCM for two numbers using the GCD (greatest common divisor). We can then use reduce to get the LCM for the whole list. Assuming x can be negative, simply subtract a from the LCM to get your answer. The code could look like this:
import math
from functools import reduce
def lcm(a, b): # lowest common multiple
return a * b // math.gcd(a, b)
n = [3, 6, 12, 24, 36, 48, 60]
smallest_divisible_by_all = reduce(lcm, n)
a = 311
x = smallest_divisible_by_all - a
print(x)
which outputs
409
If speed is not important, you could also do a brute force solution like this:
ns = [3, 6, 12, 24, 36, 48, 60]
a = 311
x = 0
while not all([(a + x) % n == 0 for n in ns]):
x += 1
(assuming that x >= 0)
So I can think of 2 solutions:
First if you want a list which show how much you have to add for the random number to get to a divisible number:
def divisible(numbers,random):
l = []
for number in numbers:
if random % number != 0:
l += [number - (random % number)]
else:
l += [0]
return l
a = 311
n = [3, 6, 12, 24, 36, 48, 60]
print(divisible(n,a))
Output:
[1, 1, 1, 1, 13, 25, 49]
Or if you want to know how far is the smallest number from the random number that everyone shares as divisible. For this take a look how you calculate lcm.
from math import gcd
def divisible_all(numbers, random):
lcm = numbers[0]
for i in numbers[1:]:
lcm = lcm*i//gcd(lcm, i)
tempLcm = lcm
while lcm < random: # in case the lcm is smaller than the random number add lcm until it is bigger (I assume you only allow positive numbers)
lcm += tempLcm
return lcm-random
print(divisible_all(n,a))
Output:
409
You can do:
import math
n = [3, 6, 12, 24, 36, 48, 60]
div_n={el: False for el in n}
a=311
a0=math.ceil(a/max(n)) * max(n)
while not all(div_n.values()):
div_n={el: False for el in n}
# print(a0)
for el in n:
if(a0 % el > 0):
a0=math.ceil(a0/el) * el
break
else:
div_n[el]=True
print(a0-a)
Output:
409
There is a question on codewars, life without primes. I solved it yet the time issue comes up. I really cannot find a better way. The instructions go like;
Consider an array that has no prime numbers, and none of its elements has any prime digit. It would start with: [1,4,6,8,9,10,14,16,18,..]. The element at index 1 is 4.
There will be given an integer n and the task will be return the number at that index in the array. For example, solve(1) = 4, as explained above.
Here is my solution
def solve(n):
no_primes=[]
a=1
if n == 1:
return 4
else:
while True:
try:
no_primes[n]
break
except IndexError:
if is_prime(a) == True:
if is_num_prime(a) == False:
no_primes.append(a)
a=a+1
return no_primes[n]
def is_prime(num):
numbers = list(map(int, list(str(num))))
#primes=[0,2,3,5,7,9]
non_primes=[0,1,4,6,8,9]
return all(list(map(lambda x:x in non_primes,numbers)))
def is_num_prime(num):
if num == 2:
return True
elif num >2:
for i in range(2,num):
if num%i == 0:
return False
else:
return True
else:
return False
Getting rid of the while loop could help but I need to keep on appending until I can reach the value from the list. A recursive for loop with using range(1,n) where n increases recursively may be an option but I could not write it anyways.
You can easily break down this problem in simple steps:
Generate the all the combinations
You can make an endless generator making ever-longer combinations of these digits
def generate_numbers():
digits= '014689'
for i in itertools.count(1): # ever longer number
for x in itertools.product(digits, repeat=i): # combine the digits
number = ''.join(x)
if number[0] != '0':
yield int(number)
print(list(itertools.islice(generate_numbers(), 40)))
[1, 4, 6, 8, 9, 10, 11, 14, 16, 18, 19, 40, 41, 44, 46, 48, 49, 60, 61, 64, 66, 68, 69, 80, 81, 84, 86, 88, 89, 90, 91, 94, 96, 98, 99, 100, 101, 104, 106, 108]
Check whether a number is prime
def is_prime(num):
if num in {0, 1,}:
return False
if num == 2:
return True
if not (num % 2):
return False
for i in range(3, round(num **.5 + 1), 2):
if not (num % i):
return False
return True
return the nth non-prime number
def solve(n):
non_prime_solutions = (i for i in generate_numbers() if not is_prime(i))
return next(itertools.islice(non_prime_solutions, n, None))
[solve(i) for i in (1, 2, 10, 100)]
[4, 6, 44, 644]
Since all of this is lazily evaluated, this should go pretty fast. The one thing that can be optimised is the is_prime
import math
import itertools
def is_prime(n):
return all(n % i for i in range(2, int(math.sqrt(n) + 1)))
prime_digits = {"2", "3", "5", "7"}
def no_prime_digit(n):
return not any(x in prime_digits for x in str(n))
def non_primes():
return (i for i in itertools.count() if no_prime_digit(i) and not is_prime(i))
def get_non_prime(n):
return next(x for i, x in enumerate(non_primes()) if i == n - 1)
print([(x, get_non_prime(x)) for x in [1, 10, 100]])
I'm trying to check modulo of a number against a tuple of numbers, if the modulo is equals to one of the values in the tuple I want to return True else return False.
This is what I had tried so far:
def check(y):
k = (2, 5, 8, 10, 13, 16, 19, 21, 24, 27, 29)
for i in range(0, len(k)):
if k[i] == y % 30:
return True
else:
return False
def main():
print(check(1439))
main()
It always returns false.
This is always returning false as only first item is checked. If first item is a match then it will return true. For example, if y is 32 then it will return true. You need to return false after checking all values, i.e. outside of for loop. Or a better solution is to use in operator.
def check(y):
k = (2, 5, 8, 10, 13, 16, 19, 21, 24, 27, 29)
return y % 30 in k
It always returns false because this code:
for i in range(0, len(k)):
if k[i] == y % 30:
return True
else:
return False
returns true or false based only on the first item in the array, because it returns in both possible code paths. Either k[0] == y % 30 and it returns true, or k[0] != y % 30 and it returns false.
If you want to use this loop-based solution, you need to check every item in the array, returning true immediately if it matches, otherwise returning false only after the list is exhausted, something like (using the for n in k variant of the loop since the index is irrelevant here):
for n in k:
if n == y % 30:
return True
return False
The full program is thus:
def check(y):
k = (2, 5, 8, 10, 13, 16, 19, 21, 24, 27, 29)
for n in k:
if n == y % 30:
return True
return False
def main():
print(check(1439))
print(check(36))
main()
with the first call producing true as 1439 % 30 == 29 (in the list) but the second giving false because 36 % 30 == 6 (not in the list).
Of course, there's a far more Pythonic way to achieve this:
def check(y):
k = (2, 5, 8, 10, 13, 16, 19, 21, 24, 27, 29)
return any (x == y % 30 for x in k)
That basically finds any element in k for which that element is equal to y % 30. See this link for more information on the Python any operation, and you'll see instantly the equivalent code given is remarkably similar to your loop:
def any(iterable):
for element in iterable:
if element:
return True
return False
But, of course, it turns out to be unnecessary to use any in this particular case as y % 30 is effectively a fixed value in the context of searching through the list. Instead, you can opt for the much simpler:
def check(y):
k = (2, 5, 8, 10, 13, 16, 19, 21, 24, 27, 29)
return (y % 30) in k
leaving the any variant for more complex comparisons not easily doable, such as only checking even numbers from the list:
def check(y):
k = (2, 5, 8, 10, 13, 16, 19, 21, 24, 27, 29)
return any (x == y % 30 for x in k if x % 2 == 0)
You can accomplish this with a generator expression inside any():
def check(y):
return any(n == y % 30 for n in k)
This builds an iterator of booleans that is true for all elements of k that are divisors of y.