Anagram function says "ellhe" and "hello" are anagrams - python

I am trying to check whether two given strings are anagrams.
def Anagram(Word1, Word2):
if len(Word1.lower()) == len(Word2.lower()):
for Char in Word1.lower():
if Char in Word2.lower():
return (Word2,"Is An Anagram Of", Word1)
else:
return (Word2, "Is Not A Anagram", Word1)
else:
return (Word2, "Is Not A Anagram", Word1)
print(Anagram("Hello", "ellhe"))
The problem is that this prints that it is an anagram when it is not. FOr instance, it says that "ellhe" and "hello" are anagrams, but they differ by one letter ('o' vs a second 'e'). What am I doing wrong?

You're returning after only checking one letter, but your method is flawed anyway. Implemented correctly it will return true if the words contain the same letters, but will disregard how often they occur.

Here are a few things:
1) You're returning as soon as one character matches, not when the entire word matches
2) I believe you need to add some logic to handle situations where the same letter appears multiple times. Otherwise, helo and hello will show as anagrams of each other.

This is a one-liner: sort both strings and compare the sorted lists of characters:
if sorted(word1.lower()) ==
sorted(word2.lower()):
I trust you can do the rest of the routine, as you've already handled that logic.

Related

Python - Finding all uppercase letters in string

im a really beginner with python and I'm trying to modify codes that I have seen in lessons.I have tried the find all uppercase letters in string.But the problem is it only gives me one uppercase letter in string even there is more than one.
def finding_upppercase_itterative(string_input):
for i in range(len(string_input)):
if string_input[i].isupper:
return string_input[i]
return "No uppercases found"
How should i modify this code to give me all uppercase letters in given string. If someone can explain me with the logic behind I would be glad.
Thank You!
Edit 1: Thank to S3DEV i have misstyped the binary search algorithm.
If you are looking for only small changes that make your code work, one way is to use a generator function, using the yield keyword:
def finding_upppercase_itterative(string_input):
for i in range(len(string_input)):
if string_input[i].isupper():
yield string_input[i]
print(list(finding_upppercase_itterative('test THINGy')))
If you just print finding_upppercase_itterative('test THINGy'), it shows a generator object, so you need to convert it to a list in order to view the results.
For more about generators, see here: https://wiki.python.org/moin/Generators
This is the fixed code written out with a lot of detail to each step. There are some other answers with more complicated/'pythonic' ways to do the same thing.
def finding_upppercase_itterative(string_input):
uppercase = []
for i in range(len(string_input)):
if string_input[i].isupper():
uppercase.append(string_input[i])
if(len(uppercase) > 0):
return "".join(uppercase)
else:
return "No uppercases found"
# Try the function
test_string = input("Enter a string to get the uppercase letters from: ")
uppercase_letters = finding_upppercase_itterative(test_string)
print(uppercase_letters)
Here's the explanation:
create a function that takes string_input as a parameter
create an empty list called uppercase
loop through every character in string_input
[in the loop] if it is an uppercase letter, add it to the uppercase list
[out of the loop] if the length of the uppercase list is more than 0
[in the if] return the list characters all joined together with nothing as the separator ("")
[in the else] otherwise, return "No uppercases found"
[out of the function] get a test_string and store it in a variable
get the uppercase_letters from test_string
print the uppercase_letters to the user
There are shorter (and more complex) ways to do this, but this is just a way that is easier for beginners to understand.
Also: you may want to fix your spelling, because it makes code harder to read and understand, and also makes it more difficult to type the name of that misspelled identifier. For example, upppercase and itterative should be uppercase and iterative.
Something simple like this would work:
s = "My Word"
s = ''.join(ch for ch in s if ch.isupper())
return(s)
Inverse idea behind other StackOverflow question: Removing capital letters from a python string
The return statement in a function will stop the function from executing. When it finds an uppercase letter, it will see the return statement and stop.
One way to do this is to append letters to list and return them at the end:
def finding_uppercase_iterative(string_input):
letters = []
for i in range(len(string_input)):
if string_input[i].isupper():
letters.append(string_input[i])
if letters:
return letters
return "No uppercases found"

Checking if a word is a subset of another word with same amount of letters [duplicate]

