Exhaustive Enumeration python - python

I need to create a program that finds the base and exponent of a single number given that the exponent is less than 7 and greater than 1. I am using python 2.7.
My code is as follows:
def determineRootAndPower(inputInteger):
pwr = 1
num = inputInteger
while (num) > 0 and (0 < pwr < 7):
inputInteger = inputInteger - 1
pwr = pwr + 1
num = num - 1
if int(num)**int(pwr) == inputInteger:
print(str(num) + (" to the power of ") + str(pwr) + (" equals ") + str(inputInteger) + ("!"))
else:
print("No base and root combination fit the parameters of this test")
Can anyone give me any general advice on this issue? Right now I am always receiving the 'else' statement which is not correct.

First, the reason you're always hitting the else is that you're doing the if check after the loop is over. So, instead of checking each value, you're just checking the very last values.
You want to print the "Yes" answer if any value matches, and the "No" only if all values fail. For that, you need to put the if inside the loop, and break as soon as you find the first success (unless you want to print all matches, instead of just the first one), and then the else becomes something you do only if you didn't find any of them.
You can use an else: with a while:, which gets run only if you didn't break anywhere. But many people find that confusing, so it might be simpler to just return instead of break on success, and just always print the failure message if you finish the loop.
Meanwhile, I think what you're hoping to do is handle all num values from inputNumber to 0, and, for each one, all pwr values from 1 to 7. To do that, you need a nested loop.
While we're at it, using a for loop is a whole lot easier than using a while loop around a variable that you initialize and +1 or -1 each time through.
Putting all of that together:
def determineRootAndPower(inputInteger):
for num in range(inputInteger, 0, -1):
for pwr in range(1, 7):
if int(num)**int(pwr) == inputInteger:
print(str(num) + (" to the power of ") + str(pwr) + (" equals ") + str(inputInteger) + ("!"))
return
print("No base and root combination fit the parameters of this test")
You can simplify this further.
What you really want is all combinations of any num in range, and any pwr in range. You don't care about how the nesting works, you just want all the combinations. In mathematical terms, you want to loop over the cartesian product of the two ranges. The function itertools.product does exactly that. So:
def determineRootAndPower(inputInteger):
for num, pwr in itertools.product(range(inputInteger, 0, -1), range(1, 7)):
if int(num)**int(pwr) == inputInteger:
print(str(num) + (" to the power of ") + str(pwr) + (" equals ") + str(inputInteger) + ("!"))
return
print("No base and root combination fit the parameters of this test")
As a side note, there are two things that make this code harder to read for no good reason.
First, if you want to print out an expression, it's a lot easier to use format (or %) than to manually convert things to strings and concatenate them together. Formatting lets you see what the output will look like, instead of having to figure it out, and it takes care of the stringifying and related stuff automatically.
Second, adding parentheses where they're not needed makes the code harder to read. The parentheses around your print expression makes your code look like Python 3, but it's actually Python 2. And the parentheses around each string inside the expression are even worse—at first glance, it looks like those are supposed to be inside the quotes. Even the parentheses in your test expression, (num) > 0 and (0 < pwr < 7), force the reader to pause—normally, parentheses like that are used to override the normal way operators combine together, so you have to think through what would be wrong with the normal num > 0 and 0 < pwr < 7 and how the parentheses make it different, only to eventually figure out that it's actually exactly the same.
Anyway, compare these two and see which one is easier to follow:
print "{} to the power of {} equals {}!".format(num, pwr, inputInteger)
print(str(num) + (" to the power of ") + str(pwr) + (" equals ") + str(inputInteger) + ("!"))

Related

Why is a string printed although print isn't used?

This is an example program from the Python book that I am using to learn. What does the message += line signify? And how does it print that statement even though we've never used a print there?
This works as expected and returns $number is too high or $number is too low. But how does it do so even without print statement?
And what does message += str(guess) + .... do here, given that we've declared message as an empty string in the beginning (message = "")?
import random # We cover random numbers in the
rng = random.Random()
number = rng.randrange(1, 1000)
guesses = 0
message = ""
while True:
guess = int(input(message + "\nGuess my number between 1 and 1000:"))
guesses += 1
if guess > number:
message += str(guess) + " is too high.\n"
elif guess < number:
message += str(guess) + " is too low.\n"
else:
break
input("\n\nGreat, you got it in "+str(guesses)+" guesses!\n\n")
I tried using message like in the above program in one of my other scripts and it doesn't print statement like it does in the above program.
The call to input() includes message in its prompt.
Addition of strings concatenates them in Python. "ab" + "cd" produces "abcd". Similarly, message += "stuff" adds "stuff" to the end of the variable's earlier value. If it was the empty string before, "" + "stuff" produces simply "stuff".
The operator += is an increment assignment; a += b is short for a = a + b. (Some people also dislike the longer expression because it is mathematically implausible unless at least one of the values is zero; but = does not have its mathematical semantics anywhere else in Python, either.)

