Not all arguments converted during string formatting (Proving Collatz Conjecture) - python

When I run the code below I get an error. I have looked here on StackOverflow, but I ended up not solving my problem.
print "insert value"
value = raw_input ()
flag = False
i = 0
while flag:
if value == 1:
flag = True
elif value % 2 == 0:
value = value / 2
else:
value = value * 3
value = value + 1
i = i + 1
print "After", i, "attempts the conjecture has been demonstrated"
I get an error in the elif logical test value% 2 == 0 which says
not all arguments converted during string formatting
I think the problem is in the variable type but I tried the input function and forcing the int type, value = int (input (....)), but that also didn't work.

In IDLE this worked for me
value = int(raw_input ())
converting raw input into integer
while True:
if value == 1:
break
elif value % 2 == 0:
value = value / 2
else:
value = value * 3
value = value + 1
i = i + 1
a bit simpler way to do while without having arbitrary flag

iScrE4m has shown how to fix your program, but I'll explain why you got that
TypeError: not all arguments converted during string formatting
error message.
When the Python interpreter sees % after a string it interprets the % as the string interpolation operator, which is used to convert data and insert it into a string.
For example
a = 2
b = 3
print "%d + %d = %d" % (a, b, a + b)
output
2 + 3 = 5
In your code, value is a string so the interpreter tries to do string interpolation on value % 2 but then it sees that value isn't a valid format string to format the data 2, so it gives you that TypeError.
In modern code use of %-style string formatting is discouraged and the str.format method is preferred. The equivalent to the above example is:
print "{0} + {1} = {2}".format(a, b, a + b)
In Python 2.7 and later you can omit the field numbers:
print "{} + {} = {}".format(a, b, a + b)
I have a few more comments on your code.
When calling a function in Python it's conventional to not put a space after the function name.
There's no need to use print to print a prompt before calling raw_input: you can (and should) supply the prompt as an argument to raw_input.
When performing integer division you should use the integer division operator //. A single slash works ok in Python 2, but in Python 3 it won't behave as expected here because it will perform a floating-point division. Eg, 10 / 2 will result in 5.0.
When you need to perform a single operation on a variable and save the result of that operation back to the same variable you can use an augmented assignment operator. Eg,
instead of i = i + 1 you can write i += 1;
instead of value = value // 2 you can write value //= 2.
Also, instead of
value = value * 3
value = value + 1
you could do
value *= 3
value += 1
However, when performing multiple operations on a variable it's a little more compact and efficient to do them on one line. So it would be more usual to do:
value = value * 3 + 1
Putting it all together, here's a re-worked version of your code.
value = int(raw_input("Enter value: "))
i = 0
while True:
if value == 1:
break
elif value % 2 == 0:
value //= 2
else:
value = value * 3 + 1
i += 1
print "After {} attempts the conjecture has been demonstrated.".format(i)

Related

Is it possible to filter out zero values in formatted string literals?