This question already has answers here:
Python Counter Comparison as Bag-type
(3 answers)
Closed 7 months ago.
I am making a word game program where I get a list of ~80,000 words from a text file, then use those words as a lexicon of words to choose from. The user requests a word of a certain length which is then given to them scrambled. They then guess words that are of the same length or less and that use the same letters in the same amount or less. I have this list comprehension in order to get all the words from the lexicon that are subsets of the scrambled word and are also in the lexicon. However it allows more occurrences of letters than appear in the original word. For example: If the scrambled word was 'minute', then 'in' should be a correct answer but 'inn' should not. The way I have it written now allows that though. Here is the list comprehension:
correct_answers = [
word for word in word_list
if set(word).issubset(random_length_word)
and word in word_list
and len(word) <= len(random_length_word)]
So I'm looking for something like issubset but that only allows the same number of letters or less. Hopefully that makes sense. Thanks in advance.
I wrote a function that does this for playing the Countdown letters game. I called the desired input a "subset-anagram", but there's probably a better technical term for it.
Essentially, what you're looking for is a multiset (from word) that is a subset of another multiset (from random_length_word). You can do this with collections.Counter, but I actually found it much faster to do it a different way: make a list out of random_length_word, then remove each character of word. It's probably faster due to the overhead of creating new Counter objects.
def is_subset_anagram(str1, str2):
"""
Check if str1 is a subset-anagram of str2.
Return true if str2 contains at least as many of each char as str1.
>>> is_subset_anagram('bottle', 'belott') # Just enough
True
>>> is_subset_anagram('bottle', 'belot') # less
False
>>> is_subset_anagram('bottle', 'bbeelloott') # More
True
"""
list2 = list(str2)
try:
for char in str1:
list2.remove(char)
except ValueError:
return False
return True
>>> [w for w in ['in', 'inn', 'minute'] if is_subset_anagram(w, 'minute')]
['in', 'minute']
For what it's worth, here's the Counter implementation:
from collections import Counter
def is_subset_anagram(str1, str2):
delta = Counter(str1) - Counter(str2)
return not delta
This works because Counter.__sub__() produces a multiset, that is, counts less than 1 are removed.
Your approach loses the information, how often a certain character appears, because set(answer) does not contain this information any more.
Anyway, I think you are over-complicating things with your approach. There is a more efficient way for checking whether an answer is correct, instead of creating a list of all possible answers:
We could just check whether the answer has the matching character frequencies with any of the words in word_list. More specifically, "matching character frequencies" means that all characters appear less (or equally) often in the answer and the candidate from word list.
Getting the character frequencies of a string is a classic job collections.Counter has been invented for.
Checking that the character frequencies match means that all characters in the word have less or equal count in the answer.
Finally, checking that an answer is correct means that this condition is true for any of the words in word_list.
from collections import Counter
from typing import List
def correct_answer(word_list: List[str], answer: str) -> bool:
return any(
all(
# this checks if each char occurs less often in the word
Counter(answer)[character] <= Counter(word)[character]
for character in Counter(answer).keys()
)
for word in word_list
)
This is more efficient than your approach, because it takes way less memory space. Thanks to any and all being short-circuit, it is also quite time-efficient.

Count Occurrences using for, in, and return

I have been trying to write the code for this program for a while now, but I just cannot figure it out. I am very confused. I would appreciate the help:
Write a function that takes two strings. The second string should only be one character long. The function should return how many times the second string occurs in the first string.
You will need:
A function declaration, with parameters.
A for loop.
An if statement.
A return statement.
What I have so far:
string_one = "I love coding!"
string_two = "I"
if string_two in string_one: print "Hi"
Considering the code you have provided, it indeed works if string_two is in string_one, meaning that your if-condition is correct. However, it will only run once, so if string_two occurs multiple times in string_one, it will ignore all other occurences and print Hi only once. As a result, you need to add your if-condition into a for-loop to catch all occurences of string_two in string_one.
string_one = "I love coding!"
string_two = "o" # changed to 'o' since it has more than 1 occurence in string_one
for letter in string_one: # look at each letter in string_one, one after another
if string_two in letter: # also possible: if string_two == letter
print "Hi" # print Hi when the letter is found
All that's left to do now according to your task is to wrap this code into a function with two parameters (ideally one parameter called sentence and another one called character or similar) and return something. However, I will leave figuring this out to yourself, good luck! :)
First off, let's note that this problem could be solved using str.count(thing_to_count). That's what you should use in general, but I see here you are probably asking for help on an assignement (generally discouraged on Stack Overflow, but I personally don't have an issue with it). Anyway, here's the code I made for this.
def count_in_string (sentence, thing_to_count):
times = 0
for word in sentence:
for letter in word:
if letter == thing_to_count: times += 1
return times
So:
Declare count_in_string as a function with the arguments sentence and thing_to_count.
Set times to be the amount of times thing_to_count_ appears in sentence (so far 0).
Loop through every word, and then letter in the sentence.
See if the letter is the thing_to_count, and if so add 1 to times.
Return times as the result.

Check that input is composed of letters from other word

I have this code:
print('abcdefg')
input('Arrange word from following letters: ')
I want to return True if the input consists of letters from the printed string but it doesn't have to have all of printed letters.
That's a perfect use case for sets especially for set.issubset:
print('abcdefg')
given_input = input('Arrange word from following letters: ')
if set(given_input).issubset('abcdefg'):
print('True')
else:
print('False')
or directly print (or return) the result of the issubset operation without if and else:
print(set(given_input).issubset('abcdefg'))
This sounds a little like homework...
Basically you would need to do this: Store both strings in variables. e.g. valid_chars and s.
Then loop through s one character at a time. For each character check if it is in valid_chars (using the in operator). If any character is not found in valid_chars then you should return False. If you get to the end of the loop, return True.
If the valid_chars string is very long it would be better to first put them into a set but for short strings this is not necessary.

Only print the lowercase characters in a string

How can I write the code so python ONLY prints out the lower case letters of the string. In this case, it should exclude the P.
I tried this:
word = "Programming is fun!"
for letter in word:
if letter.lower():
print letter
But it doesn't solely print out the lowercase letters. How could I only get the lower-case characters out of the string instead of the whole string in lower-case.
You want letter.islower() (which tests), not letter.lower() (which converts).
If you want to print non-cased characters too, you'd check:
if letter.islower() or not letter.isalpha():
Try using islower instead :
letter.islower()
Yours doesn't work because you've called .lower(), which is a method of the String class - it changes the case of the letter in question, and results in True.
There are likely many ways to obtain the result you want, the simplest I can think of being:
word = "Hello World!"
for letter in word:
if letter.islower():
print(letter)
Note that there is an equality test in mine, which is what yours is missing.
EDIT: As other answers pointed out, .islower() is a more succinct way of checking the case of the letter. Similarly, .isupper() would print only the capital letters.
You could use
print filter(lambda c: c.islower(), word)
What will actually answer to your question (as i can tell from provided output) will be something like:
import string
word="Programming is fun!"
filter(lambda c: c.islower() or not(c.isupper() and c in string.printable), word)

Categories