EE-VibeCoding

Высокоэнтропийный вайбкодинг

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

Задача довольно простая - как с использованием минимально возможного набора слов без приставок, суффиксов, окончаний или с их минимумом, а также союзов и других вспомогательных речевых конструкций получить на выходе годный код с 0% ошибок и 90% функционала согласно такому промпт-ТЗ.

Итак, приступим. Будем использовать VS Code/блокнот с пустой папкой.

Для начала необходимо развернуть виртуальное окружение. Для этого пишем следующий промпт. >Замечание - пора на Хабре добавить в язык программирования "Промптинг"<

Развёртывание виртуального окружения

Хотеть бэш скрипт проверь .venv если нет создать, обновить pip последняя версия найти requirements.txt установить библиотеки файл этот. Опция аргумент имя файла.py скрипт проверь наличие окружения .вэнв если нет установи рекварементс.txt. Если .вэнв уже есть запускай питон 3 скрипт проверь что запуск внутри вэнв. Хотеть список зависимостей флаг --g сохранить в файл requirements-текущая дата-время.txt изменить версия == на >=. выйди из вэнв по завершению питона.

Данный промпт генерирует следующий код

`#!/bin/bash

Имя виртуального окружения

VENV_DIR=".venv"

Имя файла скрипта из аргумента

PY_SCRIPT=$1

1. Если передан флаг --g, сохраняем зависимости и выходим

if [[ "$1" == "--g" ]]; then

if [ -d "$VENV_DIR" ]; then

source "$VENV_DIR/bin/activate"

FILENAME="requirements-$(date +'%Y%m%d-%H%M%S').txt"

# Сохраняем, меняя == на >=

pip freeze | sed 's/==/>=/g' > "$FILENAME"

echo "Зависимости сохранены в $FILENAME"

deactivate

else

echo "Ошибка: .venv не найден. Нечего сохранять."

fi

exit 0

fi

2. Проверка и создание .venv

if [ ! -d "$VENV_DIR" ]; then

echo "Создаю виртуальное окружение..."

python3 -m venv "$VENV_DIR"

source "$VENV_DIR/bin/activate"

echo "Обновляю pip..."

pip install --upgrade pip

if [ -f "requirements.txt" ]; then

echo "Устанавливаю библиотеки из requirements.txt..."

pip install -r requirements.txt

fi

else

source "$VENV_DIR/bin/activate"

fi

3. Запуск Python скрипта (если передан аргумент)

if [ -n "$PY_SCRIPT" ]; then

if [ -f "$PY_SCRIPT" ]; then

echo "Запуск $PY_SCRIPT внутри $(which python)..."

python3 "$PY_SCRIPT"

else

echo "Ошибка: Файл $PY_SCRIPT не найден."

fi

else

echo "Окружение готово. Имя скрипта для запуска не указано."

fi

4. Выход из venv

deactivate

`запуская командой ./generate_requirements.sh my.py можно получить запуск скрипта с автоматической установкой виртуального окружения на основе файла requirements.txt когда виртуальное окружение уже создано и имеется повторный запуск применяется уже к установленному venv. Пример файла requirements.txt

pygame

PyOpenGL

PyOpenGL_accelerate

numpy

matplotlib

Если необходимо сканировать пакеты которые установлены, запускается скрипт с флагом --g, создаётся файл с таймстемпом requirements-20260427-213724.txt

содержащий

contourpy>=1.3.3

cycler>=0.12.1

fonttools>=4.62.1

kiwisolver>=1.5.0

matplotlib>=3.10.9

numpy>=2.4.4

...

подправленные версии с точки зрения последующей установкой новых

my.py - любой hello world, но лучше использовать промпт

пример Питон numpy вектор вывод умножение число

`import numpy as np

Создание вектора

vector = np.array([1, 2, 3])

Умножение на число

result = vector * 5

print(result)

Вывод: [ 5 10 15]`Обратить внимание на характер фраз и введение "промпт" переменных такой как вэнв и скрипт.

Следующий пример - создаём цифровой фильтр с БИХ характеристикой на языке С и проверяем его с генерацией выходного csv файла с отсчётами и значениями коэффициентов.

