Нейросеть пишет код на C++: где она ошибается. Эксперимент на десяти учебных задачах

Мы дали трём нейросетям десять учебных задач на C++ с ловушками: переполнение, отрицательный остаток, пустой ввод, ограничение по времени. Каждую задачу — в двух формулировках, всего 60 решений. Рассказываем, что прошло тесты, что нет и почему.

Содержание

Нейросети уверенно пишут программы. Но насколько этим программам можно верить, если задача — обычная учебная, а спрашивает начинающий? Мы проверили это на практике: взяли десять задач уровня первых месяцев обучения, в каждую заложили типичную ловушку и попросили три модели написать решение на C++.

Результат оказался не таким, как мы ожидали, и вывод из него полезнее, чем «нейросеть ошибается» или «нейросеть не ошибается».

Как устроен эксперимент

Модели. Три модели, подключённые к песочнице нашего курса: GPT-6 Luna (лёгкая), Claude 5.5 Sonnet и GPT-6.1 Sol. Запросы отправлялись 10 октября 2026 года, без системного промпта, по одному разу на каждую пару «модель — промпт».

Задачи. Десять задач, в каждой — ловушка, на которую попадаются новички.

ЗадачаЛовушка
Сумма N чиселсумма не помещается в int
Максимум из чисел до конца вводавсе числа отрицательные; чисел нет вовсе
Сколько различных чиселдвойной цикл не успевает при N = 200 000
Среднее с двумя знаками после запятойцелочисленное деление
Неотрицательный остаток от деленияв C++ -7 % 3 равно -1
НОК двух чисел до 10^18произведение переполняет 64 бита
Простое ли число до 10^12единица, квадрат простого, переполнение i * i, перебор до N
Первый элемент массива не меньше xлинейный поиск не успевает; ошибка на единицу
Високосный годгоды, кратные 100 и 400
Палиндром в строке с пробеламиcin >> s читает только первое слово

Две формулировки. Каждую задачу мы задавали дважды. Первый раз — полным условием, как в задачнике:

TXT
Дано число N (1 ≤ N ≤ 100000), затем N целых чисел, каждое по модулю
не больше 10^9. Выведите их сумму.

Напиши программу на C++17. Ввод — со стандартного ввода, вывод —
в стандартный вывод.

Второй раз — так, как обычно спрашивает ученик:

TXT
Напиши программу на C++: вводится N и потом N целых чисел, надо вывести
их сумму.

Проверка. Из каждого ответа мы брали код, компилировали его g++ 14.2 с флагами -O2 -std=c++17 и запускали на тестах с ограничением две секунды. Всего 53 теста, среди них — крайние случаи и большие входные данные. Вывод сравнивался с эталоном автоматически. Один тест — пустой ввод в задаче о максимуме — применялся только к полному условию: в коротком промпте не сказано, что выводить, если чисел нет.

Итого 60 решений: 10 задач × 2 формулировки × 3 модели.

Результат: полное условие

МодельЗадач решено
GPT-6 Luna10 из 10
Claude 5.5 Sonnet10 из 10
GPT-6.1 Sol10 из 10

Все тридцать решений прошли все тесты. Ни одна ловушка не сработала: сумма считалась в long long, остаток приводился к неотрицательному, простота проверялась перебором до корня, а поиск в массиве был двоичным.

Результат: короткий промпт

МодельПрошли тестыНе прошли
GPT-6 Luna9 из 10поиск в массиве
Claude 5.5 Sonnet8 из 10поиск в массиве, НОК
GPT-6.1 Sol9 из 10поиск в массиве

Четыре решения из тридцати тесты не прошли. Но ни в одном из них нет ошибки в алгоритме.

Поиск в массиве: модели угадывали формат ввода

Короткий промпт звучал так: «дан отсортированный массив из N чисел и Q запросов». В каком порядке идут числа во входных данных, сказано не было. В наших тестах сначала записано N, потом массив, потом Q, потом запросы. Все три модели решили иначе: N и Q в первой строке.

C++
int N, Q;
cin >> N >> Q;

Программа читает первое число массива как Q и дальше выводит бессмыслицу. Мы переставили числа во входном файле так, как ожидали модели, — и все три решения прошли самый большой тест: сто тысяч запросов к массиву из ста тысяч чисел. Алгоритм верный, двоичный поиск на месте.

Отличались модели другим. Claude 5.5 Sonnet и GPT-6.1 Sol написали под кодом, какой формат ввода они предположили; Sonnet добавила: «Если в вашей задаче другой формат ввода, поправьте считывание». GPT-6 Luna о своём предположении не сказала ничего.

НОК: программа разговаривает с пользователем

Claude 5.5 Sonnet на короткий промпт написала программу для человека, а не для проверяющей системы:

