PRK
PRK

Reputation: 431

Iterate over two strings and count repeated letters

I am accepting two strings through command line.

What I want is,

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

Answers (2)

Rahul Verma
Rahul Verma

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

Martijn Pieters
Martijn Pieters

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

Related Questions