Replace a substring in a string with python - python

I am trying to replace every instance of a substring in a string using python. The following is the code that I have done and it is giving me some weird result.
def main():
s='IN GOING GO'
x='IN'
y='aa'
print(rep_str(s,x,y))
def rep_str(s,x,y):
result=""
if x in s:
for i in range(len(s)):
if s[i:i+len(x)] == x:
result=result+y
else:
result=result+s[i+1:i+len(x)]
return result
main()
I am not allowed to use the replace method. In fact, my function is supposed to do what replace function does in python. The following is the output that I am getting.
aa GOIaaG GO
I would appreciate if someone could give me some input about how to change the logic to get the right out put i.e.
aa GOaaG GO.

As I mentioned in comments, the mistake is that you are not skipping len(x) characters after match. Also in keyword is quite high-level routine (it does not less than search part of search & replace), so here is fixed version without in:
def rep_str(string, search, replacement):
result = ''
i = 0
while i < len(string):
if string[i : i + len(search)] == search:
result += replacement
i += len(search)
else:
result += string[i]
i += 1
return result

If you just want to have the result try with:
import re
re.sub(r'IN','aa','IN GOING GO')
but if you need some logic then you should compare for blocks of same length as the pattern, not char by char
#Zag asnwer is better, because can compare longer patterns and has return when it does not match nothing but if you want to get your code running you need to skip for when you have a match like this :
def rep_str(s,x,y):
result=""
skip = False
if x in s:
for i in range(len(s)):
if skip:
skip = False
continue
if s[i:i+2] == x:
result+=y
skip = True
else:
result+=s[i:i+1]
return result
else:
return s
but your code won't work when you will call the function with rep_str("A example test","test", "function") for example.

If you are allow to use the index() function, you can try this:
def main():
s='IN GOING GO'
x='IN'
y='aa'
print(rep_str(s,x,y))
def rep_str(s,x,y):
while x in s:
s = s[:s.index(x)] + y + s[s.index(x) + len(x):]
return s
main()

Related

How do make a function that verifies if a piece of string is the mirror of another using a for loop? [duplicate]

