Двоичные мысли интерпретация

Шахматные задачки. Шахматная доска

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

Заданы две клетки шахматной доски. Если они покрашены в один цвет, то выведите слово YES, а если в разные цвета — то NO. Программа получает на вход четыре числа от 1 до 8 каждое, задающие номер столбца и номер строки сначала для первой клетки, потом для второй клетки.

И тут меня понесло куда-то не туда. Код конечно заработал, но он оказался так далек от совершенства. После решения мне стал доступен код разработчиков задачи, глянув на него я моментально понял принцип его работы и ведь я мог догадаться. Я должен был догадаться! Все было так просто и изящно. Но. У меня получилось как получилось. Обо всем по порядку.

Я рассуждал так. На шахматной доске клетки располагаются в следующей последовательности, если начинается с белой, следом идет черная, следом белая и так далее. Я принял за точку отсчета белую клетку с координатой (1;1).

Всё дальнейшее рассуждение некорректное, но оставлено как есть чтобы передать ход мыcлей.

Следующая белая имела бы координату (1;3), затем (1;5) и последняя в ряду (1;7). Белые второго ряда имели бы координаты (2;2), (2;4), (2;6), (2;8). Следующий третий ряд повторял бы первый ряд и отсюда уже можно было сделать вывод, что белые в нечетных рядах имеют нечетные координаты а в четных четные и наоборот, черные в нечетных рядах имели бы четные координаты а в четных нечетные. Это уже само по себе подсказывает решение, но я в тот момент этого не понял и решил действовать так, буду сравнивать координаты первой и второй клетки шаг за шагом. Чтобы определять нечетные и четные клетки решил воспользоваться остатком от деления на 2. Четные числа имели бы в остатке 0, так как любое четное число делится на два без остатка, отсюда вытекает обратное, что если число делиться на 2 без остатка то оно четное. А нечетные 1. Но и это не пришло мне в голову, логика отдыхала. Поэтому нечетные клетки я обозначил как остаток отделения не равный 0. Координаты первой клетки обозначались переменными (a;b), а второй (c;d). Условие было таким.

  1. ЕСЛИ первая И вторая координата первой клетки (уже очень глупо получается, но рассуждал я к сожалению именно так) была нечетной ИЛИ первая И вторая координата первой клетки была четной
  2. снова проверяем условие ЕСЛИ первая И вторая координата второй клетки тоже нечетная ИЛИ первая и вторая координата второй клетки тоже четная
  3. выводим на экран YES — т.е. две клетки одного цвета. Поясню. Если бы обе координаты каждой клетки были бы нечетные то как было видно выше в нечетных рядах у нас белые клетки, соответственно обе клетки были бы белые, а с четными координатами черные.
  4. ИНАЧЕ, т.е. если данные не соответствуют вышеперечисленному условию выводим на экран NO — т.е. обе клетки разного цвета. Но! Белая клетка может иметь четные координаты в четных рядах. И если первая клетка получает нечетные координаты а вторая четные, то они обе будут белые но программка напишет NO — они разные. На этом этапе именно так. Поэтому продолжаю условие изначальное условие №1
  5. ИНАЧЕ если первая координата первой клетки нечетная И вторая координата первой клетки четная ИЛИ наоборот первая координата первой клетки четная, а вторая нечетная, проверяем условие
  6. ЕСЛИ первая координата второй клетки нечетная И вторая координата второй клетки четная ИЛИ наоборот первая координата второй клетки четная, а вторая нечетная
  7. выводим на экран YES — т.е. две клетки одного цвета. Это условие исправляет тот недочет, когда первая и вторая клетка могут иметь четные и нечетные координаты соответственно и быть при этом одного цвета.
  8. ИНАЧЕ, т.е. если данные не соответствуют вышеперечисленному условию выводим на экран NO

Данный код прошел все тесты с различными входными данными и успешно выполнил задание.

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). Что это нам дает? А это нам дает отличное решение.

  1. ЕСЛИ сумма координатов первой клетки четная И сумма координатов второй клетки четная ИЛИ сумма координатов первой клетки нечетная И сумма координатов второй клетки нечетная
  2. выводим на экран YES — т.е. две клетки одного цвета.
  3. ИНАЧЕ т.е. если данные не соответствуют вышеперечисленному условию выводим на экран NO.

Сам код:

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')

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

Поделитесь, если Вам понравилось!