i am adding str[1] that is causing one repeated element to be left but if donot do that string does not get printed. any solutions
def removeCD(str):
l = len(str)
if l == 0 or l == 1:
return str
if(str[0]==str[1]):
return str[1] + removeCD(str[2:])
else:
return str[0] + removeCD(str[1:])
string = input().strip()
print(removeCD(string))
When characters are equal, you again adding duplicate character. This should work:
def removeCD(str):
l = len(str)
if l == 0 or l == 1:
return str
if(str[0]==str[1]):
return removeCD(str[1:])
else:
return str[0] + removeCD(str[1:])
string = input().strip()
print(removeCD(string))
Here is the case analysis we need to perform -
If string length is less than two (base case), there is nothing to compare, simply return the string
Otherwise (by induction) the string is at least two characters long. If the first matches the second, drop the first letter and return the recursive result
Otherwise (by induction) the string is at least two characters long and the first two characters do not match. Return the first char combined with the recursive result.
This encodes to a python program in a straightforward way -
def remove_adjacent_dupes (s = ""):
if len(s) < 2:
return s
elif s[0] == s[1]:
return remove_adjacent_dupes(s[1:])
else:
return s[0] + remove_adjacent_dupes(s[1:])
print(remove_adjacent_dupes("bookkeeper"))
# bokeper
When the characters are equal, you should be recursing on everything but the first character:
if(str[0]==str[1]):
return removeCD(str[1:])
def remove(string):
l = len(string)
if l==0 or l==1:
return string
if string[0] == string[1]:
s = remove(string[1:])
return s
else:
s = remove(string[1:])
return string[0]+s
string = input().strip()
print(remove(string))
Related
My goal is to write a function which change every even letter into upper letter and odd to lower (space also count as a one element).
This is my code
def to_weird_case(s):
for i in s:
if len(i) % 2 == 0:
s[i] = i.upper() + s(i+1)
else:
s[i] = i.lower() + s(i+2)
return i
I think it should be quite correct, but it gives me error.
line 7, in to_weird_case
s[i] = i.lower() + s(str(i)+2)
TypeError: must be str, not int
EDIT:
I have a sugesstion but I don't know how to make it. I try it for myself and back here.
This needs to definitly explicietly state that the zero indexing uppercase is for each word.
Do you know guys how to make it?
So we can analyze your code and just explain what you typed:
def to_weird_case(s):
for i in s: # s is your string, and i is the actual character
if len(i) % 2 == 0: # if your length of the character can be divided by 2. Hmm this is weird
s[i] = i.upper() + s(i+1) # s[i] change a character in the string but you should provide an index (i) so an integer and not a character. But this is not supported in Python.
else:
s[i] = i.lower() + s(i+2)
return i # This will exit after first iteraction, so to_weird_case("this") will return "t".
So what you need to is first create a output string and fill that. And when iteration over s, you want the index of the char and the char value itself.
def to_weird_case(s):
output = ""
for i, myChar in enumerate(s):
if i % 2 == 0:
output += myChar.upper()
else:
output += myChar.lower()
return output
my_sentence = "abcdef"
print(to_weird_case(my_sentence))
And when you want to ignore spaces, you need to keep track of actual characters (excluding spaces)
def to_weird_case(s):
output = ""
count = 0
for myChar in s:
if myChar.isspace():
output += myChar
else:
if count % 2 == 0:
output += myChar.upper()
else:
output += myChar.lower()
count += 1
return output
my_sentence = "abc def"
print(to_weird_case(my_sentence))
Test this yourself
def to_weird_case(s):
for i in s:
print (i)
After doing this you will find that i gives you characters.
if len(i) % 2 == 0:
This line is incorrect as you are trying to find the length of a single character. len(s) would be much better.
So the code will be like
def to_weird_case(s):
s2 = "" #We create another string as strings are immutable in python
for i in range(len(s)):
if i % 2 == 0:
s2 = s2 + s[i].upper()
else:
s2 = s2 + s[i].lower()
return s2
From #RvdK analysis, you'ld have seen where corrections are needed. In addition to what has been pointed out, I want you to note that s[i] will work fine only if i is an integer, but in your case where (by assumption) i is a string you'll encounter several TypeErrors. From my understanding of what you want to do, it should go this way:
def to_weird_case(s):
for i in s:
if s.index(i) % 2 == 0:
s[s.index(i)] = i.upper() + s[s.index(i)]
elif s.index(i) % 2 == 1:
s[s.index(i)] = i.lower() + s[s.index(i)]
return i # or possibly return s
It is possible to do in a single line using a list comprehension
def funny_case(s):
return "".join([c.upper() if idx%2==0 else c.lower() for idx,c in enumerate(s)])
If you want to treat each word separately then you can split it up in to a list of words and "funny case" each word individually, see below code
original = "hello world"
def funny_case(s):
return "".join([c.upper() if idx%2==0 else c.lower() for idx,c in enumerate(s) ])
def funny_case_by_word(s):
return " ".join((funny_case(word) for word in s.split()))
print(funny_case_by_word(original))
Corrected code is as follows
def case(s):
txt=''
for i in range(len(s)):
if i%2==0:
txt+=s[i].upper()
else:
txt+=s[i].lower()
return txt
String assignment gives error in Python therefore i recommend considering my approach
When looping over elements of s, you get the letter itself, not its index. You can use enumerate to get both index and letter.
def to_weird_case(s):
result = ''
for index, letter in enumerate(s):
if index % 2 == 0:
result += letter.upper()
else:
result += letter.lower()
return result
correct code:
def to_weird_case(s):
str2 = ""
s.split() # through splitting string is converted to list as it is easy to traverse through list
for i in range(0,len(s)):
n = s[i] # storing value in n
if(i % 2 == 0):
str2 = str2 + n.upper()
else:
str2 = str2 + n.lower()
return str2
str1 = "hello world"
r = to_weird_case(str1)
print(r)
Write a function repfree(s) that takes as input a string s and checks whether any character appears more than once. The function should return True if there are no repetitions and False otherwise.
I have tried this but I don't feel this is an efficient way of solving it. Can you suggest an efficient code for this, thanks?
def repfree(s):
newlist = []
for i in range(0, len(s)):
newlist.append(s[i])
newlist2 = set(newlist)
if len(newlist) == len(newlist2):
print("True")
else:
print("False")
One easy way to meet this requirement is to use regular expressions. You may not be allowed to use them, but if you can, then consider this:
def repfree(s):
if re.search(r'^.*(.).*\1.*$', s):
print("True")
else:
print("False")
Believe it or not, this problem can be solved in O(1) time, because every sufficiently large string contains at least one duplicate character. There are only a finite number of different Unicode characters, after all, so a string cannot be arbitrarily long while also using each Unicode character at most once.
For example, if you happen to know that your strings are formed of only lowercase letters, you can do this:
def has_repeated_char(s):
return len(s) > 26 or len(s) != len(set(s))
Otherwise you can replace the 26 with whatever number of characters your string could possibly contain; e.g. 62 for upper- and lowercase letters and digits.
As of February 2020, the whole of Unicode has 137,994 distinct characters (Wikipedia), so if your string length is 150,000 then you can return True without searching.
Try
chars = 'abcdefghijklmnopqrstuvwxyz'
def repfree(s):
for char in chars:
count = s.count(char)
if count > 1:
return False
return True
But, this is a long way as it scans the list 26 times. A much better and Pythonic way would be
import collections
def repfree(s):
results = collections.Counter(s)
for i in results:
if results[i] > 1:
return False
return True
Here, results is a dictionary that contains all the characters of s as key, and their respective frequency as value. Further, it is checked if any value is greater than 1, repetition has occurred.
You could split the string characters to a set and compare the length
def repfree(s):
se = set(string)
print(len(se) == len(s))
You can make your approach more efficient by removing the for loop.
len(s) == len(set(s))
Otherwise, try using any
any(s.count(c) > 1 for c in s)
You could do this way:
Method 1:
def repfree(s):
if len(set(s)) == len(s):
return True
return False
Method 2:
def repfree(s):
return len(set(s)) == len(s)
Why set?
set will return the list of all unique characters in the string in sorted order
Example :
set('shubham')
Output:
{'a', 'b', 'h', 'm', 's', 'u'}
So,if a character in a string appears more than once,it will not be equal to the length of string itself.
def repfree(str):
l=list(str)
for i in range(len(l)):
check=str.count(l[i])
if check>1:
flag=1
else:
flag=0
if(flag==1):
return False
else:
return True
def matched(s):
stack = []
for char in s:
if char == '(':
stack.append(char)
elif char == ')':
if not stack:
return False
stack.pop()
return not stack
I am creating a function that takes in a string and returns a matching string where every even letter is uppercase and every odd letter is lowercase. The string only contains letters
I tried a for loop that loops through the length of the string with an if statement that checks if the index is even to return an upper letter of that index and if the index is odd to return a lowercase of that index.
def my_func(st):
for index in range(len(st)):
if index % 2 == 0:
return st.upper()
else:
return st.lower()
I expected to have even letters capitalize and odd letter lowercase but I only get uppercase for the whole string.
Some issues in your code:
Currently you are returning from the function on the first index itself, i.e index=0 when you do return st.lower(), so the function will stop executing after it encounters the first index and breaks out of the for loop
Doing st.lower() or st.upper() ends up uppercasing/lowercasing the whole string, instead you want to uppercase/lowercase individual characters
One approach will be to loop over the string, collect all modified characters in a list, convert that list to a string via str.join and then return the result at the end
You also want to refer to each individual characters via the index.
def my_func(st):
res = []
#Iterate over the character
for index in range(len(st)):
if index % 2 == 0:
#Refer to each character via index and append modified character to list
res.append(st[index].upper())
else:
res.append(st[index].lower())
#Join the list into a string and return
return ''.join(res)
You can also iterate over the indexes and character simultaneously using enumerate
def my_func(st):
res = []
#Iterate over the characters
for index, c in enumerate(st):
if index % 2 == 0:
#Refer to each character via index and append modified character to list
res.append(c.upper())
else:
res.append(c.lower())
#Join the list into a string and return
return ''.join(res)
print(my_func('helloworld'))
The output will be
HeLlOwOrLd
You can store your operations beforehand and use them in join with enumerate:
def my_func(st):
operations = (str.lower, str.upper)
return ''.join(operations[i%2](x) for i, x in enumerate(st))
print(my_func('austin'))
# aUsTiN
Tweaking your code a bit, You can use the 'enumerate' and keep appending to the string based on the condition evaluations( for me this was easier since I have been coding in java :))
def myfunc(st):
str=''
for index, l in enumerate(st):
if index % 2 == 0:
str+=l.upper()
else:
str+=l.lower()
return str
def myfunc(str):
rstr = ''
for i in range(len(str) ):
if i % 2 == 0 :
# str[i].upper()
rstr = rstr + str[i].upper()
else:
#str[i].lower()
rstr = rstr + str[i].lower()
return rstr
l = 'YourString'
li=[]
for index,i in enumerate(l):
if index % 2 == 0:
i=i.lower()
li.append(i)
elif index % 2 == 1:
i=i.upper()
li.append(i)
print(''.join(li))
Use this enumerate method to perform your operation
return will terminate your function, so there isn't much point of the loop
st is the whole string, so st.upper() will yield the whole string in upper case.
You can use a bitwise and (&) to check for odd positions. The enumerate function will give you both the positions and the characters so you can easily use it in a list comprehension:
def upLow(s):
return "".join(c.lower() if i&1 else c.upper() for i,c in enumerate(s))
upLow("HelloWorld") # HeLlOwOrLd
The below code should do what you are looking for.
def myfunc(name):
str=""
lc=1;
for character in name:
if(lc%2==0):
str+=character.upper()
else:
str+=character.lower()
lc+=1
return str
def myfunc(a):
newString = ''
for count, ele in enumerate(a, 0):
if count %2 == 0:
newString += (a[count].lower())
else:
newString += ((a[count].upper()))
return newString
You can deconstruct string into collection of characters, apply transformations and reconstruct string back from them
Logic:
First enumerate() over the string to generate key-value pairs of characters and their positions
Then use comprehensions to loop over them and use conditional statement to return odd position characters in lower() case and even position in upper()
Now you have the list ready. Just join() it with an empty string '' to convert the list into a string
Code:
str = 'testing'
''.join([y.upper() if x%2 ==0 else y.lower() for x,y in enumerate(str)])
here we just have to add the num written to the previous character ascii value .
I tried that
if __name__ == '__main__':
n = input()
list1 = list(n)
for i in list1:
if list1[i] is not chr:
list1[i] = list1[i-1] + list1[i]
print(list(n))
This approach has the advantage to not use a list. It stores the previous char in the prev variable to use in case of a digit.
text = 'a2c3d'
result = ''
prev = None
for ch in text:
if ch.isdigit() and prev:
result += chr(int(ch) + ord(prev))
else:
result += ch
prev = ch
print(result)
You iterate the given string, if it is a character you add it to a list. if not you take the ord() of the last char in your list and add the number. you stick all together at the end:
def change(t):
rv = [] # accumulates all characters
for c in t: # iterate all characters in t
if c.isdigit(): # if a digit
if not rv: # and no characters in rv: error
raise ValueError("Cant have number before character")
rv.append(chr(ord(rv[-1])+int(c))) # else append the number to the last char
else:
rv.append(c) # not a number, simply append
return ''.join(rv) # join all characters again
print(change("a2c3d"))
Output:
accfd
I have a function that decrements a whole number parameter represented by a string. For instance, if I pass in the string "100", it should return "99."
def dec(s):
i = len(s) - 1
myString = ""
while (i >= 0):
if s[i] == '0':
s[i] = '9'
i -= 1
else:
s[i] = chr(int(s[i]) - 1)
break
return s
However, Python issues this error.
s[i] = '9'
TypeError: 'str' object does not support item assignment
I am assuming that s[i] cannot be treated as an lvalue. What is a solution around this?
You can do:
s = s[:i] + "9" + s[i+1:]
This takes the part of the string before character index i, appends a 9, then appends the part of the string after character index i. However, doing a lot of string appends like this is not terribly efficient.
The other answer is that if you're dealing with numbers, why not actually use numbers instead of strings?
def dec(s):
return str(int(s) - 1)
Strings aren't mutable, but lists are. You can easily convert the string to a list of individual characters:
l = list(s)
Then convert it back:
s = ''.join(l)
Since you're working with a numeric string there are more direct approaches, but this answer works for the general case.
You can't. In Python, strings are immutable -- once created, they can't be changed.
You have two options without changing your function entirely.
Convert the string to a list and back:
def dec(s):
s = list(s)
i = len(s) - 1
myString = ""
while (i >= 0):
if s[i] == '0':
s[i] = '9'
i -= 1
else:
s[i] = chr(int(s[i]) - 1)
break
return ''.join(s)
Create a new string each time you want to make a change:
def dec(s):
i = len(s) - 1
myString = ""
while (i >= 0):
if s[i] == '0':
s = s[:i] + "9" + s[i+1:]
i -= 1
else:
s = s[:i] + chr(int(s[i]) - 1) + s[i+1:]
break
return s
I'm not sure why you are playing with the string character by character. Isn't this simpler?
def decrement_string(s):
try:
i = int(s)
i = i - 1
return str(i)
except:
# do something else
return "that's no number!"
while True:
s = raw_input("give me a number and I'll decrement it for you: ")
print decrement_string(s)
The solution to your specific problem of "decrementing" strings is to convert s to an int with int(s), decrease that, and convert back to a str: str(int(s)-1).
In [175]: str(int('100')-1)
Out[175]: '99'
The general solution is to not attempt to alter the elements of a string; use some other type to represent your work, and convert to a string as the last step.
Python strings are immutable so you cannot modify them. You have to create a new string that contains the value that you need. You are better off converting the string to an integer, decrementing it, and then converting it back to an integer again.
The reason for immutable strings is primarily efficiency.