Неэффективный алгоритм(Python)

Возникла проблема по решению задачи на питоне,а точнее по оптимизации алгоритма. Имеем такое условие: Гоша и Тимофей нашли необычный тренажёр для скоростной печати и хотят освоить его. Тренажёр представляет собой поле из клавиш 4× 4, в котором на каждом раунде появляется конфигурация цифр и точек. На клавише написана либо точка, либо цифра от 1 до 9. В момент времени t игрок должен одновременно нажать на все клавиши, на которых написана цифра t. Гоша и Тимофей могут нажать в один момент времени на k клавиш каждый. Если в момент времени t были нажаты все нужные клавиши, то игроки получают 1 балл.

Найдите число баллов, которое смогут заработать Гоша и Тимофей, если будут нажимать на клавиши вдвоём.

Формат ввода В первой строке дано целое число k (1 ≤ k ≤ 5).

В четырёх следующих строках задан вид тренажёра –— по 4 символа в каждой строке. Каждый символ —– либо точка, либо цифра от 1 до 9. Символы одной строки идут подряд и не разделены пробелами.

Формат вывода Выведите единственное число –— максимальное количество баллов, которое смогут набрать Гоша и Тимофей.

Пример 1

Ввод:

3
1231
2..2
2..2
2..2

Вывод:

2

Пример 2

Ввод:

4
1111
9999
1111
9911

Вывод:

1

Пример 3

Ввод:

4
1111
1111
1111
1111

Вывод:

0

Я написал алгоритм, но учитель просит улучшить его, по следующим критериям: 1.Избавиться от работы с цифрами-числами. Использовать готовый набор цифр-символов. 2.Применить sum().(Заменитm цикл, которые считает число удачных случаев на вызов sum 3.Преобразование в списки и их сложение лишние. Поле в виде строки подходит для Counter()

Я вроде бы и понимаю что нужно получить, но как это сделать пока не доходит. В связи с этим, прошу помощи у вас. Мой код

from collections import Counter


def dexterity(fingers, symbols):

    counter = Counter([int(x) for x in symbols])
    score = 0
    for iteration in range(0, 10):
        if (iteration in counter) and (counter[iteration] <= fingers*2):
            score += 1
    return score


if __name__ == '__main__':
    fingers = int(input())
    symbols = sum([list(input().replace('.', '')) for i in range(4)], [])
    print(dexterity(fingers, symbols))

Ответы (3 шт):

Автор решения: CrazyElf

Второе понятно, хотя это немного хак, основанный на том, что для функции sum значение True = 1, а False = 0:

score = sum((iteration in counter) and (counter[iteration] <= fingers*2) for iteration in range(0, 10))

Хотя возможно с вас требуют что-то менее хардкорное, с явным суммированием единичек, вроде такого:

score = sum([1 if (iteration in counter) and (counter[iteration] <= fingers*2) else 0 for iteration in range(0, 10)])

А вот первое я тоже не понял.

→ Ссылка
Автор решения: GrAnd

Я вижу такой вариант оптимизации:

  • symbols - это просто строка
  • sum - считает по условию
  • чтобы не проверять был символ или нет, просто итерируемся по значениям словаря counter
from collections import Counter

def dexterity(fingers, symbols):
    counter = Counter(symbols)
    return sum(value <= fingers*2 for value in counter.values())


if __name__ == '__main__':
    fingers = int(input())
    symbols = ''.join(input() for _ in range(4)).replace('.', '')

    print(dexterity(fingers, symbols))
→ Ссылка
Автор решения: Stanislav Volodarskiy

Код не переводит символы в числа. Находит результат суммированием подходящих вариантов. Не складывает строки или списки вместе. Не использует isdigit. Не итерируется по цифрам которых не было на входе:

import collections
import itertools


threshold = 2 * int(input())
c = collections.Counter(itertools.chain.from_iterable(input() for _ in range(4)))
s = sum(1 for k, v in c.items() if k != '.' and v <= threshold)
print(s)

Если не хочется использовать itertools то

import collections


threshold = 2 * int(input())
c = collections.Counter(k for _ in range(4) for k in input() if k != '.')
s = sum(1 for v in c.values() if v <= threshold)
print(s)
→ Ссылка