Неэффективный алгоритм(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 шт):
Второе понятно, хотя это немного хак, основанный на том, что для функции 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)])
А вот первое я тоже не понял.
Я вижу такой вариант оптимизации:
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))
Код не переводит символы в числа. Находит результат суммированием подходящих вариантов. Не складывает строки или списки вместе. Не использует 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)