Lexicographically smallest palindrome in python - string

I found this question to be interesting and I would like to share this here and find reasonably good codes, specific to py :
Given a string S having characters from English alphabets ['a' - 'z'] and '.' as the special character (without quotes).
Write a program to construct the lexicographically smallest palindrome by filling each of the faded character ('.') with a lower case alphabet.
Definition:
The smallest lexicographical order is an order relation where string s is smaller than t, given the first character of s (s1 ) is smaller than the first character of t (t1 ), or in case they
are equivalent, the second character, etc.
For example : "aaabbb" is smaller than "aaac" because although the first three characters
are equal, the fourth character b is smaller than the fourth character c.
Input Format:
String S
Output Format:
Print lexicographically smallest palindrome after filling each '.' character, if it
possible to construct one. Print -1 otherwise.
Example-1
Input:
a.ba
Output:
abba
Example-2:
Input:
a.b
Output:
-1
Explanation:
In example 1, you can create a palindrome by filling the '.' character by 'b'.
In example 2, it is not possible to make the string s a palindrome.

You can't just copy paste questions from NPTEL assignments and ask them here without even trying!
Anyways,since the "code" is your only concern,try copy pasting the lines below:
word = input()
length = len(word)
def SmallestPalindrome(word, length):
i = 0
j = length - 1
word = list(word) #creating a list from the input word
while (i <= j):
if (word[i] == word[j] == '.'):
word[i] = word[j] = 'a'
elif word[i] != word[j]:
if (word[i] == '.'):
word[i] = word[j]
elif (word[j] == '.'):
word[j] = word[i]
else: # worst case situation when palindrome condition is not met
return -1
i = i + 1
j = j - 1
return "".join(word) # to turn the list back to a string
print(SmallestPalindrome(word, length)) #Print the output of your function

s=input()
s=list(s)
n=len(s)
j=n
c=0
for i in range(n):
j=j-1
if((s[i]==s[j]) and (i==j) and (s[i]=='.' and s[j]=='.')):
s[i]='a'
s[j]='a'
elif(s[i]==s[j]):
continue
elif((s[i]!=s[j]) and (i!=j) and (s[i]=='.' or s[j]=='.')):
if(s[i]!='.'):
s[j]=s[i]
else:
s[i]=s[j]
elif((i==j) and (s[i]=='.')):
s[i]=a
else:
c=c+1
break
if(c<1):
for k in s:
print(k,end="")
else:print("-1")

Related

The algorithm receives a natural number N > 1 as input and builds a new number R from it as follows:

Python.
It's a problem:
The algorithm receives a natural number N > 1 as input and builds a new number R from it as follows:
We translate the number N into binary notation.
Invert all bits of the number except the first one.
Convert to decimal notation.
Add the result with the original number N.
The resulting number is the desired number R. Indicate the smallest odd number N for which the result of this algorithm is greater than 310. In your answer, write this number in decimal notation.
This is my solution:
for n in range(2, 10000):
s = bin(n)[2:]
for i in range(len(s)):
if s[i+1] == 0:
s[i] = '1'
else:
s[i] = 'k'
for i in range(len(s)):
if s[i] == 'k':
s[i] = '0'
h = int(s, 2)
r = h + n
if n % 2 == 1 and r > 310:
print(n)
break
So it doesn't work and i dont know why. I am now preparing for the exam, so I would be grateful if you could explain the reason to me
the bin function returns a string and my idea is to go through the binary elements of this string, starting from the second element, to replace 0 with 1, and 1 with k. Then iterate over the elements of a new line again and replace k with 0
Took me longer than I expected but feels good.
Comments might make it look chaotic but will make it easily understandable.
#since N is supposed to be odd and >1 the loop is being run from 3
for N in range(3, 10000,2):
#appending binary numbers to the list bin_li
bin_li=[]
bin_li.append((bin(N)[2:]))
for i in bin_li:
#print("bin_li item :",i)
#storing 1st digit to be escaped in j
j=i[:1]
#reversing the digits
for k in i[1:]:
if k=='0':
#putting together the digits after reversing
j=j+'1'
else:
j=j+'0'
#print("reversed item :",j) #note first digit is escaped
#converting back to decimal
dec=int(j,2)
R=dec+N
#print("current sum:---------" ,R)
if R > 310:
print("The number N :",N)
print("The reversed binary number:",dec)
print("Sum :",R)
break
#break will only break the inner loop
# for reference https://www.geeksforgeeks.org/how-to-break-out-of-multiple-loops-in-python/
else:
continue
break

Why doesn't this function always return the longest palindromic substring in a string?

