Struggling to comprehend this while loop - python

num_list = [422, 136, 524, 85, 96, 719, 85, 92, 10, 17, 312, 542, 87, 23, 86, 191, 116, 35, 173, 45, 149, 59, 84, 69, 113, 166]
count_odd = 0
list_sum = 0
i = 0
len_num_list = len(num_list)
while (count_odd < 5) and (i < len_num_list):
if num_list[i] % 2 != 0:
list_sum += num_list[i]
count_odd += 1
i += 1
print ("The numbers of odd numbers added are: {}".format(count_odd))
print ("The sum of the odd numbers added is: {}".format(list_sum))
Disclaimer: I'm a complete beginner and I find myself struggling most with while loops. For loops make sense to me.
The purpose of this code is to get the first 5 odd numbers in the list and find their sum.
I'm struggling to understand the purpose of the i variable and why they used num_list[i] % 2 != 0 (if i is set to 0 globally before the loop) to find the odd number. I'm guessing it mimics a for loop so it can iterate over the list but I'm not sure how it works. and the block of code beneath that
list_sum += num_list[i]
count_odd += 1
i += 1
is what I'm struggling with most. I don't understand what this block of code is meant to achieve and how it is working.

Your while loop continues to loop as long as the count_odd variable (number of odd numbers evaluated so far) is less than 5 and i (total number of numbers evaluated so far) is less than the length of the the list of numbers to evaluate.
Each time the code runs, if the number at the current index (i) is odd (has no remainder after being divided by 0) then the sum of the odd numbers (list_sum) is increased by the value of that number. Also the number of odd numbers evaluated (count_odd) is increase by 1 to show that another odd number is evaluated. But no matter whether or not it is an odd number, the index of the current number (i) is increased by 1 to show that the next number can be evaluated.

The code is preatty simple:
The condition on the wile mean that while he hasn't find 5 number, and while there are number in the first list, it has to work.
Than the condition:
if num_list[i] % 2 != 0:
The variabile is used to read each element of the list, while the variabile increase itself.
Then num % 2 return the
remainder of the division num/2. If it is not 0, It will be 1 for sure, so the number is odd.
The variabile increase itself because it has to read the next number in the list. If it isn't fine for you, try to learn something about list, tuples and so on
Hope will be useful

#it is the first initializing, essentially starting with 0
i = 0
len_num_list = len(num_list)
# you can reframe the while to:
# as long as you do not have 5 odd numbers AND you are not through the whole list, continue
while (count_odd < 5) and (i < len_num_list):
# num_list[i] means that you take the element with index i from the list
# since i is initialized with 0, at the first loop you take the first element (in python index starts at 0 not 1)
# SomeNumber % 2 means that if you divide the number by 2, what are the decimals.
# Only odd numbers will have decimals after division with 2, e.g. 4/2 = 2.0 but 3/2 = 1.5 so the rest would be 5
# and 5 is != 0
if num_list[i] % 2 != 0:
# number += other_number is essentially short for: number = number + other_number
# essentially you have e.g. numb = 100 and want to add 10, you can either do:
# numb = numb + 10 OR numb += 10
list_sum += num_list[i]
count_odd += 1
# since we are now through the first number of the list, which had index 0
# we now add 1 to the index and the while loop continues until the criterias stated after the "while" keyword are met.
i += 1

You can convert it to 'for' loop separating the condition checks. Indexing the num_list is unnecessary, it can be iterated over.
for n in num_list:
if n%2==0:
continue
if count_odd==5:
break
list_sum+= n
count_odd+= 1

