Месяца два назад в комментариях вот к этой статье участники сообщества привели с десяток решений несложной задачи. Решения интересные, в чём-то красивые, но они напоминают мне сферического коня в вакууме.
Поясню. Джуниор разработчик проходит собеседование. Ему дали следующее задание.
Одна из задач, которую мы даём соискателям: написать код, который выводит числа от 0 до 1000, которые делятся на 3, но не делятся на 5, и сумма цифр в которых меньше десяти
Интервьюер хочет убедиться что:
Кандидат знает синтаксис языка программирования.
Он умеет решать алгоритмические задачи в рамках имеющихся ресурсов.
Его не придётся переучивать на стандарты использующиеся в компании.
Разработчик решает следующие проблемы:
Ему нужно выставить себя в лучшем свете
Ему нужно обойти других кандидатов
И в конечном итоге получить вакансию
Давайте попробуем максимизировать пользу для обоих участников процесса.
Решение #1 от @Filex
List<Integer> numList = IntStream.range(MIN, MAX).boxed()
.filter(i -> (i % GOOD_DIV == 0 && i % BAD_DIV != 0 && checkSumDigits(i)))
.toList();
Интервьюер:
Начинающий программист демонстрирует навыки функционального программирования.Ну ок, начитанный. Но сможет ли он писать код без ошибок в реальной жизни? ФП сравнительно новая концепция, тем более в применении к языку ООП. Вряд ли в нашем legacy это пригодится.
Кандидат:
Я вижу что интервьюер хмурится. Я быстренько говорю что это моё хобби, для роста. И накидываю более традиционное решение
Решение #2 от @pin2t
for (int i = 0; i < 1000; i++) {
if (i % 3 == 0 && i % 5 != 0 && (i / 100 + (i / 10) % 10 + i % 10) < 10) {
out.println(i);
}
}
Интервьер:
Решение вполне себе рабочее, но уж слишком примитивное. Сможет ли начинающий программист расти? Понимает ли он что всякое число в коде это потенциальная проблема?
Кандидат:
Это я вам набрасал интуитивное решение. В реальной жизни я бы так поступил когда нужно срочно сделать прототип и показать заказчику. Потом разумеется будут написаны тесты и код будет приведён в соответствии со стандартами.
Решение #3 от @igolikov
for (int i = 3; i <= 1000; i += 3) {
if (i % 5 != 0 && check(i)) {
System.out.println(i);
}
}
Интервьер:
Молодец, отсеял 2/3 заведомо неправильных решений, оптимизировать может. Но циклы в Java вполне себе оптимизированы, а вот деление операция долгая. Тут оно не нужно в принципе. Начал с тройки, но почему упустил 1000, оно же не делится на три. Кандидат думает, но не вникает в детали.
Кандидат:
Тут либо всё делаешь аккуратно, либо не лезешь в предварительную оптимизацию которая есть зло.
Ну и моё решение
for (int i = 0; i < 10; ++i)
for (int j = 0; j + i < 10; ++j)
for (int k = 0; i + j + k < 9; ++k)
if (k == 5 || k ==0)
continue;
if (i + j + k != 3 && i + j + k != 6)
continue;
print(i * 100 + j * 10 + k)
Интервьюер:
Кандидат знает, как работают процессоры. Он вникает в суть задачи. Может быть немного overqualified, но есть потенциал роста. Но сможет ли он писать поддерживаемый код?
Кандидат:
Обязательно упомянуть, что это лучшее решение с его точки зрения. Но если производительность не важна, лучше конечно написать более простое решение, которое понятно другим членам команды.