Продалжаю решать задачки и знакомиться с языком Python на Питонтьютор. Попалась задачка которая мне очень понравилась и заставила попотеть. Условие:
Заданы две клетки шахматной доски. Если они покрашены в один цвет, то выведите слово
YES
, а если в разные цвета — тоNO
. Программа получает на вход четыре числа от 1 до 8 каждое, задающие номер столбца и номер строки сначала для первой клетки, потом для второй клетки.
И тут меня понесло куда-то не туда. Код конечно заработал, но он оказался так далек от совершенства. После решения мне стал доступен код разработчиков задачи, глянув на него я моментально понял принцип его работы и ведь я мог догадаться. Я должен был догадаться! Все было так просто и изящно. Но. У меня получилось как получилось. Обо всем по порядку.
Я рассуждал так. На шахматной доске клетки располагаются в следующей последовательности, если начинается с белой, следом идет черная, следом белая и так далее. Я принял за точку отсчета белую клетку с координатой (1;1).
Следующая белая имела бы координату (1;3), затем (1;5) и последняя в ряду (1;7). Белые второго ряда имели бы координаты (2;2), (2;4), (2;6), (2;8). Следующий третий ряд повторял бы первый ряд и отсюда уже можно было сделать вывод, что белые в нечетных рядах имеют нечетные координаты а в четных четные и наоборот, черные в нечетных рядах имели бы четные координаты а в четных нечетные. Это уже само по себе подсказывает решение, но я в тот момент этого не понял и решил действовать так, буду сравнивать координаты первой и второй клетки шаг за шагом. Чтобы определять нечетные и четные клетки решил воспользоваться остатком от деления на 2. Четные числа имели бы в остатке 0, так как любое четное число делится на два без остатка, отсюда вытекает обратное, что если число делиться на 2 без остатка то оно четное. А нечетные 1. Но и это не пришло мне в голову, логика отдыхала. Поэтому нечетные клетки я обозначил как остаток отделения не равный 0. Координаты первой клетки обозначались переменными (a;b), а второй (c;d). Условие было таким.
Данный код прошел все тесты с различными входными данными и успешно выполнил задание.
a = int(input())
b = int(input())
c = int(input())
d = int(input())
if a%2 != 0 and b%2 != 0 or a%2 == 0 and b%2 == 0:
if c%2 != 0 and d%2 != 0 or c%2 == 0 and d%2 == 0:
print ("YES")
else:
print ("NO")
else a%2 != 0 and b%2 == 0 or a%2 == 0 and b%2 != 0:
if c%2 != 0 and d%2 == 0 or c%2 == 0 and d%2 != 0:
print ("YES")
else:
print ("NO")
Что c ним (с кодом) не так? Да наверное все. Это пример того, как не нужно писать код, именно такое программисты называют говнокод.
Для этого надо было включить логику и хорошенько подумать. Во первых обозначить координаты правильно (x1;y1), а для второй клетки (x2;y2). Если бы я это сделал сразу то тогда возможно понял бы, что не правильно передаю координаты клетки. Для первого ряда координаты белых будут не (1;1), (1;3) и т.д., а (1;1), (3;1)! и т.д.. Для черных (2;1), (4:1) и т.д.. Для второго ряда для белых (2;2), (4;2), а для черных (1;2), (3;2) и т.д.. Всмотримся в координаты повнимательнее. Сумма координатов белых всегда в любом ряду четная, а для черных нечетная! Т.е. можно наугад взять любой столбец по x, например 7 и раз он нечетный значит в сумме с нечетной строкой по y он даст четное число, т.е. белый цвет. Проверим, (7;1) — белый, (7;5) — белый. А в сумме с четным числом даст нечетное, т.е. черный цвет. (7;2) — черный как и (7;6). Что это нам дает? А это нам дает отличное решение.
Сам код:
x1 = int (input())
y1 = int (input())
x2 = int (input())
y2 = int (input())
if (x1 + y1)%2 == 0 and (x2 + y2)%2 == 0 or (x1 + y1)%2 == 1 and (x2 + y2)%2 == 1:
print(‘YES’)
else:
print(‘NO’)
Можно поступить еще проще, просто сравнить остатки от деления на 2 сумм координатов первой и второй клетки, если они равны, то соответственно клетки тоже одинаковые, ведь если обе клетки с четными координатами то остатки будут нулями, а если нечетные то единицей:
x1 = int(input())
y1 = int(input())
x2 = int(input())
y2 = int(input())
if (x1 + y1)%2 == (x2 + y2)%2:
print('YES')
else:
print('NO')
Если и дальше рассуждать логически можно прийти к следующему. Сумма координатов каждой из клеток может быть либо четной либо нечетной. А сумма двух четных или двух нечетных чисел всегда будет четное число. Отсюда мы можем написать следующее условие. Если сумма координатов обеих клеток четное число то значит и клетки одинаковые.
x1 = int(input())
y1 = int(input())
x2 = int(input())
y2 = int(input())
if (x1 + y1 + x2 + y2) % 2 == 0:
print('YES')
else:
print('NO')
Это и есть код разработчиков задачи. Цель моего обучения программированию прийти в итоге к вот таким изящным решениям задач и писать не говнокод, а писать качественный код, лаконичный код, чтобы программки были как можно меньше, менее требовательны к ресурсам при том же функционале и за счет этого были быстрые и качественные. Задачки с шахматами продолжатся, теперь уже с фигурами, про них напишу в следующей заметки, так как эта и так получилась очень объемной.
Опубликованно April 13th, 2018 by Aziz Madazimov