Converting binary to decimal only using basic functions len(), ord(), print(), etc

I'm trying to create a scientific calculator for an assignment. I'm looking for a bit of help with python syntax, and I think my design and pseudo code are doing well, but for whatever reason python isn't having any of my syntactical issues. Here is the code I have for converting binary to decimal.
I need the code to reprompt when the input is invalid, but when it does reprompt, it gets stuck in a loop of reprompting and won't give me any way out.
def bintodec(var):
power = (len(var) + 1)
value = ' '
while True:
var = input('Give a number to convert from binary to decimal: ')
for x in range(len(var)):
if (ord(var[x]) == 49):
power -= 1
value += x * (2 ** power)
if (ord(var[x]) == 48):
power -= 1
value += x * (2 ** power)
if power == -1:
break
else:
boo = True
return value
Any help is greatly appreciated!
This is pretty classic. Reading in a base is easier than writing in one.
def bintodec(var):
assert set(var) <= set("01") # Just check that we only have 0s and 1s
assert isinstance(var, str) # Checks that var is a string
result = 0
for character in var: # character will be each character of var, from left to rigth
digitvalue = ord(character) - ord("0")
result *= 2
result += digitvalue
return result
Ok, how does it work ?
Well, it reads the value from left to right. digitvalue will contain 1 or 0. For each digit we read, if it is 0, there is nothing to add the result (so result += digitvalue adds indeed 0), but we still need take into account that there is one more 0 at the end of the number.
Now, in base 10, adding a zero to the end makes a number 10 times as big. This is the same in base 2. Adding a zero at the end makes a number twice as big. This is why we multiply it by 2.
Finally, if digitvalue is 1 instead of 0, we need to add 1 to the number and result += digitvalue does it.
Note: Just for things to be clear, the two for loops below are equivalent.
for character in var:
pass # pass does nothing
for i in range(len(var)):
character = var[i]
pass
#JayF.:
Is there any way to reprompt without using assert?
I suppose you want to reprompt if the input is incorrect. You need to use a loop for that:
while True:
var = input()
if set(var) <= set("01"):
print(bintodec(var))
break # Remove this `break` statement if you want to reprompt forever
else:
# print("The input must consist of only 0s and 1s.")
pass # `pass` does nothing.
If you leave the asserts in the bintodec function, it can be done in a more pythonic way, using exception handling:
while True:
var = input()
try:
print(bintodec(var))
break
except AssertionError:
print("The input must consist of only 0s and 1s.")

Python: Adding odd numbers together from an input

Have a little problem. I'm writing a simple program that takes an input of numbers (for example, 1567) and it adds the odd numbers together as well as lists them in the output. Here is my code:
import math
def oddsum(n):
y=n%10
if(y==0):
return
if(y%2!=0):
oddsum(int(n/10))
print (str(y),end="")
print (" ",end="")
else:
oddsum(int(n/10))
def main():
n=int(input("Enter a value : "))
print("The odd numbers are ",end="")
oddsum(n)
s = 0
while n!=0:
y=n%10
if(y%2!=0):
s += y
n //= 10
print("The sum would be ",end=' ')
print("=",s)
return
main()
It outputs just fine, in the example it will print 1 5 and 7 as the odd numbers. However, when it calculates the sum, it just says "7" instead of 13 like it should be. I can't really understand the logic behind what I'm doing wrong. If anyone could help me out a bit I'd appreciate it :)
I understand it's an issue with the "s += y" as it's just adding the 7 basically, but I'm not sure how to grab the 3 numbers of the output and add them together.
As #Anthony mentions, your code forever stays at 156 since it is an even num.
I would suggest you directly use the string input and loop through each element.
n = input("Enter a value : ") #'1567'
sum_of_input = sum(int(i) for i in n if int(i)%2) #1+5+7=13
[print(i, end="") for i in n if int(i)%2] #prints '157'
Note that int(i)%2 will return 1 if it is odd.
1567 % 10 will return 7. You might want to add the numbers you printed in oddsum to a list, and use the sum function on that list to return the right answer.
The immediate issue is that n only changes if the remainder is odd. eg 1,567 will correctly grab 7 and then n=156. 156 is even, so s fails to increment and n fails to divide by 10, instead sitting forever at 156.
More broadly, why aren't you taking advantage of your function? You're already looping through to figure out if a number is odd. You could add a global parameter (or just keep passing it down) to increment it.
And on a even more efficient scale, you don't need recursion to do this. You could take advantage of python's abilities to do lists. Convert your number (1567) into a string ('1567') and then loop through the string characters:
total = 0
for c in '1567':
c_int = int(c)
if c_int%2!= 0:
total += c_int
print(c)
print(total)

