Во всех примерах я буду использовать либо C++, либо Python
Олимпиадное программирование, безусловно, является одним из захватывающих и интеллектуально стимулирующих видов соревновательной деятельности в мире информатики. Эта область привлекает молодых умов своей сложностью, нестандартностью задач и возможностью проявить свои навыки в области алгоритмов и программирования. Однако, за этим блеском и азартом соревнований скрываются страшные картины, о которых мы сегодня и поговорим.
Ален Голуб в своей книге «Веревка достаточной длины, чтобы выстрелить себе в ногу» пишет, что «читабельность кода — это способность человека понять, что делает код, не запуская его». Читабельность кода важна не только для того, чтобы другие разработчики могли легко разобраться в вашем коде, но и для того, чтобы вы сами могли поддерживать и улучшать свой код в будущем.
В своей жизни, я много вижу, как люди укорачивают названия переменных на олимпиадах, и это больше всего меня злит. Почему? Потому что во многих книгах, да взять даже того же Роберта Мартина с книгой «Чистый код / Создание, анализ и рефакторинг», то даже там говорится, что название переменной, функции или структуры данных должно иметь название с кратким описанием, смотря на которое мы сразу сможем понять, зачем этот кусок кода нужен. Я соглашусь использовать короткие наименования, если дело касается математических переменных. Давайте посмотрим на пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | //-| Плохой стиль именований |---- #include <iostream> int x; // Переменная с неясным предназначением void p(); // Функция с неясным назначением int main() { x = 5; p(); std::cout << "x: " << x << std::endl; return 0; } void p() { // Изменение значения неясной переменной x = 10; } //-| Хороший стиль именований |---- #include <iostream> int userAge; // Возраст пользователя void printUserAge(); // Функция для вывода возраста пользователя int main() { userAge = 25; printUserAge(); std::cout << "User's Age: " << userAge << std::endl; return 0; } void printUserAge() { // Изменение и вывод возраста пользователя userAge = 30; std::cout << "Updated User's Age: " << userAge << std::endl; } |
Из этого примера мы видим, как важно правильно именовать функции и переменные.
Качество, также как и читаемость, является важной частью программирования, которую необходимо учитывать. Нередко я также писал плохой код, когда только учился, но важно понимать, что все мы были такими, а кто-то может быть и сейчас таков. Главное не в том, что мы писали грязный код, а в том, что мы осознаем это и перестаем его писать.
Так в чем же суть, на чем я остановился? Правильно, на качестве. Программа подобна автомобилю, в который мы можем установить качественную или не качественную деталь. Будет ли автомобиль двигаться с не качественной деталью? Да, конечно. На долго ли? Возможно, и на долго, но, как правило, нет. Так и с программой. Для меня главным правилом является "1 функция - 1 действие". Как это понимать, рассмотрим на примере:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | // Функция, которая делает две вещи: проверяет, является ли число простым, и выводит его на экран void check_and_print(int n) { bool prime = true; // Флаг, указывающий, является ли число простым for (int i = 2; i <= sqrt(n); i++) { if (n % i == 0) { prime = false; // Число не простое, если делится на i break; // Выходим из цикла } } if (prime) { cout << n << " "; // Выводим простое число } } // Главная функция программы int main() { int limit; cout << "Введите предел для поиска простых чисел: "; cin >> limit; for (int n = 2; n <= limit; n++) { check_and_print(n); // Вызываем функцию, которая делает две вещи } cout << endl; return 0; } ///////////////////////////////////// // Функция, которая проверяет, является ли число простым bool is_prime(int n) { for (int i = 2; i <= sqrt(n); i++) { if (n % i == 0) { return false; // Число не простое, если делится на i } } return true; // Число простое, если не нашлось делителей } // Функция, которая выводит все простые числа до заданного предела void print_primes(int limit) { for (int n = 2; n <= limit; n++) { if (is_prime(n)) { cout << n << " "; // Выводим простое число } } cout << endl; } // Главная функция программы int main() { int limit; cout << "Введите предел для поиска простых чисел: "; cin >> limit; print_primes(limit); // Вызываем функцию для вывода простых чисел return 0; } |
Теперь когда у нас каждая функция выполняет собственную задачу, нам удобнее улучшать программу. Даже просто с точки зрения читабильности - нам понятнее.
Подчеркнем главные мысли. 1. Я не хочу сказать, что олимпиады ненужны, я лишь хочу сказать - что они убивают новичков, с точки зрения проффесиональности. 2. Не бойтесь использовать структуры данных.
На этой замечательной ноте, я хочу с вами попращаться!