Доброго времени суток каждому жителю Хабрвилля! Давненько я не писал статей! Пора это исправить!

В сегодняшней статье поговорим о насущной для многих выпускников школ теме - ЕГЭ. Да-да-да! Я знаю, что Хабр - это сообщество разработчиков, а не начинающих айтишников, но сейчас ребятам как никогда нужна поддержка именно сообщества. Ребят опять посадили на дистант. Пока не ясно на какой период, но уже сейчас можно сказать, что ЕГЭ по информатике будет на компьютерах и его можно зарешать при помощи языка Python.

Вот я и подумал, чтобы не получилось как в песне, стоит этим заняться. Я расскажу про все задачи первой части и их решения на примере демо варианта ЕГЭ за октябрь.

Всех желающих - приглашаю ниже!

Быстрый перевод из системы в систему

В Python есть интересные функции bin(), oct() и hex(). Работают данные функции очень просто:

bin(156) #Выводит '0b10011100'
oct(156) #Выводит '0o234'
hex(156) #Выводит '0x9c'
Вывод в интерпретационном режиме
Вывод в интерпретационном режиме

Как вы видите, выводится строка, где 0b - означает, что число далее в двоичной системе счисления, 0o - в восьмеричной, а 0x - в шестнадцатеричной. Но это стандартные системы, а есть и необычные...

Давайте посмотрим и на них:

n = int(input()) #Вводим целое число
 
b = '' #Формируем пустую строку
 
while n > 0: #Пока число не ноль
    b = str(n % 2) + b #Остатот от деления нужной системы (в нашем сл записываем слева
    n = n // 2 #Целочисленное деление
 
print(b) #Вывод

Данная программа будет работать при переводе из десятичной системы счисления в любую до 9, так как у нас нет букв. Давайте добавим буквы:

n = int(input()) #Вводим целое число

b = '' #Формируем пустую строку

while n > 0: #Пока число не ноль
	if (n % 21) > 9: #Если остаток от деления больше 9...
		if n % 21 == 10: #... и равен 10...
			b = 'A' + b #... запишем слева A
		elif n % 21 == 11:#... и равен 11...
			b = 'B' + b#... запишем слева B

'''

И так далее, пока не дойдём до системы счисления -1 (я переводил в 21-ную систему и шёл до 20)

'''

		elif n % 21 == 11:
			b = 'B' + b
		elif n % 21 == 12:
			b = 'C' + b
		elif n % 21 == 13:
			b = 'D' + b
		elif n % 21 == 14:
			b = 'E' + b
		elif n % 21 == 15:
			b = 'F' + b
		elif n % 21 == 16:
			b = 'G' + b
		elif n % 21 == 17:
			b = 'H' + b
		elif n % 21 == 18:
			b = 'I' + b
		elif n % 21 == 19:
			b = 'J' + b
		elif n % 21 == 20:
			b = 'K' + b
	else: #Иначе (остаток меньше 10)
		b = str(n % 21) + b #Остатот от деления записываем слева
	n = n // 21 #Целочисленное деление

print(b) #Вывод

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