how to use for loop to create right angled triangle?

I want to print :
1
12
123
1234
and i have tried:
num=int(input("number"))
space=int(num)
count=1
while count<num:
if count==1:
print(" "*space,count)
count=count+1
space=space-1
while count>=2:
for n in range(2,num):
print(" "*space,list(range(1,n))
space=space-1
But it doesn't work.
How can i print the designated result ?
Thanks
print(" "*space,list(range(1,n))
Count the parentheses on this line. One of them isn't closed, which it has to be to work as you intend.
Also note that your while loop will never stop running.
As a general rule of thumb, whenever you know exactly how many times you should do something, you should use a for loop instead of a while loop
Let's try to rewrite you code using a for loop:
num=int(input("number"))
output = ""
for n in range(1,num+1):
output = ''.join([output, str(n)])
space = ' ' * (num - len(output))
print(space, output, sep='')
The only real substantive change I made other than a for loop is treating the output as a string rather than a list of numbers.

Beginning Python: For Loop- what do to afterwards

Found this exercise in a textbook online and am attempting to battle my way through it. I believe they intended it to be answered with a while loop, but I'm using a for loop instead which could be my problem.
"Write a program that prompts the user to enter an integer and returns two integers pwr and root such that 0 < pwr < 6 and root**pwr is equal to the integer entered by the user. If no such pair of integers exists, it should print "No such integers exist."
How can I test to see if any #s meet the criteria and if none do, say that?
u_i = int(input("input a #:"))
root = u_i**.5
for pwr in range(1,6):
ans = root**pwr
if ans == u_i:
print(pwr)
print(int(root))
#here is where the problem comes in as it will do this every time and I'm\ failing to discover what I should do instead.
if ans!= u_i:
print("No such integer exists")
Full disclosure: Its been a long time since my last math class so I'm not convinced my "solution" is even correct for what the question is asking. I'm more interested in solving the dilemma I'm facing however as I'm trying to wrap my head around using loops properly.
You want to check if there is an integer root such that root ** pwr == user_input. With a little math we can re-write the above statement as root = user_input ** (1. / pwr). You've got a pretty small number of pwr values to choose from, so you can simply loop over those values (it looks like you've already got that part figured out). The last thing you need to do is (for each pwr) check to see if root is an integer, you could use root % 1 == 0 or int(root) == root.
If you want to look "fancy" you could use python's for ... else syntax. The else block in a for loop only gets executed if the loop finishes without a break. For example:
def has_dogs(pets):
# This functions check to see if "dog" is one of the pets
for p in pets:
if p == "dog":
print "found a dog!"
break
else:
# This block only gets run if the loop finishes
# without hitting "break"
print "did not find any dogs :("
The for ... else syntax is basically a fancy way to do this:
def has_dogs(pets):
# This functions check to see if "dog" is one of the pets
dog_found = False
for p in pets:
if p == "dog":
print "found a dog!"
dog_found = True
break
if not dog_found:
print "did not find any dogs :("
Here's my solution using #BiRico's for..else strategy and an inner while loop to make it more efficient. Of course, because there is no bounds on root and we're only looking for one solution, it only finds the trivial case (root = number, pwr = 1).
number = int(input("Choose a number: "))
for pwr in range(1,6):
root = 1
guess = root ** pwr
# We can stop guessing once it's too big
while guess < number:
root += 1
guess = root ** pwr
if guess == number:
print('root = {}, pwr = {}'.format(root, pwr))
break
else: # nobreak
print('No such integers exist')
How about this?
userNum = int(input("Choose a number: "))
for i in range(1,6):
for j in range(userNum):
if j ** i == userNum:
pwr = i
root = j
if pwr:
print('pwr = {}, root = {}'.format(pwr, root))
print("No such integers exist.")

Categories

Resources