ЕГЭ, ОГЭ, программирование и робототехника в Калининграде

Алгоритм решения задания 8. Часть 3

Пришло время рассмотреть третий тип задания 8 ЕГЭ по информатике. Ранее мы уже научились применять функцию product() для поиска номера подходящего слова в первом типе и количества комбинаций во втором типе этих заданий.

Третий тип похож на второй: мы также считаем последовательности, удовлетворяющие условиям. Главное отличие — фраза «все цифры различны». Поэтому вместо размещений с повторениями используем размещения без повторений.

Примеры этого типа решаются по одному шаблону. Перейдём к алгоритму.

Алгоритм решения

Алгоритм почти совпадает со вторым типом. Единственное принципиальное отличие: вместо product() используем permutations().

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

Начнём с типовой формулировки:

Сколько существует восьмеричных пятизначных чисел, не содержащих в своей записи цифру 1, в которых все цифры различны и никакие две чётные или две нечётные цифры не стоят рядом?

Открыть задание

Числа восьмеричные, поэтому алфавит обычно состоит из цифр от 0 до 7. Числа пятизначные, значит укажем r=5. Кроме того, нужно проверить чередование чётных и нечётных цифр.

Переберём все соседние пары. Для каждой пары чётность цифр должна различаться: если первая цифра чётная, вторая должна быть нечётной, и наоборот.

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

Функция принимает один аргумент — проверяемую последовательность цифр в виде строки:

def alternates_parity(digits):

В цикле переберём индексы всех цифр, кроме последней. Остановиться нужно на предпоследней позиции, потому что мы сравниваем digits[i] и digits[i + 1].

def alternates_parity(digits):
    for i in range(len(digits) - 1):

Определим чётность текущей цифры с индексом i:

def alternates_parity(digits):
    for i in range(len(digits) - 1):
        current_is_even = int(digits[i]) % 2 == 0

Аналогично определим чётность следующей цифры:

def alternates_parity(digits):
    for i in range(len(digits) - 1):
        current_is_even = int(digits[i]) % 2 == 0
        next_is_even = int(digits[i + 1]) % 2 == 0

Если значения current_is_even и next_is_even равны, обе цифры имеют одинаковую чётность. Такая последовательность не подходит, поэтому функция сразу возвращает False:

def alternates_parity(digits):
    for i in range(len(digits) - 1):
        current_is_even = int(digits[i]) % 2 == 0
        next_is_even = int(digits[i + 1]) % 2 == 0
        if current_is_even == next_is_even:
            return False

Если цикл завершился, и одинаковая чётность ни разу не встретилась, цифры чередуются. После цикла возвращаем True:

def alternates_parity(digits):
    for i in range(len(digits) - 1):
        current_is_even = int(digits[i]) % 2 == 0
        next_is_even = int(digits[i + 1]) % 2 == 0
        if current_is_even == next_is_even:
            return False
    return True

Функция для проверки чередования чётности готова. Используем её во всех примерах статьи.

Вернёмся к задаче. Из восьмеричного алфавита сразу исключим цифру 1, потому что она запрещена условием:

from itertools import permutations

# Сразу исключаем 1
alph = '0234567'

Далее вставляем код нашей функции:

from itertools import permutations

# Сразу исключаем 1
alph = '0234567'

def alternates_parity(digits):
    for i in range(len(digits) - 1):
        current_is_even = int(digits[i]) % 2 == 0
        next_is_even = int(digits[i + 1]) % 2 == 0
        if current_is_even == next_is_even:
            return False
    return True

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

Вся наша программа в итоге выглядит так:

from itertools import permutations

# Сразу исключаем 1
alph = '0234567'

def alternates_parity(digits):
    for i in range(len(digits) - 1):
        current_is_even = int(digits[i]) % 2 == 0
        next_is_even = int(digits[i + 1]) % 2 == 0
        if current_is_even == next_is_even:
            return False
    return True

count = 0
for val in permutations(alph, r=5):
    val = "".join(val)
    if val[0] != '0' and alternates_parity(val):
        count += 1

print(count)

Программа выводит 180. Это ответ.

Пример 1