The variable i is the variable that runs the while loop.
In the code initial i=0,and the use of (num_list[i] % 2 != 0) is to find the odd number.
Because any number divisible by 2 is a even number.Therefore in the code it is given when the number is divided by 2 it should be not equal to zero.
So it is a odd number.
Explanation of the code.
num_list[0]=422
422/2 is equal to zero.so it is not a odd number.
Then the i value is incriminating by 1
So i=i+1
i=0+1
i=1
now the value of i=1
num_list[1]=136
136/2=0 it is a even number.
Now i will again incriminating by 1
i=1+1
i=2
num_list[2]=524
524 is again even.
Then i again incriminating by 1
i=2+1
i=3
num_list[3]=85
85/2 is not zero
then list_sum=0+85
now list_sum=85
And i keeps on incriminating by 1 till 5 odd numbers is achieved.
Here is the same code with for loop
num_list = [422, 136, 524, 85, 96, 719, 85, 92, 10, 17, 312, 542, 87, 23, 86, 191, 116, 35, 173, 45, 149, 59, 84, 69, 113, 166]
countodd=0
sum=0
l=len(num_list)
for i in range(l):
if countodd<5 and num_list[i] % 2 != 0:
sum+=num_list[i]
countodd+=1
print("The numbers of odd numbers are",countodd)
print("The sum of the odd numbers is",sum)

Related

Calculate circular shift pairs in a list

A circular shift moves some of the digits in a number to the beginning of the number, and shifts all other digits forward to the next position. For example, all of the circular shifts of 564 are 564, 645, 456.
Lets say two numbers of equal length a and b are circular pairs if a can become b via circular shifting. Using the example above, the circular pairs of 564 are 645 and 456.
Given an array of positive integers nums, count the number of circular pairs i and j where 0 <= i < j < len(nums)
For example, circular_shifts([13, 5604, 31, 2, 13, 4560, 546, 654, 456]) should return 5. With the pairs being (13, 31), (13, 13), (5604, 4560), (31, 13), (546, 654).
I wrote a brute force solution that saves all circular shifts of a number in a dictionary shifts and for every number num in nums, I check all the following numbers and if a number num2 the same digits as num, I see if num2 is in num's circular shifts. If it is then I added this to the total count.
Unfortunately this algorithm runs too slowly and times out, I'm looking for a faster way to solve this problem can anyone think of optimizations, clever tricks, or other strategies to speed this up?
Not very elegant as not much time but the following should be faster as does not repeatedly access the list. Shifting is done on string for simplicity.
from collections import Counter
def big(num):
max = num
s = str(num)
for _ in s:
x = int(s[-1] + s[0:-1])
if x > max:
max = x
return max
circs = [big(z) for z in mylist]
c = Counter(circs)
total = 0
for i in c:
if c[i] > 1:
total += c[i]
print(total)
Replace every number in the array with its greatest cyclic shift. 1234, for example, would become 4123
Count the occurrences of each resulting number
If a number occurs n times, that represents n(n-1)/2 cyclic shift pairs. Add them all up.
Here's my solution, where we
iterate through the list
rotate each number length-1 times
and print only if the number is found in the remaining list
numbers = [13, 5604, 31, 2, 13, 4560, 546, 654, 456]
# shift_pairs = [(13,31),(13,13),(5604,4560),(31,13),(546,654)]
pairsFound = 0
for i in range(len(numbers)):
number = numbers[i]
length = len(str(number))
numberToRotate = number
shift_remaining = length - 1
temp_list = numbers[i+1:]
while(shift_remaining >= 0):
t_remainder = numberToRotate % 10 # 4
numberToRotate = numberToRotate // 10 # 560
numberToRotate = numberToRotate + t_remainder * 10 **(length-1) # 4560
# we should also check for length for cases like 4560, where on a shift we get 456
if(numberToRotate in temp_list and len(str(numberToRotate)) == length):
print("({},{})".format(number,numberToRotate))
pairsFound += 1
shift_remaining -= 1
print("no of pairs:", pairsFound)
output
(13,31)
(13,13)
(5604,4560)
(31,13)
(546,654)
no of pairs: 5

Getting an incorrect output which is off by 1 - Min number of moves required to make all elements equal

