I am getting a "Time Limit Exceeded " error in the following code. How to fix that error - python-3.x

The following code is my view of checking whether the sum of a number and it's reverse is a palindrome or not.If the sum is a palindrome then sum will be displayed.Otherwise the process will be repeated until we get a palindrome. When it is set to execute, I am getting a time limit exceeded error.Where do I need to correct the code?
def pal(n1):
temp=n1
rev=0
while(temp>0):
rev=(rev*10)+(temp%10)
temp=temp/10
sum1=n1+rev
temp=sum1
rev=0
while(temp>0):
rev=(rev*10)+(temp%10)
temp=temp/10
if(rev==sum1):
print(sum1)
else:
pal(sum1)
n=int(input())
pal(n)
I expect the output of a number 453 to be 6666.
i.e.
453+354=807 (not a palindrome. So repeat the process)
807+708=1515
1515+5151=6666 (it is a palindrome)

Your problem is that you are checking for while temp > 0: but inside that loop you are using float division: temp=temp/10. So the condition will always hold. For example:
>>> 8/10
0.8
>>> 0.8/10
0.08
What you want is to change your divisions to int division:
>>> 8//10
0
Still you might consider working with strings which is much easier in that case:
def pal(n):
rev_n = str(n)[::-1]
sum_str = str(n + int(rev_n))
while sum_str != sum_str[::-1]:
# print(sum_str)
sum_rev = sum_str[::-1]
sum_str = str(int(sum_str) + int(sum_rev))
print(sum_str)
And with the commented print this gives:
>>> pal(453)
807
1515
6666

Here is one way of doing this using string manipulation, which goes a lot easier than trying to do this with numbers. It is also a more direct translation of what you describe afterwards. (I do not really see the link between your code and your description...)
def is_palindrome(text):
# : approach1, faster for large inputs
# mid_length = len(text) // 2
# offset = 0 if len(text) % 2 else 1
# return text[:mid_length] == text[:-mid_length - offset:-1]
# : approach2, faster for small inputs
return text == text[::-1]
def palindrome_sum(num):
while not is_palindrome(num):
num = str(int(num) + int(num[::-1]))
return num
num = input() # 453
palindrome = palindrome_sum(num)
print(palindrome)
# 6666

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

Horizotal print of a complex string block

Once again I'm asking for you advice. I'm trying to print a complex string block, it should look like this:
32 1 9999 523
+ 8 - 3801 + 9999 - 49
---- ------ ------ -----
40 -3800 19998 474
I wrote the function arrange_printer() for the characters arrangement in the correct format that could be reutilized for printing the list. This is how my code looks by now:
import operator
import sys
def arithmetic_arranger(problems, boolean: bool):
arranged_problems = []
if len(problems) <= 5:
for num in range(len(problems)):
arranged_problems += arrange_printer(problems[num], boolean)
else:
sys.exit("Error: Too many problems")
return print(*arranged_problems, end=' ')
def arrange_printer(oper: str, boolean: bool):
oper = oper.split()
ops = {"+": operator.add, "-": operator.sub}
a = int(oper[0])
b = int(oper[2])
if len(oper[0]) > len(oper[2]):
size = len(oper[0])
elif len(oper[0]) < len(oper[2]):
size = len(oper[2])
else:
size = len(oper[0])
line = '------'
ope = ' %*i\n%s %*i\n%s' % (size,a,oper[1],size,b,'------'[0:size+2])
try:
res = ops[oper[1]](a,b)
except:
sys.exit("Error: Operator must be '+' or '-'.")
if boolean == True:
ope = '%s\n%*i' % (ope,size+2, res)
return ope
arithmetic_arranger(['20 + 300', '1563 - 465 '], True)
#arrange_printer(' 20 + 334 ', True)
Sadly, I'm getting this format:
2 0
+ 3 0 0
- - - - -
3 2 0 1 5 6 3
- 4 6 5
- - - - - -
1 0 9 8
If you try printing the return of arrange_printer() as in the last commented line the format is the desired.
Any suggestion for improving my code or adopt good coding practices are well received, I'm starting to get a feel for programming in Python.
Thank you by your help!
The first problem I see is that you use += to add an item to the arranged_problems list. Strings are iterable. somelist += someiterable iterates over the someiterable, and appends each element to somelist. To append, use somelist.append()
Now once you fix this, it still won't work like you expect it to, because print() works by printing what you give it at the location of the cursor. Once you're on a new line, you can't go back to a previous line, because your cursor is already on the new line. Anything you print after that will go to the new line at the location of the cursor, so you need to arrange multiple problems such that their first lines all print first, then their second lines, and so on. Just fixing append(), you'd get this output:
20
+ 300
-----
320 1563
- 465
------
1098
You get a string with \n denoting the start of the new line from each call to arrange_printer(). You can split this output into lines, and then process each row separately.
For example:
def arithmetic_arranger(problems, boolean:bool):
arranged_problems = []
if len(problems) > 5:
print("Too many problems")
return
for problem in problems:
# Arrange and split into individual lines
lines = arrange_printer(problem, boolean).split('\n')
# Append the list of lines to our main list
arranged_problems.append(lines)
# Now, arranged_problems contains one list for each problem.
# Each list contains individual lines we want to print
# Use zip() to iterate over all the lists inside arranged_problems simultaneously
for problems_lines in zip(*arranged_problems):
# problems_lines is e.g.
# (' 20', ' 1563')
# ('+ 300', '- 465') etc
# Unpack this tuple and print it, separated by spaces.
print(*problems_lines, sep=" ")
Which gives the output:
20 1563
+ 300 - 465
----- ------
320 1098
If you expect each problem to have a different number of lines, then you can use the itertools.zip_longest() function instead of zip()
To collect all my other comments in one place:
return print(...) is pretty useless. print() doesn't return anything. return print(...) will always cause your function to return None.
Instead of iterating over range(len(problems)) and accessing problems[num], just do for problem in problems and then use problem instead of problems[num]
Debugging is an important skill, and the sooner into your programming career you learn it, the better off you will be.
Stepping through your program with a debugger allows you to see how each statement affects your program and is an invaluable debugging tool

