Псевдокод – это формализованная запись алгоритма естественным языком с минимальным набором строгих конструкций (переменные, выражения, ветвления, циклы, подпрограммы), достаточных для однозначной интерпретации человеком и лёгкой трансляции в любой язык программирования. Псевдокод служит мостом между задачей и реализацией: фиксирует логику и инварианты, при этом не отвлекает на синтаксические детали конкретного языка.
Для ЕГЭ по информатике владение псевдокодом – практический навык: он требуется при разборе условий, построении алгоритмов, анализе сложностей, доказательстве корректности циклов и преобразовании блок-схем в программы.
Алгоритм как кортеж
Алгоритм в псевдокоде рассматривается как кортеж
A = (Σ, V, T, S, R)
где
Σ – алфавит лексем (идентификаторы, литералы, операторы);
V – конечное подмножество идентификаторов (переменных, констант, имён подпрограмм);
T – система типов (целые, вещественные, логические, строки, массивы, записи);
S – множество корректных операторов (присваивание, if, for, while, вызов подпрограммы, return/вывод/ввод);
R – отношения вывода, задающие правила синтаксиса и операционную семантику.
Исполнение – это трансформация состояния памяти M (отображение V → значения T) последовательным (или ветвящимся) применением операторов S согласно правилам R.
Синтаксическая форма
Мы используем структурно-отступный стиль (как в Python/псевдокоде CLRS). Базовые элементы:
Присваивание:
x ← expr
Условие:
если cond то
S1
иначе
S2
все
Циклы:
пока cond делай S все
для i от a до b шаг h делай S все
повторяй S пока cond
Подпрограммы:
функция f(параметры): тип
тело
вернуть значение
конец
Операционная семантика (набросок)
Присваивание: вычислить expr в текущем окружении Env, записать результат в x.
Условие: если cond = true, выполнить S1, иначе S2 (если есть).
Цикл пока: предикатная итерация – проверка cond перед телом; инвариант Inv должен быть истинным до/после каждой итерации; вариант (уменьшающаяся величина) обеспечивает завершимость.
Цикл для: синтаксический сахар над пока с автоматическим изменением счётчика.
Подпрограмма: при вызове создаётся новое локальное окружение; параметры передаются по значению (дефолт) либо по ссылке (по явной пометке).
Система типов
цел // целые
веще // вещественные
лог // булевы
строка // строковые
массив[T] // индексируемая коллекция
запись {...} // агрегаты (по необходимости)
Неявные преобразования запрещены: если нужно, пишем явно цел(x) или веще(x).
Область видимости
Локальные переменные: объявлены внутри подпрограммы/блока, недоступны снаружи.
Глобальные: объявлены снаружи всех подпрограмм (для учебных задач избегайте, если не требуется).
Тени: локальное имя может перекрывать глобальное; рекомендуется не злоупотреблять.
Параметры подпрограмм
знач – передача по значению (копия);
ссылка – псевдоним на аргумент (изменения видны снаружи);
результат – возвращаемое значение; для функций – через вернуть; для процедур – через параметры по ссылке.
Контракт (Design by Contract)
Для каждой функции/процедуры фиксируем:
имя(типы параметров) → тип результата
предусловия: P(args) // что должно быть истинно на входе
постусловия: Q(args, result) // что гарантируется на выходе
побочные эффекты: описание (или "нет")
Пример (аргмин):
функция argmin(A: массив[цел]) → запись {знач: цел, индекс: цел}
пред: |A| ≥ 1
пост: A[результат.индекс] = минимум(A) и это первое вхождение
Чистота и детерминизм
Чистая функция: возвращаемое значение определяется только параметрами, без I/O и изменения внешнего состояния. В учебных задачах ЕГЭ – стремимся к чистоте.
Линейная конструкция
ввод n
S ← 0
для i от 1 до n делай
S ← S + i
все
вывод S
Ветвление
если x % 2 = 0 то
вывод "чётное"
иначе
вывод "нечётное"
все
Циклы и инварианты
Шаблон доказательства корректности цикла пока:
инвариант Inv: ... // формулируем
// база: Inv истинно до входа
пока cond делай
// предположим Inv истинно в начале итерации
тело цикла
// докажем, что Inv истинно в конце итерации
все
// после выхода: Inv и ¬cond → цель доказана
Пример (поиск минимума):
m ← A[1]; i_min ← 1
для k от 2 до n делай
если A[k] < m то
m ← A[k]; i_min ← k
все
все
Инвариант: после обработки A[1..k]: m = min(A[1..k]), i_min – индекс первого минимума.
Массивы и алгоритмы обработки
Однопроходные агрегаты: сумма/минимум/максимум/счётчики.
Двухуказательный метод (два индекса) для сжатия/фильтрации.
Префиксные суммы для быстрых запросов по отрезкам:
P[0] ← 0
для i от 1 до n делай
P[i] ← P[i−1] + A[i]
все
// сумма на [l..r] = P[r] − P[l−1]
Рекурсия и «разделяй и властвуй»
функция gcd(a:цел, b:цел) → цел
если b = 0 то вернуть |a|
вернуть gcd(b, a % b)
конец
Присваивание
x ← выражение
Условие
если условие то
S1
иначе
S2
все
Циклы
пока условие делай
тело
все
для i от a до b шаг h делай
тело
все
повторяй
тело
пока условие
Подпрограмма
функция f(a:тип, b:тип) → типРез
// предусловие: ...
// постусловие: ...
...
вернуть результат
конец
Префиксные суммы
P[0] ← 0
для i от 1 до n делай P[i] ← P[i−1] + A[i] все
сумма(l, r) = P[r] − P[l−1]
Параметр по ссылке
процедура swap(ссылка x:цел, ссылка y:цел)
t ← x; x ← y; y ← t
конец

