Python while if not working - python

I'm given with an array with numbers.
I'm trying to build a program that identifies if the number is an even or odd number.
Here's what I've done.
a = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
i=0
while i <= len(a):
if a[i] % 2 == 0:
print(a[i], " is an even number")
i = i + 1
else:
print(a[i], " is an odd number")
I was thinking since a[0], a[1] represents 1, 4, I thought that I can use a[i] where i increases until the length of a.
But this code gives me an infinite loop.
This is the only way I figured to use individual numbers in array.
I tried using
if a%2==0:
print(a, " is an even number")
But that gave me an error.
Thanks in advance

You can achieve that simply with a for loop like below:
a = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
for n in a:
if n % 2:
print(n, "is an odd number")
else:
print(n, "is an even number")
For your above code issues, you are not incrementing i inside else block and your condition should be < len(a) instead of <= len(a)

Put your i = i+1 outside of the if/else and replace <= with a < otherwise it goes over the array length.
a = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
i=0
while i < len(a):
if a[i] % 2 == 0:
print(a[i], " is an even number")
else:
print(a[i], " is an odd number")
i = i + 1

your problem is that the following:
instead of using <= use <.
Add your i = i + 1 in both if and else.
Because if you hit an even number it will add 1 to i, but also if you hit a odd number it will add 1 too.
a = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
i=0
while i < len(a):
if a[i] % 2 == 0:
print(a[i], " is an even number")
i = i + 1
else:
print(a[i], " is an odd number")
i = i + 1
Then if you use this code:
if a%2==0:
print(a, " is an even number")
What happens here is that the variable "a" is a list and to loop through it you need to break up the list into single components as you did "a[i]". What you are doing here is taking the list as a single component and not breaking up the list to get each value of the list.
Hope you get it.

Related

How to check all the numbers in a range against a calculation?

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]

Iterate through list and find prime numbers and add to another list

I want to iterate through a list in python, detect prime numbers and then add them to another list.
primes = []
nprimes = []
for j in range(0, len(arr)):
num = arr[j] #my list with numbers to check
if num > 1:
for k in range(2, num):
if (num % k) == 0:
nprimes.append(num)
break
else:
primes.append(num)
else:
print(num, " can't be checked, because its smaller than 1")
I have the problem that numbers are always added which are not prime numbers. Also in general the code does not seem to work properly.
If num % k == 0 is false you can't say it's prime directly you have to wait the whole loop, so move the else with the for loop, it'll be executed of no break has been encountered which means it's prime
you may iterate directly on the values for num in arr
you can stop your loop at sqrt(num) you won't find a new divisor after that
for num in arr:
if num > 1:
for k in range(2, int(num ** 0.5) + 1):
if num % k == 0:
nprimes.append(num)
break
else:
primes.append(num)
else:
print(num, " can't be checked, because its smaller than 1")
For learning purposes, let's play with a different approach. First, I recommend you move your trial division code into its own predicate function is_prime(), that returns True or False, so it can be optimized independently of the rest of your code.
Then, I'm going to have itertools.groupby divide the list into prime and non-prime sequences that we splice onto the appropriate lists:
def is_prime(number):
if number < 2:
return False
if number % 2 == 0:
return number == 2
for divisor in range(3, int(number ** 0.5) + 1, 2):
if number % divisor == 0:
return False
return True
if __name__ == "__main__":
from random import sample
from itertools import groupby
array = sample(range(1, 100), 15)
primes = []
composites = []
for are_prime, numbers in groupby(array, is_prime):
if are_prime:
primes.extend(numbers)
else:
composites.extend(numbers)
print("Numbers:", array)
print("Primes:", primes)
print("Composites:", composites)
OUTPUT
% python3 test.py
Numbers: [91, 87, 10, 2, 11, 24, 21, 12, 46, 61, 15, 32, 57, 22, 5]
Primes: [2, 11, 61, 5]
Composites: [91, 87, 10, 24, 21, 12, 46, 15, 32, 57, 22]
%
There are lots of ways to go about this problem, many of them educational!

List with odd_even function