Formatted string literals (:+) are used to show the sign of a number (+ or -). e.g:
a = 2
b = -5
print(f"{a+b:+}")
output: -3
or
a = 2
b = 5
print(f"{a+b:+}")
output: +7
If the output is 0, it is given as +0.
Is there a way in which if the sum of a and b is 0, the output should return nothing (I'm not sure what that would mean), or maybe output an empty string?
Example: Gn = c + (a-b)
If a is 3 and b is 3 as well, the output should be Gn = c. Not Gn=c+0
I have tried to apply some conditional statement wrt 0, to return an empty string instead but Formatted string literals (:+) only work on integers.
Is there a way in which if the sum of a and b is 0, the output should return nothing (I'm not sure what that would mean), or maybe output an empty string?
Make a format helper. Non-zero is considered True, so you can return an empty string if the number is false:
def fmt(i):
return f'{i:+}' if i else ''
a = 1
for b in range(3):
print(f'result: {fmt(a-b)}')
Output:
result: +1
result:
result: -1
I'm not sure I'm totally following, but in your case, maybe just do the computation and branch on that:
c = 1
a = 2
b = 3
a_minus_b = a - b
if a_minus_b:
print(f"Gn = {c} + ({a} - {b})")
else:
print(f"Gn = {c}")
Of course this could be done more fancily (if less readably), e.g.
print(f"Gn = {c} + ({a} - {b})" if a_minus_b else f"Gn = {c}")
or
print(f"Gn = {c}" + f" + ({a} - {b})" if a_minus_b else "")
You could insert a conditional statement to check sum of both variables, and if if the sum is zero you can print an empty string literals or else you can print the actual value.
a = 2
b = -3
if a + b == 0:
print(f"")
else:
print(f"{a+b:+}")

I need to get rid of the print statement while outputting the same thing. How can I change this code so there is zero print statements

#Converts decimal to binary after the user inputs
def Decimaltobinary(Decimal):
#if user inputs 0 then it will return 0
if Decimal == 0:
#returns
return 0
#repeats if number is not 0
else:
#Decimal divided by 2
Decimaltobinary(int(Decimal / 2))
#i need to get rid of this print
print(Decimal % 2, end="")
return str(Decimal)
# Not sure how to change the print to a return while giving
the same output
#input 2
#Output 01
def divide_Decimal():
Decimal = Decimal / 2
return str(Decimal)
divide_Decimal(#value_of_decimal)
If you are not allowed to use the print statement, you can define a function and use return instead, which has the same effect as print if you simply want to output a value.
def Decimaltobinary(Decimal):
if Decimal == 0:
return 0
else:
Decimaltobinary(int(Decimal / 2))
var = str(Decimal % 2, end="")
return var, str(Decimal)

If, else return else value even when the condition is true, inside a for loop

Here is the function i defined:
def count_longest(field, data):
l = len(field)
count = 0
final = 0
n = len(data)
for i in range(n):
count = 0
if data[i:i + l] is field:
while data[i - l: i] == data[i:i + l]:
count = count + 1
i = i + 1
else:
print("OK")
if final == 0 or count >= final:
final = count
return final
a = input("Enter the field - ")
b = input("Enter the data - ")
print(count_longest(a, b))
It works in some cases and gives incorrect output in most cases. I checked by printing the strings being compared, and even after matching the requirement, the loop results in "OK" which is to be printed when the condition is not true! I don't get it! Taking the simplest example, if i enter 'as', when prompted for field, and 'asdf', when prompted for data, i should get count = 1, as the longest iteration of the substring 'as' is once in the string 'asdf'. But i still get final as 0 at the end of the program. I added the else statement just to check the if the condition was being satisfied, but the program printed 'OK', therefore informing that the if condition has not been satisfied. While in the beginning itself, data[0 : 0 + 2] is equal to 'as', 2 being length of the "field".
There are a few things I notice when looking at your code.
First, use == rather than is to test for equality. The is operator checks if the left and right are referring to the very same object, whereas you want to properly compare them.
The following code shows that even numerical results that are equal might not be one and the same Python object:
print(2 ** 31 is 2 ** 30 + 2 ** 30) # <- False
print(2 ** 31 == 2 ** 30 + 2 ** 30) # <- True
(note: the first expression could either be False or True—depending on your Python interpreter).
Second, the while-loop looks rather suspicious. If you know you have found your sequence "as" at position i, you are repeating the while-loop as long as it is the same as in position i-1—which is probably something else, though. So, a better way to do the while-loop might be like so:
while data[i: i + l] == field:
count = count + 1
i = i + l # <- increase by l (length of field) !
Finally, something that might be surprising: changing the variable i inside the while-loop has no effect on the for-loop. That is, in the following example, the output will still be 0, 1, 2, 3, ..., 9, although it looks like it should skip every other element.
for i in range(10):
print(i)
i += 1
It does not effect the outcome of the function, but when debugging you might observe that the function seems to go backward after having found a run and go through parts of it again, resulting in additional "OK"s printed out.
UPDATE: Here is the complete function according to my remarks above:
def count_longest(field, data):
l = len(field)
count = 0
final = 0
n = len(data)
for i in range(n):
count = 0
while data[i: i + l] == field:
count = count + 1
i = i + l
if count >= final:
final = count
return final
Note that I made two additional simplifications. With my changes, you end up with an if and while that share the same condition, i.e:
if data[i:i+1] == field:
while data[i:i+1] == field:
...
In that case, the if is superfluous since it is already included in the condition of while.
Secondly, the condition if final == 0 or count >= final: can be simplified to just if count >= final:.

How do I return the middle of a python array?

Here is the prompt:
On the first line display the first, last and middle element of the list separated by the , character.
I have been trying to get this figured out for a few hours now, but do not know the correct process to return the middle of the array. Here is my code so far:
primary = []
length = 0
i = ("MORE")
while i != "NOMORE":
i = str(input("?"))
print(i)
if i == "NOMORE":
break
primary.append(i)
length = length + 1
mid = (length/2)
print(primary[0]," , ", primary[-1]," , ",primary.pop([mid]))
The code works to get the correct inputs from the program, but as the lists will be variable lengths I assume some form of a loop will be used. The primary.pop([mid]) was my poor attempt at getting the median printed. I know that the mid will not be printed as it is the wrong variable type, but how would I replace this?
Any help is appreciated.
You're unnecessarily calling the pop() method on primary with [mid] when you should simply be indexing primary with mid. You should also use the // operator instead of / to obtain an integer value for the index. Since the index is 0-based, the mid point should be (length - 1) // 2 instead:
primary = []
length = 0
i = ("MORE")
while i != "NOMORE":
i = str(input("?"))
print(i)
if i == "NOMORE":
break
primary.append(i)
length = length + 1
mid = (length - 1) // 2
print(primary[0]," , ", primary[-1]," , ",primary[mid])

Add leading 0's to value until length is 8 characters long

For homework, we are asked to create a function that takes a binary input, increments the value by 1, and then displays the binary value of the new number. The output value must be an 8-bit string (8 characters long).
The following code returns the correct value, but I do not know how to add the leading zeros to the value.
def numToBinary(n):
if n == 0:
return ''
elif isOdd(n):
return numToBinary(n // 2) + '1'
else:
return numToBinary(n // 2) + '0'
def binaryToNum(s):
if s == '':
return 0
elif int(s[0]) == 0:
return 0 + binaryToNum(s[1:])
elif int(s[0]) == 1:
return 2**(len(s) - 1) + binaryToNum(s[1:])
def increment(s):
binToNum = binaryToNum(s) + 1
numToBin = numToBinary(binToNum)
return numToBin
A hint given to solve this problem was: "Consider how could you use the
function len() and string multiplication with * to make sure that the output has enough leading zeros?"
Could someone please point me in the right direction? Thank you!
Note: An example output should be:
>>> increment('00000001')
'00000010'
Calculate how many zeroes you will need. Then prepend them to value.
value = '01'
needed = 8 - len(value)
value = '0' * needed + value
You can also use zfill():
value = value.zfill(8)

Categories

Resources