oeis

18 Sep 2026
by ignat

Это потрясающее расширение эмулятора! Предложенная вами точная формула для ряда OEIS A391838 использует беззнаковые числа Стирлинга I рода \left[{n-k\atop n-2k}\right], которые берутся по весьма специфическим «косым» (наклонным) диагоналям матрицы. Шаг этой диагонали: при увеличении индекса суммирования k на 1, мы смещаемся на 1 строку вверх (n-k) и на 2 столбца влево (n-2k).

Внедрение Действия 11 позволит наглядно продемонстрировать этот красивый геометрический паттерн на счётной доске. В соответствии с вашей задумкой:

  • Левая юпана (Таблица A) будет предварительно заполнена классической эталонной матрицей беззнаковых чисел Стирлинга I рода.
  • Правая юпана (Таблица B) будет позиционно подсвечивать те самые нетрадиционные наклонные ячейки, которые вносят вклад в расчёт текущего числа a_n.
  • Нижняя синяя строка выведет результат вычисления a_n.

Ниже приведены точные куски кода и места, куда их необходимо вставить для реализации этого функционала.


Шаг 1. Добавление Действия 11 в словарь ACTIONS

Найдите словарь ACTIONS в файле yupana_emulator.py и добавьте элемент 11 в самый конец:

ACTIONS = {
    0: {"name": "A391838 (авто)", "desc": "Последовательность A391838 в нижнюю строку"},
    1: {"name": "Stirling S(n,k)", "desc": "Числа Стирлинга 2-го рода"},
    2: {"name": "Сложение", "desc": "Сложение камешков по строкам"},
    3: {"name": "Вычитание", "desc": "Вычитание камешков по строкам"},
    4: {"name": "Сдвиг", "desc": "Сдвиг камешков вправо"},
    5: {"name": "Зеркало", "desc": "Зеркальное отражение матрицы"},
    6: {"name": "Транспонирование", "desc": "Транспонирование матрицы"},
    7: {"name": "Обращение", "desc": "Обращение последовательности"},
    8: {"name": "Умножение (решётка)", "desc": "Умножение методом 4 клеток / 3x3 юпана"},
    9: {"name": "Синус (NCO)", "desc": "Генерация синуса на треугольной сетке"},
    10: {"name": "Умножение инков", "desc": "Поклеточное умножение на 9 клетках (палочки и камешки)"},
    11: {"name": "Диагонали A391838", "desc": "Косые диагонали Стирлинга I рода для формулы OEIS"},
}

Шаг 2. Описание нового алгоритма в yupana_lattice.py

Чтобы не загромождать графический интерфейс, всю пошаговую историю для диагоналей мы рассчитаем в файле математики. В качестве параметра n мы будем использовать значение, введённое пользователем в поле «Число A» (по умолчанию 3, что наглядно продемонстрирует косые шаги в пределах сетки).

Откройте файл yupana_lattice.py и добавьте в самый конец новую функцию emulator_stirling_diagonal_action:

def emulator_stirling_diagonal_action(n_target: int) -> dict:
    """
    Действие 11: Расчёт косых диагоналей чисел Стирлинга I рода для формулы A391838.
    Генерирует историю пошагового прохода по компонентам суммы k от 0 до n//2.
    """
    import math
    
    # 1. Генерируем эталонную матрицу беззнаковых чисел Стирлинга I рода s(row, col)
    # Для визуализации на доске 4x5 строим матрицу размером 4 строки на 5 столбцов (индексы 0..3 и 0..4)
    stirling_base = [[0] * 5 for _ in range(4)]
    stirling_base[0][0] = 1
    for r in range(1, 4):
        for c in range(1, 5):
            if c <= r + 1:
                # s(n, k) = s(n-1, k-1) + n * s(n-1, k)
                # Переводим в наши индексы:
                stirling_base[r][c] = (stirling_base[r-1][c-1] if c-1 >= 0 else 0) + r * stirling_base[r-1][c]
            if c == 0:
                stirling_base[r][c] = 0

    steps_history = []
    
    # Считаем итоговое значение a_n по точной формуле через Fraction
    from fractions import Fraction
    total_sum = Fraction(0)
    k_max = n_target // 2
    
    # Накопительный словарь для правой юпаны (будем позиционно выводить слагаемые)
    right_yupana_accum = {}
    highlighted_cells = [] # Список координат для подсветки

    # --- ШАГ 0: Подготовка. Заполнение Таблицы A базовыми числами Стирлинга ---
    left_start = {}
    for r in range(4):
        for c in range(5):
            if stirling_base[r][c] > 0:
                left_start[(r, c)] = stirling_base[r][c]
                
    steps_history.append({
        "left": dict(left_start),
        "right": {},
        "highlight": [],
        "text": f"Шаг 0: На левой юпане развёрнута эталонная матрица беззнаковых чисел Стирлинга I рода.\nНачинаем расчёт для n = {n_target}."
    })

    # Проходим по всем k для вычисления компонентов
    for k in range(k_max + 1):
        s_row = n_target - k
        s_col = n_target - 2 * k
        
        # Проверяем, укладывается ли координата в физические размеры доски 4x5
        valid_cell = (0 <= s_row < 4 and 0 <= s_col < 5)
        s_val = stirling_base[s_row][s_col] if valid_cell else 0
        
        # Вычисляем знаменатель компоненты: (2k+1)! * (n-k)!
        denom = math.factorial(2 * k + 1) * math.factorial(s_row)
        component_fraction = Fraction(s_val, denom)
        total_sum += component_fraction
        
        # Формируем текст шага
        step_text = f"Шаг {k+1}: Вычисляем компоненту для k = {k}.\n"
        if valid_cell:
            step_text += f" Косая диагональ указывает на ячейку s[{s_row}, {s_col}] со значением {s_val}.\n"
            highlighted_cells.append((s_row, s_col))
            # Позиционно выводим значение числа Стирлинга на правую юпану
            right_yupana_accum[(s_row, s_col)] = s_val
        else:
            step_text += f" Косая координата s[{s_row}, {s_col}] выходит за рамки доски. Значение = 0.\n"
            
        step_text += f" Знаменатель (2k+1)! * (n-k)! = {denom}. Частичная сумма дробей: {total_sum}"
        
        steps_history.append({
            "left": dict(left_start),
            "right": dict(right_yupana_accum),
            "highlight": list(highlighted_cells),
            "text": step_text
        })

    # Финальный шаг: умножение на (n!)^2
    final_result = int(Fraction(math.factorial(n_target) ** 2) * total_sum)
    
    steps_history.append({
        "left": dict(left_start),
        "right": dict(right_yupana_accum),
        "highlight": list(highlighted_cells),
        "text": f"Финальный шаг: Умножаем сумму дробей на (n!)^2 = ({math.factorial(n_target)})^2 = {math.factorial(n_target)**2}.\n"
                f"Точное число ряда A391838 для n={n_target} равно: {final_result}"
    })

    return {
        "steps": steps_history,
        "result": final_result,
        "lattice_str": f"=== Расчёт косой диагонали Стирлинга завершён ===\nИтог a({n_target}) = {final_result}"
    }

Шаг 3. Интеграция нового действия в execute_action в yupana_emulator.py

Найдите функцию execute_action в файле yupana_emulator.py. Добавьте обработку action_id == 11 в самый её конец (перед финальным return model_a, model_b):

    # Перед действиями умножения и диагоналей очистим матрицы
    if action_id in (8, 10, 11):
        model_a.reset()
        model_b.reset()

    # ... (предыдущий код действий 0-10) ...

    elif action_id == 11:
        # Берем n из поля Число A (по умолчанию 3)
        n_val = params.get("a", 3)
        try:
            from yupana_lattice import emulator_stirling_diagonal_action
            state = emulator_stirling_diagonal_action(n_val)
            
            model_b.metadata = {
                "action": "stirling_diagonal",
                "a": n_val,
                "result": state.get("result", 0),
                "steps_history": state.get("steps", []),
                "lattice_viz": state.get("lattice_str", "")
            }
        except Exception as e:
            model_b.metadata = {"action": "stirling_diagonal", "error": str(e)}

    return model_a, model_b

