using while loop based on argument - python-3.x

Define a function positive that takes an argument (either integer or float with or without a sign) and writes all the positive powers of 2 less than or equal to a valid argument. You must begin writing the function with the following segment of code below and must include a while loop. Hints: consider isdigit() function and continue and break statements.
def positive(n):
i = 0
poweroftwo = 0
Your program should write a message (e.g., Pass a valid argument) if an argument is invalid). Do not use the input function to make this program interactive. Test the function by calling it as follows:
positive(10)
positive(+10)
positive(-10)
positive(10.4)
positive(+10.4)
positive(-10.4)
The output form the 6 calls to the function must be:
1
4
9
1
4
9
Pass a valid arg
Pass a valid arg
Pass a valid arg
Pass a valid arg
The output implies that arguments other than 10 and +10 are all invalid
My code is below this, I don't know if I am doing it right
def isdigit(n):
if n < 1:
print("Pass a valid argument")
return False
elif n != int(n):
print("Pass a valid argument")
return False
else:
return True
def positive(n):
i = 1
poweroftwo = 2
value = isdigit(n)
if value:
while (i ** poweroftwo) < n:
print(i **poweroftwo)
i += 1
positive(10)
positive(+10)
positive(-10)
positive(10.4)
positive(+10.4)
positive(-10.4)

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.

Complete eval_strfrac(s, base), so that it returns its floating-point value

something is wrong with my while loop inside my eval_strfrac(s, base=2) function. for 3.14 base 10 it is very close,for 100.101 base 2 it is way off.Thanks!
#TEST to validate
def is_valid_strfrac(s, base=2):
return all([is_valid_strdigit(c, base) for c in s if c != '.']) \
and (len([c for c in s if c == '.']) <= 1)
def eval_strfrac(s, base=2):
assert is_valid_strfrac(s, base), "'{}' contains invalid digits for a base-{} number.".format(s, base)
#
predot,postdot = s.split('.')
whole = eval_strint(predot,bse)
whole = int(predot,base)
postlist = [int(p) for p in postdot]
print(postlist)
i = 0
while i <= len(postlist):
yo = (postlist[i])*((float(base))**-(float(i + 1)))
yo += yo
i +=1
return float(whole) + float(yo)
#### Test 0: `eval_strfrac_test0`#####
def check_eval_strfrac(s, v_true, base=2, tol=1e-7):
v_you = eval_strfrac(s, base)
assert type(v_you) is float, "Your function did not return a `float` as instructed."
delta_v = v_you - v_true
msg = "[{}]_{{{}}} ~= {}: You computed {}, which differs by {}.".format(s, base, v_true,
v_you, delta_v)
print(msg)
assert abs(delta_v) <= tol, "Difference exceeds expected tolerance."
# Test cases from the video
check_eval_strfrac('3.14', 3.14, base=10)
check_eval_strfrac('100.101', 4.625, base=2)
check_eval_strfrac('11.0010001111', 3.1396484375, base=2)
# A hex test case
check_eval_strfrac('f.a', 15.625, base=16)
print("\n(Passed!)")
[3.14]_{10} ~= 3.14: You computed 3.2, which differs by 0.06000000000000005.
[100.101]_{2} ~= 4.625: You computed 5.0, which differs by 0.375.
In the while loop, yo = (postlist[i])*((float(base))**-(float(i + 1))) calculates the value of one digit. Then yo += yo doubles it. Instead, you should be adding the values of digits to an accumulating sum.
Two lines later, return float(whole) + float(yo) returns from the function from inside the loop, so only one iteration of the loop is performed. The return should be after and outside the loop (not indented with the code inside the loop).

about nested function unboundlocalerror in python3

here is my function with 3 arguments of which two are with default values, and there is a nested function within this function.
def announce_highest(who=1, previous_high=0, previous_score=0):
assert who == 0 or who == 1, 'The who argument should indicate a player.'
# BEGIN PROBLEM 7
"*** YOUR CODE HERE ***"
sentence = "That's the biggest gain yet for Player"
def say_highest(score0, score1):
#nonlocal previous_score, previous_high
print(who, previous_score)
if who == 0:
target = score0
else:
target = score1
score_gap = target - previous_score
if score_gap > previous_high:
print(score_gap, "point" + 's' *(1 - (1 // score_gap)) + '!', sentence, who)
previous_high = score_gap
previous_score = target
return announce_highest(who)
return say_highest
f0 = announce_highest() # Only announce Player 1 score gains
f1 = f0(11, 0)
When i do the assignment to f0, it runs ok. But when doing the assignment to f1, it raised a unboundlocal error:local variable 'previous_score' referenced before assignment.
Why I do something to the argument 'who'(such as print it), it runs normally, but to the argument 'previous_high' and 'previous_score' with same operation, unboundlocal error……
why does this happen? Did not 'who' and 'previous_score' have the same scope?
I got the answer from the professor John. This error is caused by the following assignment statement 'previous_score = target'. Once an assignment of "previous_score" exsits somewhere within the function defined in another function, the previous "previous_score" in the parent frame is no longer accessible.
That's why it raised an error.

I am trying to pass the arguments a and b to the local function "isPrimes" to be used as a range

If I try to run the isPrime function on it's own -- replacing n with any integer, it will find if it is a prime number or not; but getting a and b from primes to be used as the range of numbers to check if they are prime is where the issue lies .
def primes(a,b):
pass
def isPrime(n):
# I want to make n take the values of a and b so that the is Prime
# function executes all the prime numbers within the range a to b
if n == 1:
return False
# here I've tried referencing n and (a,b) as the range but neither
# option does anything
for z in range(a, b):
if n % z == 0:
return False
else:
# this is supposed to print the n each time it comes up as a prime
# number but when I run this nothing happens and I'm not sure where
# I'm going wrong
print(n)
return True
Switch the order of your return and print statement. Your program is
ending before your print statement executes
If you want to specify a range for which you are going to test if a
number is prime, you will either have to declare a and b in your
function, or pass it in as a parameter.
In your range statement, for each integer from a to b, but you are returning false whenever n%z = 0. This will occur for when you attempt to use the % operator on a prime with a prime (ex. 17 % 17 would return false). add a statement to compare if n != z.
You return false in your if statement, and true in your else statement. This means your code will only make one comparison before your function will exit. Add your return true statement at the end of your program.
see below:
def isPrime(n):
a = 2
b = 100000
if n == 1:
print("1 is not a prime number.")
return False
for z in range(a,b):
if n%z==0 and n != z:
print(str(n) + " is not a prime number.")
return False
print(str(n) + " is a prime number.")
return True

Resources