How can I change upper case to lower and vice versa? - python-3.x

I am playing around with a small script, just for fun. I'm trying to reverse the items in a string and witch the upper case to lower and lower to upper. The reverse part works, but the case part doesn't. What am I doing wrong here?
def reverse(s):
if len(s) == 0:
return s
else:
if s.lower():
s.upper()
else:
s.lower()
return reverse(s[1:]) + s[0]
mytxt = reverse("I wonder how this text looks like Backwards")
print(mytxt)
Here is my current output.
sdrawkcab ekil skool txet siht woh rednow I

str.lower does not return a boolean of whether it's lowercase or not. It returns a string in lowercase. It also doesn't change a string in place.
Since that is the case you need to check the character you are currently interested in.
In this case s[0]. Additionally, strings aren't mutable so you can't change them in place. You'll need a temp variable.
def reverse(s):
if len(s) == 0:
return s
else:
# The character of interest
char = s[0]
# If it's equal to the lowercase version of it
if char == char.lower():
# Change it to upper
char = char.upper()
else:
# and vice versa
char = char.lower()
return reverse(s[1:]) + char
mytxt = reverse("I wonder how this text looks like Backwards")
print(mytxt)

s.lower() and s.upper() do not modify s but instead return another string with all letters converted to lowercase or uppercase, respectively. They don't return booleans, either (which is done by s.islower() and s.isupper()).
If you want to rewrite s, you must construct a new string from the return values.
def reverse(s):
if len(s) == 0:
return s
else:
s0 = s[0]
if s0.islower():
s0 = s0.upper()
elif s0.isupper():
s0 = s0.lower()
return reverse(s[1:]) + s0
mytxt = reverse("I wonder how this text looks like Backwards")
print(mytxt)
Here I checked for both islower and isupper, because both return False in the absence of cased characters (e.g. "0".islower() and "0".isupper() are both false).

str.lower() and str.upper() return a copy of the string converted to lower and upper case. To check whether a string is lower or uppercase, use str.islower() and str.isupper()
Python also has str.swapcase() to do exactly what you want.
Reversing a string can be done simply by using the slice notation, no need for recursion or loops. Your code could be simplified to something like:
def swapcasereverse(s):
return s[::-1].swapcase()
If you want to write your own code for swapcase as an exercise, here's a pythonic way:
def swapcasereverse(s):
newlist = [c.upper() if c.islower() else c.lower() for c in reversed(s)]
return "".join(newlist)
This function uses a list comprehension to
iterate over s in reverse order, with each character going in c
if c is lowercase, adds c.upper() to the list
otherwise, adds c.lower() to the list
Joins the list with "" to make a string, returns the joined string

def reverse(s):
if len(s) == 0:
return s
else:
if s.lower():
s.upper()
else:
s.lower()
return reverse(s[1:]) + s[0]
mytext = reverse("I wonder how this text looks like Backwards").swapcase()
print(mytext)

Related

Replace string only if all characters match (Thai)

The problem is that มาก technically is in มาก็. Because มาก็ is มาก + ็.
So when I do
"แชมพูมาก็เยอะ".replace("มาก", " X ")
I end up with
แชมพู X ็เยอะ
And what I want
แชมพู X เยอะ
What I really want is to force the last character ก็ to count as a single character, so that มาก no longer matches มาก็.
While I haven't found a proper solution, I was able to find a solution. I split each string into separate (combined) characters via regex. Then I compare those lists to each other.
# Check is list is inside other list
def is_slice_in_list(s,l):
len_s = len(s) #so we don't recompute length of s on every iteration
return any(s == l[i:len_s+i] for i in range(len(l) - len_s+1))
def is_word_in_string(w, s):
a = regex.findall(u'\X', w)
b = regex.findall(u'\X', s)
return is_slice_in_list(a, b)
assert is_word_in_string("มาก็", "พูมาก็เยอะ") == True
assert is_word_in_string("มาก", "พูมาก็เยอะ") == False
The regex will split like this:
พู ม า ก็ เ ย อ ะ
ม า ก
And as it compares ก็ to ก the function figures the words are not the same.
I will mark as answered but if there is a nice or "proper" solution I will chose that one.

Python3: Midnumeral Strings to Rightnumeral Strings

