Cant figure out conditionals - python-3.x

I'm working on a 30 day of code challenge and passed 5/8 tests on my code and can't figure out the reason it keeps failing
The parameters are that
if N is odd print weird,
if N is even and in the range of 2-5 print not weird
if N is even and in the range of 6-20 print weird
if N is even and greater than 20 print not weird
N = int(input())
if N % 2 == 0 and range(2-5):
print("Not Weird")
elif N % 2 == 0 and range(6-20):
print("Weird")
elif N % 2 == 0 and N > 20:
print("Not Weird")
elif N % 2 == 1 :
print("Weird")

if N % 2 == 0 and range(2-5):
does not do what you think, it should instead be something like:
if N % 2 == 0 and N in range(2, 6):
Specifically:
each sub-condition (on either side of your 'and') should be complete.
range, in your example, was range(-3) since that's what 2-5 gives.
the range is half open, meaning it includes the start but excludes the end.

1) The function range with defined begging and end is a function that takes 2 parameters as argument. Therefore I'd recommend you to use it as range(x,y) instead of range(x-y).
If you use it like range(2-5), you're actually asking for range(-3). When used with only 1 arg, the function range will give you a list of int from 0 up to the input arg.
Regarded that there is no integer greater than 0 and less than -3, then you're getting an empty list.
2) Also, notice that the upper limit is not inclusive:
>>> for i in range(2,5):
... print(i)
...
2
3
4
so you might consider to use range(2,6) for the first case, range(6,21) for the second case and so on and so forth..

To expand on #paxdiablo's answer, you can also use the step argument of range to test for even numbers:
if N in range(2, 6, 2):

Related

How do I write a python function to count consecutive zeros in a binary representation of a number?

Given a number N, the function should convert the number to binary form, count the number of consecutive zero (the binary gap), and return the maximum binary gap. For example, 9 = 1001, the binary gap of length 2. The number 529 = 1000010001, has 2 binary gaps with length 4 and 3. If the number has 2 or more binary gaps, the function should return the maximum binary gap i.e. 4 in the case of N = 529.
I tried this function:
def solution(N):
binaryN = bin(N)[2:]
n = len(binaryN)
binaryGap = []
for i in range(n):
if binaryN[i] == 0 and binaryN[i + 1] == 0:
m = len(binaryN)
else:
return 0
binaryGap = binaryGap.append(m)
return max(binaryGap)
The function returns 0 for all values of N which is incorrect. How do I debug/improve the code to produce the accurate result?
Check out the below code. It would solve your problem.
The code is self-explanatory, yet let me know in-case of any doubts.
The Code:
import sys
num = int(sys.argv[1])
# Function to get the binary gap.
def binaryGapFinder(num):
binnum = bin(num).replace("0b", "") # binnum is binary form of the given number.
i = 0
x = 0
x_list = []
while i <= len(binnum)-1:
if binnum[i] == "0":
x += 1
if i == len(binnum)-1: # This loop will also consider if binary form is ending with 0. for example: 12 -> 1100
x_list.append(x)
else:
x_list.append(x)
x = 0
i += 1
return f"The Number: {num}\nIt's Binary Form: {binnum}\nMaximum Consecutive 0's: {max(x_list)}"
print(binaryGapFinder(num))
The Output:
python3 /the/path/to/your/script/binarygap.py 529
The Number: 529
It's Binary Form: 1000010001
Maximum Consecutive 0's: 4
python3 /the/path/to/your/script/binarygap.py 12
The Number: 12
It's Binary Form: 1100
Maximum Consecutive 0's: 2
python3 /the/path/to/your/script/binarygap.py 512
The Number: 512
It's Binary Form: 1000000000
Maximum Consecutive 0's: 9
There's a few issues here worth mentioning to aid you. (Just a side note to start with is that, in Python, it's recommended/best practice to use all lower case for variable names, so I'll replace them in my examples below.)
The bin() built in function returns a string. So you should be checking for equality with "0" (or '0') instead of an integer. e.g.
if binaryN[i] == "0" and binaryN[i + 1] == "0":
With Python you don't need to bother with checking for lengths of strings (or any other iterables) to use in a for loop in scenarios like this. e.g. You can replace:
n = len(binaryN)
for i in range(n):
with the more "Pythonic" way:
for bit in binary_number:
You can then use the variable bit (call it whatever you want of course, bearing in mind that good variable names make code more readable) instead of binary_number[index]. In this case, with each iteration of the for loop, bit will be replaced with the next character in the binary_number string.
From there on in your code:
m = len(binaryN)
will always be the same value, which is the total length of the string binaryN. e.g. 4 for '1001'.) This is not what you intended.
The first statement in your else block of code return 0 will terminate your function immediately and return 0 and thus your binaryGap = binaryGap.append(m) code will never, ever execute as it's unreachable due to that preceding return stopping any further execution of code in that suite.
You've got the right idea(s) and heading towards the right track for a solution but I don't think your code, even when the issues above are corrected, will match all possible binary numbers you may encounter. So, another possible alternative (and yet roughly sticking with the solution I think that you had in mind yourself) would be something like this which I hope will help you:
def solution(n):
binary_no = bin(n)[2:]
binary_gaps = []
gap_counter = 0
for bit in binary_no:
if bit == "0":
gap_counter += 1
else:
# Encountered a 1 so add current count of 0's -- if any -- to list and reset gap_counter
if gap_counter > 0:
binary_gaps.append(gap_counter)
gap_counter = 0
else:
# A for else suite (block of code) is run when all iterables have been exhausted.
if gap_counter > 0:
binary_gaps.append(gap_counter)
if binary_gaps: # If there is at least one element in the list
if len(binary_gaps) > 1:
return max(binary_gaps)
else:
return binary_gaps[0]
else:
# The list is empty, so no gaps were found at all. i.e. Binary number was all 1's.
return 0
print(solution(529))