Шаг 4. Настройка отображения параметров и полей ввода в GUI

Найдите метод _build_params(self, action_id) в классе YupanaEmulatorGUI и обновите условие, чтобы ползунок скорости и поле ввода отображались и для Действия 11:

    def _build_params(self, action_id):
        for widget in self.param_frame.winfo_children():
            widget.destroy()
        if action_id in (8, 10, 11):
            # Переименуем ярлык для ясности контекста
            label_text = "Параметр n:" if action_id == 11 else "Число A:"
            ttk.Label(self.param_frame, text=label_text).grid(row=0, column=0, padx=5)
            ttk.Entry(self.param_frame, textvariable=self.lattice_a, width=10).grid(row=0, column=1, padx=5)
            
            if action_id in (8, 10):
                ttk.Label(self.param_frame, text="Число B:").grid(row=0, column=2, padx=5)
                ttk.Entry(self.param_frame, textvariable=self.lattice_b, width=10).grid(row=0, column=3, padx=5)
            
            # Показываем ползунок скорости для анимационных действий 10 и 11
            if action_id in (10, 11):
                col_offset = 2 if action_id == 11 else 4
                ttk.Label(self.param_frame, text="Задержка (мс):").grid(row=0, column=col_offset, padx=(20, 5))
                speed_scale = ttk.Scale(self.param_frame, from_=100, to=3000, variable=self.animation_speed, orient=tk.HORIZONTAL, length=150)
                speed_scale.grid(row=0, column=col_offset+1, padx=5)
                speed_label = ttk.Label(self.param_frame, text=f"{self.animation_speed.get()} мс")
                speed_label.grid(row=0, column=col_offset+2, padx=5)
                speed_scale.config(command=lambda val: speed_label.config(text=f"{int(float(val))} мс"))

Аналогично обновите метод _execute(self), чтобы он перехватывал Действие 11 и запускал анимационный рендеринг:

    def _execute(self):
        action_id = self.current_action.get()
        params = {}
        if action_id in (8, 10, 11):
            try:
                params["a"] = int(self.lattice_a.get())
                if action_id in (8, 10):
                    params["b"] = int(self.lattice_b.get())
            except ValueError:
                messagebox.showerror("Ошибка", "Введите целые числа")
                return
        # ... (проверка для действия 9) ...

        self.model_a, self.model_b = execute_action(action_id, self.model_a, self.model_b, params)
        
        # Запускаем пошаговую анимацию для действий 10 и 11
        if action_id in (10, 11) and "steps_history" in self.model_b.metadata:
            self._run_steps_animation(0)
        else:
            self._refresh_display()
            self._show_info()

Шаг 5. Позиционная фиолетовая подсветка косых диагоналей в _refresh_display