def convert_base(num, to_base=10, from_base=10):
    # Перевод в десятичную систему
    if isinstance(num, str): # Если число - строка, то ...
        n = int(num, from_base) # ... переводим его в нужную систему счисления
    else: # Если же ввели число, то ...
        n = int(num) # ... просто воспринять его как число
    # Перевод десятичной в 'to_base' систему
    alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" # Берём алфавит
    if n < to_base: # Если число меньше системы счисления в которую переводить...
        return alphabet[n] # ... вернуть значения номера в алфавите (остаток от деления)
    else: # Иначе...
        return convert_base(n // to_base, to_base) + alphabet[n % to_base] # ... рекурсивно обратиться к функии нахождения остатка

Вызвав функцию вывода print(convert_base(156, 16, 10)) мы переведём 156 из 10 в 16 систему счисления, а введя print(convert_base('23', 21, 4)) переведёт 23 из 4-ичной в 21-ичную систему (ответ: B).

Задача 2

Все задания беру из первого октябрьского варианта (он же вариант № 9325894) с сайта Решу.ЕГЭ.

Решение данной задачи совсем простое: банальный перебор.

print('y', 'x', 'z', 'F') #Напечатаем заголовки таблицы
for y in range(2): #Берём все переменные и меняем их в циклах '0' и '1'
	for x in range(2):
		for z in range(2):
			for w in range(2):
				F = ((not x or y) == (not z or w)) or (x and w) #Записываем функцию
				print(x, y, z, F) #Выводим результат

Результат:

Нам вывелась вся таблица истинности (1 = True, 0 = False). Но это не очень удобно. Обратите внимание, что в задании, функция равно 0, так и давайте подправим код:

print('y', 'x', 'z', 'F') #Напечатаем заголовки таблицы
for y in range(2): #Берём все переменные и меняем их в циклах '0' и '1'
	for x in range(2):
		for z in range(2):
			for w in range(2):
				F = ((not x or y) == (not z or w)) or (x and w) #Записываем функцию
				if not F:
					print(x, y, z, F) #Выводим результат

Результат:

Далее - простой анализ.

Задача 5

Данная задача легко решается простой последовательностью действий в интерпретационном режиме:

Задача 6

Перепечатали и получили ответ:

s = 0
k = 1
while s < 66:
    k += 3
    s += k
print(k)

Задача 12

В очередной раз, просто заменим слова на код:

a = '9' * 1000

while '999' in a or '888' in a:
	if '888' in a:
		a = a.replace('888', '9', 1)
	else:
		a = a.replace('999', '8', 1)
print(a)

Задача 14

Компьютер железный, он всё посчитает:

a = 4 ** 2020 + 2 ** 2017 - 15
k = 0

while a > 0:
    if a % 2 == 1:
    	k += 1
    a = a // 2

print(k)

Задача 16

Опять же, просто дублируем программу в python:

def F(n):
    if n > 0:
        F(n // 4)
        print(n)
        F (n - 1)
print(F(5))

Результат:

Задача 17

Задача с файлом. Самое сложное - достать данные из файла. Но где наша не пропадала?!

with open("17.txt", "r") as f: #Открыли файл 17.txt для чтения
    text = f.read() #В переменную text запихнули строку целиком
a = text.split("\n") #Разбили строку энтерами (\n - знак перехода на новую строку)

k = 0 #Стандартно обнуляем количество
m = -20001 #Так как у нас сумма 2-ух чисел и минимальное равно -10000, то минимум по условию равен -20000, поэтому...

for i in range(len(a)): #Обходим все элементы массива
	if (int(a[i - 1]) % 3 == 0) or (int(a[i]) % 3 == 0): #Условное условие
		k += 1 #Счётчик
		if int(a[i - 1]) + int(a[i]) > m: #Нахождение минимума
			m = int(a[i - 1]) + int(a[i])

print(k, m) #Вывод

Немного пояснений. Функция with() открывает файл считывает данные при помощи функции read() и закрывает файл. В остальном - задача стандартна.

Задача 19, 20 и 21

Все три задачи - задачи на рекурсию. Задачи идентичны, а вопросы разные. Итак, первая задача:

Пишем рекурсивную функцию и цикл перебора S:

def f(x, y, p): #Рекурсивная функция
	if x + y >= 69 or p > 3: #Условия завершения игры
		return p == 3
	return f(x + 1, y, p + 1) or f(x, y + 1, p + 1) or\
		   f(x * 2, y, p + 1) or f(x, y * 3, p + 1) #Варианты действий

for s in range (1, 58 + 1): #Перебор S
	if f(10, s, 1): #Начали с 10 камней
		print(s)
		break

Немного пояснений. В рекурсивной функции существует 3 переменные x - число камней в первой куче, y - число камней во второй куче, p - позиция. Позиция рассчитывается по таблице:

Игра

Петя

Ваня

Петя

Ваня

Петя

p

1

2

3

4

5

6

Далее - всё по условию задачи.

Вторая задача на теорию игр:

Все отличия в рамке. Ну и код, соответственно, не сильно отличается:

def f(x, y, p): #Рекурсивная функция
	if x + y >= 69 or p > 4: #Условия завершения игры
		return p == 4
	if p % 2 != 0:
		return f(x + 1, y, p + 1) or f(x, y + 1, p + 1) or\
			   f(x * 2, y, p + 1) or f(x, y * 3, p + 1) #Варианты действий
	else:
		return f(x + 1, y, p + 1) and f(x, y + 1, p + 1) and\
			   f(x * 2, y, p + 1) and f(x, y * 3, p + 1) #Варианты действий


for s in range (1, 58 + 1): #Перебор S
	if f(10, s, 1): #Начали с 10 камней
		print(s)

Отличия:

  1. Выиграл Петя, соответственно, позиция 4

  2. Так как Петя не может выиграть за один ход - он выигрывает за 2 хода (and, а не or на нечётных позициях (играх Пети))

  3. Убрали break, так как нам нужны все S, а не единственный

Последняя вариация задачи:

Сразу код:

def f(x, y, p): #Рекурсивная функция
	if x + y >= 69 or p > 5: #Условия завершения игры
		return p == 3 or p == 5
	if p % 2 == 0:
		return f(x + 1, y, p + 1) or f(x, y + 1, p + 1) or\
			   f(x * 2, y, p + 1) or f(x, y * 3, p + 1) #Варианты действий
	else:
		return f(x + 1, y, p + 1) and f(x, y + 1, p + 1) and\
			   f(x * 2, y, p + 1) and f(x, y * 3, p + 1) #Варианты действий


for s in range (1, 58 + 1): #Перебор S
	if f(10, s, 1): #Начали с 10 камней
		print(s)

Ну и всего лишь 2 отличия:

  1. Позиции 3 или 5, а не 4, так как выиграл Ваня

  2. На второй ход выигрывает Ваня и нам нужно or и and поменять. Я заменил только кратность 2.

Задача 22

Ctrl+C, Ctrl+V - наше всё! :)

for i in range(1, 100000):
	x = i
	L = 0
	M = 0
	while x > 0 :
		L = L+1
		if (x % 2) != 0:
			M = M + x % 8
		x = x // 8
	if L == 3 and M == 6:
		print(i)

Задача 23

Итак, код:

def f(x, y):
	if x > y: #Перегнали цель
		return 0
	if x == y:  #Догнали цель
		return 1
	if x < y: #Догоняем цель тремя методами
		return f(x + 1, y) + f(x + 2, y) + f(x * 2, y)

print(f(3, 10) * f(10, 12)) #Прошло через 10, значит догнали 10 и от де догоняем 12

Так как в условии задачи мы увеличиваем число, но будем числа "догонять". Три метода описаны, ну а пройти через 10 - значит дойти до него и идти от него.

Собственно, это и есть вся первая часть ЕГЭ по информатике решённая на Python.

Ссылка на репозиторий со всеми программами:

Надеюсь, что смог помочь в своей статье выпускникам и готовящимся ;)