Automate the Boring Stuff With Python Practice Project: collatz sequence Unknown loop?

The outline:
Write a function named collatz() that has one parameter named number. If the number is even, then collatz() should print number // 2 and return this value. If the number is odd, then collatz() should print and return 3 * number + 1. Then write a program that lets the user type in an integer and that keeps calling collatz() on that number until the function returns the value 1.
my code:
def collatz(number):
if number % 2 == 0:
print(number // 2)
return number // 2
elif number % 2 == 1:
result = 3 * number + 1
print(result)
return result
n = input("Give me a number")
while n != 1:
collatz(int(n))
the output keeps infinitely printing the n value, and I can't figure out why. Please enlighten me
Your loop should update the value of n:
while n != 1:
n = collatz(int(n))
Otherwise, your loop has no progression, hence the infinite loop.
Edit: Here's an explanation as to why this is necessary.
Think about it logically. If you enter the body of the loop, then n must not be equal to 1. The loop continues to execute until n becomes 1. The only way for this to happen is for you to change (i.e. update) n so that it eventually reaches 1 and the loop can terminate.

Polydivisible Calculator Fails, Despite Previous Implementation Working

To begin, a definition:
A polydivisible number is an integer number where the first n digits of the number (from left to right) is perfectly divisible by n. For example, the integer 141 is polydivisible since:
1 % 1 == 0
14 % 2 == 0
141 % 3 == 0
I'm working on a recursive polydivisible checker, which, given a number, will check to see if that number is polydivisible, and if not, recursively check every other number after until it reaches a number that is polydivisible.
Unfortunately, my code doesn't work the way I want it to. Interestingly, when I input a number that is already polydivisible, it does its job and outputs that polydivisible number. The problem occurs when I input a non-polydivisible number, such as 13. The next polydivisible number should be 14, yet the program fails to output it. Instead, it gets stuck in an infinite loop until the memory runs out.
Here's the code I have:
def next_polydiv(num):
number = str(num)
if num >= 0:
i = 1
print(i)
while i <= len(number):
if int(number[:i]) % i == 0:
i += 1
print(i)
else:
i = 1
print(i)
num += 1
print(num)
else:
return num
else:
print("Number must be non-negative")
return None
I'm assuming the problem occurs in the else statement inside the while loop, where, if the number fails to be polydivisible, the program resets i to 0, and adds 1 to the original number so it can start checking the new number. However, like I explained, it doesn't work the way I want it to.
Any idea what might be wrong with the code, and how to make sure it stops and outputs the correct polydivisible number when it reaches one (like 14)?
(Also note that this checker is only supposed to accept non-negative numbers, hence the initial if conditional)
The mistake is that you are no updating number after incrementing num.
Here is working code:
def next_polydiv(num):
number = str(num)
if num >= 0:
i = 1
print(i)
while i <= len(number):
if int(number[:i]) % i == 0:
i += 1
print(i)
else:
i = 1
print(i)
num += 1
print(num)
number = str(num) # added line
else:
return num
else:
print("Number must be non-negative")
return None
I have a similar answer to #PranavaGande, the reason is I did not find any way to iterate an Int. Probably because there isn't one...Duh !!!
def is_polydivisible(n):
str_n = str(n)
list_2 = []
for i in range(len(str_n)):
list_2.append(len(str_n[:i+1]))
print(list_2)
list_1 = []
new_n = 0
for i in range(len(str_n)):
new_n = int(str_n[:i+1])
list_1.append(new_n)
print(list_1)
products_of_lists = []
for n1, n2 in zip(list_1, list_2):
products_of_lists.append(n1 % n2)
print(products_of_lists)
for val in products_of_lists:
if val != 0:
return False
return True
Now, I apologise for this many lines of code as it has to be smaller. However every integer has to be split individually and then divided by its index [Starting from 1 not 0]. Therefore I found it easier to list both of them and divide them index wise.
There is much shorter code than mine, however I hope this serves the purpose to find if the number is Polydivisible or Not. Of-Course you can tweak the code to find the values, where the quotient goes into decimals, returning a remainder which is Non-zero.

Find the sum of the digits using a loop and a function

I am using a function to get the number from user, and I am trying to use a while loop to separate the digits of a number. And I am trying to add the digits of the number. But my code runs infinitely.
Example : 2345 -> 15
def sumDigits(n):
sum=0
while len(str(n))>0:
a = n%10
n = n//10
sum += a
return sum
print(sumDigits(2345))
Expected: 15
Actual: I had to shut down the jupyter kernel to stop the while loop.
Edit 2: Removed the updated code as it was answered by the community.
This condition len(str(n))>0 can never be false as long as n is an integer, because str(0) is '0', which has a length of 1.
You need to change the looping condition to exit where there is no more digit to sum, which happens when n reaches 0:
def sum_digits(n):
total = 0
while n > 0:
a = n % 10
n = n // 10
total += a
return total
print(sum_digits(2345))
Note: sum is a built-in in python, so naming a variable sum is not advised. Also, method names usually are written in snake_case, so sum_digits is recommended.
def all_sum(number):
total = 0
if number > 0:
for e in str(number):
if e.isdigit():
total += int(e)
else:
pass
return total
a = all_sum(567897)
This should do your work. Instead of doing two arithmetic operations to 'fetch' the digits, better to change the argument to string and just use each digit. Its faster and saves memory (though it's not too memory consuming).

Prime number python nested loops

I am new to python and I am having some problems with this code that should print all the prime numbers that are smaller than 50 using nested loops.
Here is the code:
i = 2
while(i < 50):
j = 2
while(j <= (i/j)):
if not(i%j):
break
j = j + 1
if (j > i/j):
print(i, " is prime")
i = i + 1
Its output is:
2 is prime
3 is prime
5 is prime
7 is prime
11 is prime
13 is prime
17 is prime
19 is prime
23 is prime
29 is prime
31 is prime
37 is prime
41 is prime
43 is prime
47 is prime
So after 3, j should be 2 and i should be 4. Then it's not a prime number, so it goes back to the while loop.
And the process starts over. j and i should be incremented by one. So j should be 3 and i should be 5, 5 is prime, then it increments again to 6.
So j should still be 3 and i should be 6. But (3 <= (6/3)) <-- this is not true, so it goes to if statement and 3 which is j is bigger than 2 which is i/j, which means 6 should be prime.
But it's not. You can tell that by common sense. And I want to know what part I did wrong here. Did I miss any increments here? Thank you.
First of all, I would like to post the correct syntax for the code.
i = 2
while(i < 50):
j = 2
while(j <= (i/j)):
if not(i%j):
break
j = j + 1
if (j > i/j):
print(i, " is prime")
i = i + 1
By writing the code like this, we are able to do several things. The first thing we are able to do is get a nice visual of what is inside of what, instead of assuming anything. The second thing that we are able to do is see what is being incremented where.
Now, let us approach what is going on inside of this code. The first to realize is that we are starting off with i=2. We are then initializing a while loop that is going to stop when i is greater than 50.
So, now we are inside of the first while loop, and the next thing we are doing is calling j. This variable is equal to 2, as we can see. Not only is it equal to 2, but every time we go down to the bottom of this FIRST WHILE LOOP THAT ENDS WHEN i >=50, we go back to the start and reinitialize j to be 2 again.
This means that j is never going to start out to be two, even though we are adding to j in the SECOND (NESTED) while loop.
Everything from here should make sense, if I understood your question right. The only thing that is weird about this code, in my opinion is the:
if not (i%j)
This seems a little odd, for it would be more clerical if it said:
if (i%j == 0):
break
If you have any other questions, please feel free to ask. And if you find this helpful, feel free to accept it as your answer :)
The indented code is as follows.
i = 2
while(i < 50):
j = 2
while(j <= (i/j)):
if not(i%j):
break
j = j + 1
if (j > i/j) :
print(i, " is prime")
i = i + 1
In your code, j is getting initialized to 2 with every increment of i.
See this snippet if not(i%j): break
If any j divides i, the if not(i%j) becomes true and the loop breaks but j <= (i/j) still holds else control wouldn't have entered this loop. So control skips print(i, " is prime")
So only way if(j > i/j) becomes true is when above loop never breaks. That would mean i didn't get any divisor, hence i is a prime.
I made this infinite prime number generator:
def primes_generator():
n = 1
while True:
for x in range(2, n):
if n % x == 0:
#not prime
break
else:
#prime
yield n
n+=1
you can use it like:
primes = primes_iterator()
for prime in primes:
print(i)

Resources