When my program is done printing 10 random numbers, it should print something like this. (These numbers 3, 7, and 10 are just used as example.)
List had 3 evens and 7 odds
The 3rd element in sorted nums is 10
For some reason this isn't happening for me.
This is the code I have so far:
import random
nums =[]
for i in range (1,11):
x = random.randint(1,50)
nums.append(x)
print(nums)
nums.sort()
print(nums)
start = nums[0:5]
print(start)
finish = nums[7:10]
print(finish)
def evenOdd(num):
odd = 0
even = 0
for x in num:
if (x % 2 == 0):
even += 1
else:
odd += 1
print('List had', even, 'evens and', odd, 'odds')
print('The 3rd element in sorted nums is', num[2])
When I run it, this is what the program displays:
Traceback (most recent call last):
[7, 21, 6, 14, 22, 8, 24, 20, 26, 27]
line 35, in <module>
[6, 7, 8, 14, 20, 21, 22, 24, 26, 27]
print('List had', even, 'evens and', odd, 'odds')
[6, 7, 8, 14, 20]
NameError: name 'even' is not defined
[24, 26, 27]
Process finished with exit code 1
You have a number of problems in your code. You aren't actually calling your evenOdd function, if you did call it, you have provided no way to get its results, and you have some variable name mismatches. Also, your evenOdd() function wasn't doing the right thing because the else clause needed to be indented to be within the for loop. The way it is in your version, odd will always be 1:
Here's code that fixes all of these issues:
import random
nums =[]
for i in range (1,11):
x = random.randint(1,50)
nums.append(x)
print(nums)
nums.sort()
print(nums)
start = nums[0:5]
print(start)
finish = nums[7:10]
print(finish)
def evenOdd(num):
odd = 0
even = 0
for x in num:
if (x % 2 == 0):
even += 1
else:
odd += 1
return even, odd
even, odd = evenOdd(nums)
print('List had', even, 'evens and', odd, 'odds')
print('The 3rd element in sorted nums is', nums[2])
The main thing here is that the evenOdd function returns a "tuple" that contains the resulting counts of odd and even numbers so that you can use them outside the function.
Sample result:
[2, 36, 20, 32, 6, 40, 39, 27, 24, 47]
[2, 6, 20, 24, 27, 32, 36, 39, 40, 47]
[2, 6, 20, 24, 27]
[39, 40, 47]
('List had', 7, 'evens and', 3, 'odds')
('The 3rd element in sorted nums is', 20)
I am assuming the last print statements ought to be in your evenOdd function, in which case your code isn't properly indented. It should be like this:
def evenOdd(num):
odd = 0
even = 0
for x in num:
if (x % 2 == 0):
even += 1
else:
odd += 1
print('List had', even, 'evens and', odd, 'odds')
print('The 3rd element in sorted nums is', num[2])
After that, you can call the function thus:
evenOdd(nums)
Define the variables even and odd globally - they're only available inside the function.
even = 0
odd = 0
# ...
def evenOdd(num):
global even
global odd
even = 0
odd = 0
# ...
you can use this also, :-
import random
nums =[random.randint(1,51,) for var in range(1,11)] # creating nums list by short method
nums.sort()
print(nums)
def evenOdd(num):
odd = 0
even = 0
for x in num:
if (x % 2 == 0):
even += 1
else:
odd += 1
return even,odd
even,odd = evenOdd(nums)
print('List had', even, 'evens and', odd, 'odds')
print('The 3rd element in sorted nums is', nums[2])
I hope you learn something new.

python solution in codewars could not pass time limit, needs optimization

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]])

For-Else Statement with Multiple If-Break Conditions

I wrote a simple python module that returns the prime numbers up to a given N, using a bool flag is_prime as follows:
def generate_primes_up_to(M):
n = 2
primes = []
while n <= M:
is_prime = True
for p in primes:
if p**2 > n: break
if n % p == 0:
is_prime = False
break
if is_prime: primes.append(n)
n += 1
return primes
if __name__ == '__main__':
generate_primes_up_to(100)
which outputs:
[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]
Now, this is actually an ideal case for using the for-else construct, since the number n is prime only if no breaks occurred in the for loop. Thus, I changed the function into:
def generate_primes_up_to(M, flag='nonumpy'):
n = 2
primes = []
while n <= M:
for p in primes:
if p**2 > n: break
if n % p == 0: break
else: primes.append(n)
n += 1
return primes
but now the code outputs:
[2, 5, 27]
I don't understand why the if p**2 > n: break expression is interfering with the flow of the for-else clause. If I remove that line the code yields the right output again.
The condition causing the issue is -
if p**2 > n: break
Lets take an example - 7 , when we are checking if 7 is prime or not , we have already found out that - [2,3,5] are primes, the above condition breaks the for loop, when we check 3 as 3**2 = 9 which is greater than 7 .
Remove that condition and it works fine (Though its very slow).
In the original loop (without the for-else construct) , it worked because in that condition you just broke out of the loop, you did not change the flag is_prime .
With the for..else construct, what happens is that, the else part is only executed when we exit the loop without using break statement.
But in the case of the above condition , we use break statement and hence else part is not executed.
You can also use next:
def generate_primes_up_to(M):
n = 2
primes = []
while n <= M:
if next((False for p in primes if not n % p), True):
primes.append(n)
n += 1
return primes

Categories

Resources