Упражнение 1. Формальный инвариант для суммы и количества положительных
Условие. Напишите псевдокод, который по массиву A[1..n] возвращает сумму положительных элементов и их количество, и докажите корректность с помощью инварианта цикла.
Решение (псевдокод):
функция sum_pos(A: массив[цел]) → запись {S:цел, K:цел}
треб: |A| ≥ 0
S ← 0; K ← 0
для i от 1 до |A| делай
если A[i] > 0 то
S ← S + A[i]
K ← K + 1
все
все
вернуть {S, K}
конец
Инвариант после шага i:
S = сумма положительных из A[1..i], K = их количество. База: i=0 – верно. Переход: на i+1 либо прибавляем A[i+1] и 1, либо нет; свойства сохраняются. После i=n получаем требуемое.
Упражнение 2. Аргмин с первым вхождением
Условие. Реализуйте псевдокод функции argmin(A) (минимум и индекс первого появления). Приведите предусловия/постусловия.
Решение:
функция argmin(A: массив[цел]) → запись {знач:цел, индекс:цел}
пред: |A| ≥ 1
m ← A[1]; i_min ← 1
для k от 2 до |A| делай
если A[k] < m то
m ← A[k]; i_min ← k
все
все
пост: A[i_min] = m и ∀j< i_min: A[j] ≥ m
вернуть {m, i_min}
конец
Сложность: время Θ(n), память Θ(1).
Упражнение 3. Префиксные суммы и запросы по отрезкам
Условие. По массиву A[1..n] отвечать на q запросов «сумма элементов на [l..r]». Дайте псевдокод с предварительной обработкой и оценкой сложности.
Решение:
процедура build_prefix(A: массив[цел], ссылка P: массив[цел])
P[0] ← 0
для i от 1 до |A| делай
P[i] ← P[i−1] + A[i]
все
конец
функция range_sum(P: массив[цел], l:цел, r:цел) → цел
вернуть P[r] − P[l−1]
конец
Сложность: препроцессинг Θ(n), один запрос – Θ(1), память Θ(n).
Упражнение 4. Два указателя: фильтрация нечётных
Условие. Сжать массив «на месте», оставив только нечётные элементы в начале, порядок сохранить. Вернуть новую длину.
Решение:
процедура compact_odds(ссылка A: массив[цел]) → цел
write ← 1
для read от 1 до |A| делай
если A[read] % 2 ≠ 0 то
A[write] ← A[read]
write ← write + 1
все
все
вернуть write − 1
конец
Инвариант: перед каждой итерацией A[1..write−1] – исходные нечётные в прежнем порядке. Сложность Θ(n).
Упражнение 5. Доказательство корректности цикла: поиск подмассива с максимальной суммой (Кадане)
Условие. Напишите псевдокод Кадане (значение и границы) и обоснуйте корректность шага.
Решение:
функция max_subarray(A: массив[цел]) → запись {best:цел, l:цел, r:цел}
треб: |A| ≥ 1
cur ← A[1]; best ← A[1]
start ← 1; l ← 1; r ← 1
для j от 2 до |A| делай
если A[j] ≥ cur + A[j] то
cur ← A[j]
start ← j
иначе
cur ← cur + A[j]
все
если (cur > best) или (cur = best и (j − start < r − l)) то
best ← cur; l ← start; r ← j
все
все
вернуть {best, l, r}
конец
Инвариант: cur – максимум сумм подмассивов, оканчивающихся в j; best – максимум по всем позициям < j. Шаг корректен, т.к. любая лучшая сумма, оканчивающаяся в j, либо стартует в j, либо продолжает оптимум на j−1.
Псевдокод – это дисциплина точного мышления: он делает алгоритм независимым от синтаксиса языка, подчёркивает инварианты и сложность, снимает неоднозначность и упрощает проверку. Для ЕГЭ владение псевдокодом ускоряет путь от идеи к корректному решению, повышает качество аргументации и снижает риск ошибок на границах и в циклах. Осваивайте предложенные шаблоны, следуйте чек-листу, прорабатывайте упражнения – и ваш псевдокод станет надёжной опорой при решении любых экзаменационных задач.