Just started python and working through Automate The Boring Stuff with Python. Any recommendations on cleaning my code?

New here at stackoverflow. I'm learning python right now and picked up the book Automate the Boring Stuff with Python. Need some recommendations or tips on how to clean up my code. Here is one of the small projects from the book:
Write a function named collatz() that has one parameter named number. If number is even, then collatz() should print number // 2 and return this value. If 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.
The output of this program could look something like this:
Enter number:
3
10
5
16
8
4
2
1
Here's the code I came up with. Any recommendations on cleaning up the code or is this good enough? Thank you all!
def collatz(number):
if number % 2 == 0: # Even numbers
print(number // 2)
return number // 2
elif number % 2 == 1: # Odd numbers
result = 3 * number + 1
print(result)
return result
while True: # Made a loop until a number is entered
try:
n = input("Enter a random number: ")
while n != 1:
n = collatz(int(n))
break
except ValueError:
print("Enter numbers only.")
Use else in the place of elif , it will give same reasult.
Optimized for readability and usage, not on performance.
def collatz(number):
print(n)
return number // 2 if number % 2 == 0 else 3 * number + 1
while True: # Made a loop until a number is entered
try:
n = input("Enter a random number: ")
while n != 1: n = collatz(int(n))
break
except ValueError: print("Enter numbers only.")

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.

Python Collatz Infinite Loop

Apologies if similar questions have been asked but I wasn't able to find anything to fix my issue. I've written a simple piece of code for the Collatz Sequence in Python which seems to work fine for even numbers but gets stuck in an infinite loop when an odd number is enter.
I've not been able to figure out why this is or a way of breaking out of this loop so any help would be greatly appreciate.
print ('Enter a positive integer')
number = (int(input()))
def collatz(number):
while number !=1:
if number % 2 == 0:
number = number/2
print (number)
collatz(number)
elif number % 2 == 1:
number = 3*number+1
print (number)
collatz(number)
collatz(number)
Your function lacks any return statements, so by default it returns None. You might possibly wish to define the function so it returns how many steps away from 1 the input number is. You might even choose to cache such results.
You seem to want to make a recursive call, yet you also use a while loop. Pick one or the other.
When recursing, you don't have to reassign a variable, you could choose to put the expression into the call, like this:
if number % 2 == 0:
collatz(number / 2)
elif ...
This brings us the crux of the matter. In the course of recursing, you have created many stack frames, each having its own private variable named number and containing distinct values. You are confusing yourself by changing number in the current stack frame, and copying it to the next level frame when you make a recursive call. In the even case this works out for your termination clause, but not in the odd case. You would have been better off with just a while loop and no recursion at all.
You may find that http://pythontutor.com/ helps you understand what is happening.
A power-of-two input will terminate, but you'll see it takes pretty long to pop those extra frames from the stack.
I have simplified the code required to find how many steps it takes for a number to get to zero following the Collatz Conjecture Theory.
def collatz():
steps = 0
sample = int(input('Enter number: '))
y = sample
while sample != 1:
if sample % 2 == 0:
sample = sample // 2
steps += 1
else:
sample = (sample*3)+1
steps += 1
print('\n')
print('Took '+ str(steps)+' steps to get '+ str(y)+' down to 1.')
collatz()
Hope this helps!
Hereafter is my code snippet and it worked perfectly
#!/usr/bin/python
def collatz(i):
if i % 2 == 0:
n = i // 2
print n
if n != 1:
collatz(n)
elif i % 2 == 1:
n = 3 * i + 1
print n
if n != 1:
collatz(n)
try:
i = int(raw_input("Enter number:\n"))
collatz(i)
except ValueError:
print "Error: You Must enter integer"
Here is my interpretation of the assignment, this handles negative numbers and repeated non-integer inputs use cases as well. Without nesting your code in a while True loop, the code will fail on repeated non-integer use-cases.
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)
# Program starts here.
while True:
try:
# Ask for input
n = input('Please enter a number: ')
# If number is negative or 0, asks for positive and starts over.
if int(n) < 1:
print('Please enter a positive INTEGER!')
continue
#If number is applicable, goes through collatz function.
while n != 1:
n = collatz(int(n))
# If input is a non-integer, asks for a valid integer and starts over.
except ValueError:
print('Please enter a valid INTEGER!')
# General catch all for any other error.
else:
continue

Resources