My attempt:
m = str(input())
# m = list(m)
w = ""
r = ""
num = [int(i) for i in m.split() if i.isdigit()]
for c in range(0,len(m)-1):
if m[len(m)-1]:
for num in w:
if num.isnumeric():
w.remove(num)
num.join(r)
elif m[c].isalpha():
r.join(m[c])
elif m[c].isnumeric() and (len(w)==0 or w[c]=='('):
w.join(m[c])
elif len(num)!=0:
try:
if int(m[c])>int(w[c]):
w.join(m[c])
else:
n = [int(i) for i in w.split() if i.isdigit()]
if len(n)!=0:
r = ''.join([str(elem) for elem in w])
except:
continue
elif m[c]==')':
for number in m:
if number.isnumeric():
w+=number
elif number=='(':
m.remove('(')
m.remove(')')
break
elif (w[c]=='(') or ((int(w[c]))<(int(m[c]))) or (w=""): # In this statement it gives an invalid syntax error
w = m[c]
else:
break
print(r)
I would like to know why get a invalid syntax at line 34 (elif statement).
Also, would like to know if there is any better way to solve this question.
Thanks
QUESTION:
Midnumeral Strings to Rightnumeral Strings
Midnumeral string is a string which contains one number in between letters. For example, a1b2c is a midnumeral string. A midnumeral strings may contain letters a to z, numbers 1 to 9 and both left and the right parentheses.
Rightnumeral string is a string which can be formed from midnumeral string:
(i) All the characters except left and right parenthesis in the midnumeral string is present in rightnumeral string.
(ii) A number ‘n’ which is between letters ‘a’ anb ‘b’ in the midnumeral string will appear in the right hand of side of the letters ‘a’ and ‘b’ in rightnumeral string in a particular fashion.
(iii)During the process of conversion of a midnumeral string to a rightnumeral string, a waiting stream is used.
Given a midnumeral string ‘m’ it can be converted to a rightnumeral string ‘r’ as follows:
i. Process character by character of midnumeral string ‘m’.
ii. When a letter is seen add it to rightnumeral string ‘r’.
iii. When a number ‘n’ is seen and waiting stream is empty or the recently added character to waiting stream is left parenthesis then add ‘n’ to waiting stream
iv. If a number ‘n’ seen and there are some numbers in the waiting stream then, If the recently added numeral in waiting stream is less than ‘n’ then add ‘n’ to waiting stream, Otherwise process waiting stream from most recent to least recent:-Remove number from waiting stream and add it to ‘r’
Repeat part (i), until the recent value available in waiting stream is less than ‘n’ or the recent character the waiting stream is left parenthesis or the waiting stream becomes empty
v. Add ‘n’ to the waiting stream
vi. If a left parenthesis is seen then add it to waiting stream
vii. When right parenthesis is seen then remove all numbers from most recent to least recent from waiting stream and add it to r till left parenthesis is seen. Discard left and right parenthesis
viii. When the end of the midnumeral ‘m’ string is reached remove all numerals from most recent to least recent from waiting stream and add it to right numeral string ‘r’
For example,
a1b2c will be abc21
a2b1c will be ab2c1
(a1b)2c will be ab1c2
a1b4(c5d2e)7f will be abcd5e2f741
Note: All the characters in the midnumeral will be distinct and only valid input is given
Input Format
First line contains the midnumeral string, m
Output Format
First line should contain the rightnumeral string, r
.1 The Syntax error
It is simple a missing '=' sign, so change it to this
elif (w[c]=='(') or ((int(w[c]))<(int(m[c]))) or (w==""):
w = m[c]
else:
break
.2 Code improvements & Best practices
I suggest you for this to post the answer on Code Review as is meant for this. There are quite few errors and not best practices follow.
For instance, this error block:
try:
if int(m[c])>int(w[c]):
w.join(m[c])
else:
n = [int(i) for i in w.split() if i.isdigit()]
if len(n)!=0:
r = ''.join([str(elem) for elem in w])
except:
continue
The except is catching too many types of error, better like:
try:
if int(m[c])>int(w[c]):
w.join(m[c])
else:
n = [int(i) for i in w.split() if i.isdigit()]
if len(n)!=0:
r = ''.join([str(elem) for elem in w])
except ValueError:
continue
Have a look at Should I always specify an exception type in except statements? for more information about this. Also there is too much 'logic' in that try block. but for simplicity that is ok.
EDIT
Consideration
Note that I used different combination of sets ( accepted_numbers, accepted_chars, left_parenthesis, right_parenthesis) instead of list of other thing, this is because set are super fast when used for Looks up, more info --> Time complexity of python set operations?. And also is very clear what you are trying to use them for.
The Variable r, is way better decision to use it during the Algorithm as a List and Then turn it as a String, that's because is just easier to manipulate.
I don't even used 1 try except block, this is because, is was clear what to do, I mean we knew it ahead, so you can just handle it with a if else block, apart of what I stated Above regarding the Try blocks, another important aspect is that the slow down the code if finds and exception (in this code it won't even matter) look here try-except vs If in Python
The Algorithm problem that you posted uses and demands a Stack as a Collection, you can see it implemented in the process_waiting_stream() function
in a LIFO (last in, first out) fashion.
process_waiting_stream()
Answer Testing one case
m = '(a1b)2c' # test string Added on the top as requested in the exercise
import string # If you don't want to import string, just hard code the letters
m = m
r = []
# ----- CONSTANTS
accepted_numbers = {str(i) for i in range(1, 10)} # 1 to 9
accepted_chars = {*string.ascii_lowercase}
left_parenthesis = '('
right_parenthesis = ')'
parenthesis = {left_parenthesis, right_parenthesis}
midnumeral_string = accepted_numbers | accepted_chars | parenthesis
# ---- NOTE: Run a quick check is Input is Correct |!(a1b)2c or (a1b)0c is not good
for char in m:
if char in midnumeral_string:
pass
else:
print('Input String is not a Midnumeral string')
continue
# ---------------------------
WAITING_STREAM = []
r = [] # Use a list, not a string, easier to work with :)
def process_waiting_stream():
global WAITING_STREAM
if WAITING_STREAM:
WAITING_STREAM.reverse() # LIFO from most recent to least recent
while True:
if not WAITING_STREAM:
break
item = WAITING_STREAM[0]
if item == left_parenthesis:
break
elif item in accepted_numbers:
item = WAITING_STREAM.pop(0)
r.append(item)
WAITING_STREAM.reverse()
def checK_stream(): # NOTE: We check this in case there is only '(' and not a num
return any([item in accepted_numbers for item in WAITING_STREAM])
for char in m:
if WAITING_STREAM:
recently_added = WAITING_STREAM[-1]
if char in accepted_chars:
r.append(char)
elif char in accepted_numbers:
if not WAITING_STREAM or recently_added == left_parenthesis:
WAITING_STREAM.append(char)
elif checK_stream():
if (recently_added not in parenthesis
and recently_added not in accepted_chars) and int(recently_added) < int(char):
WAITING_STREAM.append(char)
else:
process_waiting_stream()
WAITING_STREAM.append(char)
else:
WAITING_STREAM.append(char)
elif char == left_parenthesis:
WAITING_STREAM.append(char)
elif char == right_parenthesis:
process_waiting_stream()
for item in WAITING_STREAM:
if item == left_parenthesis:
left_para = WAITING_STREAM.index(left_parenthesis)
WAITING_STREAM.pop(left_para)
break
process_waiting_stream()
r = ''.join(r)
print(r)
Answer 2
Testing All cases
import string # If you don't want to import string, just hard code the letters
def rightnumeral_string(m):
# ----- CONSTANTS
accepted_numbers = {str(i) for i in range(1, 10)} # 1 to 9
accepted_chars = {*string.ascii_lowercase}
left_parenthesis = '('
right_parenthesis = ')'
parenthesis = {left_parenthesis, right_parenthesis}
midnumeral_string = accepted_numbers | accepted_chars | parenthesis
# ---- NOTE: Run a quick check is Input is Correct |!(a1b)2c or (a1b)0c is not good
for char in m:
if char in midnumeral_string:
pass
else:
print('Input String is not a Midnumeral string')
continue
# ---------------------------
WAITING_STREAM = []
r = [] # Use a list, not a string, easier to work with :)
def process_waiting_stream():
nonlocal WAITING_STREAM
if WAITING_STREAM:
WAITING_STREAM.reverse() # LIFO from most recent to least recent
while True:
if not WAITING_STREAM:
break
item = WAITING_STREAM[0]
if item == left_parenthesis:
break
elif item in accepted_numbers:
item = WAITING_STREAM.pop(0)
r.append(item)
WAITING_STREAM.reverse()
def checK_stream(): # NOTE: We check this in case there is only '(' and not a num
return any([item in accepted_numbers for item in WAITING_STREAM])
# ------ Iterate Through each Character (number included) in the string
for char in m:
if WAITING_STREAM:
recently_added = WAITING_STREAM[-1]
if char in accepted_chars:
r.append(char)
elif char in accepted_numbers:
if not WAITING_STREAM or recently_added == left_parenthesis:
WAITING_STREAM.append(char)
elif checK_stream(): # Check if there are currently nums in stream
if (recently_added not in parenthesis
and recently_added not in accepted_chars) and int(recently_added) < int(char):
WAITING_STREAM.append(char)
else:
process_waiting_stream()
WAITING_STREAM.append(char)
else:
WAITING_STREAM.append(char)
elif char == left_parenthesis:
WAITING_STREAM.append(char)
elif char == right_parenthesis:
process_waiting_stream()
# Last Step is to Remove left_parenthesis
for item in WAITING_STREAM:
if item == left_parenthesis:
left_para = WAITING_STREAM.index(left_parenthesis)
WAITING_STREAM.pop(left_para)
break
process_waiting_stream()
r = ''.join(r)
return r
print(rightnumeral_string('a1b2c'))
print(rightnumeral_string('a2b1c'))
print(rightnumeral_string('(a1b)2c'))
print(rightnumeral_string('a1b4(c5d2e)7f'))
# Checking if the Answer Are correct
assert rightnumeral_string('a1b2c') == 'abc21'
assert rightnumeral_string('a2b1c') == 'ab2c1'
assert rightnumeral_string('(a1b)2c') == 'ab1c2'
assert rightnumeral_string('a1b4(c5d2e)7f') == 'abcd5e2f741'
Documentation
string
Iterating each character in a string using Python
What is the use of “assert” in Python?

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