Цифровой фильтр - ядроДай цифровой фильтр чистый С файл калькюляйт си функция калькуляйт цикл по n отсчётам вход n, массив выходов размер n, массив отсчётов х, и коэффициентов сх одинаковые размер, число коэффициентов эникс, массив отсчётов у, и коэффициентов су одинаковые размер, число коэффициентов энигрек, отсчёты и коэффициенты флоат остальное инт размер. внутри аккумулятор акк ноль, вход х нулевой константа задать 1 затем цикл умножение с накоплением сх и с цикл умножение с накоплением су и у в аккумулятор. сдвигать элементы массивы х и у прямой порядок отсчётов на один только инкремент индекса плюс плюс, начать индекс ноль использовать временная переменная t1 t2 обмен сохранить аккумулятор массив выходов

По данному промпту генерируется следующий код, причём, +- одинаковый для любых моделей.

`void calculate(int n, float outputs, float x, float cx, int nx, float y, float* cy, int ny) {

for (int i = 0; i Отличный фильтр! Как и требуется - умножение с накоплением, сдвиг элементов на 1 только с использованием инкремента указателя. На архитектурах DSP процессоров есть команды, которые используют пост-инкремент указателя. Пример кода ассемблера и промпт для этого:

иметь реализация сдвиг массивов Х и У фрагмент кода ассемблер для Техас Инструменты процессор семейства С2000 используй пост-инкремент

`; Предположим:

; XAR4 указывает на начало массива (X[0])

; XAR5 указывает на X[1]

; AL используется как временная переменная (T1)

; PH используется как счетчик (NX - 1)

MOVZ AR6, @NX ; Загружаем NX

SUBB XAR6, #1 ; Нам нужно NX-1 итераций для сдвига

MOVZ AR0, @AR6 ; Переносим в AR0 для использования в BANZ

; Настройка указателей

MOVL XAR4, #_X ; Адрес X[0]

MOVL XAR5, #_X ; Адрес X[0]

ADDB XAR5, #1 ; Теперь XAR5 указывает на X[1]

SHIFT_LOOP:

MOV AL, *XAR4 ; T1 = X[i]

MOV AH, *XAR5 ; Временный буфер для обмена (T2)

MOV *XAR4++, AH ; X[i] = X[i+1], инкремент указателя i

MOV *XAR5++, AL ; X[i+1] = T1, инкремент указателя i+1

BANZ SHIFT_LOOP, AR0-- ; Цикл, пока AR0 не станет 0

`Довольно неплохо, но требует проверки, которую оставим за кадром. Что касается оптимизации то можно получить классическое решение

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

`; На входе:

; XAR4 - указатель на массив данных (X)

; XAR5 - указатель на массив коэффициентов (CX)

; PH - количество коэффициентов (NX)

; ACC - результат (аккумулятор)

ZAPA ; Обнулить ACC и P (регистр произведения)

MOVZ AR0, @NX ; Загрузить количество итераций (NX)

SUBB XAR0, #1 ; RPT выполняет N+1 раз, поэтому вычитаем 1

; --- Цикл умножения с накоплением (MAC) ---

; RPT повторяет следующую инструкцию AR0 раз

; *XAR4++ : берет X[i], пост-инкремент адреса

; *XAR5++ : берет CX[i], пост-инкремент адреса

RPT @AR0

MAC XAR4++, XAR5++, ACC

ADDL ACC, P ; Добавить последний результат произведения в ACC

`Достаточно попросить использовать команды RPT (рэп) - повторение заданного количества раз в регистре и MAC (мак) - умножение с накоплением. Последовательность на ассемблере RPT-MAC означает выполнить эту команду заданное количество раз, очень удобно для повторяющихся операций.

Для оптимизации попросить MACD. Оптимизированная версия

дать реализация ассемблер код фрагмент фильтр для Техас Инструменты процессор семейства С2000 используй команду Макдональдс вместо Т1 Т2

`; XAR4 — указывает на ПОСЛЕДНИЙ элемент массива данных X (X[NX-1])

; XAR5 — указывает на ПОСЛЕДНИЙ элемент массива коэффициентов CX (CX[NX-1])

; ACC — аккумулятор (результат)

; Обязательно: массивы должны идти "задом наперед" для логики сдвига MACD

SETC SXM ; Включить знаковое расширение

ZAPA ; Обнулить ACC и P

MOVZ AR0, @NX ; Загружаем число коэффициентов

SUBB XAR0, #1 ; Корректировка для RPT (выполняет N+1 раз)

; --- Главный цикл фильтрации ---

; MACD делает: P = XAR4 *XAR5, ACC = ACC + P,

; затем копирует: (XAR4+1) = XAR4 (сдвиг!)