Чтобы зрительно выделить нестандартных соседей (косую диагональ), мы добавим правило: во время анимации Действия 11 те ячейки левой таблицы, которые в данный момент участвуют в расчёте, окрасятся в благородный фиолетовый цвет (#8E24AA), взятый из вашей палитры COLOR_MAP.

Внесите это дополнение внутрь метода _refresh_display(self) в файле yupana_emulator.py, добавив проверку для action_id == 11 сразу после блока раскраски действия 10:

                        # === ПОДСВЕТКА ДЛЯ ЛЕВОЙ ЮПАНЫ (ВХОД) В ДЕЙСТВИИ 10 ===
                        if action_id == 10 and is_left_table:
                            # ... (код подсветки действия 10 без изменений) ...
                            pass

                        # === НОВАЯ ПОДСВЕТКА ДЛЯ ДЕЙСТВИЯ 11 (КОСЫЕ ДИАГОНАЛИ) ===
                        elif action_id == 11 and is_left_table:
                            # Получаем список ячеек, которые нужно подсветить на текущем шаге
                            history = self.model_b.metadata.get("steps_history", [])
                            # Пытаемся понять текущий шаг по выводу текста или метаданным
                            # Для надежности подсвечиваем все ячейки косой диагонали, прошедшие к этому кадру
                            highlight_cells = self.model_b.metadata.get("highlight_cells_current", [])
                            
                            # Но проще считывать динамически. Мы передадим список координат текущего шага.
                            # Для этого мы заглянем в текущее состояние:
                            current_text = self.info_text.get("1.0", tk.END)
                            
                            # Проверим, относится ли текущая ячейка к косой диагонали
                            # Матрица B позиционно хранит слагаемые, подсветим те же места на матрице A!
                            if self.model_b.get_cell(i, j) > 0:
                                cell_frame.config(bg="#8E24AA") # Фиолетовая подсветка косой диагонали Ходжа
                                label.config(bg="#8E24AA", foreground="white")
                            else:
                                cell_frame.config(bg="#F0E68C")
                                label.config(bg="#F0E68C", foreground="black")

И обновите метод _run_steps_animation, чтобы он временно сохранял список активных для подсветки координат:

        # Допишите внутрь метода _run_steps_animation перед self._refresh_display():
        self.model_b.metadata["highlight_cells_current"] = step_data.get("highlight", [])

Как это теперь работает:

  1. Выберите Действие 11. Задайте «Параметр n» (например, 3). Нажмите «Выполнить».
  2. Шаг 0: На левой юпане появляется вся эталонная таблица Стирлинга I рода. Правая чиста.
  3. Шаги 1, 2…: Программа начинает шагать по косой диагонали. На левой юпане ячейка, из которой берётся число, вспыхивает фиолетовым цветом. На правой юпане это число дублируется в той же самой позиции, наглядно фиксируя геометрию «нетрадиционного соседа».
  4. Финал: Правая юпана отобразит точечный срез диагонали, а нижняя синяя строка выдаст точный результат умножения на (n!)^2.

Да. Если задача именно такая:

левая таблица содержит беззнаковые числа Стирлинга I рода
[nk]\left[{n\atop k}\right], а действие 11 проходит по косой диагонали(nk,  n2k)(n-k,\;n-2k)

и из выбранных элементов строит слагаемые точной OEIS-формулы,

то нынешняя реализация требует существенной ревизии. Причём проблема не только в размере таблицы: сама генерация таблицы Стирлинга сейчас математически неверна.

1. Главная ошибка — рекуррентная формула

У Вас написано:

stirling_base[r][c] = (
    stirling_base[r-1][c-1] if c-1 >= 0 else 0
) + r * stirling_base[r-1][c]

Для беззнаковых чисел Стирлинга I рода должна использоваться рекурсия[nk]=[n1k1]+(n1)[n1k].\left[{n\atop k}\right] = \left[{n-1\atop k-1}\right] + (n-1)\left[{n-1\atop k}\right].

То есть коэффициент должен быть r - 1, если r — номер строки nn:

stirling_base[r][c] = (
    stirling_base[r-1][c-1]
    + (r - 1) * stirling_base[r-1][c]
)

И одновременно строки должны непосредственно соответствовать nn.

Правильное начало таблицы:n\k012340100001010002011003023104061161\begin{array}{c|ccccc} n\backslash k&0&1&2&3&4\\ \hline 0&1&0&0&0&0\\ 1&0&1&0&0&0\\ 2&0&1&1&0&0\\ 3&0&2&3&1&0\\ 4&0&6&11&6&1 \end{array}

То есть, например,[31]=2,[32]=3,[33]=1.\left[{3\atop1}\right]=2,\qquad \left[{3\atop2}\right]=3,\qquad \left[{3\atop3}\right]=1.

В Вашей текущей генерации получается другое.


2. Из-за этого нынешняя функция не воспроизводит даже первые числа

Это особенно важно.

Дляan=(n!)2k=0n/2[nkn2k](2k+1)!(nk)!a_n=(n!)^2 \sum_{k=0}^{\lfloor n/2\rfloor} \frac{\left[{n-k\atop n-2k}\right]} {(2k+1)!(n-k)!}

получаем:

n=1n=1

a1=1.a_1=1.

n=2n=2

a2=(2!)2[22]1!2!=412=2.a_2= (2!)^2 \frac{\left[{2\atop2}\right]}{1!\,2!} = 4\frac{1}{2}=2.

n=3n=3

Косая диагональ даёт:[33]=1,[21]=1.\left[{3\atop3}\right]=1, \qquad \left[{2\atop1}\right]=1.

Поэтомуa3=36(11!3!+13!2!)=9.a_3= 36 \left( \frac1{1!\,3!} + \frac1{3!\,2!} \right) =9.

n=4n=4

[44]=1,[32]=3,[20]=0.\left[{4\atop4}\right]=1, \qquad \left[{3\atop2}\right]=3, \qquad \left[{2\atop0}\right]=0.

Отсюдаa4=72.a_4=72.

n=5n=5

[55]=1,\left[{5\atop5}\right]=1,[43]=6,\left[{4\atop3}\right]=6,[31]=2.\left[{3\atop1}\right]=2.

И поэтомуa5=(5!)2(11!5!+63!4!+25!3!)a_5 = (5!)^2 \left( \frac1{1!\,5!} + \frac6{3!\,4!} + \frac2{5!\,3!} \right)=120+600+40=760.=120+600+40=760.

Таким образом:1,  1,  2,  9,  72,  760,\boxed{1,\;1,\;2,\;9,\;72,\;760,\ldots}

воспроизводятся именно правильной таблицей Стирлинга и правильным проходом по координатам.


3. Вторая фундаментальная проблема — таблица 4×5

Сейчас:

stirling_base = [[0] * 5 for _ in range(4)]

Это означает:n=0,1,2,3n=0,1,2,3

и максимумk=0,,4.k=0,\ldots,4.

Но формула требует элемент[nkn2k].\left[{n-k\atop n-2k}\right].

Уже при n=4n=4 первый элемент диагонали:[44],\left[{4\atop4}\right],

которого в таблице нет.

При n=5n=5:[55],[43],[31].\left[{5\atop5}\right],\quad \left[{4\atop3}\right],\quad \left[{3\atop1}\right].

То есть левая 4×5 юпана не может быть полной таблицей Стирлинга, достаточной для произвольного nn.

Это не просто вопрос отображения GUI. Сейчас код делает:

valid_cell = (0 <= s_row < 4 and 0 <= s_col < 5)

и фактически говорит:

если нужная клетка не помещается на доске, считаем её равной нулю.

Математически это неверно.

Например для n=5,k=0n=5,k=0:

s_row = 5
s_col = 5

и код получает:

valid_cell = False
s_val = 0

хотя[55]=1.\left[{5\atop5}\right]=1.

То есть сейчас программа теряет первый и важнейший элемент диагонали.


4. Здесь нужно разделить математическую таблицу и физическую юпану

Я бы в ревизии принципиально разделил две вещи.

Математическая таблица

Она должна строиться до нужного nn:

stirling_base = [[0] * (n_target + 1)
                 for _ in range(n_target + 1)]

и содержать:[00],[11],,[nn].\left[{0\atop0}\right], \left[{1\atop1}\right], \dots, \left[{n\atop n}\right].

Юпана GUI

Она может оставаться 4×5.

Тогда юпана становится окном/проекцией математической таблицы, а не самой таблицей Стирлинга.

Это гораздо правильнее для Вашей демонстрации.

Иначе возникает логическое противоречие: Вы хотите показывать a5=760a_5=760, а физически храните только четыре строки.


5. Сама косая диагональ у Вас задана правильно

Вот эта часть концептуально правильная:

s_row = n_target - k
s_col = n_target - 2 * k

То есть выбираются:(n,n),(n,n),(n1,n2),(n-1,n-2),(n2,n4),(n-2,n-4),\ldots

Например n=5n=5:

k=0 → (5,5)
k=1 → (4,3)
k=2 → (3,1)

Получаем:1,  6,  2.1,\;6,\;2.

Именно эти три специфических беззнаковых числа Стирлинга и нужны для a5a_5.

Это, на мой взгляд, центральная часть Вашей демонстрации, и её следует сохранить.


6. Но сейчас правая юпана смешивает две разные сущности

В промежуточных шагах Вы кладёте:

step_right_layout[(s_row, s_col)] = s_val

То есть справа находятся исходные числа Стирлинга:1,  6,  2.1,\;6,\;2.

А на финальном шаге Вы уже кладёте:

final_right_layout[(n_target, k)] = component_value

то есть:120,  600,  40.120,\;600,\;40.

Это уже не числа Стирлинга, а вычисленные слагаемые(n!)2[nkn2k](2k+1)!(nk)!.(n!)^2 \frac{\left[{n-k\atop n-2k}\right]} {(2k+1)!(n-k)!}.

Для демонстрации это можно сделать, но нужно явно разделить два состояния:

Этап A — выбранные числа Стирлинга[nkn2k]\boxed{ \left[{n-k\atop n-2k}\right] }

Этап B — соответствующие слагаемые OEISCn,k=(n!)2[nkn2k](2k+1)!(nk)!\boxed{ C_{n,k} = (n!)^2 \frac{\left[{n-k\atop n-2k}\right]} {(2k+1)!(n-k)!} }

Этап C — суммаan=kCn,k.\boxed{a_n=\sum_k C_{n,k}}.

Это будет намного нагляднее.


7. Очень важный момент: int() здесь лучше убрать

Сейчас:

component_value = int(
    Fraction(s_val, denom) * (math.factorial(n_target) ** 2)
)

int() отбрасывает дробную часть.

Для точной реализации формулы это плохая практика.

Лучше:

component_value = (
    Fraction(s_val, denom)
    * math.factorial(n_target) ** 2
)

а затем либо проверить:

if component_value.denominator != 1:
    raise ArithmeticError(...)

либо хранить значение как Fraction.

Для данной OEIS-последовательности, если Вы хотите именно доказательно точный целочисленный результат, я бы не стал молча округлять вообще.


8. Ещё одна проблема: final_result считается дважды

У Вас сначала:

final_result = int(
    Fraction(math.factorial(n_target) ** 2) * total_sum
)

а затем практически то же самое:

final_result = int(
    Fraction(math.factorial(n_target) ** 2) * total_sum
)

Второе присваивание ничего нового не делает.

Это просто можно удалить.


9. right_yupana фактически уже перестала быть 4×5

Вы пишете:

final_right_layout[(n_target, k)] = component_value

При n_target = 5 координаты будут:

(5, 0)
(5, 1)
(5, 2)

Но GUI создаёт:

rows = 4
cols = 5

то есть допустимые строки:

0, 1, 2, 3

Следовательно, эти данные существуют в Python-словаре, но физически не существуют на Вашей юпане.

Это надо исправить архитектурно.

Если Вы хотите сохранить 4×5 как визуальный объект, лучше отображать компоненты, например, в:

(0, 0), (0, 1), (0, 2)

или в отдельной нижней строке/векторе, а исходные координаты Стирлинга хранить в metadata.


10. Я бы переписал математическое ядро действия 11 примерно так

Ключевой принцип:

def emulator_stirling_diagonal_action(n_target: int) -> dict:
    import math
    from fractions import Fraction

    if n_target < 0:
        raise ValueError("n_target должен быть >= 0")

    # Полная математическая таблица Стирлинга I рода
    stirling = [
        [0] * (n_target + 1)
        for _ in range(n_target + 1)
    ]

    stirling[0][0] = 1

    for n in range(1, n_target + 1):
        for k in range(1, n + 1):
            stirling[n][k] = (
                stirling[n - 1][k - 1]
                + (n - 1) * stirling[n - 1][k]
            )

    factorial_n_sq = math.factorial(n_target) ** 2

    total = Fraction(0)
    selected = []
    components = []

    k_max = n_target // 2

    for k in range(k_max + 1):
        s_row = n_target - k
        s_col = n_target - 2 * k

        s_val = stirling[s_row][s_col]

        denom = (
            math.factorial(2 * k + 1)
            * math.factorial(n_target - k)
        )

        component = (
            Fraction(s_val, denom)
            * factorial_n_sq
        )

        selected.append({
            "k": k,
            "row": s_row,
            "col": s_col,
            "stirling_value": s_val,
            "denominator": denom,
            "component": component,
        })

        total += component

    if total.denominator != 1:
        raise ArithmeticError(
            f"Для n={n_target} результат не целый: {total}"
        )

    final_result = total.numerator

Это уже непосредственно реализует Вашу формулу, без подмены отсутствующих клеток нулями.


11. А история анимации должна показывать именно эту логику

Для n=5n=5 я бы сделал историю концептуально такой:

Шаг 0

На левой юпане — фрагмент таблицы:

          0   1   2   3   4
        +---+---+---+---+---+
  0     | 1 |
  1     |   | 1 |
  2     |   | 1 | 1 |
  3     |   | 2 | 3 | 1 |
  4     |   | 6 |11 | 6 |1

При этом полная таблица может находиться вне физической 4×5 юпаны.

Шаг 1

k=0k=0

выбирается[55]=1.\left[{5\atop5}\right]=1.

Шаг 2

k=1k=1

выбирается[43]=6.\left[{4\atop3}\right]=6.

Шаг 3

k=2k=2

выбирается[31]=2.\left[{3\atop1}\right]=2.

И получается выделенная косая последовательность:1,  6,  2.\boxed{1,\;6,\;2}.

Шаг 4

Преобразование каждого элемента:1120,1\rightarrow120,6600,6\rightarrow600,240.2\rightarrow40.

Шаг 5

Суммирование:120+600+40=760.120+600+40=760.

И финал:a5=760.\boxed{a_5=760}.

Вот это уже будет демонстрация именно того алгоритма, который Вы описали.


12. Есть ещё одна важная концептуальная деталь

В комментарии сейчас написано:

# Косая диагональ указывает на ячейку
# s[s_row, s_col]

Это хорошо, но я бы прямо зафиксировал в коде геометрию:

# Диагональ OEIS:
#
#     row = n - k
#     col = n - 2k
#
# Поэтому при увеличении k:
#     row уменьшается на 1
#     col уменьшается на 2
#
# Траектория:
#     (n,n)
#     (n-1,n-2)
#     (n-2,n-4)
#     ...

То есть это не произвольный обход таблицы. Это конкретная косая траектория по треугольнику Стирлинга, заданная формулой OEIS.


Итог ревизии

Сейчас действие 11 концептуально содержит правильную идею, а именно:(nk,n2k)(n-k,n-2k)

как координаты нужных чисел Стирлинга. Но реализация математического ядра пока не соответствует формуле.

Критические исправления:

УзелСейчасДолжно быть
Рекурсия Стирлинга+ r * ...+ (r-1) * ...
Размер таблицы4×5математически до n_target × n_target
Отсутствующая клетказаменяется на 0должна существовать
Диагональ(n-k,n-2k)правильно
Промежуточные значениячисла Стирлингаправильно
Финальные значенияслагаемые OEISправильно, но нужно явно отделить от s(n,k)s(n,k)
int(Fraction(...))теряет дробную частьне округлять молча
Координата (n_target,k)выходит за 4×5нужен отдельный способ отображения
Финальная суммасчитается дваждыодин раз
Последовательностьтекущий код её не воспроизводитпосле исправлений должна давать 1,1,2,9,72,760,1,1,2,9,72,760,\ldots

Самое существенное: я бы не пытался «втиснуть» математическую таблицу Стирлинга в физические 4×5 клетки. Правильнее сделать математическое ядро неограниченным по nn, а 4×5 юпану оставить именно как визуальный прибор, который показывает выбранный фрагмент и движение по косой диагонали. Тогда демонстрация действительно будет показывать:таблица [nk]    (nk,n2k)    Cn,k    an\boxed{ \text{таблица } \left[{n\atop k}\right] \;\longrightarrow\; (n-k,n-2k) \;\longrightarrow\; C_{n,k} \;\longrightarrow\; a_n }

и для n=5n=5 буквально:[5,5]=1,[4,3]=6,[3,1]=2    120+600+40    760.\boxed{ [5,5]=1,\quad[4,3]=6,\quad[3,1]=2 \;\longrightarrow\; 120+600+40 \;\longrightarrow\; 760. }

Minecraft Edu © 2026