Головка движется по ленте с нулями и единицами и меняет символы по таблице команд. Нужно понять, что делает программа, и найти наибольшее или наименьшее возможное число нулей или единиц в исходной последовательности.
Как читать таблицу
Строка — состояние, столбец — символ под головкой.
Команда «0, L, q1»: записать 0, сдвинуться влево, перейти в q1.
S — остановка после записи символа.
Как решать
Прогнать программу на короткой ленте (5–8 символов) на бумаге.
Сформулировать, что машина делает с последовательностью.
Связать числа нулей и единиц до и после и найти крайний случай.
Проверить крайний случай моделированием.
Типичные ошибки
Забыть, что машина может остановиться раньше конца последовательности.
Перепутать направление: головка начинает справа.
Не учесть ограничение на длину последовательности.
Разобранные варианты
Сначала прогони программу на короткой ленте и найди закономерность, потом открой разбор.
Вариант 1
вычитание единицы · максимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 1000 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
1
0
q0
λ, L, q1
q1
λ, S, q1
0, S, q1
1, L, q1
После выполнения программы на ленте осталось ровно 312 нулей. Определите максимально возможное число нулей в исходной последовательности.
Разбор
Шаг 1. Что делает программа. В состоянии q0 головка на пустой ячейке сдвигается влево — на последний символ последовательности. Головка идёт влево от конца последовательности. Каждый 0 заменяется на 1, пока не встретится 1; эта единица заменяется на 0, и машина останавливается. Если записать последовательность как A10…0 (в конце t нулей), получится A01…1 — это вычитание единицы из двоичного числа.
Шаг 2. Считаем. Пусть в конце t нулей перед единицей: A10…0 → A01…1. Нули после работы — нули части A и ещё один (бывшая 1): z(A) + 1 = 312, значит z(A) = 311. Нулей было z(A) + t = 311 + t. Длина A равна 1000 − 1 − t и не меньше z(A), откуда t ≤ 1000 − 1 − 311 = 688. Наибольшее число нулей: 311 + 688 = 999.
Пример крайней ленты (сжато: «0×5» — пять нулей подряд, «(01)×3» — 010101): 0×311 1 0×688. После работы: 0×312 1×688.
Ответ: 999
Проверка на Python. Перебрать все ленты из тысячи символов нельзя, поэтому программа моделирует МТ и проверяет крайний случай из рассуждения: печатает число символов после работы и в исходной ленте.
L = 'λ'
prog = {
('q0', 'λ'): ('λ', 'L', 'q1'),
('q1', 'λ'): ('λ', 'S', 'q1'),
('q1', '1'): ('0', 'S', 'q1'),
('q1', '0'): ('1', 'L', 'q1'),
}
def run(seq):
tape = dict(enumerate(seq))
pos, st = len(seq), 'q0' # головка справа от последовательности
while True:
w, mv, st2 = prog[(st, tape.get(pos, L))]
tape[pos] = w
st = st2
if mv == 'S':
return ''.join(c for k, c in sorted(tape.items()) if c != L)
pos += -1 if mv == 'L' else 1
# крайний случай из рассуждения
seq = '0' * 311 + '1' * 1 + '0' * 688
after = run(seq)
print(after.count('0')) # должно быть 312
print(seq.count('0'))
Вариант 2
инверсия через один · максимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 1500 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
0
1
q0
λ, L, q1
q1
λ, S, q1
1, L, q2
0, L, q2
q2
λ, S, q2
0, L, q1
1, L, q1
После выполнения программы на ленте осталось ровно 1112 нулей. Определите максимально возможное число нулей в исходной последовательности.
Разбор
Шаг 1. Что делает программа. В состоянии q0 головка на пустой ячейке сдвигается влево — на последний символ последовательности. Состояния q1 и q2 чередуются: в q1 символ инвертируется (0 ↔ 1), в q2 остаётся прежним. Значит, если нумеровать символы справа налево, меняются все символы на нечётных местах, а на чётных — остаются.
Шаг 2. Считаем. Пронумеруем символы справа налево. Нечётных мест 750, чётных 750. Пусть на нечётных местах было a нулей, на чётных — b. После работы нули на нечётных местах станут единицами и наоборот: нулей станет (750 − a) + b = 1112, то есть b = a + 362. Было нулей a + b = 2a + 362. Чтобы это было наибольшим, берём a как можно больше: a ≤ 750 и b = a + 362 ≤ 750, значит a = 388, b = 750. Ответ: 388 + 750 = 1138.
Пример крайней ленты (сжато: «0×5» — пять нулей подряд, «(01)×3» — 010101): (01)×362 0×776. После работы: 0×725 (10)×387 1.
Ответ: 1138
Проверка на Python. Перебрать все ленты из тысячи символов нельзя, поэтому программа моделирует МТ и проверяет крайний случай из рассуждения: печатает число символов после работы и в исходной ленте.
L = 'λ'
prog = {
('q0', 'λ'): ('λ', 'L', 'q1'),
('q1', 'λ'): ('λ', 'S', 'q1'),
('q1', '0'): ('1', 'L', 'q2'),
('q1', '1'): ('0', 'L', 'q2'),
('q2', 'λ'): ('λ', 'S', 'q2'),
('q2', '0'): ('0', 'L', 'q1'),
('q2', '1'): ('1', 'L', 'q1'),
}
def run(seq):
tape = dict(enumerate(seq))
pos, st = len(seq), 'q0' # головка справа от последовательности
while True:
w, mv, st2 = prog[(st, tape.get(pos, L))]
tape[pos] = w
st = st2
if mv == 'S':
return ''.join(c for k, c in sorted(tape.items()) if c != L)
pos += -1 if mv == 'L' else 1
# крайний случай из рассуждения
seq = '01' * 362 + '0' * 776
after = run(seq)
print(after.count('0')) # должно быть 1112
print(seq.count('0'))
Вариант 3
прореживание единиц · максимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 1200 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
0
1
q0
λ, L, q1
q1
λ, S, q1
0, L, q1
1, L, q2
q2
λ, S, q2
0, L, q1
0, L, q1
После выполнения программы на ленте осталось ровно 431 единица. Определите максимально возможное число единиц в исходной последовательности.
Разбор
Шаг 1. Что делает программа. В состоянии q0 головка на пустой ячейке сдвигается влево — на последний символ последовательности. Состояние q2 означает «предыдущий (правее) символ — сохранённая единица». Если в q2 снова встречается 1, она стирается в 0. Поэтому в каждой группе подряд идущих единиц длины r, считая справа, единицы через одну заменяются нулями: остаётся ⌈r / 2⌉ единиц.
Шаг 2. Считаем. Группа из r единиц даёт ⌈r / 2⌉ единиц. На одну оставшуюся единицу приходится не больше двух исходных (группа чётной длины 2m даёт ровно m). Поэтому исходных единиц не больше 2·431 = 862; столько получается, например, у ленты из 338 нулей и 862 единиц подряд (862 ≤ 1200).
Пример крайней ленты (сжато: «0×5» — пять нулей подряд, «(01)×3» — 010101): 0×338 1×862. После работы: 0×339 (10)×430 1.
Ответ: 862
Проверка на Python. Перебрать все ленты из тысячи символов нельзя, поэтому программа моделирует МТ и проверяет крайний случай из рассуждения: печатает число символов после работы и в исходной ленте.
L = 'λ'
prog = {
('q0', 'λ'): ('λ', 'L', 'q1'),
('q1', 'λ'): ('λ', 'S', 'q1'),
('q1', '0'): ('0', 'L', 'q1'),
('q1', '1'): ('1', 'L', 'q2'),
('q2', 'λ'): ('λ', 'S', 'q2'),
('q2', '0'): ('0', 'L', 'q1'),
('q2', '1'): ('0', 'L', 'q1'),
}
def run(seq):
tape = dict(enumerate(seq))
pos, st = len(seq), 'q0' # головка справа от последовательности
while True:
w, mv, st2 = prog[(st, tape.get(pos, L))]
tape[pos] = w
st = st2
if mv == 'S':
return ''.join(c for k, c in sorted(tape.items()) if c != L)
pos += -1 if mv == 'L' else 1
# крайний случай из рассуждения
seq = '0' * 338 + '1' * 862
after = run(seq)
print(after.count('1')) # должно быть 431
print(seq.count('1'))
Вариант 4
пары «01» · максимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 1200 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
0
1
q0
λ, L, q1
q1
λ, S, q1
0, L, q1
1, L, q2
q2
λ, S, q2
1, L, q1
1, L, q2
После выполнения программы на ленте осталось ровно 515 нулей. Определите максимально возможное число нулей в исходной последовательности.
Разбор
Шаг 1. Что делает программа. В состоянии q0 головка на пустой ячейке сдвигается влево — на последний символ последовательности. Состояние q2 означает «правее стоит единица». Если в q2 встречается 0, он заменяется на 1. Поэтому каждый 0, стоящий сразу слева от группы единиц (то есть каждая пара «01»), превращается в 1, а остальные символы не меняются.
Шаг 2. Считаем. Каждая пара «01» теряет нуль. Если пар r, то нулей было Z = 515 + r. Для r пар нужно r нулей и r единиц, а единиц всего 1200 − Z, поэтому r ≤ 1200 − (515 + r), то есть 2r ≤ 685, r ≤ 342. Наибольшее Z = 515 + 342 = 857.
Пример крайней ленты (сжато: «0×5» — пять нулей подряд, «(01)×3» — 010101): 0×516 (10)×341 1×2. После работы: 0×515 1×685.
Ответ: 857
Проверка на Python. Перебрать все ленты из тысячи символов нельзя, поэтому программа моделирует МТ и проверяет крайний случай из рассуждения: печатает число символов после работы и в исходной ленте.
L = 'λ'
prog = {
('q0', 'λ'): ('λ', 'L', 'q1'),
('q1', 'λ'): ('λ', 'S', 'q1'),
('q1', '0'): ('0', 'L', 'q1'),
('q1', '1'): ('1', 'L', 'q2'),
('q2', 'λ'): ('λ', 'S', 'q2'),
('q2', '1'): ('1', 'L', 'q2'),
('q2', '0'): ('1', 'L', 'q1'),
}
def run(seq):
tape = dict(enumerate(seq))
pos, st = len(seq), 'q0' # головка справа от последовательности
while True:
w, mv, st2 = prog[(st, tape.get(pos, L))]
tape[pos] = w
st = st2
if mv == 'S':
return ''.join(c for k, c in sorted(tape.items()) if c != L)
pos += -1 if mv == 'L' else 1
# крайний случай из рассуждения
seq = '0' * 516 + '10' * 341 + '1' * 2
after = run(seq)
print(after.count('0')) # должно быть 515
print(seq.count('0'))
Вариант 5
инверсия через один · минимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 1500 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
0
1
q0
λ, L, q1
q1
λ, S, q1
1, L, q2
0, L, q2
q2
λ, S, q2
0, L, q1
1, L, q1
После выполнения программы на ленте осталось ровно 931 нуль. Определите минимально возможное число нулей в исходной последовательности.
Разбор
Шаг 1. Что делает программа. В состоянии q0 головка на пустой ячейке сдвигается влево — на последний символ последовательности. Состояния q1 и q2 чередуются: в q1 символ инвертируется (0 ↔ 1), в q2 остаётся прежним. Значит, если нумеровать символы справа налево, меняются все символы на нечётных местах, а на чётных — остаются.
Шаг 2. Считаем. Пронумеруем символы справа налево. Нечётных мест 750, чётных 750. Пусть на нечётных местах было a нулей, на чётных — b. После работы нули на нечётных местах станут единицами и наоборот: нулей станет (750 − a) + b = 931, то есть b = a + 181. Было нулей a + b = 2a + 181. Чтобы это было наименьшим, берём a как можно меньше: b = a + 181 ≥ 0 и a ≥ 0, значит a = 0, b = 181. Ответ: 0 + 181 = 181.
Пример крайней ленты (сжато: «0×5» — пять нулей подряд, «(01)×3» — 010101): 1×1138 (01)×181. После работы: (10)×569 0×362.
Ответ: 181
Проверка на Python. Перебрать все ленты из тысячи символов нельзя, поэтому программа моделирует МТ и проверяет крайний случай из рассуждения: печатает число символов после работы и в исходной ленте.
L = 'λ'
prog = {
('q0', 'λ'): ('λ', 'L', 'q1'),
('q1', 'λ'): ('λ', 'S', 'q1'),
('q1', '0'): ('1', 'L', 'q2'),
('q1', '1'): ('0', 'L', 'q2'),
('q2', 'λ'): ('λ', 'S', 'q2'),
('q2', '0'): ('0', 'L', 'q1'),
('q2', '1'): ('1', 'L', 'q1'),
}
def run(seq):
tape = dict(enumerate(seq))
pos, st = len(seq), 'q0' # головка справа от последовательности
while True:
w, mv, st2 = prog[(st, tape.get(pos, L))]
tape[pos] = w
st = st2
if mv == 'S':
return ''.join(c for k, c in sorted(tape.items()) if c != L)
pos += -1 if mv == 'L' else 1
# крайний случай из рассуждения
seq = '1' * 1138 + '01' * 181
after = run(seq)
print(after.count('0')) # должно быть 931
print(seq.count('0'))
Вариант 6
прибавление единицы · максимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 1200 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
0
1
q0
λ, L, q1
q1
1, S, q1
1, S, q1
0, L, q1
После выполнения программы на ленте осталось ровно 592 нуля. Определите максимально возможное число нулей в исходной последовательности.
Разбор
Шаг 1. Что делает программа. В состоянии q0 головка на пустой ячейке сдвигается влево — на последний символ последовательности. Головка идёт влево от конца последовательности. Каждая 1 заменяется на 0, пока не встретится 0; он заменяется на 1, и машина останавливается. Последовательность A01…1 (в конце t единиц) превращается в A10…0 — это прибавление единицы к двоичному числу. Если нулей нет совсем, слева допишется 1.
Шаг 2. Считаем. Пусть в конце t единиц перед нулём: A01…1 → A10…0. Нулей после: z(A) + t = 592, а было z(A) + 1 = 592 − t + 1. Это больше всего при t = 0 (последовательность оканчивается нулём): 592 + 1 = 593. Нужно, чтобы в A поместилось 592 нулей: 1200 − 1 ≥ 592 — выполняется.
Пример крайней ленты (сжато: «0×5» — пять нулей подряд, «(01)×3» — 010101): 0×592 1×607 0. После работы: 0×592 1×608.
Ответ: 593
Проверка на Python. Перебрать все ленты из тысячи символов нельзя, поэтому программа моделирует МТ и проверяет крайний случай из рассуждения: печатает число символов после работы и в исходной ленте.
L = 'λ'
prog = {
('q0', 'λ'): ('λ', 'L', 'q1'),
('q1', 'λ'): ('1', 'S', 'q1'),
('q1', '1'): ('0', 'L', 'q1'),
('q1', '0'): ('1', 'S', 'q1'),
}
def run(seq):
tape = dict(enumerate(seq))
pos, st = len(seq), 'q0' # головка справа от последовательности
while True:
w, mv, st2 = prog[(st, tape.get(pos, L))]
tape[pos] = w
st = st2
if mv == 'S':
return ''.join(c for k, c in sorted(tape.items()) if c != L)
pos += -1 if mv == 'L' else 1
# крайний случай из рассуждения
seq = '0' * 592 + '1' * 607 + '0' * 1
after = run(seq)
print(after.count('0')) # должно быть 592
print(seq.count('0'))
Вариант 7
прореживание единиц · минимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 1000 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
1
0
q0
λ, L, q1
q1
λ, S, q1
1, L, q2
0, L, q1
q2
λ, S, q2
0, L, q1
0, L, q1
После выполнения программы на ленте осталось ровно 292 единицы. Определите минимально возможное число единиц в исходной последовательности.
Разбор
Шаг 1. Что делает программа. В состоянии q0 головка на пустой ячейке сдвигается влево — на последний символ последовательности. Состояние q2 означает «предыдущий (правее) символ — сохранённая единица». Если в q2 снова встречается 1, она стирается в 0. Поэтому в каждой группе подряд идущих единиц длины r, считая справа, единицы через одну заменяются нулями: остаётся ⌈r / 2⌉ единиц.
Шаг 2. Считаем. Группа из r единиц даёт ⌈r / 2⌉ ≥ 1 единиц, а одиночная единица остаётся сама. Значит, единиц после работы не больше, чем было, и минимум — когда все 292 единиц одиночные (разделены нулями): нужно 583 ≤ 1000 клеток.
Пример крайней ленты (сжато: «0×5» — пять нулей подряд, «(01)×3» — 010101): 0×417 (10)×291 1. После работы: 0×417 (10)×291 1.
Ответ: 292
Проверка на Python. Перебрать все ленты из тысячи символов нельзя, поэтому программа моделирует МТ и проверяет крайний случай из рассуждения: печатает число символов после работы и в исходной ленте.
L = 'λ'
prog = {
('q0', 'λ'): ('λ', 'L', 'q1'),
('q1', 'λ'): ('λ', 'S', 'q1'),
('q1', '0'): ('0', 'L', 'q1'),
('q1', '1'): ('1', 'L', 'q2'),
('q2', 'λ'): ('λ', 'S', 'q2'),
('q2', '0'): ('0', 'L', 'q1'),
('q2', '1'): ('0', 'L', 'q1'),
}
def run(seq):
tape = dict(enumerate(seq))
pos, st = len(seq), 'q0' # головка справа от последовательности
while True:
w, mv, st2 = prog[(st, tape.get(pos, L))]
tape[pos] = w
st = st2
if mv == 'S':
return ''.join(c for k, c in sorted(tape.items()) if c != L)
pos += -1 if mv == 'L' else 1
# крайний случай из рассуждения
seq = '0' * 417 + '10' * 291 + '1' * 1
after = run(seq)
print(after.count('1')) # должно быть 292
print(seq.count('1'))
Вариант 8
пары «01» · максимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 800 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
0
1
q0
λ, L, q1
q1
λ, S, q1
0, L, q1
1, L, q2
q2
λ, S, q2
1, L, q1
1, L, q2
После выполнения программы на ленте осталось ровно 280 нулей. Определите максимально возможное число нулей в исходной последовательности.
Разбор
Шаг 1. Что делает программа. В состоянии q0 головка на пустой ячейке сдвигается влево — на последний символ последовательности. Состояние q2 означает «правее стоит единица». Если в q2 встречается 0, он заменяется на 1. Поэтому каждый 0, стоящий сразу слева от группы единиц (то есть каждая пара «01»), превращается в 1, а остальные символы не меняются.
Шаг 2. Считаем. Каждая пара «01» теряет нуль. Если пар r, то нулей было Z = 280 + r. Для r пар нужно r нулей и r единиц, а единиц всего 800 − Z, поэтому r ≤ 800 − (280 + r), то есть 2r ≤ 520, r ≤ 260. Наибольшее Z = 280 + 260 = 540.
Пример крайней ленты (сжато: «0×5» — пять нулей подряд, «(01)×3» — 010101): 0×281 (10)×259 1. После работы: 0×280 1×520.
Ответ: 540
Проверка на Python. Перебрать все ленты из тысячи символов нельзя, поэтому программа моделирует МТ и проверяет крайний случай из рассуждения: печатает число символов после работы и в исходной ленте.
L = 'λ'
prog = {
('q0', 'λ'): ('λ', 'L', 'q1'),
('q1', 'λ'): ('λ', 'S', 'q1'),
('q1', '0'): ('0', 'L', 'q1'),
('q1', '1'): ('1', 'L', 'q2'),
('q2', 'λ'): ('λ', 'S', 'q2'),
('q2', '1'): ('1', 'L', 'q2'),
('q2', '0'): ('1', 'L', 'q1'),
}
def run(seq):
tape = dict(enumerate(seq))
pos, st = len(seq), 'q0' # головка справа от последовательности
while True:
w, mv, st2 = prog[(st, tape.get(pos, L))]
tape[pos] = w
st = st2
if mv == 'S':
return ''.join(c for k, c in sorted(tape.items()) if c != L)
pos += -1 if mv == 'L' else 1
# крайний случай из рассуждения
seq = '0' * 281 + '10' * 259 + '1' * 1
after = run(seq)
print(after.count('0')) # должно быть 280
print(seq.count('0'))
Вариант 9
инверсия через один · максимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 1500 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
0
1
q0
λ, L, q1
q1
λ, S, q1
1, L, q2
0, L, q2
q2
λ, S, q2
0, L, q1
1, L, q1
После выполнения программы на ленте осталось ровно 1024 нуля. Определите максимально возможное число нулей в исходной последовательности.
Разбор
Шаг 1. Что делает программа. В состоянии q0 головка на пустой ячейке сдвигается влево — на последний символ последовательности. Состояния q1 и q2 чередуются: в q1 символ инвертируется (0 ↔ 1), в q2 остаётся прежним. Значит, если нумеровать символы справа налево, меняются все символы на нечётных местах, а на чётных — остаются.
Шаг 2. Считаем. Пронумеруем символы справа налево. Нечётных мест 750, чётных 750. Пусть на нечётных местах было a нулей, на чётных — b. После работы нули на нечётных местах станут единицами и наоборот: нулей станет (750 − a) + b = 1024, то есть b = a + 274. Было нулей a + b = 2a + 274. Чтобы это было наибольшим, берём a как можно больше: a ≤ 750 и b = a + 274 ≤ 750, значит a = 476, b = 750. Ответ: 476 + 750 = 1226.
Пример крайней ленты (сжато: «0×5» — пять нулей подряд, «(01)×3» — 010101): (01)×274 0×952. После работы: 0×549 (10)×475 1.
Ответ: 1226
Проверка на Python. Перебрать все ленты из тысячи символов нельзя, поэтому программа моделирует МТ и проверяет крайний случай из рассуждения: печатает число символов после работы и в исходной ленте.
L = 'λ'
prog = {
('q0', 'λ'): ('λ', 'L', 'q1'),
('q1', 'λ'): ('λ', 'S', 'q1'),
('q1', '0'): ('1', 'L', 'q2'),
('q1', '1'): ('0', 'L', 'q2'),
('q2', 'λ'): ('λ', 'S', 'q2'),
('q2', '0'): ('0', 'L', 'q1'),
('q2', '1'): ('1', 'L', 'q1'),
}
def run(seq):
tape = dict(enumerate(seq))
pos, st = len(seq), 'q0' # головка справа от последовательности
while True:
w, mv, st2 = prog[(st, tape.get(pos, L))]
tape[pos] = w
st = st2
if mv == 'S':
return ''.join(c for k, c in sorted(tape.items()) if c != L)
pos += -1 if mv == 'L' else 1
# крайний случай из рассуждения
seq = '01' * 274 + '0' * 952
after = run(seq)
print(after.count('0')) # должно быть 1024
print(seq.count('0'))
Вариант 10
вычитание единицы · максимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 1200 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
1
0
q0
λ, L, q1
q1
λ, S, q1
0, S, q1
1, L, q1
После выполнения программы на ленте осталось ровно 200 нулей. Определите максимально возможное число нулей в исходной последовательности.
Разбор
Шаг 1. Что делает программа. В состоянии q0 головка на пустой ячейке сдвигается влево — на последний символ последовательности. Головка идёт влево от конца последовательности. Каждый 0 заменяется на 1, пока не встретится 1; эта единица заменяется на 0, и машина останавливается. Если записать последовательность как A10…0 (в конце t нулей), получится A01…1 — это вычитание единицы из двоичного числа.
Шаг 2. Считаем. Пусть в конце t нулей перед единицей: A10…0 → A01…1. Нули после работы — нули части A и ещё один (бывшая 1): z(A) + 1 = 200, значит z(A) = 199. Нулей было z(A) + t = 199 + t. Длина A равна 1200 − 1 − t и не меньше z(A), откуда t ≤ 1200 − 1 − 199 = 1000. Наибольшее число нулей: 199 + 1000 = 1199.
Пример крайней ленты (сжато: «0×5» — пять нулей подряд, «(01)×3» — 010101): 0×199 1 0×1000. После работы: 0×200 1×1000.
Ответ: 1199
Проверка на Python. Перебрать все ленты из тысячи символов нельзя, поэтому программа моделирует МТ и проверяет крайний случай из рассуждения: печатает число символов после работы и в исходной ленте.
L = 'λ'
prog = {
('q0', 'λ'): ('λ', 'L', 'q1'),
('q1', 'λ'): ('λ', 'S', 'q1'),
('q1', '1'): ('0', 'S', 'q1'),
('q1', '0'): ('1', 'L', 'q1'),
}
def run(seq):
tape = dict(enumerate(seq))
pos, st = len(seq), 'q0' # головка справа от последовательности
while True:
w, mv, st2 = prog[(st, tape.get(pos, L))]
tape[pos] = w
st = st2
if mv == 'S':
return ''.join(c for k, c in sorted(tape.items()) if c != L)
pos += -1 if mv == 'L' else 1
# крайний случай из рассуждения
seq = '0' * 199 + '1' * 1 + '0' * 1000
after = run(seq)
print(after.count('0')) # должно быть 200
print(seq.count('0'))
Для самостоятельного решения
Варианты 11–15 без разборов. Ответ можно проверить кнопкой.
Вариант 11
инверсия через один · минимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 1000 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
0
1
q0
λ, L, q1
q1
λ, S, q1
1, L, q2
0, L, q2
q2
λ, S, q2
0, L, q1
1, L, q1
После выполнения программы на ленте осталось ровно 679 нулей. Определите минимально возможное число нулей в исходной последовательности.
Вариант 12
пары «01» · максимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 1500 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
0
1
q0
λ, L, q1
q1
λ, S, q1
0, L, q1
1, L, q2
q2
λ, S, q2
1, L, q1
1, L, q2
После выполнения программы на ленте осталось ровно 541 нуль. Определите максимально возможное число нулей в исходной последовательности.
Вариант 13
прореживание единиц · максимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 800 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
1
0
q0
λ, L, q1
q1
λ, S, q1
1, L, q2
0, L, q1
q2
λ, S, q2
0, L, q1
0, L, q1
После выполнения программы на ленте осталось ровно 380 единиц. Определите максимально возможное число единиц в исходной последовательности.
Вариант 14
прибавление единицы · максимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 1500 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
0
1
q0
λ, L, q1
q1
1, S, q1
1, S, q1
0, L, q1
После выполнения программы на ленте осталось ровно 537 нулей. Определите максимально возможное число нулей в исходной последовательности.
Вариант 15
инверсия через один · максимум
Исполнитель МТ — головка, которая движется вдоль бесконечной ленты из ячеек; в каждой ячейке записан ровно один символ алфавита, в том числе пустой символ λ. За один такт головка в состоянии q, обозревая символ в текущей ячейке, выполняет команду из таблицы: записывает символ, затем сдвигается влево (L), вправо (R), остаётся на месте (N) или останавливается (S), и переходит в новое состояние. Команда «1, L, q1» означает: записать 1, сдвинуться влево, перейти в состояние q1. В начальный момент головка находится в состоянии q0.
На ленте в соседних ячейках записана последовательность из 999 символов, включающая только нули и единицы. Ячейки справа и слева от последовательности заполнены пустыми символами «λ». В начальный момент головка расположена в ближайшей ячейке справа от последовательности.
Программа работы исполнителя:
λ
1
0
q0
λ, L, q1
q1
λ, S, q1
0, L, q2
1, L, q2
q2
λ, S, q2
1, L, q1
0, L, q1
После выполнения программы на ленте осталось ровно 580 нулей. Определите максимально возможное число нулей в исходной последовательности.