Теория
Что нужно знать
Задание 12 проверяет умение исполнить алгоритм для исполнителя с фиксированным набором команд. В банке Kompege это исполнитель МТ — машина Тьюринга: бесконечная лента, читающая и записывающая головка, алфавит с пустым символом λ и программа в виде таблицы. В 2027 году тематика задания не менялась. Нужно либо выполнить программу и записать результат, либо по результату восстановить исходные данные, количество символов или их сумму.
Как устроено задание 12
По спецификации 2027 года задание проверяет умение исполнить алгоритм для конкретного исполнителя с фиксированным набором команд. В базе Kompege почти все задачи этого номера построены на исполнителе МТ — машине Тьюринга. Задание относится к разделу «Алгоритмы и программирование», оценивается в 1 первичный балл и считается заданием повышенного уровня.
- Ответ — целое число: результат, количество, сумма или восстановленное значение.
- В условии дана таблица команд и описано начальное положение ленты.
- Лента почти всегда состоит из нулей и единиц, иногда добавляются двойки, тройки или буквы.
- Встречаются задачи на прямое выполнение, подсчёт, сумму, восстановление и экстремумы.
- Файлы к заданию не прилагаются: все данные есть в тексте и таблице.
- Время выполнения — около 6 минут, но длинную ленту нельзя трассировать по шагам.
Лента, алфавит и головка
Лента бесконечна и разделена на одинаковые ячейки. В каждой ячейке записан ровно один символ алфавита. Специальный символ λ (a0) означает пустую ячейку. Последовательность из условия занимает соседние ячейки, а справа и слева от неё находятся λ. Головка читает текущую ячейку, может записать в неё символ и сдвинуться.
- В начальный момент головка стоит в состоянии q0.
- Головка может находиться слева от последовательности, справа от неё или над заданным символом.
- За один такт головка обрабатывает ровно одну ячейку.
- Машина может выйти за пределы последовательности в ячейки с λ.
- Если в условии сказано «без ведущих нулей», первый символ последовательности не равен 0.
- Двоичная последовательность на ленте — это запись числа, а не набор цифр.
- Пустые символы λ не входят в итоговое число, но важны для остановки.
- Лента не обрывается: машина может уходить влево и вправо сколько угодно.
A = {a0, a1, …, an−1}a0 = λQ = {q0, q1, …, qm−1}
Как читать таблицу команд
Программа машины Тьюринга задаётся таблицей. В первой строке перечислены символы, которые могут стоять в текущей ячейке. В первом столбце — состояния головки. На пересечении строки и столбца записана команда, которую нужно выполнить. Пустая клетка означает, что такая пара «состояние — символ» невозможна.
- Порядок столбцов может быть λ, 0, 1 или λ, 1, 0 — всегда сверяйтесь с заголовком.
- Команда состоит из трёх частей: записываемый символ, направление, новое состояние.
- Запись 0, L, q3 означает: записать 0, сдвинуться влево, перейти в q3.
- Запись 1, R, q1 означает: записать 1, сдвинуться вправо, остаться в q1.
- Если записывается тот же символ, содержимое ячейки не меняется.
- Сначала символ записывается, и только потом головка сдвигается.
- Пустая клетка не означает «ничего не делать»: команды просто нет.
- В экзаменационных задачах до пустой клетки обычно не доходят.
a, D, qa ∈ A, q ∈ QD ∈ {L, R, N, S}
Один такт и трассировка
Такт выполняется по одному и тому же правилу: посмотреть на символ под головкой, найти в таблице нужную строку и столбец, выполнить команду, записать новый символ, сдвинуть головку и сменить состояние. Для ручной проверки удобно выписывать состояние, ленту с отметкой головки и выполненную команду.
- Отметьте головку квадратными скобками: λ[1]010.
- На каждом шаге выписывайте только изменившуюся ячейку.
- Сдвиг L уменьшает позицию головки на 1, R увеличивает на 1.
- N оставляет головку на месте, но состояние может измениться.
- S завершает работу после записи символа; сдвига при S нет.
- Если состояние после команды то же, машина продолжает с новой ячейки.
- Остановитесь, когда встретили S или пустую клетку.
- В конце прочитайте последовательность между λ и переведите её в число.
write → move → stateL: i → i − 1R: i → i + 1N: i → i
Типовые программы МТ
В банке задач повторяются несколько конструкций. Одни программы просто сканируют ленту и ничего не меняют, другие переворачивают биты, сдвигают число, прибавляют единицу или обрабатывают каждый второй символ. Полезно сначала понять смысл программы на коротком примере, а потом считать результат для длинной ленты.
- Сканирование: головка идёт в одну сторону, записывая те же символы, и останавливается на λ.
- Переворот: 0 заменяется на 1, а 1 — на 0; количества нулей и единиц меняются местами.
- Сдвиг числа: дописывание нуля справа удваивает двоичное число.
- Прибавление единицы: машина идёт по младшим разрядам и обрабатывает перенос.
- Каждый второй символ: состояния чередуются, поэтому меняются позиции одной чётности.
- Циклическая замена: например, 0 → 2, 1 → 0, 2 → 1.
- Копирование и разворот строки: больше состояний, но принцип трассировки тот же.
- Если программа не меняет символы, её результат — исходная последовательность.
0 ↔ 10 → 2 → 1 → 0запись 0 справа: N → 2N
От выполнения к подсчёту
Если на ленте 1000 символов, трассировать каждый такт бессмысленно. Нужно понять, сколько символов каждого вида изменится и во что они превратятся. После этого задача сводится к системе уравнений на количества n0, n1, n2 и общую длину L. Такой подход работает и для суммы цифр.
- Обозначьте количество каждого символа: n0, n1, n2, …
- Длина последовательности: n0 + n1 + n2 + … = L.
- Сумма значений: S = 0·n0 + 1·n1 + 2·n2 + …
- Для каждой пары «было → стало» запишите изменение количества.
- Если программа переворачивает все биты, то новый n1 равен старому n0.
- Если меняется каждый второй символ, считайте позиции, а не все символы подряд.
- Условие «во сколько раз больше» даёт уравнение вида n1 = k·n0.
- Условие «на сколько больше» даёт уравнение вида S1 − S2 = d.
n0 + n1 + n2 = LS = n1 + 2n2 + 3n3n1(конечн) = n0(нач) при перевороте
Обратная задача
В обратной задаче известна конечная лента, а нужно найти начальную. Если программа обратима, команды можно выполнить в обратном порядке: вернуть старый символ, сдвинуться в противоположную сторону и перейти к предыдущему состоянию. Если обратить программу сложно, проще перебрать возможные начальные числа или строки и выполнить программу вперёд.
- Для обратимых программ меняйте L на R, R на L, N на N.
- Порядок команд при обратном ходе — от последней к первой.
- Если программа дописывает 0 справа, конечное число в два раза больше начального.
- Если программа дописывает 1, из конечного числа вычитают 1 и делят на 2.
- Перебор удобен, когда начальное число невелико или задана граница.
- Двоичная строка переводится в число через int(s, 2).
- Не забывайте про возможные ведущие нули: они могут не входить в ответ.
- Найденное значение обязательно подставьте в программу и проверьте.
int(s, 2)bin(n)[2:]N = 2·N₀ + d
Максимум, минимум и неизвестный символ
В задачах на экстремум известно конечное количество или сумма, а найти нужно наибольшее или наименьшее начальное значение. Сначала определите, какие символы программа меняет и как расположение влияет на число изменений. Затем используйте ограничение на длину последовательности. Неизвестный символ X находится из уравнения и проверяется как цифра от 0 до 9.
- Число изменённых символов зависит от их расположения, а не только от количества.
- Чтобы максимизировать начальное количество, минимизируйте или максимизируйте число изменений.
- Помните об ограничении длины: количество символов не может превышать L.
- Если в последовательности есть хотя бы один другой символ, остальные могут быть нулями.
- Для неизвестного X составьте уравнение с X и решите его.
- X — десятичная цифра, поэтому 0 ≤ X ≤ 9.
- Проверьте, что при найденном X все условия выполняются.
- Для сложных случаев переберите X или количество символов на Python.
n0(нач) = n0(конечн) + изменённыеn0(нач) ≤ L − 10 ≤ X ≤ 9
Проверка ответа
Последний шаг — убедиться, что ответ действительно получается при выполнении программы. Небольшую программу можно прогнать вручную или на Python. Для длинной ленты проверьте уравнение: подставьте найденные количества в условия задачи и пересчитайте конечную сумму или количество.
- Проверьте начальную позицию головки и состояние q0.
- Убедитесь, что учитывались λ за границами последовательности.
- Проверьте, что S срабатывает после записи, а не до неё.
- Пересчитайте конечную сумму и конечное количество символов.
- Убедитесь, что ответ — целое число в нужных единицах.
- Если ответ — двоичная строка, переведите её в десятичное число.
- Если в ответе получается ведущий ноль, проверьте, не потерян ли он.
- При переборе выведите все подходящие варианты и выберите нужный по условию.
проверка: выполнить программу зановопроверка: подставить в уравнение