Первая проблема здесь в том, что, несмотря на использование itertools, вы все еще делаете явный уровень python на уровне цикла. Чтобы получить ускорение уровня C при использовании itertools, вы хотите сохранить все итерации в высокоскоростных itertools.
Итак, давайте сделаем это шаг за шагом, сначала мы хотим получить количество символов в конечной строке. Для этого вы можете использовать метод itertools.islice, чтобы получить первые n символов в строке:
str_first_n_chars = islice(cycle(str_), n)
Далее вы хотите подсчитать количество вхождений буквы (a), чтобы сделать это Вы можете сделать несколько вариантов любого из них (вы можете поэкспериментировать, какие варианты быстрее):
count_a = sum(1 for c in str_first_n_chars if c == 'a')
count_a = len(tuple(filter('a'.__eq__, str_first_n_chars))
Это все и хорошо, но это все еще медленно для очень больших n
, потому что вам нужно перебирать str_
много, много раз для действительно больших n
, как, например, n = 10**10000
. Другими словами, этот алгоритм O(n)
.
Есть одно последнее улучшение, которое мы могли бы сделать. Обратите внимание, что число (a) в str_
никогда не меняется на каждой итерации. Вместо того, чтобы многократно повторять str_
для большого n
, мы можем сделать немного умнее с небольшим количеством математики, так что нам нужно только перебрать str_
дважды. Сначала мы посчитаем число (a) в одном отрезке str_
:
count_a_single = str_.count('a')
Затем мы выясним, сколько раз нам пришлось бы пройти через str_
, чтобы получить длину n
по используя функцию divmod:
iter_count, remainder = divmod(n, len(str_))
, тогда мы можем просто умножить iter_count на count_a_single и добавить число (a) в оставшейся длине. Нам не нужен цикл или островок, и это здесь, потому что remainder < len(str_)
count_a = iter_count * count_a_single + str_[:remainder].count('a')
При использовании этого метода производительность алгоритма во время выполнения возрастает только на длину одного цикла str_, а не на n
, Другими словами, этот алгоритм O(len(str_))
.
Чтобы заморозить объект Freezable
, объявленный в разметке, вы используете атрибут Freeze
, определенный в пространстве имен XML http://schemas.microsoft .com / winfx / 2006 / xaml / presentation / options
.
В следующем примере SolidColorBrush
объявлен как ресурс страницы и заморожен. Затем он используется для установки фона кнопки.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:po="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="po">
<Page.Resources>
<!-- This brush is frozen -->
<SolidColorBrush x:Key="MyBrush" po:Freeze="True" Color="Red" />
</Page.Resources>
<!-- Use the frozen brush -->
<Button Background="{StaticResource MyBrush}">Click Me</Button>
</Page>
Источник: Обзор замораживаемых объектов
Добавьте это к своим объявлениям пространства имен xaml:
xmlns:po="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="po"
затем, в ваши замораживаемые объекты, включите этот атрибут
po:Freeze="True"