2

I have managed to solve this exercise from the codewars website using the following code

def find_uniq(arr):
    diff = None
    first = None
    for s in arr:
        if first is None:
            first = s
            continue

        if (len(first) in [0, 1]) and (len(s) in [0, 1]):
            if arr.count(first) == 1:
                return first
            elif arr.count(s) == 1:
                return s

        temp = set(first.lower()).difference(set(s.lower()))
        if temp:
            diff = s

        if diff is not None:
            temp = set(diff.lower()).difference(set(s.lower()))
            return first if temp else diff

My code passes all their unit tests but problem is when I try it using the following custom unit test, it fails

test.assert_equals(['foo', 'abc', 'acb', 'bac', 'bca', 'cab', 'cba dab'], 'foo')  # fails, returns 'abc'

The exercise is a follows:

There is an array / list of strings. All strings contains similar letters except one. Try to find it!

and rules are:

  • Strings may contain spaces. Spaces is not significant, only non-spaces symbols matters. E.g. string that contains only spaces is like empty string.

  • It’s guaranteed that array / list contains more than 3 strings.

Any suggestions on how this can be improved to handle such cases or even just general improvement of the function overall.

Thank you.

3
  • @DanielMesejo no, it is not Commented Oct 24, 2019 at 16:37
  • 1
    Include all relevant information as text in the question, not as link (like meaning of "unique" here). Commented Oct 24, 2019 at 16:39
  • @MichaelButscher I have added that information Commented Oct 24, 2019 at 16:45

1 Answer 1

1

Calling the list.count method in a loop is inefficient. You can instead use a dict keep track of the unique sets of characters you have iterated through so far. Make the set of characters the string minus the space the key of the dict, the string itself the value. If the current key is already in the dict, you would then know that the key is not unique. The task then becomes to find the key that is different from this common key. If there already is a different key in the dict, then return the value of that different key. If not, keep iterating until you get a key that's different from the known common key:

def find_uniq(arr):
    seen = {}
    common = None
    for string in arr:
        key = frozenset(set(string.lower()).difference(' '))
        if key in seen:
            common = key
        if common is not None:
            if key != common:
                return string
            if len(seen) > 1:
                del seen[common]
                return next(iter(seen.values()))
        seen[key] = string

so that the following expressions will all be True:

find_uniq(['foo', 'abc', 'acb ']) == 'foo'
find_uniq(['abbc', 'foo', 'acb ']) == 'foo'
find_uniq(['abc', 'acb ', 'foo']) == 'foo'
Sign up to request clarification or add additional context in comments.

4 Comments

thank you for your answer, I will give you response when I test it in the morning
your solution fails to pass this test test.assert_equals( find_uniq(['Aa', 'aaa', 'aaaaa', 'BbBb', 'Aaaa', 'AaAaAa', 'a']), 'BbBb') # returns 'Aa' instead of 'BbBb' but works for all the rest
I see. I did not realize that letters of different casings are treated the same. Fixed with a call to the str.lower method then.
blhsing They now all pass, thank you for taking time to help

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.