I wrote this solution to a codewars problem (https://www.codewars.com/kata/longest-palindrome). It passes all but one of the tests, in which it returns 2 instead of 7.
Why might this solution fail?
def longest_palindrome (s):
if s == '':
return 0
if len(s) == 1:
return 1
palindrome_lengths = []
for i in range(len(s)):
# determine all indices for the character
indices = []
for p, character in enumerate(s):
if character == s[i]:
indices.append(p)
# check if each substring is a palindrome and, if so, add length to palindrome_lengths
index = 1
while index < len(indices):
# grab the substring
substring = s[indices[0]:indices[index]+1]
# reverse the substring
reverse_substring = substring[::-1]
# if forward substring equals reverse, add length to a list of lengths
if substring == reverse_substring:
palindrome_lengths.append(len(substring))
index += 1
if palindrome_lengths == []:
return 1
else:
palindrome_lengths.sort(reverse=True)
return palindrome_lengths[0]
You never check any substring that doesn't start with the first occurrence of its first letter in the original string (for example, for the string "mamadam", you never test the substring starting with the second m).

Palindrome rearrangement in Python

I am given a string and I have to determine whether it can be rearranged into a palindrome.
For example: "aabb" is true.
We can rearrange "aabb" to make "abba", which is a palindrome.
I have come up with the code below but it fails in some cases. Where is the problem and how to fix this?
def palindromeRearranging(inputString):
a = sorted(inputString)[::2]
b = sorted(inputString)[1::2]
return b == a[:len(b)]
def palindromeRearranging(inputString):
return sum(map(lambda x: inputString.count(x) % 2, set(inputString))) <= 1
this code counts occurrence for every character in string. in palindromes there is one character with odd occurrence if length of string is odd, if length of string is even then no character has odd occurance.
see here
def palindromeRearranging(inputString):
elements = {c:inputString.count(c) for c in set(inputString)}
even = [e % 2 == 0 for e in elements.values()]
return all(even) or (len(inputString) % 2 == 1 and even.count(False) == 1)
It counts each character number of appearances, and checks whether all elements appear an even number of times or if the length of the input string is odd, checks whether only one character appears an odd number of times.
Python3
def palindromeArrange (string):
string = list(string)
for i in range (len(string)):
"""if the string has even element count"""
if len(string) % 2 == 0 and len(string)/2 == len (set (string)):
return True
"""if the string has odd element count"""
if len(string) - ((len(string)-1)/2) == len (set (string)):
return True
return False
One liner using list comprehension in Python3
return len([x for x in set(inputString) if inputString.count(x) % 2 != 0]) <= 1
Basically counts those characters that have counts that aren't divisible by 2.
For even strings it would be zero, and for odd strings, it would be one.
The solution I can think of right away has time complexity is O(n). The assumption is, palindrome can not be made if there is more than one character with the odd count.
def solution(inputString):
string = list(inputString)
n = len(string)
s_set= set(string)
from collections import Counter
dic = Counter(string)
k =0 #counter for odd characters
for char in s_set:
if dic.get(char)%2!=0:
k+=1
if k>1:
return False
else:
return True

compare 2 strings, determine whether A contains all of the characters in B in python using list

question is :
Compare two strings A and B, determine whether A contains all of the characters in B.
The characters in string A and B are all Upper Case letters.
and I saw the solution is:
def compareStrings(self, A, B):
if len(B) == 0:
return True
if len(A) == 0:
return False
trackTable = [0 for _ in range(26)]
for i in A:
trackTable[ord(i) - 65] += 1
for i in B:
if trackTable[ord(i) - 65] == 0:
return False
else:
trackTable[ord(i) -65] -= 1
return True
I do not understand :
1) why give 26 '0' in the list at beginning ?
2) what does trackTable[ord(i) - 65] += 1 do ?
what is ord(i)?
Thanks !
Min
This is an interesting solution for sure (it's pretty convoluted). It creates a 26-element array to count the occurences of each letter in A, then makes sure that the count for each of those letters in B is greater than or equal to the count in A.
To directly answer your questions:
1) why give 26 '0' in the list at beginning ?
We are starting with a list of 26 0's, one for each letter A-Z. We will increment this in the first for loop.
2) what does trackTable[ord(i) - 65] += 1 do ?
This does the counting. Assuming the input is just capital letters A-Z, then ord('A')=65 and ord('Z')=90. We subtract 65 to make this range from 0-25.
3) what is ord(i)?
I would recommend searching online for this. https://www.programiz.com/python-programming/methods/built-in/ord
"The ord() method returns an integer representing Unicode code point for the given Unicode character."

find position of sequences of the same character in a line

This seems to be extremely simple, but if I've got a mental block.
I have a string which contains, say, only '_' and 'x', and I need to find backwards positions of all x-sequences:
xxx___xxx___xxx
___x__xxx_xxx__
What is the fastest approach? Should I use KMP or BM or it's an overkill?
You can scan the string letter by letter. Here's the pseudocode in python:
prev = ''
# enumerate(collection) enumerates collection elements along with their indices
# in the form of tuple (index, element)
# in python strings are collections of characters
for i, c in enumerate(string):
if c == 'x' and c != prev:
print "found x sequence at position %d" % i # (this prints out the index)
prev = c

Resources