How to obtain the closest, lowest palindrome of a given number - python

I am trying to modify the answer to give me the closest lowest palindrome number.
I have tried modifying the answer to this:
def lowest(n):
s = str(n + 1)
l = len(s)
if s[:l//2][::-1] < s[(l+1)//2:]:
head = str(int(s[:(l+1)//2]))
else:
head = s[:(l+1)//2]
print int(head + head[:l//2][::-1])
But for the number 1000, it still returns 1001. What am i doing wrong?

In case you are looking for the previous palindrome, you have invert a couple of signals in the linked answer and add an edge-case exception (for 10^k+1, for all even k>0)
def prev_palindrome(n):
s = str(n - 1)
l = len(s)
if s[:l//2][::-1] > s[(l+1)//2:]:
head = str(int(s[:(l+1)//2])-1)
else:
head = s[:(l+1)//2]
if len(head) < l/2:
return int(head + '9' + head[:l//2][::-1]) #edge case
else:
return int(head + head[:l//2][::-1])
If you want the closest you can try:
nxt = next_palindrome(n)
prv = prev_palindrome(n)
if abs(prv-n) <= abs(nxt-n):
print prv
else:
print nxt
Please note that both next_palindrome and prev_palindrome returns are strictly higher/lower than n.

Related

Splitting Array and adding splitted part to end

I want to split the array at a point s and add it to the end of the array. But my output is my input list.
def split_and_add(arr, s):
n = len(arr)
if n >= s or s <=0:
return arr
else:
end = []
for i in range(0,s):
end = end + [arr[i]]
start = []
for i in range(s,n):
start = start + [arr[i]]
return start + end
print(split_and_add([1,2,3,4,5,6],3))
The output is still [1,2,3,4,5,6]. Could somebody help?
Only issue in your code is in line
if n >= s or s <=0:
Here, you are checking if length of array n is greater than the break point s and if yes, you are returning the originl array. But what you need to do is check if s is greater than or equal to length of array and if yes, return original array. So, all you need to do is replace n >= s with s >= n. So your condition would be
if s >= n or s <=0:
return arr
Now, this should work.
You could do this in a simple way. Just append the left half arr[:s] to the right half arr[s:] like this.
def split_and_add(arr, s):
n = len(arr)
if s >= n or s <=0:
return arr
return arr[s:] + arr[:s]
For the sample input, this gives:
split_and_add([1,2,3,4,5,6],3)
# [4, 5, 6, 1, 2, 3]

What is the difference between the following seemingly same two python functions?

I'm new to data structures and algorithms, so I was kind of confused when I was writing a function to find a pair of numbers from two arrays (one from each array) that the absolute value of difference of the two numbers is the smallest. My first draft was version 2, but it did not pass all the tests. However, when I assigned arrayOne[i] to firstNum and arrayTwo[j] to secondNum, it passed all the test cases. Could anyone explain what happened exactly? Since I thought these two versions were exactly the same.
Version 1:
def smallestDifference(arrayOne, arrayTwo):
arrayOne.sort()
arrayTwo.sort()
i = j = 0
smallest = float('inf')
current = float('inf')
smallestPair = []
while i < len(arrayOne) and j < len(arrayTwo):
firstNum = arrayOne[i]
secondNum = arrayTwo[j]
if firstNum < secondNum:
current = abs(firstNum - secondNum)
i += 1
elif firstNum > secondNum:
current = abs(firstNum - secondNum)
j += 1
else:
return [firstNum, secondNum]
if current < smallest:
smallest = current
smallestPair = [firstNum, secondNum]
return smallestPair
Version 2:
def smallestDifference(arrayOne, arrayTwo):
arrayOne.sort()
arrayTwo.sort()
i = j = 0
smallest = float('inf')
current = float('inf')
smallestPair = []
while i < len(arrayOne) and j < len(arrayTwo):
if arrayOne[i] < arrayTwo[j]:
current = abs(arrayOne[i] - arrayTwo[j])
i += 1
elif arrayOne[i] > arrayTwo[j]:
current = abs(arrayOne[i] - arrayTwo[j])
j += 1
else:
return [arrayOne[i], arrayTwo[j]]
if current < smallest:
smallest = current
smallestPair = [arrayOne[i], arrayTwo[j]]
return smallestPair
In version 1, you are indexing arrayOne and arrayTwo for your first if,elif,else statement which is fine, however you change the value of i/j so if the program hits the if current < smallest part of the algorithm, the value of i/j has changed.
For example lets say i and j where both 0 and arrayOne[0] < arraytwo[0], you would increment i and continue on. Once you get to the bottom and you want to delclare smallestPair, you are now setting the value to [arrayOne[1], arrayTwo[0] rather than [arrayOne[0], arrayTwo[0] because you incremented i.
Version one declares the two variables and uses those declarations for the WHOLE function.

I am attempting to create a binary search program for a school project, but certain numbers cause infinite recursion

This is my code:
list = []
line = 50
def genList(list):
i = 0
while i < 1000:
list.append(i)
i += 1
return list
def displayList(list, line):
i = 0
while i < 1000:
if i != 0 and i % line == 0:
print('\n')
print('{0:03}'.format(list[i]), end = ' ')
i += 1
print('\n')
def binarySearch(min, max, list, goal):
mid = min + (max - 1) // 2
if list[mid] == goal:
return mid
elif list[mid] > goal:
return binarySearch(min, mid - 1, list, goal)
else:
return binarySearch(mid + 1, max, list, goal)
genList(list)
displayList(list, line)
goal = int(input('What number do you want to find, from 0 to 999?\n'))
result = binarySearch(0, len(list) - 1, list, goal)
print(result)
...and like I said, certain numbers work but others don't, for example 999 will return 999 but 998 will return:
RecursionError: maximum recursion depth exceeded in comparison
Anyone know what's wrong with it? I'm at a bit of a loss...
mid = min + (max - 1) // 2 probably should be (min + max) // 2. Also, your code should have a base case that returns a value, say -1 if the element does not exist within the list. Something like if min > max: return -1 right at the beginning of your search function.
This line is definitely wrong:
mid = min + (max - 1) // 2
Perhaps you meant ( as #Nikolaos Chatzis pointed out)
mid = min + (max - min) // 2
but following works as well and needs one less operation:
mid = (min + max) // 2
Additionally you should abort recursion if minval > maxval (if the value you search for is not in the list)
I didn't look if you can do better. but this should work
def binarySearch(minval, maxval, list_, goal):
mid = (minval + maxval) // 2
# print(minval, maxval, mid, goal) # uncomment for debugging
if minval > maxval: # couldn't find search value
return None
if list_[mid] == goal:
return mid
elif list_[mid] > goal:
return binarySearch(minval, mid - 1, list_, goal)
else:
return binarySearch(mid + 1, maxval, list_, goal)
Also don't hesitate to add print statements (or logs) for debugging.
It makes it very often obvious what is going wrong.
What you could also do is run some simple test code to show that it works for all cases:
for v in range(1000):
assert binarySearch(0, len(list_) -1, list_, v) == v
Also as general recommendation to not stumble into funny or strange bugs.
min, max and list are all python keywords.
You can avoid funny surprises by not using variables with these names. It makes your code also look better with many basic syntax highlighters.
Using them as variable names is not forbidden, but I think it's not a good idea.

How to determine the complexity of python code?

I need to understand the complexity of the following code. I am familiar with the concepts of all the Big O() notation and also have read a lot of blogs but I cant figure how to apply to big programs.
Following is the code for largest pallindrome number from 100 to 999:
def isPaindrome(number):
stringNum = str(number)
firstDigit_index,lastDigit_index=0,len(stringNum)-1
isPalindrome = False
while(lastDigit_index > 0 and firstDigit_index < lastDigit_index):
#print(stringNum[f],"==",stringNum[l],"......")
if(stringNum[firstDigit_index]==stringNum[lastDigit_index]):
isPalindrome = True
else:
isPalindrome = False
break
firstDigit_index = firstDigit_index + 1
lastDigit_index = lastDigit_index - 1
if(isPalindrome):
return number
else:
return 0
max = 0
startRange = 100
endRange = 999
for i in range(endRange*endRange,startRange*startRange,-1):
factors = []
result = isPaindrome(i)
if(result!=0):
for i in range(startRange,endRange+1):
if(result%i==0):
factors.append(i)
if(len(factors)>1):
sumFactor = factors[(len(factors))-1] + factors[(len(factors))-2]
mul = factors[(len(factors))-1] * factors[(len(factors))-2]
if(sumFactor>max and mul==result):
max = sumFactor
print("Largest Palindrome made from product of two 3 digit numbers(",factors[(len(factors))-1],",",factors[(len(factors))-2] ,") is", result,".")
If anyone could just make me understant step by step how to calculate I'd be grateful.
As I mentioned, your isPalindrome function is literally incorrect, as you're not changing the indexes. I changed a bit of your also, so this is the version I'm analysing. (I'm only analysing the isPalindrome function, since I actually couldn't understand what the main function is doing), sorry!
def isPalindrome(n):
num = str(n)
head, tail = 0, len(num) - 1
while tail > head:
if num[head] != num[tail]: # Not symmetrical!! WARNING!
return False
head += 1 # move position
tail -= 1 # move position
return True
This code on average is O(|n|) i.e. O(log N) where N is the number. This is because on average, the if comparison has 50% chance of breaking (returning False) and 50% of continuing. Therefore the expected number of comparisons would be |n|/4 which is O(|n|).

Build a max heap and Iteration

I have two questions:
1) Recently I'm try to build a max heap. Even though I read CLRS I can't find the bug as I run it. The following is my code...
def maxHeapify(list, index):
int = index
left = (int+1) * 2 - 1
right = (int+1) * 2
largest = 0
if left < len(list):
if (left <= len(list)) & (list[left] >= list[int]):
largest = left
else:
largest = int
if right < len(list):
if (right <= len(list)) & (list[right] >= list[largest]):
largest = right
else:
pass
if largest != int:
listNew = swapWithinList(list, int, largest)
listNew = maxHeapify(listNew, largest)
else:
return listNew
def swapWithinList(list, id1, id2):
num1 = list[id1]
num2 = list[id2]
listNew = list[:id1]
listNew.append(num2)
listNew = listNew + list[(id1+1):id2]
listNew.append(num1)
listNew = listNew + list[(id2+1):]
return listNew
I give input but the console just says:
UnboundLocalError: local variable 'listNew' referenced before assignment
does it mean that I put the return statement on the wrong line or there's something I haven't mentioned?
2) What is a iteration?
I am a bit embarrassed when I ask the question. But what is a iteration? Wiki says each repetition of the process means it, so is it a result the loop gives each round?
And iterator seems a basic element in Python, what's difference between iterator and iteration?
1:
Without further comments, here's the code adapted from Wikipedia:
def max_heapify(A, i):
left = 2 * i + 1
right = 2 * i + 2
largest = i
if left < len(A) and A[left] > A[largest]:
largest = left
if right < len(A) and A[right] > A[largest]:
largest = right
if largest != i:
A[i], A[largest] = A[largest], A[i]
max_heapify(A, largest)
def build_max_heap(A):
for i in range(len(A) // 2, -1, -1):
max_heapify(A, i)
Example:
def ptree(A, i=0, indent=0):
if i < len(A):
print ' ' * indent, A[i]
ptree(A, i * 2 + 1, indent + 1)
ptree(A, i * 2 + 2, indent + 1)
A = range(9)
build_max_heap(A)
ptree(A)
Result:
8
7
3
1
0
4
6
5
2
Let us know if you have any questions.
2:
Iteration in python is technically a process of repeatedly calling some object's next() method until it raises the StopIteration exception. Object that possesses this next method is called Iterator. An object that is able to provide an Iterator for the calling code is called Iterable.
The problem is here:
if largest != int:
listNew = swapWithinList(list, int, largest)
listNew = maxHeapify(listNew, largest)
else:
return listNew
If the if statement is false, you try to return listNew, but listNew might not exist at this point (it's only assigned to if the if statement is true).
An iteration is just a pass through a loop or in general, a single pass through some larger thing. Iterators are objects are iterate through data structures, or go through the elements one at a time.

Categories

Resources