How to check if a list is one step away from being perfect according to a particular requirement?

Viewed 62

Suppose there is a list called my_list that can have up to 4 different unique values e.g. my_list = ['d','a','d','c','d','c','b','a','b']. We call my_list a perfect list if, among the list's unique elements, there are at least 3 occurrences of any element, at least 2 occurrences of another element and at least 1 occurrence of another element. For example, my_list = ['d','a','d','c','d','c','b','a','b'] is perfect according to the criteria since the number of occurences are as follows:

'd' = 3 (at least 3 times)
'a' = 2 (at least 2)
'c' = 2 (at least 1)
'b' = 2 (at least 2)

therefore the requirement of at least 3, 2 and 1 repetitions is met whereas another_list = ['d','a','d','c','d','b'] is not perfect as:

'd' = 3 
'a' = 1 
'c' = 1 
'b' = 1

so the requirement of 3, 2, 1 is not there. Please note that the order is irrelevant. In another_list, if we only add one 'a' or one 'c' or one 'b', then it will become perfect; in other words, it is only one step away from being perfect. I am looking for a function that takes a list and returns True if the list is only one step away from becoming perfect; otherwise, it returns False. I have coded as follows:

def fun(some_list):

    unique = list(set(some_list))

        dict = {}
        for i in unique:
            dict[i] = unique.count(i)

        counts = list(dict.values())

which finds the counts of unique elements in the list but I need help to complete the function to check if the list is one step away from being perfect based on the above explanation.

1 Answers

You can use collections.Counter:

import collections
def almost_perfect(d):
  r = collections.Counter(d)
  c = {b:a for a, b in r.items()}
  k = [i for i in range(1, 4) if i not in c]
  return len(k) == 1 and (k[0]+1 in c or any(i+1 == k[0] and sum(j == i for j in r.values()) > 1 for i in c))

vals = ['d','a','d','c','d','b']
vals1 = ['a', 'a', 'b', 'b', 'c', 'd']
vals2 = ['d', 'a', 'a', 'c'] 
print(almost_perfect(vals))
print(almost_perfect(vals1))
print(almost_perfect(vals2))

Output:

True
True
False
Related