I have a program that, simplified, looks like this:
def listAssign(lst,index,item):
"""Assigns item item to list lst at index index, returns modified list."""
lst[index] = item
return lst
def listInsert(lst,index,item):
"""Inserts item item to list lst at index index, returns modified list."""
lst.insert(index.item)
return lst
# ...
def listSurgery(lst,indices,f,*extraArgs):
"""Performs operation f on list lst at depth at indices indices, returns modified list."""
parent = lst
for index in indices[:-1]:
parent = parent[index]
parent = f(parent,indices[-1],*extraArgs)
return listSurgery(lst,indices[:-1],listAssign,parent)
# ...
def parseStringToList(s):
"""Takes in a user-input string, and converts it into a list to be passed into parseListToExpr."""
for c in s[:]: # Removes extra spaces from beginning of string
if c == ' ':
s = s[1:]
else:
break
for c in s[::-1]: # Removes spaces from end of string
if c == ' ':
s = s[:-1]
else:
break
l = [] # List to build from string; built by serially appending stuff as it comes up
b = True # Bool for whether the parser is experiencing spaces (supposed to be True if last character processed was a space)
t = False # Bool for whether the parser is experiencing a string of non-alphanumeric characters (supposed to be True if last character was a non-alphanumeric character)
lvl = 0 # Keeps track of depth at which operations are supposed to be occurring
for c in s:
if c == ' ': # If the character is a space, do nothing, but make sure that it's documented that the last character processed was a space
b = True
elif c == '(' or c == '[': # If the character is an opening parenthesis, add a new level of depth to the list, by appending another list to the lowest level and incrementing lvl
l = listSurgery(l,[-1]*(lvl+1),listInsert,[])
lvl += 1
if c == '[': # ] (left here for overzealous parsers) If the bracket is square, also append a comma as the first element of the appended list
l = listSurgery(l,[-1]*(lvl+1),listInsert,',')
elif c == ')' or c == ']': # If it's a closing parenthesis, make it stop paying attention to the list it's working on
lvl -= 1
elif c == ',': # If it's a comma, then append it to the list as a separate element and start a new string to append characters to
l = listSurgery(l,[-1]*(lvl+1),lambda x,y,z:listAssign(x,y,x[y]+z),[',',''])
elif not c.alnum(): # If it's non-alphanumeric and not any of the above, then append it to string that it's working on if it's a non-alphanumeric string
if not t: # If the string that it's working on isn't non-alphanumeric, then finish working on that string and append a new string to work on
l = listSurgery(l,[-1]*(lvl+1),listInsert,'')
l = listSurgery(l,[-1]*(lvl+1),lambda x,y,z:listAssign(x,y,x[y]+z),c)
t = True
else: # If the character is alphanumeric, append it to the string it's working on
assert c.isalnum()
if b or t: # If the string it's working on isn't alphanumeric or doesn't exist, append a new string
l = listSurgery(l,[-1]*(lvl+1),listInsert,'')
b, t = False, False
l = listSurgery(l,[-1]*(lvl+1),lambda x,y,z:listAssign(x,y,x[y]+z),c)
return l
# ...
cmds = {
'help':"List the available functions.",
'quit':"Quit this application.",
'exit':"Exit this application (exactly the same thing)."
}
print "MAT (Michael's Analysis Tool), version 0.0.0"
op = '' # Declare string to use for input
while op != 'exit' and op != 'quit': # Keep a REPL unless the user types "exit" or "quit", in which case exit
op = raw_input("> ")
if op == 'help':
print "The commands available in addition to free evaluation are:"
for item in cmds:
print ' ', item + ":", cmds[item]
elif op == 'quit' or 'exit':
pass
else:
print str(parseStringToList(op))
When I use help, quit, or exit as a command, it comes out fine. But when I give it any other kind of input like 1 + 1 = 2 (which should elicit ['1','+','1','=','2']) or This is a sentence. (which should elicit ['This','is','a','sentence','.'], it doesn't print anything, just asks for more input. (That is, it's functionally equivalent to the last line of this program getting replaced with continue.) And I don't understand why. parseStringToList is defined in a very straightforward manner. It should at least return [], the original value of the variable it returns. But instead it doesn't print anything. Why? (I'll try more thorough debugging tomorrow, but so far it's eluded my efforts.)
You need to change this:
elif op == 'quit' or 'exit':
to this
elif op == 'quit' or op == 'exit':
Related
So let's say I have a string, like this:
string = '12345+67890'
I want to go back to search for that plus, and add a letter 'H', so the end result would be like this:
string = '12345+h67890
Also, what if I want to get the latest +, so if there is two +'s, I want to get the last +?
Any help would be appreciated!
You could use reverse split to split on the last instance of +, then join with +H:
>>> '+H'.join('123+456+789'.rsplit('+',1))
'123+456+H789'
Convert into list, iterate through list, when you find the plus add an 'h' into the next index.
string = '12345+67890'
stringList = list(string)
i = 0
newString = ''
for i in range(len(stringList)):
if stringList[i] == '+':
stringList.insert(i+1,'h')
for letter in stringList:
newString += letter
print(newString)
Since you asked how to do it with if statements:
i = -1
for i in range(len(my_str)):
if my_str[i] == '+':
plus = i+1 # <- will update every time you see a + symbol
if i != -1:
my_str = my_str[:i] + 'h' + my_str[i:]
Alternatively, you can search backwards:
i = -1
for i in reversed(range(len(my_str))):
if my_str[i] == '+':
plus = i+1 # <- will update every time you see a + symbol
break
if i != -1:
my_str = my_str[:i] + 'h' + my_str[i:]
As others have mentioned you can use built-in functions like find and rfind. My personal choice is to refer to regular expressions for this type of thing:
import re
my_str = re.sub('(.*\+)(.*)',r"\1h\2", my_str))
when I run that code it comes out to me this error:
IndexError: string index out of range
I have no idea why I comes out to me this error and I don't have
any note but if you want to ask me about any thing don't hesitate
letters_string = "d g o"
letters_list = []
# Check Space
def convert_letters_to_list(word):
"""
This Function takes the letters from the users
and checks if users put more than one space
between letters if True It Removes The extra Spaces
"""
if word[0].isspace() == True:
convert_letters_to_list(word[1])
elif word[0].isalpha() == True:
letters_list.append((word[0])) + convert_letters_to_list(word[1:])
else:
convert_letters_to_list(word[1:])
convert_letters_to_list(letters_string)
print(letters_list)
You function is recursive so after a while, any letter index past 0 will be out of the original string.
Here is a fixed version of your code.
letters_string = "d g o"
letters_list = []
# Check Space
def convert_letters_to_list(word):
"""
This Function takes the letters from the users
and checks if users put more than one space
between letters if True It Removes The extra Spaces
"""
if word[0].isalpha() == True or (word[0].isspace() and not letters_list[-1].isspace()):
letters_list.append((word[0]))
if len(word) == 1:
return
convert_letters_to_list(word[1:])
convert_letters_to_list(letters_string)
print(letters_list)
I did an implementation on checking if whether a string has balanced parentheses or not using a STACK only. But I checked for balanced parentheses when the string has words. For example:
>>> is_paren_balanced("[{whoa (this is rough [how do I do this!])}]")
True
I was successful in doing that. However, I am not trying to check for a case if the string has NO parenthesis. And then i got this result:
>>> is_paren_balanced("Hi i love food.")
no parenthesis
True
>>> is_paren_balanced("[{whoa (this is rough [how do I do this!])}]")
no parenthesis
False
For the first result, I don't want the boolean result as thats kind of vague. I'm trying to show the user that the string has no parenthesis so it is neither True or False. I just want the print statement shown saying "no parentheses here" or whatever. For the second result, obviously just the boolean result and it shouldve returned True.
Any suggestions? I'm stumped.
Here is the code I'm practicing with:
from stack import Stack
def is_match(p1, p2):
if p1 == "(" and p2 == ")":
return True
elif p1 == "{" and p2 == "}":
return True
elif p1 == "[" and p2 == "]":
return True
else:
return False
def is_paren_balanced(paren_str):
s = Stack() #initialize a stack object
is_balanced = True #boolean flag: whether the str has balanced parenthesis or not
# then set to false if otherwise
index = 0 # keep track of where we are in the string
paren_str = paren_str.replace(" ", "") #accounts for possible spaces in the input
while index < len(paren_str) and is_balanced:
paren = paren_str[index]
if paren in "({[":
s.push(paren)
elif paren in ")}]":
if s.is_empty():
is_balanced = False
else:
top = s.pop()
if not is_match(top, paren):
is_balanced = False
else:
if paren not in "({[]})":
print("no parenthesis")
break
index += 1
if s.is_empty() and is_balanced:
return True
else:
return False
Sorry if it doesn't seem pythonic. I was just mostly exploring with this problem and will edit and improve later on.
You can use either regex or list comprehension to get the total amount of parenthesis first:
import re
def all_parenthesis(msg):
left = re.findall(r"[\[{(]",msg)
right = re.findall(r"[\]|})]",msg)
if not left and not right:
return "No parenthesis"
#or
def check_balance(msg):
d = {"[":"]",
"{":"}",
"(":")"}
left = [char for char in msg if char in d]
right = [char for char in reversed(msg) if char in d.values()]
#if not left not right...
But if you already constructed a list of parenthesis on both sides, why don't go ahead and compare them instead? Could be something like this:
def check_balance(msg):
d = {"[":"]",
"{":"}",
"(":")"}
left = [char for char in msg if char in d]
right = [char for char in reversed(msg) if char in d.values()]
if not left and not right:
return "No parenthesis"
elif len(left) != len(right):
return False
for a, b in zip(left,right):
if d.get(a) != b:
return False
return True
I wanted to test append in my small program. Unfortunately, if does the wrong thing.
Input format
A non-empty text in English, ending with a dot, is supplied to the input of the program (there are no other dot characters in the text).
Output format:
The original line and number on the new line is the number of letters 's' in a line.
init = input()
sentence = []
ses = 0
for i in range(len(init)):
if init[i] == '.':
break
elif init[i] == 's':
ses += 1
elif init[i] != '.' or init[i] == 's':
sentence.append(init[i])
print(''.join(sentence))
print(ses)
Input:
It is not a simple task. Yes!
Expected output:
It is not a simple task
3
But it does:
It i not a imple tak
3
You're forgetting to append the s's and full stops.
init = input()
sentence = []
ses = 0
for i in range(len(init)):
if init[i] == '.':
sentence.append(init[i])
break
elif init[i] == 's':
ses += 1
sentence.append(init[i])
elif init[i] != '.' or init[i] == 's':
sentence.append(init[i])
print(''.join(sentence))
print(ses)
the above should work perfectly
init = input()
Let's say the user typed:
init = 'something is sad.'
Then:
init = init.upper()
list_of_s = []
for letter in init:
if letter == "S":
list_of_s.append(letter)
print(init + str(len(list_of_s)))
First you should transform the input string all to upper letters to normalize the string (you could also user the method .lower()).
Then you define the variable list_of_s where you will store each s matched using append as you requested.
With Python you can iterate a string as if it was a list, each letter we check if it's equal to "S" and if it is we add one s to our list variable.
Finally we use len() to calculate the number of s in our list and print the desired output (we must first transform the number to a string using str()).
My code is about creating a password using the first character/digit of every word/number as a character in a sentence/phrase and printing it just as so.
Example: Stop and smell the 350 "roses". -> Sast3r. (Ignoring
quotations using r instead)
This would be very easy using lists, but you cannot use them in this assignment for my code. So, I don't know what to do now after what I have done so far
Function:
def create_password(phrase):
q = "'" # quotations
dq = '"' # double quotes
password = phrase[0]
for i in phrase:
x = phrase.find(" ")
if i.isalnum:
password += phrase[x + 1]
elif x == q or x == dq:
password += phrase[x + 2]
return password
Main:
# Imports
from credentials import create_password
# Inputs
phrase = str(input("Enter a sentence or phrase: "))
# Outputs
password = create_password(phrase)
print(password)
I think it is more straightforward to walk through the entire phrase without worrying about splitting on spaces. Instead keep track of whether or not you've just seen a space. You only want to add the character after just seeing a space.
def create_password(phrase):
q = "'" # quotations
dq = '"' # double quotes
#Initialize the password to be an empty string
password = ""
#We are at the start of a new word (want to add first index to password)
new_word = True
#Walk through every character in the phrase
for char in phrase:
#We only want to add char to password if the following is all true:
#(1) It's a letter or number
#(2) It's at the start of a new word
#(3) It's not a single quote
#(4) It's not a double quote
if char.isalnum and new_word:
if char != q and char != dq:
password += char
new_word = False #<-- After adding char, we are not at a new word
#If we see a space then we are going to be at a new word
elif char == " ":
new_word = True
return password
p = create_password('Stop and smell the 350 "roses"')
print(p)
Output:
Sast3r
You're definitely on the right track! Using the str.find() method is definitely the way to go!
However, you need to understand what the str.find() method does. Look at the signature:
str.find(sub [,start [,end) -> int
# sub -> character to find
# start -> where the function should start looking in the string
# end -> where the function should stop looking
# Returns a number, which is the place it found the character.
# If it didn't find anything, then return -1.
Without telling the function where to start, it will always find the first occurrence of the character in the string. It won't know that you're going through each character of the string.
So let's change it up a little bit:
for char_index in xrange(len(phrase)):
# Tell the method to look after char_index: we've already looked before this!
x = phrase.find(' ', char_index) index
if phrase[x+1].isalnum(): # It's a function, notice the brackets?
password += phrase[x + 1]
elif phrase[x+2] == q or phrase[x+2] == dq:
password += phrase[x + 2]
Hopefully, this should get your desired password.
Give priority to the use of built-in function, for example, every time you find the location of space, then why not directly in accordance with the space for spilt function, so that the string directly to the character list, each element is a word, and then remove each element in the list.
def create_password(phrase):
password = ''
phrase_list = phrase.split(' ')
print (phrase_list)
for i in phrase_list:
print (i[0])
password += i[0]
return password
if __name__ == '__main__':
# Inputs
phrase = str(input("Enter a sentence or phrase: "))
# Outputs
password = create_password(phrase)
print(password)
Try taking the first character in the string, and then every character that follows a space. It looks like you have the right idea.