; и делает декремент: XAR4--, XAR5-- (пост-декремент)

RPT @AR0

MACD ACC, XAR4--, XAR5--

ADDL ACC, P ; Добавить финальное произведение в ACC

`Получаем полностью оптимизированный вариант. Но это уже другая история, какой командой обнулить аккумулятор.

Создаём заголовочник

генерируй калькюляйт аш с прототипом функции кальк, документ и кислород но будь осторожен с типами и указателями

`/**

  • @file calculate.h
  • @brief Реализация цифрового фильтра (Прямая форма I).

*/

#ifndef CALCULATE_H

#define CALCULATE_H

/**

  • @brief Вычисляет выходные значения цифрового фильтра.
  • Функция проходит циклом по n отсчетам, выполняя умножение с накоплением (MAC)
  • и обновляя линии задержки x и y.
  • @param n [in] Количество итераций (отсчетов).
  • @param outputs [out] Массив для записи результатов (размер n).
  • @param x [in,out] Массив предыдущих входных отсчетов (размер nx).
  • @param cx [in] Массив коэффициентов для входов (размер nx).
  • @param nx [in] Количество входных коэффициентов.
  • @param y [in,out] Массив предыдущих выходных отсчетов (размер ny).
  • @param cy [in] Массив коэффициентов обратной связи (размер ny).
  • @param ny [in] Количество выходных коэффициентов.

*/

void calculate(int n, float outputs, float x, float cx, int nx, float y, float* cy, int ny);

#endif // CALCULATE_H

`Любезно позаботился сделав Doxygen формат описания, необходимый как воздух (кислород)

Далее продолжаем с новым контекстным окном. Пробуем сопряжение без запоминания предыдущего, описываем прототип функции промптом вместо кода. Рассчитываем коэффициенты цифрового фильтра - нерекуррентная часть скользящее среднее, рекуррентная - комплексно сопряжённые (колебательные) полюса, расположенные случайным образом на комплексной окружности.

Генерация коэффициентов цифрового фильтра и главная функцияДать проверку чистый С вызови готовая функция калькюляйт прототип аргументы вход N, массив выходов вых размер N, массив отсчётов Х, и коэффициентов СХ одинаковые размер, число коэффициентов ЭнИкс, массив отсчётов У, и коэффициентов СУ одинаковые размер, число коэффициентов ЭнИгрек, отсчёты коэффициенты флоат остальное инт, инклуд калькюляйт аш без заглушек. Сделать формирование коэффициентов СХ и СУ так что СУ индекс ноль всегда ноль. Коэффициенты СХ одинаково единица делённая на ЭнИкс размер. Коэффициенты СУ функция рандом внутри единичной комплексная окружность устойчивость учти, альфа амплитуда количество по размеру ЭнИгрек. Хардкод Пи. Обнули массивы Х и У. Массивы статические макросы ЭнИкс 5 ЭнИгрек 7 Эн 50. Дай вывод CSV файл и на экран сначала коэффициенты СХ СУ потом отсчёты вых Эн с индекс. Внимательно вызов калькюляйт число аргументов типы и массивы последовательность.

Вывод

`#include

#include

#include

#include

#include "calculate.h"

#define NX 5

#define NY 7

#define N 50

#define PI 3.14159265358979323846