I'm trying to check for a palindrome with Python. The code I have is very for-loop intensive.
And it seems to me the biggest mistake people do when going from C to Python is trying to implement C logic using Python, which makes things run slowly, and it's just not making the most of the language.
I see on this website. Search for "C-style for", that Python doesn't have C-style for loops. Might be outdated, but I interpret it to mean Python has its own methods for this.
I've tried looking around, I can't find much up to date (Python 3) advice for this. How can I solve a palindrome challenge in Python, without using the for loop?
I've done this in C in class, but I want to do it in Python, on a personal basis. The problem is from the Euler Project, great site By the way,.
def isPalindrome(n):
lst = [int(n) for n in str(n)]
l=len(lst)
if l==0 || l==1:
return True
elif len(lst)%2==0:
for k in range (l)
#####
else:
while (k<=((l-1)/2)):
if (list[]):
#####
for i in range (999, 100, -1):
for j in range (999,100, -1):
if isPalindrome(i*j):
print(i*j)
break
I'm missing a lot of code here. The five hashes are just reminders for myself.
Concrete questions:
In C, I would make a for loop comparing index 0 to index max, and then index 0+1 with max-1, until something something. How to best do this in Python?
My for loop (in in range (999, 100, -1), is this a bad way to do it in Python?
Does anybody have any good advice, or good websites, or resources for people in my position? I'm not a programmer, I don't aspire to be one, I just want to learn enough so that when I write my bachelor's degree thesis (electrical engineering), I don't have to simultaneously LEARN an applicable programming language while trying to obtain good results in the project. "How to go from basic C to great application of Python", that sort of thing.
Any specific bits of code to make a great solution to this problem would also be appreciated, I need to learn good algorithms.. I am envisioning 3 situations. If the value is zero or single digit, if it is of odd length, and if it is of even length. I was planning to write for loops...
PS: The problem is: Find the highest value product of two 3 digit integers that is also a palindrome.
A pythonic way to determine if a given value is a palindrome:
str(n) == str(n)[::-1]
Explanation:
We're checking if the string representation of n equals the inverted string representation of n
The [::-1] slice takes care of inverting the string
After that, we compare for equality using ==
An alternative to the rather unintuitive [::-1] syntax is this:
>>> test = "abcba"
>>> test == ''.join(reversed(test))
True
The reversed function returns a reversed sequence of the characters in test.
''.join() joins those characters together again with nothing in between.
Just for the record, and for the ones looking for a more algorithmic way to validate if a given string is palindrome, two ways to achieve the same (using while and for loops):
def is_palindrome(word):
letters = list(word)
is_palindrome = True
i = 0
while len(letters) > 0 and is_palindrome:
if letters[0] != letters[(len(letters) - 1)]:
is_palindrome = False
else:
letters.pop(0)
if len(letters) > 0:
letters.pop((len(letters) - 1))
return is_palindrome
And....the second one:
def is_palindrome(word):
letters = list(word)
is_palindrome = True
for letter in letters:
if letter == letters[-1]:
letters.pop(-1)
else:
is_palindrome = False
break
return is_palindrome
The awesome part of python is the things you can do with it. You don't have to use indexes for strings.
The following will work (using slices)
def palindrome(n):
return n == n[::-1]
What it does is simply reverses n, and checks if they are equal. n[::-1] reverses n (the -1 means to decrement)
"2) My for loop (in in range (999, 100, -1), is this a bad way to do it in Python?"
Regarding the above, you want to use xrange instead of range (because range will create an actual list, while xrange is a fast generator)
My opinions on question 3
I learned C before Python, and I just read the docs, and played around with it using the console. (and by doing Project Euler problems as well :)
Below the code will print 0 if it is Palindrome else it will print -1
Optimized Code
word = "nepalapen"
is_palindrome = word.find(word[::-1])
print is_palindrome
Output:
0
word = "nepalapend"
is_palindrome = word.find(word[::-1])
print is_palindrome
Output:
-1
Explaination:
when searching the string the value that is returned is the value of the location that the string starts at.
So when you do word.find(word[::-1]) it finds nepalapen at location 0 and [::-1] reverses nepalapen and it still is nepalapen at location 0 so 0 is returned.
Now when we search for nepalapend and then reverse nepalapend to dnepalapen it renders a FALSE statement nepalapend was reversed to dnepalapen causing the search to fail to find nepalapend resulting in a value of -1 which indicates string not found.
Another method print true if palindrome else print false
word = "nepalapen"
print(word[::-1]==word[::1])
output:
TRUE
There is also a functional way:
def is_palindrome(word):
if len(word) == 1: return True
if word[0] != word[-1]: return False
return is_palindrome(word[1:-1])
I know that this question was answered a while ago and i appologize for the intrusion. However,I was working on a way of doing this in python as well and i just thought that i would share the way that i did it in is as follows,
word = 'aibohphobia'
word_rev = reversed(word)
def is_palindrome(word):
if list(word) == list(word_rev):
print'True, it is a palindrome'
else:
print'False, this is''t a plindrome'
is_palindrome(word)
There is much easier way I just found. It's only 1 line.
is_palindrome = word.find(word[::-1])
The most pythonic way to do this is indeed using the slicing notation to reverse the string as mentioned already:
def is_palindrome(string: str) -> bool:
return string == string[::-1]
In some other occasions though (like technical interviews), you may have to write a "proper" algorithm to find the palindrome. In this case, the following should do the trick:
def is_palindrome(string: str) -> bool:
start = 0
end = len(string) - 1
while end >= start:
if string[end] != string[start]:
return False
start += 1
end -= 1
return True
Set pointers to the start and end of the string
Iterate while end exceeds start
If the character in end and start indices don't match then this is not a palindrome, otherwise keep comparing
Increase start pointer by 1
Decrease end pointer by 1
Test Cases:
import unittest
class Test(unittest.TestCase):
palindromes = ['a', 'aa', 'aba', '12321']
non_palindromes = ['ab', 'aab', 'cacacc']
def test_is_palindrome(self):
for case in self.palindromes:
self.assertTrue(is_palindrome(case))
for case in self.non_palindromes:
self.assertFalse(is_palindrome(case))
if __name__ == '__main__':
unittest.main()
You could use this one-liner that returns a bool value:
str(x)==str(x)[::-1]
This works both for words and numbers thanks to the type casting...
Here a case insensitive function since all those solutions above are case sensitive.
def Palindrome(string):
return (string.upper() == string.upper()[::-1])
This function will return a boolean value.
doing the Watterloo course for python, the same questions is raised as a "Lesseon" find the info here:
http://cscircles.cemc.uwaterloo.ca/13-lists/
being a novice i solved the problem the following way:
def isPalindrome(S):
pali = True
for i in range (0, len(S) // 2):
if S[i] == S[(i * -1) - 1] and pali is True:
pali = True
else:
pali = False
print(pali)
return pali
The function is called isPalindrome(S) and requires a string "S".
The return value is by default TRUE, to have the initial check on the first if statement.
After that, the for loop runs half the string length to check if the character from string "S" at the position "i" is the same at from the front and from the back.
If once this is not the case, the function stops, prints out FALSE and returns false.
Cheers.kg
If the string has an uppercase or non-alphabetic character then the function converts all characters to lowercase and removes all non-alphabetic characters using regex finally it applies palindrome check recursively:
import re
rules = [
lambda s: any(x.isupper() for x in s),
lambda s: not s.isalpha()
]
def is_palindrome(s):
if any(rule(s) for rule in rules):
s = re.sub(r'[^\w]', '', s).lower()
if len(s) < 2:
return True
if s[0] != s[-1]:
return False
return is_palindrome(s[1:-1])
string = 'Are we not drawn onward, we few, drawn onward to new era?'
print(is_palindrome(string))
the output is True for the input above.
maybe you can try this one:
list=input('enter a string:')
if (list==list[::-1]):
print ("It is a palindrome")
else:
print("it is not palindrome")
You are asking palindrome in python. palindrome can be performed on strings, numbers and lists. However, I just posted a simple code to check palindrome of a string.
# Palindrome of string
str=raw_input("Enter the string\n")
ln=len(str)
for i in range(ln/2) :
if(str[ln-i-1]!=str[i]):
break
if(i==(ln/2)-1):
print "Palindrome"
else:
print "Not Palindrome"
The real easy way to do that it is
word = str(raw_input(""))
is_palindrome = word.find(word[::-1])
if is_palindrome == 0:
print True
else:
print False
And if/else here just for fancy looks. The question about palindrome was on Amazon's interview for QA
Assuming a string 's'
palin = lambda s: s[:(len(s)/2 + (0 if len(s)%2==0 else 1)):1] == s[:len(s)/2-1:-1]
# Test
palin('654456') # True
palin('malma') # False
palin('ab1ba') # True
word = "<insert palindrome/string>"
reverse = word[::-1]
is_palindrome = word.find(reverse)
print is_palindrome
This was a question in Udacity comp 101, chapter 1. Gives a 0 for palindrome gives a -1 for not. Its simple, and does not use loops.
I wrote this code:
word = input("enter: ")
word = ''.join(word.split())`
for x in range(len(word)):
if list(word)[x] == ((list(word)[len(word)-x-1])):
if x+1 == len(word):
print("its pali")
and it works.
it gets the word, then removes the spaces and turns it into a list
then it tests if the first letter is equal to the last and if the 2nd is equal to 2nd last and so on.
then the 'if x+1 == len(word)' means that since x starts at 0 it becomes 1 and then for every next .. blah blah blah it works so it works.
#compare 1st half with reversed second half
# i.e. 'abba' -> 'ab' == 'ba'[::-1]
def is_palindrome( s ):
return True if len( s ) < 2 else s[ :len( s ) // 2 ] == s[ -( len( s ) // 2 ):][::-1]
You can use Deques in python to check palindrome
def palindrome(a_string):
ch_dequeu = Deque()
for ch in a_string:
ch_dequeu.add_rear(ch)
still_ok = True
while ch_dequeu.size() > 1 and still_ok:
first = ch_dequeu.remove_front()
last = ch_dequeu.remove_rear()
if first != last:
still_ok = False
return still_ok
class Deque:
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def add_rear(self, item):
self.items.insert(0, item)
def add_front(self, item):
self.items.append(item)
def size(self):
return len(self.items)
def remove_front(self):
return self.items.pop()
def remove_rear(self):
return self.items.pop(0)
import string
word = input('Please select a word to test \n')
word = word.lower()
num = len(word)
x = round((len(word)-1)/2)
#defines first half of string
first = word[:x]
#reverse second half of string
def reverse_odd(text):
lst = []
count = 1
for i in range(x+1, len(text)):
lst.append(text[len(text)-count])
count += 1
lst = ''.join(lst)
return lst
#reverse second half of string
def reverse_even(text):
lst = []
count = 1
for i in range(x, len(text)):
lst.append(text[len(text)-count])
count += 1
lst = ''.join(lst)
return lst
if reverse_odd(word) == first or reverse_even(word) == first:
print(string.capwords(word), 'is a palindrome')
else:
print(string.capwords(word), 'is not a palindrome')
the "algorithmic" way:
import math
def isPalindrome(inputString):
if inputString == None:
return False
strLength = len(inputString)
for i in range(math.floor(strLength)):
if inputString[i] != inputString[strLength - 1 - i]:
return False
return True
There is another way by using functions, if you don't want to use reverse
#!/usr/bin/python
A = 'kayak'
def palin(A):
i = 0
while (i<=(A.__len__()-1)):
if (A[A.__len__()-i-1] == A[i]):
i +=1
else:
return False
if palin(A) == False:
print("Not a Palindrome")
else :
print ("Palindrome")
It looks prettier with recursion!
def isPalindrome(x):
z = numToList(x)
length = math.floor(len(z) / 2)
if length < 2:
if z[0] == z[-1]:
return True
else:
return False
else:
if z[0] == z[-1]:
del z[0]
del z[-1]
return isPalindrome(z)
else:
return False
def is_palindrome(string):
return string == ''.join([letter for letter in reversed(string)])
print ["Not a palindrome","Is a palindrome"][s == ''.join([s[len(s)-i-1] for i in range(len(s))])]
This is the typical way of writing single line code
def pali(str1):
l=list(str1)
l1=l[::-1]
if l1==l:
print("yess")
else:
print("noo")
str1="abc"
a=pali(str1)
print(a)
I tried using this:
def palindrome_numer(num):
num_str = str(num)
str_list = list(num_str)
if str_list[0] == str_list[-1]:
return True
return False
and it worked for a number but I don't know if a string
def isPalin(checkWord):
Hsize = len(lst)/2
seed = 1
palind=True
while seed<Hsize+1:
#print seed,lst[seed-1], lst [-(seed)]
if(lst[seed-1] != lst [-seed]):
palind = False
break
seed = seed+1
return palind
lst = 'testset'
print lst, isPalin(lst)
lst = 'testsest'
print lst, isPalin(lst)
Output
testset True
testsest False

doesn't test all code when fixing my string index out range

Okay so the following code is supposed to test whether or not r and b are alternating. So a test of "rbrbrb" would be accepted but "rbbrbbr" would not be accepted.
However my issue is that only tests the first two under def manufactoria()
def manufactoria():
test(alternating_colors, "")
test(alternating_colors, "r")
test(alternating_colors, "rb")
test(alternating_colors, "rbrbrbr")
test(alternating_colors, "b")
test(alternating_colors, "brbr")
test(alternating_colors, "brbrbrbr")
def alternating_colors(string):
length = len(string)
check = 0
if len(string) == 0 or len(string)==1:
return True
while check <= len(string)-1:
if string[check]+string[check+1] == "rr" or string[check]+string[check+1] == "bb":
return False
check +=1
def test(fn, string):
if fn(string):
result = "accepted"
else:
result = "not accepted"
print('The string "' + string + '" is ' + result)
manufactoria()
Here is the corrected version:
def alternating_colors(s):
length=len(s)
if length<2:
return True
for i in range(length-1):
curr_slice = s[i:i+2]
if curr_slice in ["rr", "bb"]:
return False
return True
This is basically using most of what Prune answered.
An even better solution is using regular expressions. This will find any repetition of either r or b:
import re
def alternating_colors(s):
if re.search(r"r{2,}|b{2,}", s):
return False
return True
It doesn't check all of your code because the "index out of range" exception kills your program.
Your index is out of range because you tried to access position 2 of a string of length 2: "rb" has indices 0 and 1, but you tried to check string[1] + string[1+1]. You need to stop your checking loop one index earlier, as one commenter already mentioned.
You can make this program shorter and easier to maintain if you learn to use these Python language features:
< (less than operator)
for statement (replaces your while and
increment loop)
string slicing (instead of concatenating individual
characters)
in operator (instead of checking individual locations)

How can i fix the following Python code freeze issue?

I have a Python problem where i need to take input as a string in a function and need to return back a string where every alternate letter is a sequence of small case and Capital case. Ex: String passed to the function: AmsTerdam then the returned string should be AmStErDaM. It can start with any case i.e., small case or capital case.
I am still in learning phase of Python and have come up with the following but somehow when i try to execute, the code hangs. Could anyone please help me in fixing this?
def myfunc(NAME='AmsTerdam'):
leng=len(NAME)
ind=1
newlist=[]
while ind <= leng:
if ind%2==0:
newlist.append(NAME[ind-1].upper())
else:
newlist.append(NAME[ind-1].lower())
str(mylist) # Can we typecast a list to a string?
return newlist
OUT=myfunc('Ankitkumarsharma')
print('Output: {}'.format(OUT))
If the typecasting cannot be done, is the following correct?
def myfunc(NAME='AmsTerdam'):
leng=len(NAME)
ind=1
newstr=''
while ind <= leng:
if ind%2==0:
newstr=newstr+NAME[ind-1].upper()
else:
newstr=newstr+NAME[ind-1].lower()
return newstr
OUT=myfunc('AmsTerdam')
print('Output: {}'.format(OUT))
You have in essence, written a while true loop, without a break condition.
Going by your previous logic we can rewrite your loop and assume ind=1 being always the case, we get:
def myfunc(NAME='AmsTerdam'):
leng=len(NAME)
newstr=''
while 1 <= leng:
if ind%2==0:
newstr=newstr+NAME[ind-1].upper()
else:
newstr=newstr+NAME[ind-1].lower()
return newstr
Which means if len(name) > 1, the loop will run forever. Fixing that, we get the following function, which will terminate.
def myfunc(NAME='AmsTerdam'):
leng=len(NAME)
newstr=''
ind=1
while ind <= leng:
if ind%2==0:
newstr=newstr+NAME[ind-1].upper()
else:
newstr=newstr+NAME[ind-1].lower()
ind+=1
return newstr
def alternat_case(word):
word2 = []
for i in range(len(word)):
if i%2 ==0:
word2.append(word[i].upper())
else:
word2.append(word[i].lower())
word2 = "".join(word2)
return print(word2)
alternat_case("python")
PyThOn

How to write a function to count how many times a character occurs in a string?

This is what I have so far:
def count2(char,text):
if len(text)==0:
return 0
else:
if char==count2(char,text[:-1]):
return (1+count2(char,text[:-1]))
else:
return False
It will just go to false, but I am trying to count how many times "char" equals each character of "text."
Your base case looks correct. For your recursive case, lets take a look at the logic. There are two possible cases:
If the first character of the current string is the one you are looking for. In this case, you should return 1 + the count of the character in the rest of the string.
If the first character is not equal, then you should just return the count of the character in the rest of the string.
The function thus becomes
def count2(char,text):
if len(text)== 0:
return 0
count = 1 if text[0] == char else 0
return count + count2(char, text[1:])
Python has a neat way of treating True/False as 1/0, so you could simply write something like this:
def numberofcharacters(char, text):
if len(text) == 0:
return 0
return (text[-1] == char) + numberofcharacters(char, text[:-1])
def count2(char, text):
charCount = 0
for i in text:
if i == char:
charCount += 1
return(charCount)
Here's my two sense on the matter, a less complicated solution.
Best way to achieve this will be using string.count() function as:
>>> 'engineering'.count('e')
3
But I believe it is the part of some assignment. Since you are specific for using recursive function, below is the sample code to achieve this as:
def numberofcharacters(my_char, my_string):
if my_string:
if my_char == my_string[0]:
return 1 + numberofcharacters(my_char, my_string[1:])
else:
return numberofcharacters(my_char, my_string[1:])
else:
return 0
This solution can be further simplified as:
def numberofcharacters(my_char, my_string):
return ((my_char == my_string[0]) + numberofcharacters(my_char, my_string[1:])) if my_string else 0
Sample run:
>>> numberofcharacters('e','engineering')
3
Using a list comprehension makes things clear :
def numberofcharacters(my_char, my_string):
return len([c for c in my_string if c == my_char])

Create a new string out of the old string with python (1)

My function has three string parameters i.e. string, search, and replace. If the search parameter is an empty string, then the function is supposed to insert the replaceable parameter before the first parameter, in between each character of the old string, and after the last character of the old string. Here is what I have done so far:
def main():
s='I am going go'
x=""
y='aa'
print(rep_str(s,x,y))
def rep_str(s, x, y):
if x in s:
result = ''
i = 0
while i < len(s):
if s[i : i + len(x)] == x:
result += y
i += len(x)
else:
result += s[i]
i += 1
elif x not in s:
result= s
else:
if x=="":
result=y
for ch in s:
result+=(ch+y)
return result
main()
I developed each condition separately and put them altogether in the function when I got satisfactory result from them. My last else condition was working fine in a separate run but it is not working in the function module. I don't know what is the problem with the code.
I would appreciate, if someone could give me some pointers. Thanks
My output for the last else condition should be:
aaIaa aaaaamaa aagaaoaaiaanaagaa aagaaoaa
restructure you code:
if x=='':
pass
elif x in s:
pass
elif x not in s:
pass

Categories

Resources