How can I make my function work for any number?

I am having some issues with some code I wrote for this problem:
“Write a function namedd calc that will evaluate a simple arithmetic expression. The input to your program will be a string of the form:
operand1 operator operand2
where operand1 and operand2 are non-negative integers and operator is a single-character operator, which is either +, -, or *. You may assume that there is a space between each operand and the operator. You may further assume that the input is a valid mathemat- ical expression, i.e. your program is not responsible for the case where the user enters gibberish.
Your function will return an integer, such that the returned value is equal to the value produced by applying the given operation to the given operands.
Sample execution:
calc("5 + 10") # 15
“You may not use the split or eval functions in your solution.
Hint: the hard part here is breaking the input string into its three component. You may use the find and rfind functions to find the position of the first and last space, and then use the slice operator (that is, s[startindex:endindex]) to extract the relevant range of characters. Be careful of off-by-one errors in using the slice operator.
Hint: it’s best to test your code as you work. The first step should be to break the input string into its three components. Write a program that does that, have it print out the operator and the two operands on separate lines, and test it until you are convinced that it works. Then, modifying it to perform the desired mathematical operation should be straightforward. Test your program with several different inputs to make sure it works as you expect.”
Here is my code:
def calc(exp):
operand1 = int(exp[:1])
operand2 = int(exp[4:6])
operator = exp[2:3]
if(operator == "+"):
addition = operand1+operand2
return addition
if(operator == "-"):
subtraction = operand1-operand2
return subtraction
if(operator == "*"):
multiplication = operand1*operand2
return multiplication
print(calc("5 + 10"))
print(calc("4 - 8"))
print(calc("4 * 3"))
My code does not fully meet the criteria of this question. It only works for single digit numbers. How can I make my code work for any number?
Like:
“504 + 507”
”5678 + 76890”
and so on?
Thank you. Any help is appreciated.
As the hint says, get the position of the first and last space of the expression, use it to extract the operand and the operators, and then evaluate accordingly.
def calc(exp):
#Get the position for first space with find
low_idx = exp.find(' ')
#Get the position for last space with rfind
high_idx = exp.rfind(' ')
#Extract operators and operand with slice, converting operands to int
operand1 = int(exp[0:low_idx])
operator = exp[low_idx+1:high_idx]
operand2 = int(exp[high_idx:])
result = 0
#Evaluate based on operator
if operator == '+':
result = operand1 + operand2
elif operator == '-':
result = operand1 - operand2
elif operator == '*':
result = operand1 * operand2
return result
print(calc("5 + 10"))
print(calc("4 - 8"))
print(calc("4 * 3"))
print(calc("504 + 507"))
print(calc("5678 + 76890"))
#15
#-4
#12
#1011
#82568
The answer is in the specification:
You may use the find and rfind functions to find the position of the first and last space, and then use the slice operator (that is, s[startindex:endindex]) to extract the relevant range of characters.
find and rfind are methods of string objects.
You could split it into three components using this code: (note: this doesn't use split or eval)
def splitExpression(e):
numbers = ["1","2","3","4","5","6","7","8","9","0"] # list of all numbers
operations = ["+","-","*","/"] # list of all operations
output = [] # output components
currentlyParsing = "number" # the component we're currently parsing
buildstring = "" # temporary variable
for c in e:
if c == " ":
continue # ignore whitespace
if currentlyParsing == "number": # we are currently parsing a number
if c in numbers:
buildstring += c # this is a number, continue
elif c in operations:
output.append(buildstring) # this component has reached it's end
buildstring = c
currentlyParsing = "operation" # we are expecting an operation now
else:
pass # unknown symbol!
elif currentlyParsing == "operation": # we are currently parsing an operation
if c in operations:
buildstring += c # this is an operation, continue
elif c in numbers:
output.append(buildstring) # this component has reached it's end
buildstring = c
currentlyParsing = "number" # we are expecting a number now
else:
pass # unknown symbol!
if buildstring: # anything left in the buffer?
output.append(buildstring)
buildstring = ""
return output
Usage: splitExpression("281*14") returns ["281","*","14"]
This function also accepts spaces between numbers and operations
You can simply take the string and use the split method for the string object, which will return a list of strings based on some separator.
For example:
stringList = "504 + 507".split(" ")
stringList will now be a list such as ["504", "+", "507"] due to the separator " " which is a whitespace. Then just use stringList[1] with your conditionals to solve the problem. Additionally, you can use int(stringList[0]) and int(stringList[2]) to convert the strings to int objects.
EDIT:
Now I realized that your problem said to use find() instead of split(). Simply use the logic above but instead find(" ") the first whitespace. You will then need to find the second whitespace by slicing past the first whitespace using the two additional arguments available for find().
You need to split the string out instead of hard coding the positions of the indexes.
When coding you want to try to make your code as dynamic as possible, that generally means not hard coding stuff that could be a variable or in this case could be grabbed from the spaces.
Also in the if statements I modified them to elif as it is all one contained statement and thus should be grouped.
def calc(exp):
vals = exp.split(' ')
operand1 = int(vals[0])
operand2 = int(vals[2])
operator = vals[1]
if operator == '+':
return operand1+operand2
elif operator == '-':
return operand1-operand2
else:
return operand1*operand2

Statement has no effect(Python)

program to get a string from a given string where all occurrences of its first char have been changed to '$', except the first char itself.
Sample String : 'restart'
Expected Result : 'resta$t'
here's my code
def change(string):
string_len = len(string)
t = string[0]
for each in range(1, string_len):
if each is t:
each == '$'
else:
continue
return string
print(change("restart"))
output
restart
i'using Pycharm. Line no 6 (each == '$')says this statement has no effect. i don't want to use replace method. just want to know what is the problem.
Your code commented:
def change(string):
string_len = len(string)
t = string[0]
for each in range(1, string_len):
if each is t: # To compara strings you should use the == operator not the 'is' operator.
each == '$' # This will not have any effect because is a temporal variable visible just inside the 'for' loop and you are not using it.
else:
continue
return string
print(change("restart"))
A solution could be:
def change(s):
result = ''
for character in s:
result += '$' if character == s[0] else character
return result
print(change('restart'))
Python strings are immutable objects, so you can't do 'aaa'[1] = 'b' to get aba.
each is set to an integer and you are comparing it to a string.

Resources