Остался один вопрос - нужен ли разбор второй части ЕГЭ по информатике на Python? Оставлю этот вопрос на ваше голосование.

Всем удачи!

Комментарии (13)


  1. libroten
    27.10.2021 05:16
    +2

    Интересный подход :) В этом плане Питон хорош тем, что на нем быстро и просто можно посчитать что-то сложнее, чем просто выражение которое можно забить в калькулятор.

    Есть ощущение, что в некоторых задачах, решить самому будет тупо быстрее, чем писать код. Но это кому как, конечно.

    В задачах посложнее появляется побочный эффект - после написания программы мне бы например захотелось десять раз убедиться, что в коде нет косяков и что можно доверять ответам, которые он выдает. Хотя конечно, после решения задачи и так и так стоит тщательно проверять себя.

    PS давно ли сдавать ЕГЭ по информатике можно за компьютером?


    1. valerylinkov Автор
      27.10.2021 07:38

      Согласен с побочным эффектом. Но тут просто нужна тренировка. А с 2020 года ЕГЭ по инфе можно сдавать на компьютере


  1. notfaxl
    27.10.2021 07:38
    -1

    А разве последние две задачи можно решить в питоне? Я думал там эти задачи будут компилироваться дольше продолжительности экзамена и питон станет не очень-то хорошей средой для решения этих задач


    1. GospodinKolhoznik
      27.10.2021 08:59
      +6

      Сам то я сварщик ненастоящий, и питон плохо знаю, вот вопрос возник - а давно это код питоновский компилироваться стал?


      1. notfaxl
        27.10.2021 09:07
        +2

        Извиняюсь, не комплируется, не нашел нужного слова для того чтобы описать процесс решения кода внутри питона =)

        Но факт остается фактом, последние две задачи в питоне невозможно решить


        1. mSnus
          27.10.2021 09:42
          +4

          Интерпретируется


        1. Grunger
          27.10.2021 11:06

          Это не совсем так.

          Безусловно, переборное решение будет занимать много времени, но объем входных данных такой, что и решение на других языках будет работать дольше, чем время экзамена. В последней задаче предполагается написание эффективного алгоритма, который будет независимо от языка отрабатывать за разумное время.

          А предпоследняя прекрасно решается питоном.


        1. nukee
          28.10.2021 08:17
          +1

          Я, как школьник, который решает эти самые задачи, скажу - последние две задачи в невозможно решить руками, если будет задача будет чуть сложнее. Да и времени не так уж и много.


      1. 0xd34df00d
        27.10.2021 09:45
        +2

        Как минимум с 26-го декабря 1990-го года, когда был закоммичен dis.py, что намекает на наличие байткода, в который питон компилируется.


  1. Grunger
    27.10.2021 07:38
    +4

    Задания 5, 6 да и 16 не совсем актуальные. В той же демоверсии 2022 задания сложнее.

    В целом, программирование не стоит рассматривать как единственный способ решения. Небольшая ошибка в программе приведет к неверному ответу. Как перепроверка решения - безусловно.

    Да, здорово, что появляются новые способы решения в связи с появлением компьютера на экзамене, но злоупотреблять не стоит. Без понимания сути задачи "запрогать" превращается в решение совершенно другой задачи. Например, в номере 2 это уже не работа с логическими операциями, а задача "найди общее и отличия".


  1. NikolayNikT
    27.10.2021 09:48
    +2

    Задания первой части совершенно не самые сложные, можно сказать, что простые и писать код для их решения, все равно, что стрелять по воробьям из пушки. Достаточно для сдачи хорошей математической подготовки, так как большинство решений чистая математика. Некоторые темы первой части начинают изучаться еще в седьмом классе и если бы в школах реализовывалась образовательная программа, а не подготовка к экзамену. то по задачам первой части. в частности по информатике, ровно как и по любому предмету, говорить или писать как о каком-то значимом открытии вообще ненужно было.


  1. dimaaannn
    27.10.2021 23:26
    +1

    Такое ощущение, что задания написаны не с целью проверить знания, а чтобы запутать.

    Нормальные имена переменных? Нее, это для слабаков. Ведь a = b // 2 % 23 / (g + 1) - это именно та функция, которую вы будете писать в продакшен.

    А об осмысленности заданий даже речи не идёт. Хоть бы сортировку какую воткнули ради приличия.

    Вобщем, экзамен не на программирование а на запуск кода на бумажке. Лучший интерпретатор получит 100 баллов.


    1. MaxLevs
      29.10.2021 09:01
      +1

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