1
\$\begingroup\$

I solved the CodingBat task:

Given 2 strings, a and b, return the number of the positions where they contain the same length 2 substring. So "xxcaazz" and "xxbaaz" yields 3, since the "xx", "aa", and "az" substrings appear in the same place in both strings.

stringMatch("xxcaazz", "xxbaaz") → 3  
stringMatch("abc", "abc") → 2  
stringMatch("abc", "axc") → 0
import doctest


def all_two_chars_occurencies(string):
    """
    >>> list(all_two_chars_occurencies('abcd'))
    ['ab', 'bc', 'cd']
    >>> list(all_two_chars_occurencies('xxcaazz'))
    ['xx', 'xc', 'ca', 'aa', 'az', 'zz']
    """
    for index, char in enumerate(string[:-1]):
        yield char + string[index + 1]


def common_two_chars_occurences(a, b):
    """
    Given 2 strings, a and b, return the number of the positions where
    they contain the same length 2 substring.

    >>> common_two_chars_occurences('xxcaazz', 'xxbaaz')
    3
    >>> common_two_chars_occurences('abc', 'abc')
    2
    >>> common_two_chars_occurences('abc', 'axc')
    0
    """
    equal_duets = 0
    for a_duet, b_duet in zip(all_two_chars_occurencies(a),
                              all_two_chars_occurencies(b)):
        if a_duet == b_duet:
            equal_duets += 1
    return equal_duets


if __name__ == "__main__":
    doctest.testmod()
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

There is no such word as "occurencies". In any case, all_two_chars_occurencies is a very long name. I suggest pairwise_chars. Note that it could also be written in a style similar to the pairwise() recipe in Python's documentation.

In Python, explicit looping is slightly cumbersome. Fortunately, Python offers many ways to just do what you want as a "one-liner", without looping. Here's one approach, which uses a generator expression, and this technique to find its length.

def common_two_chars_occurences(a, b):
    """
    Given 2 strings, a and b, return the number of the positions where
    they contain the same length 2 substring.

    >>> common_two_chars_occurences('xxcaazz', 'xxbaaz')
    3
    >>> common_two_chars_occurences('abc', 'abc')
    2
    >>> common_two_chars_occurences('abc', 'axc')
    0
    """
    return sum(1 for pair
                 in zip(pairwise_chars(a), pairwise_chars(b))
                 if pair[0] == pair[1])
\$\endgroup\$
1
  • \$\begingroup\$ Note that you can sum booleans and use unpacking to get sum(left == right for left, right in zip(pairwise_chars(a), pairwise_chars(b))). My preference is actually sum(map(eq, pairwise_chars(a), pairwise_chars(b))) though (eq from operator). \$\endgroup\$
    – Veedrac
    Mar 28, 2015 at 10:16
1
\$\begingroup\$

You should refactor further writing an equal_at_same_index function:

def equal_at_same_index(list_1, list_2):
    """
    >>> equal_at_same_index("abcde", "xxcae")
    2
    >>> equal_at_same_index("qwerty", "xqwerty")
    0
    """
    return sum((i == j for i, j in zip(list_1, list_2)))


def common_two_chars_occurences(a, b):
    """
    Given 2 strings, a and b, return the number of the positions where
    they contain the same length 2 substring.

    >>> common_two_chars_occurences("xxcaazz", "xxbaaz")
    3
    >>> common_two_chars_occurences("abc", "abc")
    2
    >>> common_two_chars_occurences("abc", "axc")
    0
    """
    return equal_at_same_index(all_two_chars_occurencies(a),
                               all_two_chars_occurencies(b))
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.