where have i gone wrong in the following python code : - python

To do:
Convert python to ythonpay (i.e. pick up a first letter, put it in the end and add 'ay' and make sure the user has not entered in the word numbers or alphanumeric word )
def check(word):
if word.isalnum() or word.isdigit():
print ("Enter valid word!")
else:
print ("Thank You for Entering a valid word!")
first_letter = word[0]
new_word = word.strip(word[0])
PygLatin = new_word+first_letter+"ay"
print (PygLatin)
word= input("enter a word:").lower()
result = check(word)
result I got:
1>> enter a word -> python
2>> Enter valid word!

There are two fundamental issues with your code (and one stylistic issue).
Usually you want functions to return something. For example your intention is to take a word, move the first letter to the end of the word, and add "ay" ... in other words to render it in "Pig Latin."
But you're print-ing the results rather than return-ing them. You might think that using print returns a value (in the sense that it "returned" something to your screen or terminal). But that's not what "return" means in computer programming. The Python return statement is how your function returns a result to the rest of the program following any particular invocation of (or "call into") your function.
Here's the simplest function that would work:
def pigify(word):
return word[1:]+word[0].lower()+'ay'
... that will take a "slice" of the word from a one character offset into the string all the way to the end of the string. That's what [1:] means ... it describes a range of characters, how far to the start of the range and then how far to go to get up to (but not including) the end. Then it adds the first character (which is "zero characters" from the beginning of the string), converts that to lower case (which is harmless for all characters, and only affects capital letters) and then it adds the literal string "ay" ... and it takes all of that and returns it.
pig_latin = pigify("Python")
print(pig_latin)
# ---> prints "ythonpay"
The other issue with your code is that you're calling string methods in a confused way. word.alnum() will return True only if all the characters are alphanumeric and word.isdigit() will return True only if all of the characters are numeric. That's the same as just calling word.isdigit() since digits are a proper subset of the alphanumeric character set. In other words the only strings that will pass your code will be those which contain no letters (or other characters); clearly not what you intended.
You probably would prefer to check that the string consists entirely of alphabetic characters:
def pigify(word):
if word.isalpha():
return word[1:]+word[0].lower()+'ay'
# or else? ....
This leaves you with the question of what you should do with an invalid argument (value passed to your function's "word" parameter by the caller).
You could print an error message. But that's considered poor programming practice. You could return some special value such as Python's None value; but then code that calls your function must either check the results every time, or results can cause some other error far removed from where your function was called (where this non-string value was returned).
You can also raise an exception:
def pigify(word):
if word.isalpha():
return word[1:]+word[0].lower()+'ay'
raise ValueError("Invalid input for pigify()")
... note that I don't need to explicitly spell out else in this case; the control flow only reaches that statement if I didn't return a value, only when it's an error. Any other time the control flow returns to the calling code (the part of the program that called my pigify() function).
Another thing I could do is decide that pigify() simply returns anything that doesn't look like a "word" exactly as it was passed:
def pigify(word):
if word.isalpha():
return word[1:]+word[0].lower()+'ay'
else:
return word
... here I could just return word without the else: as it did before with the raise statement. But I personally think that looks wrong; so I've explicitly spelled out the else: clause purely for stylistic reasons.
Mostly you want your program to be composed of functions (or objects with methods) that work with (manipulate) the data, and then a smaller body of code (possibly functions or object and their methods) which then "render" the results of those manipulations. Any time you're writing a function which manipulations or transforms data and writes those results to the screen or into a web page, or out to a file or database, you should pause and reconsider your design. The transformative/manipulations and computations might be re-useable while the code which writes results is typically quite specific. So interleaving one with the other is usually a bad decision.

The str.isdigit() and str.isalnum() methods only return true if all of the characters match the criteria. Your test is written so that you want to detect whether any of the characters match the criteria:
>>> word = 'abc123'
>>> word.isdigit()
False
>>> any(map(str.isdigit, word))
True
So you can amend the code to start with something like this:
def check(word):
if not word.isalnum() or any(map(str.isdigit, word)):
print ("Enter valid word!")
else:
print ("Thank You for Entering a valid word!")
...
FWIW, str.isalpha() would be easier to use because digits are already excluded.

In your code, you have problem with isalnum() which returns true if string contains only alphabets, only numbers or contains both alphabets and numbers so you can try to match if string only contains alphabets and execute your code as follow:
def check(word):
if word.isalpha(): # process only if word contains only alphabets
print("Thank You for Entering a valid word : {}!".format(word))
print(word[1:] + word[0] + "ay") # slicing is better choice in your case
else:
print("Enter valid word!!!")
word = input("enter a word:")
result = check(word.lower())

Related

My code is incorrectly removing a strings from a larger string

"""
This code takes two strings and returns a copy of the first string with
all instances of the second string removed
"""
# This function removes the letter from the word in the event that the
# word has the letter in it
def remove_all_from_string(word, letter):
while letter in word:
find_word = word.find(letter)
word_length = len(word)
if find_word == -1:
continue
else:
word = word[:find_word] + word[find_word + word_length:]
return word
# This call of the function states the word and what letter will be
# removed from the word
print(remove_all_from_string("bananas", "an"))
This code is meant to remove a defined string from a larger define string. In this case the larger string is "bananas" and the smaller string which is removed is "an".
In this case the smaller string is removed multiple times. I believe I am very close to the solution of getting the correct output, but I need the code to output "bas". Instead, it outputs "ba".
The code is supposed to remove all instances of "an" and print whatever is left, however it does not do this. Any help is appreciated.
Your word_length should be len(letter), and as the while ensures the inclusion, don't need to test the value of find_word
def remove_all_from_string(word, replacement):
word_length = len(replacement)
while replacement in word:
find_word = word.find(replacement)
word = word[:find_word] + word[find_word + word_length:]
return word
Note that str.replace exists
def remove_all_from_string(word, replacement):
return word.replace(replacement, "")
You can simply use the .replace() function for python strings.
def remove_all_from_string(word, letter):
word = word.replace(letter, "")
return word
print(remove_all_from_string("bananas", "an"))
Output: bas
The Python language has built-in utilities to do that in a single expression.
The fact that you need to do that, indicates you are doing sme exercise to better understand coding, and that is important. (Hint: to do it in a single glob, just use the string replace method)
So, first thing - avoid using built-in tools that perform more than basic tasks - in this case, in your tentative code, you are using the string find method. It is powerful, but combining it to find and remove all occurrences of a sub-string is harder than doing so step by step.
So, what ou need is to have variables to annotate the state of your search, and your result. Variables are "free" - do not hesitate in creating as many, and updating then inside the proper if blocks to keep track of your solution.
In this case, you can start with a "position = 0", and increase this "0" until you are at the end of the parent string. You check the character at that position - if it does match the starting character of your substring, you update other variables indicating you are "inside a match", and start a new "position_at_substring" index - to track the "matchee". If at any point the character in the main string does not correspond to the character on the substring: not an occurrence, you bail out (and copy the skipped charactrs to your result -therefore you also have to accumulate all skipped characters in a "match_check" substring) .
Build your code with the simplest 'while', 'if' and variable updates - stick it all inside a function, so that whenever it works, you can reuse it at will with no effort, and you will have learned a lot.

Python Regex validation

I am brand new to Python.
I'm trying to ensure a username contains ONLY alpha characters (only a-z). I have the below code. If I type digits only (e.g. 7777) it correctly throws the error. If I type numbers and letters mix, but I START with a number, it also rejects. But if I start with a letter (a-z) and then have numbers in the string as well, it accepts it as correct. Why?
def register():
uf = open("user.txt","r")
un = re.compile(r'[a-z]')
up = re.compile(r'[a-zA-Z0-9()$%_/.]*$')
print("Register new user:\n")
new_user = input("Please enter a username:\n-->")
if len(new_user) > 10:
print("That username is too long. Max 10 characters please.\n")
register()
#elif not un.match(new_user):
elif not re.match('[a-z]',new_user):
print("That username is invalid. Only letters allowed, no numbers or special characters.\n")
register()
else:
print(f"Thanks {new_user}")
Why don't you use isalpha()?
string = '333'
print(string.isalpha()) # False
string = 'a33'
print(string.isalpha()) # False
string = 'aWWff'
print(string.isalpha()) # True
in your code, uf, un and up are unused variables.
the only point where you validate something is the line elif not re.match('[a-z]',new_user):, and you just check if there is at least one lowercase char.
To ensure that a variable contains only letters, use: elif not re.match('^[a-zA-Z]{1,10}$',new_user):
in the regex ^[a-zA-Z]{1,10}$ you find:
^ : looks for the start of the line
[a-zA-Z] : looks for chars between a and z and between A and Z
{1,10} : ensure that the char specified before (letter) is repeated between 1 and 10 times. As LhasaDad is suggesting in the comments, you may want to increase the minimum number of characters, e.g. to 4: {4,10}. We don't know what this username is for, but 1 char seems in any case too low.
$ : search for the end of the line
Since you were looking for a RegEx, I've produced and explained one, but Guy's answer is more pythonic.
IMPORTANT:
You're not asking for this, but you may encounter an error you're not expecting: since you're calling a function inside itself, you have a recursive function. If the user provides too many times (more than 1000) the wrong username, you'll receive a RecursionError
As the re.match docs say:
If zero or more characters at the beginning of string match the regular expression pattern, return a corresponding match object.
That's exactly what's happening in your case: a letter in the beginning of the string will satisfy the match. Try the expression [a-z]+$ which will make sure that the match expands till the end of the string.
You can check the length on the same go: [a-z]{1,10}$.

Capital letters in Jython/JES

I am currently writing a JES program that returns True or False dependent on whether a string containing a palindrome is passed to it. Although the program works, it fails when a capital letter or punctuation symbol is present. How could I get it to work?
print(ThisPalindrome("racecar"))
>> True
print(ThisPalindrome("Racecar"))
>> False
To solve the issue with capitalization, you could try using the str.lower() method in your checks.
def ThisPalindrome(word):
lowercase = word.lower()
reversedOrder = reversed(lowercase)
if lowercase == ''.join(reversedOrder):
return True
else:
return False
In theory, this function should work with basic punctuation too, as long as it doesn't break the function. Input such as ' could cause it to break.
The toLowerCase() method to return the calling string value converted to lowercase.
The replace() method to return a new string with some or all matches of a pattern replaced by a replacement. We will use one of the RegExp we just created earlier.
The split() method splits a String object into an array of strings by separating the string into sub strings.
The reverse() method reverses an array in place. The first array element becomes the last and the last becomes the first.

Creating a list from a string that contains numbers separated by commas; Python 3

Hi so first I would like to say this is for homework so I do not want to straight answer. The problem is:
This task will implement the functionality of creating a list from a string that contains numbers separated by commas (with possibly blank space between them). For example the string "1,2,3, 4.5, 6.7, 8" would become the list: [1, 2, 3, 4.5, 6.7, 8]. Write the following functions:
is_numeric() - This function has a string parameter and returns True if all the characters in the string are digits, comma, space, or dot. If there are any other characters, the function should return False.
string_to_list() - This function takes a string parameter and returns the list of the numbers in the string. First it should call the is_numeric() function to check that the string has no bad characters (e.g. letters). If there are any bad characters, it should return the empty list. If there are no bad characters it should try to build the list out of the data in the string. For this it should look at every substring between two consecutive commas. If there is no dot in that substring, then the substring should be converted to an integer. If there is exactly one dot (no more, no less) it should be converted into a float. If any of the substrings between two consecutive commas can not be converted to an int or a float (e.g. "4.5.8" as it has too many dots), the function should still return the empty list. Hint: the split() method may be useful for this task.
main() - The main() function that will get a string from the user, it will then call the string_to_list() function to build a list out of the user string and then print the resulting list. It will next ask the user if they want to continue. If they want to continue, they should enter 'y'. In that case the function (main) should repeat the previous steps: ask the user for an input, convert it to a list, ask the user again if they want to continue. And so on until the user does not want to continue, in which case he or she should enter 'n'.
The only piece of code I do have checks only the first letter that is in the string to see if it is a digit or a letter. I need to check whether if there is a letter, number, comma, period, or space. I got really lost reading this program. I know I need to get a string from the user, then make that string into a list if only everything is the string is one of the acceptable inputs (letter, number, comma, period, space) Below is my code so far and what my code will be reading in the shell.
s = input("Enter a set of numbers (integers or floats) separated by comma:")
def is_numeric(s):
for char in list(s):
if char.isdigit():
return True
if char.isalpha():
return False
break
if is_numeric(s) == True:
print(s)
else:
print('Error')
================================ RESTART ================================
Enter a set of numbers (integers or floats) separated by comma:1,2,3,4
1,2,3,4
================================ RESTART ================================
Enter a set of numbers (integers or floats) separated by comma:1,2,3,a
1,2,3,a
================================ RESTART ================================
Enter a set of numbers (integers or floats) separated by comma:a,1,2,3
Error
================================ RESTART ================================
Enter a set of numbers (integers or floats) separated by comma:1234a
1234a
================================ RESTART ================================
Enter a set of numbers (integers or floats) separated by comma:asdf3
Error
Thank you in advance!
Firstly, you don't want the loop to return True until the end, but you want it to return False and break if the test is false. Your loop returns True or False right on the first iteration, so you don't want the two return statements within the loop. Secondly, you can create a list or string of characters and use it to check whether each character is within that list. In this case, it would be something like ",. " or [",", ".", " "].
You should write something like this:
def is_numeric(s):
for char in s:
if not char.isdigit() and char not in [" ", ".", ","]:
return False
return True
Here, if the character is not a digit, or the character is not in the list [" ", ".", ","], the function returns False, which automatically ends the loop. If the loop completes without returning a value, then all the characters meet your criteria and the function goes to the next line and returns True.
Edit:
If you want to use a placeholder variable, set it to True and write the loop to set it to False i f the criteria aren't met. If the loop doesn't modify it, the condition is true for the entire string, so it remains True.
def is_numeric(s):
is_digit = True
for char in s:
if not char.isdigit() and char not in [" ", ".", ","]:
is_digit = False
break
return is_digit
Have you talked about regular expressions in your class yet? If so, you are probably expected to be using those. Take a look at http://docs.python.org/2/howto/regex.html
If not, you are probably expected to make a placeholder variable as true, loop through the entire string checking each character and make your placeholder variable false if bad characters are detected. You shouldn't use the return statement until you've gone through the whole string. (after the loop)

deleting letters from strings without string methods or imports?

This is a homework question. I need to define a function that takes a word and letter and deletes all occurrences of that letter in the word. I can't use stuff like regex or the string library. I've tried...
def delete(word,letter):
word = []
char = ""
if char != letter:
word+=char
return word
and
def delete(word,letter):
word = []
char = ""
if char != letter: #I also tried "if char not letter" for both
word = word.append(char)
return word
Both don't give any output. What am I doing wrong?
Well, look at your functions closely:
def delete(word,letter):
word = []
char = ""
if char != letter:
word+=char # or `word = word.append(char)` in 2nd version
return word
So, the function gets a word and a letter passed in. The first thing you do is throw away the word, because you are overwriting the local variable with a different value (a new empty list). Next, you are initializing an empty string char and compare its content (it’s empty) with the passed letter. If they are not equal, i.e. if letter is not an empty string, the empty string in char is added to the (empty list) word. And then word is returned.
Also note that you cannot add a string to a list. The + operation on lists is only implemented to combine two lists, so your append version is definitelly less wrong. Given that you want a string as a result, it makes more sense to just store the result as one to begin with.
Instead of adding an empty string to an empty string/list when something completely unrelated to the passed word happens, what you rather want to do is keep the original word intact and somehow look at each character. You basically want to loop through the word and keep all characters that are not the passed letter; something like this:
def delete(word, letter):
newWord = '' # let's not overwrite the passed word
for char in word:
# `char` is now each character of the original word.
# Here you now need to decide if you want to keep the
# character for `newWord` or not.
return newWord
The for var in something will basically take the sequence something and execute the loop body for each value of that sequence, identified using the variable var. Strings are sequences of characters, so the loop variable will contain a single character and the loop body is executed for each character within the string.
You're not doing anything with word passed to your function. Ultimately, you need to iterate over the word passed into your function (for character in word: doSomething_with_character) and build your output from that.
def delete(word, ch):
return filter(lambda c: c != ch, word)
Basically, just a linear pass over the string, dropping out letters that match ch.
filter takes a higher order function and an iterable. A string is an iterable and iterating over it iterates over the characters it contains. filter removes the elements from the iterable for which the higher order function returns False.
In this case, we filter out all characters that are equal to the passed ch argument.
I like the functional style #TC1 and #user2041448 that is worth understanding. Here's another implementation:
def delete( letter, string ):
s2 = []
for c in string:
if c!=letter:
s2.append( c )
return ''.join(s2)
Your first function uses + operator with a list which probably isn't the most appropriate choice. The + operator should probably be reserved for strings (and use .append() function with lists).
If the intent is to return a string, assign "" instead of [], and use + operators.
If the intent is to return a list of characters assign [], and use .append() function.
Change the name of the variable you are using to construct the returned value.
Assigning anything to word gets rid of the content that was given to the function as an argument.
so make it result=[] OR result="" etc..
ALSO:
the way you seem to be attempting to solve this requires you to loop over the characters in the original string, the code you posted does not loop at all.
you could use a for loop with this type of semantic:
for characterVar in stringVar:
controlled-code-here
code-after-loop
you can/should change the names of course, but i named them in a way that should help you understand. In your case stringVar would be replaced with word and you would append or add characterVar to result if it isn't the deleted character. Any code that you wish to be contained in the loop must be indented. the first unindented line following the control line indicates to python that the code comes AFTER the loop.
This is what I came up with:
def delete(word, letter):
new_word = ""
for i in word:
if i != letter:
new_word += i
return new_word

Categories

Resources