Reputation: 431
I am accepting two strings through command line.
What I want is,
If they have the same number of z’s, then the string with the most y’s wins.
If they have the same number of y’s, then the number of x’s determines the winner, etc.
If they contain the same number of z’s, y’s .... a’s, then it’s a tie and there is no winner.
What I had planned to do was,
create a dictionary with all alphabets and assign incrementing values like,
alphabets = dict(a=1, b=2, c=3, ... ,y=25, z=26)
and mulptiple its values by the number of times the letter repeated.
For example, python myprogram.py zzza zzza
string1: zzza and string2: zzza
In string1, Z is repeated 3 times and a is repeated once.
In string2, Z is repeated 2 times, b and a is repeated once.
So, (26*3) + (2*1) and (26*2) + (2*1) + (1*1)
string with maximum number would win. But, it does not give correct answer always. (string1: zzza and string2: zyyx condition fails)
word1_count = {}
word2_count = {}
class FindWinner:
def __init__(self, word1, word2):
self.word1 = word1
self.word2 = word2
def check_conditions(self):
special_chars = set('[~!@#$%^&*.-()_+{}":;01234567989\']+$')
# check conditions
if special_chars.intersection(self.word1) or
special_chars.intersection(self.word2) or \
(len(self.word1) != len(self.word2) or ('no' in self.word1)
or ('no' in self.word2)) or (self.word1 == self.word2):
print('Invalid string.')
else:
print("String is valid")
for w1 in list(self.word1):
if w1 not in word1_count:
word1_count[w1] = 1
else:
word1_count[w1] += 1
for w2 in list(self.word2):
if w2 not in word2_count:
word2_count[w2] = 1
else:
word2_count[w2] += 1
# print(word1_count, word2_count)
merged_data = [[k, word1_count.get(k, 0), word2_count.get(k, 0)] for k in word1_count.keys() | word2_count.keys()]
print(merged_data)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("word1", help="First word")
parser.add_argument("word2", help="Second word")
args = parser.parse_args()
c1 = FindWinner(args.word1, args.word2)
c1.check_conditions()
if __name__ == "__main__":
main()
Input:
python myprogramm.py qwwweq asdnnn
Output:
String is valid
{'e': 1, 'q': 2, 'w': 3} {'d': 1, 'a': 1, 'n': 3, 's': 1} # merged_data
What should be the approach? Thanks
Upvotes: 1
Views: 522
Reputation: 3089
This can be done without a dictionary.
Creating a dictionary as part of pre-processing is an additional overhead.
We can check the count of each letter starting from (z..a)
one by one in both the strings. If there is a max we can break the loop and declare the winner. This is much efficient than using dictionaries for solving this problem.
from string import ascii_lowercase
str1="hellozzzz"
str2="yellozzzz"
winner=""
for ele in reversed(ascii_lowercase):
diff=str1.count(ele)-str2.count(ele)
if(diff>0):
winner=str1
break
elif (diff<0):
winner=str2
break
print winner if(winner) else "It's a tie"
Upvotes: 1
Reputation: 1125078
Your approach doesn't work because twenty-six a
characters gives the same score as one z
character; 26 * 1 == 1 * 26.
You instead should treat this as a sorting problem, where you are sorting by the letter counts. Count the letters in each word, then take the counts in reverse alphabetical order as a tuple and have Python pick the winner with max()
. Python sequences are compared lexicographically; a list with [3, 2]
is sorted after [3, 1]
because the second digit is larger in the first; max()
would pick it over the second.
Counting is trivially done with a collections.Counter()
object:
from collections import Counter
from string import ascii_lowercase
def letter_counts(word):
counts = Counter(word)
return [counts.get(l, 0) for l in reversed(ascii_lowercase)]
lcounts1 = letter_counts(word1)
lcounts2 = letter_counts(word2)
if lcounts1 == lcounts2:
# tie
print('No winner')
else:
_, winner = max((lcounts1, word1), (lcounts2, word2))
print(winner)
letter_counts()
produces a list of 26 integers, each a count for the letters z
through to a
.
Upvotes: 2