TXT
Введите два натуральных числа: НОК(4, 6) = 12

Число верное, включая случай с двумя числами по 10^18: деление выполняется раньше умножения. Но автоматическая проверка ждёт в выводе только 12 и такое решение не засчитает. В промпте не было сказано, кто будет читать вывод, — и модель выбрала вариант «для человека».

Приёмы, которые стоит перенять

Короткий промпт не называл ограничений, но модели всё равно писали осторожно. Во всех трёх решениях задачи о сумме стоит long long, хотя про размер чисел не было ни слова.

GPT-6.1 Sol при проверке простоты написала условие цикла так, чтобы произведение не могло переполниться, — d <= n / d вместо d * d <= n:

C++
for (long long d = 2; d <= n / d; ++d) {
    if (n % d == 0) {
        cout << "NO\n";
        return 0;
    }
}

Claude 5.5 Sonnet в задаче о максимуме не стала подбирать «начальное значение поменьше». Первое прочитанное число само становится максимумом, поэтому программа верно работает и с одними отрицательными числами:

C++
long long x, mx;
if (!(std::cin >> x)) {
    std::cout << "Нет данных\n";
    return 0;
}
mx = x;
while (std::cin >> x) {
    if (x > mx) mx = x;
}

Чего промпт не сказал, модели придумали сами

Мы запустили решения ещё на нескольких входах, о которых короткий промпт молчал. Засчитывать или не засчитывать тут нечего: правильного ответа условие не задаёт. Зато хорошо видно, как по-разному модели заполняют пробелы.

СитуацияGPT-6 LunaClaude 5.5 SonnetGPT-6.1 Sol
Максимум, а чисел нетничего не выводит«Нет данных»ничего не выводит
Среднее при N = 0nan«N must be positive»ничего не выводит

Три модели, три разных поведения. Какое из них верное, зависит от задачи, а её знаете только Вы.

Что из этого следует

Слабое место — условие, а не код

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

Для того, кто учится, это меняет вопрос. Не «можно ли доверять коду нейросети», а «достаточно ли точно я описал задачу».

Что дописать в промпт

  • Ограничения. «N до 200 000, числа до 10^9» — от этого зависят и тип данных, и алгоритм.
  • Формат ввода и вывода. Порядок чисел, что выводить и в каком виде. Лучше всего — пример входных и выходных данных.
  • Крайние случаи. Что делать, если чисел нет, если N равно нулю, если ответ не существует.
  • Кто читает вывод. Проверяющая система или человек: от этого зависит, нужны ли приглашения «Введите число».

Подробнее — в статье «Как написать хороший промпт: четыре части и примеры».

Проверять всё равно нужно

Даже верное решение стоит прогнать на собственных тестах. Минимальный набор:

  1. Пример из условия.
  2. Самый маленький вход: одно число, пустая строка, ноль.
  3. Самый большой вход, разрешённый ограничениями.
  4. Отрицательные числа, если они допустимы.
  5. Случай, когда ответа нет.

Если Вы не можете придумать такие тесты, значит, задача ещё не понята — и готовое решение Вас не выручит на контрольной.

Когда учитесь — не просите решение

Модели решили всё, и в этом главная опасность для ученика. Решённая за Вас задача ничему не учит. Просите подсказку, проверку своего кода или контрпример к нему — об этом статья «Как учиться с нейросетью и не разучиться думать».

Ограничения эксперимента

  • Десять задач и один запуск на каждую пару — это мало. Ответы моделей случайны: при повторе результат может отличаться.
  • Задачи простые и похожи на тысячи задач из учебников. На олимпиадных задачах, больших программах и редких библиотеках картина будет другой.
  • Мы проверяли только правильность на тестах, но не стиль кода и не качество объяснений.
  • Сравнивать модели между собой по этим данным нельзя: разница в одну задачу из десяти при одном запуске ничего не значит.

Коротко

  • 60 решений от трёх моделей, 53 теста с ловушками.
  • С полным условием все 30 решений прошли все тесты.
  • С коротким промптом не прошли 4 из 30 — и все из-за того, что формат ввода или вывода пришлось угадывать.
  • В случаях, которые условие не описывало, модели вели себя по-разному.
  • Чем точнее условие, тем надёжнее код. А проверять его тестами нужно в любом случае.

Источники

  1. Integer overflow и неопределённое поведение — cppreference.com [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/language/ub (дата обращения: 10.10.2026).
  2. std::lower_bound — cppreference.com [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/algorithm/lower_bound (дата обращения: 10.10.2026).
  3. Arithmetic operators: остаток от деления — cppreference.com [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/language/operator_arithmetic (дата обращения: 10.10.2026).
C++НейросетиПромпты