This is from the leetcode question 453 which says :
Given an integer array nums of size n, return the minimum number of moves required to make all array elements equal.
In one move, you can increment n - 1 elements of the array by 1.
I have created a solution that works fine on most of the test cases but fails on one of the test cases. I have given that test case below. I am not sure, where am I going wrong.
class Solution(object):
def minMoves(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
max_number = max(nums)
min_number = min(nums)
total_count = max_number - min_number
_nums = nums[:]
while max_number - min_number != 1 and (max_number - min_number != 0):
diff = max_number - min_number
max_list = []
for i, n in enumerate(_nums):
if n != max_number:
_nums[i] += diff
else:
max_list.append(i)
if len(max_list) > 1:
# if there are duplicate max_numbers
for i in max_list[1:]:
_nums[i] += diff
max_number = max(_nums)
min_number = min(_nums)
if max_number - min_number == 1:
total_count += 1
else:
total_count += (max_number - min_number)
return total_count
The test case:
[83,-14,77,15,93,35,86,-8,-51,-79,62,-73,-10,-41,63,26,40,-74,72,36,-89,68,67,-71,82,30,-38,23,-33,35,29,-98,-78,-42,-31,67,93,-44,-89,-58,-71,73,-79,19,84,37,98,24,15,70,-87,26,-9,80,56,-27,-38,70,96,-19,5,25,-16,27,36,5,-54,29,13,-43,24,-5,82,45,-86,67,-66,64,-57,50,-13,-92,-24,78,88,84,-97,-49,54,99,32,-40,-24,68,39,-88,-74,86,-6,39,95,70,-66,78,-33,-99,-3,2,17,-8,-48,56,1,-20,-14,-59,-35,-11,-56,-81,-60,29,-69,17,-3,71,-19,-25,9,27,67,-44,-3,53,86,65,6,-17,-81,-76,28,-29,32,-71,3,-81,-30,68,8,15,40,49,96,23,-82,-55,-54,-49,21,55,79,-12,64,-72,-59,50,93,0,-66,64,24,14,87,-44,43,-9,-73,65,-41,36,-68,51,-63,-72,-25,-93,-26,21,-42,95,-71,-63,-65,93,-82,-72,43,-89,28,29,76,-96,-57,63,-87,38,-94,-60,4,-82,28,-12,69,17,17,96,24,43,-30,83,-10,-1,72,25,-56,90,5,39,54,86,-31,-18,42,-36,97,7,55,-96,48,-89,-78,-72,-1,43,46,68,40,-78,11,-90,-95,-99,-39,30,-22,5,20,36,-56,-74,22,-35,8,-84,-18,-42,24,-63,-38,-76,-100,-64,-48,-1,79,50,-32,-29,73,31,-19,30,33,-6,-40,63,99,81,-1,96,59,73,-87,-32,90,-5,26,-34,-16,40,-10,-16,76,42,36,7,-55,56,79,-82,-13,-88,48,72,-41,-91,36,-90,42,87,-94,1,13,72,21,-45,-81,99,21,4,39,-89,40,-33,5,-72,27,50,84,-42,20,-76,-78,-31,96,-19,-70,-16,-8,72,-28,-50,-75,85,-78,-1,-60,-58,-2,13,-2,90,24,90,-91,81,-81,36,32,55,94,-96,79,69,-27,76,-50,-45,-40,42,79,-16,93,-95,-79,67,4,-87,61,54,26,-41,44,-98,-98,6,84,-79,-58,-32,28,89,-28,8,58,-2,-64,-92,53,-52,3,33,33,-52,-10,54,67,46,68,29,0,-54,88,97,-51,90,3,-67,63,-3,-47,-8,-14,25,52,96,75,88,57,29,-64,-40,-86,21,-40,4,-72,-73,-50,48,56,2,94,-3,-1,-57,-61,-98,-72,-97,0,-19,-53,38,59,51,35,34,39,-8,-85,27,4,-71,-51,64,-15,-71,43,35,77,0,-62,71,49,-11,67,88,-8,95,43,44,-71,90,-18,40,41,69,-74,-68,-39,-58,60,17,-77,61,-19,9,90,-75,96,67,-23,-66,-10,-74,24,-43,-86,68,-95,58,12,86,0,46,26,94,16,52,78,29,46,-10,-53,70,-49,-20,-69,93,-43,-73,12,-14,-86,55,12,-10,-88,-21,-90,69,89,-26,55,-59,-80,-67,87,-12,38,66,70,-16,-44,-83,-94,-40,-51,-63,-95,-41,-83,18,45,83,-27,-42,-27,-63,-11,-17,-93,-22,57,14,-29,29,0,-41,-82,-62,-75,88,-26,-67,57,-19,-7,58,-30,-1,-83,-61,69,63,-78,94,73,-53,-69,-38,-18,90,-8,91,-43,15,21,57,74,-9,47,51,-69,-79,37,40,-46,-70,-2,25,-19,16,16,-98,-69,39,96,-96,38,80,-82,-79,70,-38,-88,79,77,-15,36,4,76,-17,-93,59,-43,44,-1,11,27,50,-64,60,-82,5,63,-51,-56,11,-95,34,-9,75,55,-86,89,68,93,18,-95,-18,-78,82,17,-70,-7,74,26,93,-14,-47,43,-26,-86,13,79,77,62,75,-12,19,10,32,-6,-83,46,-65,37,-9,53,43,73,28,25,-9,10,-82,-83,-64,63,-45,-10,-42,30,4,71,-39,-67,-15,89,-27,-96,-49,-95,-50,-32,3,-15,-94,95,-61,49,20,67,-74,63,-23,96,81,-35,60,-64,55,70,18,-89,42,32,96,79,21,-30,84,72,-73,-66,-60,-17,-28,98,-70,-37,47,50,-70,73,14,-41,22,-53,24,-18,-65,-68,-96,54,-57,-2,-14,-60,-22,59,-38,-38,-17,-59,-52,23,24,-28,22,54,35,-79,-43,65,47,71,76,-31,-82,1,3,-47,33,7,59,28,-94,97,20,-16,8,34,-2,91,76,-2,15,-48,71,89,59,6,-90,-84,-76,9,39,-100,78,9,-47,-19,14,38,89,-74,-33,47,-77,87,-69,32,22,-19,-25,-50,79,90,-46,50,31,-87,-43,-6,81,-19,-97,20,-67,82,81,-13,-85,-4,-75,-96,22,-8,51,-3,-68,34,81,6,-85,-43,8,95,99,62,-3,-17,76,54,77,9,87,32,82,-79,-34,63,-40,-18,-89,-15,-14,-15,30,90,83,14,-24,16,-80,-8,25,28,-61,25,-10,36,60,-82,-57,37,28,82,-79,10,55,-12,-75,-85,70,-63,-47,-92,22,83,50,-43,-3,-73,26,-31,-29,-49,49,10,28,-61,98,-12,-90,93,77,-10,76,99,52,31,-13,77,-1,-43,66,52,-83,-59,35,68,-2,84,95,76,-95,-34,-72,54,28,8,93,-22,97,55,-28,74,-55,-100,25,97,-17,-88,27,82,-79]
The method that I am using is simple. For example, for an array like:
[1,2,3,100]
Minimum number of moves can be maximizing the smallest number towards greatest. So,
[100, 101, 102, 100] (100 - 1 = 99 and everybody except 1 gets incremented by that). This makes 99 moves
[102, 103, 102, 102] (102 - 100 = 2 and everybody gets except 1 incremented by that. This makes 2 moves with total moves now being 99 + 2 = 101
[103, 103, 103, 103] Just one move is required here. (101 + 1 = 102)
It looks like your algorithm doesn't handle duplicate maximums correctly. It fails for [0,1,1], for example, which requires 2 moves to make all the elements the same.
This problem doesn't require such a complicated algorithm. In terms of making all elements equal, incrementing n-1 elements is the same as decrementing one element. To make all elements the same, all elements must be relatively decremented to the minimum value.
The answer is just sum(nums) - min(nums)*len(nums).

How to create a list of 5 next numbers that are not divided by 3

dear community, I started learning Python and want to create a list of 5 next (after the given number) numbers that are not divided by 3 (modulo).
Here is my code:
def main(N):
#print a list of 5 next numbers that are not divided by 3
l = list()
for i in range(int(N), 150):
if len(l) < 5:
if i%3==0:
l.append(i+1)
return [l]
at the end I get f.e. for the print(main(99)):
>>> [100, 103, 106, 109, 112]
I also tried to put i+=1 after if statement but in the end I got even weirder result:
[101, 101, 102, 104, 104]
What do I do wrong and how can I fix it?
Thanks!
I would write a generator that yields numbers not divisible by 3 with a base number and count as arguments:
def three_no_factor(n, cnt):
x = 1
while x <= cnt:
if n % 3 != 0:
yield n
x += 1
n += 1
Then use that to get the list of 5 numbers not divisible by 3:
>>> [x for x in three_no_factor(100,5)]
[100, 101, 103, 104, 106]
Unless there's a specific reason to cap the values at 150, you can just let the loop run until the list is full.
def next_nontriples(N):
# return a list of 5 next numbers that are not divisible by 3
ls = list()
nx = N + 1
while len(ls) < 5:
if nx%3 != 0:
ls.append(nx)
nx += 1
return ls
Using the != operator is the key. Note that I'm returning the resulting list, whereas you return a list that has the required list as its only element, due to the extra square brackets around your return item.
You can fill the list once per loop-5-times too:
def next_nontriples(N):
# return a list of 5 next numbers that are not divisible by 3
ls = list()
nx = N + 1
for ix in range(5):
if nx%3 == 0:
nx += 1 # skip this one
ls.append(nx)
nx += 1
return ls
Here we just add an increment to our candidate value if it fails the test (by being divisible by three). We know that the next number will qualify.
Finally you could just handle the three cases separately. Not recommended particularly here but hard-coding is sometimes your friend:
def next_nontriples(N):
# return a list of 5 next numbers that are not divisible by 3
if N%3 == 0:
return [N+1, N+2, N+4, N+5, N+7]
if N%3 == 1:
return [N+1, N+3, N+4, N+6, N+7]
if N%3 == 2:
return [N+2, N+3, N+5, N+6, N+8]
Another way - >
def main(N):
gen = (i for i in range(int(N), 150) if i % 3 != 0) # create generator
return [next(gen) for j in range(5)] # iterate 5 times
main(99) # [100, 101, 103, 104, 106]

How do I efficiently find out how many numbers are not divisible from a list of primes?

I'm new to python and in order to learn I'm trying to solve a problem as an exercise.
N is a integer between [1, 10^9]
K is a list of length <= 40 of random distinct prime numbers that are all equal or less to N.
My code has to find the quantity of number that are <= N that are not divisible by any number of the list K.
I've written the following code:
first_line = input().split()
second_line = input().split()
n = int(first_line[0])
list_of_primes = second_line
all_multiples_set = set()
for i in range(len(list_of_primes)):
prime = int(list_of_primes[i])
# Creates a set of all multiples numbers of this prime that are equal or less than N.
one_multiple_set = set(range(prime ,n if n % prime != 0 else n + prime ,prime ))
# Makes a Union of this set with the previous sets of multiples, thus getting all multiples of a and b.
all_multiples_set = all_multiples_set.union(one_multiple_set)
print(n - len(all_multiples_set))
The first input consist of 2 numbers: N and length of K respectively. (ie. "10 3").
The second input is a series of length of K primes that are less or equal to N. (ie. "2 3 7").
The output should be a integer that represents the quantity of number equal or less than N that are not dividable by any number in list K. (ie. "2" in this case)
I know my code works for some cases, but unfortunately the platform where I found this puzzle does not tell me for which cases my code does not work, it only tells me that it does not work for some cases.
I believe it is a question of memory. Given that 10^9 is a very large number, but it could also be an error that I'm not seeing.
I would appreciate some guidance in how to improve my code or a suggestion of a better approach. It is worth noticing that since this is an exercise, I can not import modules and also since I'm trying to learn, I would appreciate an explanation of why my code is ineficiente.
EDIT:
Execution time is also a factor. The code has 1 second max run time.
On my first try I wrote this code:
linha1 = input().split()
linha2 = input().split()
n = int(linha1[0])
s = linha2
x = len(s)
value_to_add = 0
value_to_subtract = 0
for i in range(1 << x):
single_set = []
multiply = 1
for j in range(x):
if i & (1 << j):
single_set.append(int(s[j]))
for num in single_set:
multiply *= num
if multiply > n:
break
if len(single_set) == 1:
value_to_add += n//single_set[0]
elif len(single_set) > 1:
value_to_subtract += n//multiply
print(n - value_to_add + value_to_subtract)
It also gets the right answer, but it takes to long to run.
Since the list contains distinct prime numbers, this problem can be reduced to finding how many numbers less than or equal to N are divisible by these primes then deduct that number from N.
Since N can be large (10^9) and K is not, you can use inclusion-exclusion principle to find that.
N/x = quantity of numbers less than or equal to N and are divisible by x
N/(x*y) = quantity of numbers less than or equal to N and are divisible by both x and y at the same time.
using inclusion exclusion principle and your sample data:
According to inclusion-exclusion, you add the number to the result when the
list_of_primes = [2, 3, 7]
n = 10
We add these:
10 / 2 = 5
10 / 3 = 3
10 / 7 = 1
-----------
9
Subtract these:
10 / (2 * 3) = 1
10 / (2 * 7) = 0
10 / (3 * 7) = 0
----------------
1
And add this:
10 / (2 * 3 * 7) = 0
--------------------
0
result = 9 - 1 + 0 = 8
n - result = 10 - 8 = 2 <-- this is the answer
You can implement that using a recursive approach as the following:
list_of_primes = [2, 3, 7]
n = 10
k = 3
def get_count(i, num, taken):
if num > n:
return 0
if i == k:
# the case 0 numbers taken
if taken == 0:
return 0
# if odd number of numbers are taken
if taken % 2:
return n // num
# if even number of numbers are taken
return -1 * (n // num)
return get_count(i+1, num * list_of_primes[i], taken+1) + get_count(i+1, num, taken)
print(n - get_count(0, 1, 0))
# 2
From wikipedia:
Generalizing the results of these examples gives the principle of
inclusion–exclusion. To find the cardinality of the union of n sets:
Include the cardinalities of the sets.
Exclude the cardinalities of the pairwise intersections.
Include the cardinalities of the triple-wise intersections.
Exclude the cardinalities of the quadruple-wise intersections.
Include the cardinalities of the quintuple-wise intersections.
Continue, until the cardinality of the n-tuple-wise intersection is included (if n is odd) or excluded (n even).
[Edited]
Be sure to convert to int before sorting:
list_of_primes = list(map(int, input().split()))
I also found a way to optimize the code roughly 2x faster. Note that if in some branch num is multiplied by min prime number from list is larger then N, than there is no need to continue and branch more, since we wouldn't change num as it is already big enough. Therefore, the following code:
list_of_primes = [11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193]
n = 10 ** 9
list_of_primes.sort(reverse=True)
k = len(list_of_primes)
min_prime = list_of_primes[-1]
def get_count(i, num, taken):
if num > n:
return 0
# if min_prime * num > n then we won't take any new numbers
# thus taken won't change
if min_prime * num > n or i == k:
# the case 0 numbers taken
if taken == 0:
return 0
# if odd number of numbers are taken
if taken % 2:
return n // num
# if even number of numbers are taken
return - 1 * (n // num)
return get_count(i+1, num * list_of_primes[i], taken+1) + get_count(i+1, num, taken)
print(n - get_count(0, 1, 0))
is almost two times faster on the given test than the previous solution: 0.25s vs 0.63s.
Old solution:
I found a way to decrease the depth of the recursion. You should iterate through descending sorted array of prime numbers to faster finish branching, i.e.:
list_of_primes.sort(reversed=True)
Thus in the worst case I improved the time from 5 seconds to 1.2 seconds.
list_of_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, 101,
103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173]
n = 10 ** 9
list_of_primes.sort(reverse=True)
k = len(list_of_primes)
def get_count(i, num, taken):
if num > n:
return 0
if i == k:
# the case 0 numbers taken
if taken == 0:
return 0
# if odd number of numbers are taken
if taken % 2:
return n // num
# if even number of numbers are taken
return -1 * (n // num)
return get_count(i+1, num * list_of_primes[i], taken+1) + get_count(i+1, num, taken)
print(n - get_count(0, 1, 0))
It's very easy for your all_multiples_set to grow to a number very close to 10^9, which is going to consume on the order of 40GB of memory -- more than is reasonable on most machines! So you'll need a strategy that doesn't require you to keep track of so many numbers.
Start by getting N and K:
n, _ = map(int, input().split())
k = list(map(int, input().split()))
From there, one possible strategy would be to keep track of only the numbers that might actually match, and prune that number down as you go:
candidates = [c for c in range(1, n + 1) if c % k[0]]
for j in k[1:]:
candidates = [c for c in candidates if c % j]
print(len(candidates))
This has the advantage of getting faster and smaller when you're going through a large K list, but it still has the space problem because you start off with a lot of candidates (e.g. if N is 10^9 and your first value of K is 2, you have 5 billion ints to keep track of, which is better than 10 billion but still too many).
The way to do this without taking up any space at all is to iterate through all the candidates from 1 to N, completely evaluate each one against each element of K, and add 1 to the count if it meets the criteria. That way the only thing you need to keep track of is the count, and not what all the actual numbers are.
print(sum(
1 if all(c % j for j in k) else 0
for c in range(1, n+1)
))

Python: Prime number algortihm implementation with square root

I am trying to solve this problem and despite wrapping my head around it I get stucked over and over and over.
I have a list made of one element [2] and given that and knowing that in order to get a prime number $N$ I have to check that it does not have any prime factor smaller or equal than $\sqrt{N}$, generate all prime numbers between 3 and 100
My code is the following and I will try to explain how I came up with it:
prime_numbers = [2]
for k in range(3,100): # k runs on all numbers to check them
for i in range (0,len(prime_numbers)): # i is the index of the elements in my list
if prime_numbers[i] <= sqrt(k): # first I need to check the sqrt condition
if k % prime_numbers[i] ==0: # check that element in list divides k
k+=1 # if so k++ and break the cicle
break
else:
i +=1 # otherwise go to the next elem of the list
else: #if the sqrt condition is not met I have found a prime number
value = k
prime_numbers.append(value)
When I run this code it gets into a loop with no exit, and I cannot individuate where the issue is. My best guess would be to correct the most indented else condition, but all the attempts I have done have resulted in failure. Thanks to everyone who is willing to partecipate.
This works:
prime_numbers = [2]
for prime_candidate in range(3, 100):
for known_prime in prime_numbers:
if known_prime <= sqrt(prime_candidate):
if prime_candidate % known_prime == 0:
break
else:
prime_numbers.append(prime_candidate)
Your problem mainly was, that i += 1 does not prevent prime_numbers.append to append again.
The for/else can be substituted by a separate flag to trigger all cases without a break happening earlier.
One way to get there is:
from math import sqrt
prime_numbers=[2]
for k in range(3,101):
prime=True
for i in range(2, int(sqrt(k))+2):
if k%i == 0:
prime=False
break
if prime:
prime_numbers.append(k)
print(prime_numbers)
#Output:
#[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]
Notes:
It's range(3,101) and not range(3,100) if assuming you want to check all numbers including 100, otherwise your last number checked will be 99.
Have a boolean variable prime; start by assuming the number is prime (prime=True)
sqrt(k) returns a float, while your range expects integers; as such - int(sqrt(k)). It's +2 to ensure your range 'to' value is never smaller than your 'from' value of 2.
if k%i == 0 (if you have a divisor) the number is not prime (prime=False) and break the for loop to move to the next k
This could be my "pythonic" by doing a list comprehension, but it may be easier for you to understand in the current format
Thanks to everyone who suggested a solution. Meanwhile I came up with one myself.
prime_numbers = [2]
for k in range(3,100):
for i in range (0,len(prime_numbers)):
if prime_numbers[i] <= sqrt(k):
if k % prime_numbers[i] ==0:
k+=1
break
else:
i +=1
else:
value = k
if(value > max(prime_numbers)):
prime_numbers.append(value)

Categories

Resources