int main() {

// Статические массивы

float out[N];

float x[NX] = {0};

float cx[NX];

float y[NY] = {0};

float cy[NY];

srand((unsigned int)time(NULL));

// 1. Формирование CX: 1/NX

for (int i = 0; i Создаём файл Main.c и сохраняем

После чего конечно же мы не будем долго думать как создать Makefile для gcc

MakefileХотеть Makefile для антилопы а также Си не хуже 2011 года, сканировать все файлы с и компилировать в оут исполняемый а также математика либа

`# Настройки компилятора

CC = gcc

CFLAGS = -Wall -Wextra -std=c11 -O2

LDFLAGS = -lm

Имя выходного файла

TARGET = out

Автоматический поиск всех .c файлов в текущей директории

SRCS = $(wildcard *.c)

Превращение списка .c в список .o

OBJS = $(SRCS:.c=.o)

Главная цель

all: $(TARGET)

Сборка исполняемого файла

$(TARGET): $(OBJS)

$(CC) $(OBJS) -o $(TARGET) $(LDFLAGS)

Правило для объектных файлов

%.o: %.c

$(CC) $(CFLAGS) -c $запускаем make, видим

gcc -Wall -Wextra -std=c11 -O2 -c calculate.c -o calculate.o

gcc -Wall -Wextra -std=c11 -O2 -c Main.c -o Main.o

gcc calculate.o Main.o -o out -lm

запускаем исполняемый файл ./out

Вывод программыType,Index,Value

CX,0,0.200000

CX,1,0.200000

CX,2,0.200000

CX,3,0.200000

CX,4,0.200000

CY,0,0.000000

CY,1,0.049448

CY,2,-0.008871

CY,3,0.092645

CY,4,0.083334

CY,5,-0.053389

CY,6,-0.077179

OUT,0,0.200000

OUT,1,0.409890

OUT,2,0.618494

OUT,3,0.845476

OUT,4,1.090962

OUT,5,1.127226

OUT,6,1.138613

OUT,7,1.153176

OUT,8,1.149394

OUT,9,1.122531

OUT,10,1.102652

OUT,11,1.099363

OUT,12,1.094917

OUT,13,1.089723

OUT,14,1.089271

OUT,15,1.091743

....

Теперь приступим к визуализации результатов нашего csv. Также очищаем контекст для старта с нуля

Визуализатор ПитонДа, Питон, визуализируй комплексная плоскость если коэффициенты отсчётов входа X как CX а выходов Y как СУ поля а на графике от отсчётов размести поле OUT. Читай csv формат тип CX или CY или OUT ,index,value. Индекс коэффициентов максимальный есть порядок фильтра. Пересчитать коэффициенты в нули и полюса для строить график комплексная плоскость и единичная окружность справа половина слева половина график отсчётов ОУТ от индекса. матплотлиб без пандас. открой любой csv папка текущая. данные идут списком в столбец, первый столбец тип, первая строка заголовок

`import matplotlib.pyplot as plt

import numpy as np

import glob

1. Чтение CSV (без pandas)

csv_files = glob.glob("*.csv")

if not csv_files:

raise FileNotFoundError("CSV файл не найден в текущей директории.")

filename = csv_files[0]

cx_dict, cy_dict, out_dict = {}, {}, {}

with open(filename, 'r') as f:

next(f) # Пропуск заголовка

for line in f:

parts = line.strip().split(',')

if len(parts) 1 else []

poles = np.roots(a) if len(a) > 1 else []

4. Визуализация

fig, (ax_out, ax_z) = plt.subplots(1, 2, figsize=(12, 5))

Слева: График отсчетов OUT

indices = sorted(out_dict.keys())

values = [out_dict[i] for i in indices]

ax_out.stem(indices, values)

ax_out.set_title("Отсчеты OUT")

ax_out.grid(True)

Справа: Комплексная плоскость

unit_circle = plt.Circle((0,0), 1, color='black', fill=False, linestyle='--', alpha=0.5)

ax_z.add_artist(unit_circle)

ax_z.scatter(np.real(zeros), np.imag(zeros), s=60, marker='o', edgecolors='blue', facecolors='none', label='Нули (CX)')

ax_z.scatter(np.real(poles), np.imag(poles), s=60, marker='x', color='red', label='Полюса (CY)')

ax_z.axhline(0, color='black', lw=1)

ax_z.axvline(0, color='black', lw=1)

ax_z.set_xlim([-1.5, 1.5])

ax_z.set_ylim([-1.5, 1.5])

ax_z.set_aspect('equal')

ax_z.set_title("Комплексная плоскость")

ax_z.legend()

ax_z.grid(True)

plt.tight_layout()

plt.show()

`

Ну что-ж, довольно неплохо вайб-ЦОС позволяет анализировать различные фильтры, хорошо видна КИХ-составляющая вначале пятого порядка (5 отсчётов) и БИХ с затуханием, построена единичная окружность, нанесены нули-полюса.

Далее следуют небольшие примеры для методов с конечными разностями

Столкновение Тейи и Земли. Луна не получиласьЯзык Змей Горыныч модель окружность 1 окружность 2 навстречу друг другу диаметры отношение один к четырём окружность есть 64 точки отрезков аппроксимация каждый отрезок масса отрезки связаны в точках использовать сохранение импульса закон Ньютона столкновение без рассеяния отрезки между собой закон Гука пружинят конечные разности расчёт шаг счёта по времени примерно одна окружность в секундe использовать матплотлиб визуализация мышь слайдер быстрее медленнее логарифм

`import numpy as np

import matplotlib.pyplot as plt

from matplotlib.widgets import Slider

from matplotlib.animation import FuncAnimation

Параметры системы

N = 64 # Количество точек в окружности

K_SPRING = 5000.0 # Жесткость пружин

MASS = 0.1 # Масса одной точки

R1, R2 = 1.0, 4.0 # Радиусы (1:4)

V_INIT = 2.5 # Начальная скорость сближения

Инициализация координат и скоростей

theta = np.linspace(0, 2 * np.pi, N, endpoint=False)

Окружность 1 (Малая)

pos1 = np.stack([R1 np.cos(theta) - 7.0, R1 np.sin(theta)], axis=1)

vel1 = np.zeros_like(pos1)

vel1[:, 0] = V_INIT

Окружность 2 (Большая)

pos2 = np.stack([R2 np.cos(theta) + 7.0, R2 np.sin(theta)], axis=1)

vel2 = np.zeros_like(pos2)

vel2[:, 0] = -V_INIT

Длины покоя (отрезки аппроксимации)

def get_lengths(p):

diff = np.roll(p, -1, axis=0) - p

return np.sqrt(np.sum(diff**2, axis=1))

L1, L2 = get_lengths(pos1), get_lengths(pos2)

Визуализация

fig, ax = plt.subplots(figsize=(10, 6))

plt.subplots_adjust(bottom=0.2)

line1, = ax.plot([], [], 'r-o', markersize=3, lw=1.5, label='Small (1x)')

line2, = ax.plot([], [], 'b-o', markersize=3, lw=1.5, label='Large (4x)')

ax.set_xlim(-12, 12)

ax.set_ylim(-6, 6)

ax.set_aspect('equal')

ax.legend()

Слайдер для скорости (логарифмический шаг)

ax_speed = plt.axes([0.25, 0.05, 0.5, 0.03])

slider = Slider(ax_speed, 'Time Step (log)', -4.0, -1.5, valinit=-3.0)

def compute_physics(p, v, L_rest):

# Силы упругости (Закон Гука)

diff = np.roll(p, -1, axis=0) - p

dist = np.sqrt(np.sum(diff**2, axis=1))

f_mag = K_SPRING * (dist - L_rest)

f_vec = (diff / dist[:, None]) * f_mag[:, None]

# Результирующая сила на каждую точку (соседние сегменты)

net_f = f_vec - np.roll(f_vec, 1, axis=0)

# Ускорение (Закон Ньютона)

a = net_f / MASS

return a

def update(frame):

global pos1, vel1, pos2, vel2

# Текущий шаг времени из слайдера

dt = 10**slider.val

# Расчет сил и обновление (метод Эйлера-Кромера для стабильности)

for _ in range(5): # Вложенные итерации для точности при больших dt

# Физика связей

vel1 += compute_physics(pos1, vel1, L1) * dt

vel2 += compute_physics(pos2, vel2, L2) * dt

# Обработка столкновения (Сохранение импульса)

# Проверка расстояния между всеми парами точек окружностей

dist_matrix = np.linalg.norm(pos1[:, None, :] - pos2[None, :, :], axis=2)

collisions = np.where(dist_matrix Как обычно запускаем ранее навайбкоженным ./generate_requirements.sh zmei.py с автоматической подцепкой виртуального окружения

Робот-манипулятор двузвенный. Используется матмодель, которой надо дать инъекцию в виде подсказок про арктангенс двойного аргумента (от 0 до 360) и sqrt - теорему Пифагора, а также что одной точке может соответствовать 2 положения (плюс минус дискриминант), которых тем больше чем больше звеньев.

Автоботы и ДесептиконыПропитонь двузвенный манипулятор да дай-ка в него PyGame numpy но будь осторожен с дискриминант sqrt а угол atan2 клавиатура меняй знак положение. Мышь точка задания фиксация первого звена центр координаты ортогональные сцены сетка имеется. Ай да обратная кинематика! Ух сольвер тригонометрический.

`import pygame

import numpy as np

import math

Константы сцены

WIDTH, HEIGHT = 800, 600

L1, L2 = 180, 140 # Длины звеньев

ORIGIN = np.array([WIDTH // 2, HEIGHT // 2])

def solve_ik(target, l1, l2, sign):

tx, ty = target

dist_sq = tx2 + ty2

dist = math.sqrt(dist_sq)

# Ограничение рабочей зоны

if dist > l1 + l2:

dist_sq = (l1 + l2)**2

dist = l1 + l2

# Закон косинусов для второго угла

cos_a2 = (dist_sq - l12 - l22) / (2 l1 l2)

cos_a2 = np.clip(cos_a2, -1, 1) # Защита от ошибок в sqrt

# Выбор знака локтя через atan2

sin_a2 = math.sqrt(1 - cos_a2*2) sign

a2 = math.atan2(sin_a2, cos_a2)

# Угол первого звена

a1 = math.atan2(ty, tx) - math.atan2(l2 sin_a2, l1 + l2 cos_a2)

return a1, a2

def run():

pygame.init()

screen = pygame.display.set_mode((WIDTH, HEIGHT))

clock = pygame.time.Clock()

elbow_sign = 1

while True:

for event in pygame.event.get():

if event.type == pygame.QUIT: return

if event.type == pygame.KEYDOWN:

if event.key == pygame.K_SPACE: elbow_sign *= -1

screen.fill((30, 30, 30))

# Сетка

for i in range(0, WIDTH, 40): pygame.draw.line(screen, (50,50,50), (i,0), (i,HEIGHT))

for i in range(0, HEIGHT, 40): pygame.draw.line(screen, (50,50,50), (0,i), (WIDTH,i))

# Таргет от мышки относительно центра

m_pos = np.array(pygame.mouse.get_pos()) - ORIGIN

# Расчет

a1, a2 = solve_ik(m_pos, L1, L2, elbow_sign)

# Координаты суставов

joint = ORIGIN + np.array([L1 math.cos(a1), L1 math.sin(a1)])

end_eff = joint + np.array([L2 math.cos(a1 + a2), L2 math.sin(a1 + a2)])

# Отрисовка (Ортогонально из центра)

pygame.draw.line(screen, (0, 255, 0), ORIGIN, joint, 6) # Плечо

pygame.draw.line(screen, (255, 100, 0), joint, end_eff, 6) # Предплечье

pygame.draw.circle(screen, (255, 255, 255), ORIGIN, 8)

pygame.draw.circle(screen, (200, 0, 0), end_eff.astype(int), 5)

pygame.display.flip()

clock.tick(60)

if __name__ == "__main__":

run()

`

Пробелом можно менять положение локтя, мышью - крутить роботом обеспечивая положение звеньев

Вайб-код-стих. Пропарсим с использованием питона C-файлы сделанные выше и выберем имена функций.

Рифмо-парсерПитоном я доволен

Файл открыть любой

Там С код стройный

Читай его любой

Используй regexp дорогой

И извлекай Имя функции () как родной

Те что в скобках и

Фигурных расписных

Строй список мне имён

Довольный и на экран выводи

Мой файл пай мне задай

Ищем мы всё в каталоге текущем

Всё что Си имеет текст грядущий

Но ты за ключевым словом следи

Всякие форы и ифы убери!

Устроит меня не имплементация

А только реализация

Результат:

`import re

import os

Регулярка: ищет потенциальное имя функции перед скобками,

игнорируя ключевые слова C, и проверяет наличие открывающей фигурной скобки

pattern = r'\b(?!if|while|for|switch|return|void|int|char|float|double|static|struct|else)\w+\s\([^)]\)\s*\{'

def find_functions():

# Ищем файлы с расширением .c в текущей папке

c_files = [f for f in os.listdir('.') if f.endswith('.c')]

if not c_files:

print("Си-файлов в округе не видать...")

return

for filename in c_files:

print(f"--- Файл: {filename} ---")

try:

with open(filename, 'r', encoding='utf-8') as f:

content = f.read()

# Находим все совпадения

matches = re.findall(pattern, content)

for match in matches:

# Очищаем имя от скобок и лишних символов

func_name = match.split('(')[0].strip()

# На случай, если в match попал тип данных (например, "int main")

func_name = func_name.split()[-1]

print(f"Найдена функция: {func_name}")

except Exception as e:

print(f"Ошибка при чтении {filename}: {e}")

if __name__ == "__main__":

find_functions()

`В созданных выше файлах он прекрасно находит наши функции

--- Файл: Main.c ---

Найдена функция: main

--- Файл: calculate.c ---

Найдена функция: calculate

Практически все модели обладают +- одинаковым выводом, так как обучающие выборки наверняка в большинстве своём примерно одни и те же, собраны из исходников, форумов и подготовлены по известным шаблонам датасетов. Промпты рабочие с первого раза за редким исключением.