Перейдём к следующему заданию:

Сколько существует десятичных четырёхзначных чисел, в которых все цифры различны и никакие две чётные или две нечётные цифры не стоят рядом?

Открыть задание

Здесь ещё проще. Алфавит состоит из десятичных цифр от 0 до 9, а числа четырёхзначные, поэтому укажем r=4.

Для проверки чередования чётности используем готовую функцию. Меняются только алфавит и значение r:

from itertools import permutations

alph = '0123456789'

def alternates_parity(digits):
    for i in range(len(digits) - 1):
        current_is_even = int(digits[i]) % 2 == 0
        next_is_even = int(digits[i + 1]) % 2 == 0
        if current_is_even == next_is_even:
            return False
    return True

count = 0
for val in permutations(alph, r=4):
    val = "".join(val)
    if val[0] != '0' and alternates_parity(val):
        count += 1

print(count)

Программа выводит 720. Это ответ.

Пример 2

Для закрепления рассмотрим ещё одно задание:

Сколько существует шестнадцатеричных трёхзначных чисел, в которых все цифры различны и никакие две чётные или две нечётные цифры не стоят рядом?

Открыть задание

Тут мы впервые работаем с системой счисления выше 10 в задании 8. Здесь воспользуемся строками из модуля string.

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

from string import ascii_uppercase, digits

print(digits + ascii_uppercase[:6])
>>>0123456789ABCDEF

С помощью этих строк сформируем алфавит:

from string import ascii_uppercase, digits
from itertools import permutations

alph = digits + ascii_uppercase[:6]

Но функцию alternates_parity() нужно немного изменить. При преобразовании шестнадцатеричной цифры в число передадим функции int() основание системы счисления — 16.

Если попытаться преобразовать шестнадцатеричное число A1 без указания основания, Python выдаст ошибку:

hex_num = "A1"

print(int(hex_num))
>>>ValueError: invalid literal for int() with base 10

Вторым аргументом int() укажем основание системы счисления:

hex_num = "A1"

print(int(hex_num, 16))
>>>161

С учётом этого исправим функцию alternates_parity():

from string import ascii_uppercase, digits
from itertools import permutations

alph = digits + ascii_uppercase[:6]

def alternates_parity(value):
    for i in range(len(value) - 1):
        current_is_even = int(value[i], 16) % 2 == 0
        next_is_even = int(value[i + 1], 16) % 2 == 0
        if current_is_even == next_is_even:
            return False
    return True

Остальная часть программы уже знакома. Полное решение выглядит так:

from string import ascii_uppercase, digits
from itertools import permutations

alph = digits + ascii_uppercase[:6]

def alternates_parity(value):
    for i in range(len(value) - 1):
        current_is_even = int(value[i], 16) % 2 == 0
        next_is_even = int(value[i + 1], 16) % 2 == 0
        if current_is_even == next_is_even:
            return False
    return True

count = 0
for val in permutations(alph, r=3):
    val = "".join(val)
    if val[0] != '0' and alternates_parity(val):
        count += 1

print(count)

Программа выводит 840. Это ответ.

Итоги

Мы разобрали три типа задания 8 и научились выбирать между product() и permutations(). В завершение запишем шаблон для третьего типа:

from itertools import permutations

alph = '*1'

count = 0
for val in permutations(alph, r=*2):
    val = "".join(val)
    if val[0] != '0' and *3:
        count += 1

print(count)

Здесь:

  • *1 — алфавит из условия: для восьмеричной системы цифры от 0 до 7, для троичной — от 0 до 2 и так далее;
  • *2 — количество цифр в числе; значение подставляется без кавычек;
  • *3 — остальные условия. Для чисел не забудьте отдельно исключить ведущий ноль.

На этом мы закончили разбор алгоритмов решения задания 8 ЕГЭ по информатике. А попрактиковаться в решении заданий данного типа вы можете в нашем тренажёре.

Разберём эту тему на бесплатном пробном занятии

Преподаватель покажет, как решать такие задачи, и подскажет, с чего начать подготовку. Группы до 8 человек, очно в Калининграде и онлайн.

Записаться на пробное занятие