Comments 31
print(i * 100 + j * 10 + k)
Зачем тут умножение?Начал с тройки, но почему упустил 1000, оно же не делится на три. Кандидат думает, но не вникает в детали.
Тут либо всё делаешь аккуратно, либо не лезешь в предварительную оптимизацию которая есть зло.
for (int i = 3; i <= 1000; i += 3) {
Этот цикл заканчивается на 999
Да, на месте кандидата я бы так и ответил, но тогда он скажет - а зачем тогда <= когда можно обойтись <
Случаи разные бывают, иногда компании нужны аккуратные, внимательные к деталям люди. Или те кто может обосновать то что он делает.
Можно было вообще на 900 закончить
У всех чисел от 900 до 999 сумма цифр заведомо не меньше 10
По факту достаточно закончить на 900, т.к. сумма цифр д.б. меньше 9
Интервьюер:
Начинающий программист демонстрирует навыки функционального программирования.Ну ок, начитанный. Но сможет ли он писать код без ошибок в реальной жизни? ФП сравнительно новая концепция, тем более в применении к языку ООП. Вряд ли в нашем legacy это пригодится.
Кандидат:
**уходит с интерьвю**
Одна из задач, которую мы даём соискателям: написать код, который выводит числа от 0 до 1000, которые делятся на 3, но не делятся на 5, и сумма цифр в которых меньше десяти
...
Ну и моё решение
А оно точно выведет 9? 54? 117?
Его решение выдаёт 25 чисел, правильное решение «в лоб» — 65.
Но в принципе, ход мыслей верный, решение довольно легко исправить.
Вопрос в том, почему не исправлено в статье. Нехорошо... Как минимум коммент под решением не помешал бы.
В целом есть замечательный признак делимости на три которых отлично ложится на условия задачи в части "сумма цифр меньше 10". Но уж больно он неявно в коде сделан. Или наоборот - намеренно явно и ошибочно.
Автора бы в студию.
Не, строка
if (i + j + k != 3 && i + j + k != 6)
Неправильная
нет, не выводит, это условие не верно написано: for (int k = 0; i + j + k < 9; ++k)
if (k == 5 || k ==0)
continue;
if (i + j + k != 3 && i + j + k != 6)
Обязательно упомянуть, что это лучшее решение с его точки зрения.
Наиболее производительное на данный момент. Более чем в два раза чем "простой" и вариант@igolikov.
Но если производительность не важна, лучше конечно написать более простое решение, которое понятно другим членам команды.
Производительность почти всегда важна, но не в ущерб читаемости и поддерживаемости.
Ваше же решение получилось хоть и производительным, но, на мой взгляд, практически не поддерживаемым - любое минимальное изменение параметров из задания будет требовать картинальной переработки всего кода.
И чаще всего такой write only
код на проекте, в действительности, не нужен.
оно реально получится самым быстрым? Три вложенных цикла, условия - не константы, на один разряд числа тратится целый int, логика работы не очевидна на первый взгляд, ...
Я, правда, в Java не писец, у меня деформация от ассемблера и С, вот второе и третье решение в ассемблер хорошо ложатся. Я бы еще даже сделал
for (int i = 3; 1 <= 1000/3; i ++)
{
if (i % 5 != 0)
{
j = i*3;
if (check(j))
{
System.out.println(j);
}
}
}
заметил ошибку, должно быть for (int i = 1; i <= 1000/3; i ++)
j
на цифры. Программист напишет это через операции div/mod 10/100, а компилятор превратит деления на 10/100 в сдвиги и умножения на «магические константы» типа 0x0CCCCCCCD, 0x66666667 и 0x51EB851F. Вроде как итераций цикла в три раза меньше, зато тело цикла раздувается. Плюс ещё проверка на кратность 5, тоже тяжелее, чем у автора. Впрочем, не исключено, что ваша версия будет быстрее.Код автора
for (int k = 0; i + j + k < 9; ++k)
if (k == 5 || k == 0) continue;
можно ещё упростить
for (int k = 1; i + j + k < 9; ++k)
if (k == 5) continue;
Я бы вообще для начала спросил, как будет использоваться этот код, предъявляются ли требования к производительности и насколько вероятно изменение критериев в будущем. И только после этого думал про решение.
Хотя это конечно аналитическая профдеформация уже.
Каждый раз, когда я вижу continue
, рука тянется к киянке.
ФП сравнительно новая концепция
Гхм, Лиспу более 60 лет, Хаскелю — более 30.
Каждый раз, когда я вижу continue, рука тянется к киянке.И return в середине функции тоже не нравится? Мы бы с вами не сработались )))
Возврат в середине функции иногда может быть оправдан, continue
же — code smell в чистом виде, goto
на минималках. Его обожают начинающие ждуниоры с кашей в голове.
Мы бы с вами не сработались )))
Открывающую фигурную скобку вы где ставите, заветам Кернигана и Ритчи следуете?
Думается мне continue настолько же goto, насколько while является return'ом.
Пример кода из свежей Symfony:
foreach ($transitions as $transition) {
if ($transition->getName() !== $transitionName) {
continue;
}
$transitionBlockerList = $this->buildTransitionBlockerListForTransition($subject, $marking, $transition);
if ($transitionBlockerList->isEmpty()) {
return true;
}
}
Там далеко не джуниоры пишут проект, как мне кажется.
continue же — code smell в чистом виде, goto на минималках. Его обожают начинающие ждуниоры с кашей в головеКак-то я себе слабо представляю, что человек писал-писал break и continue, и тут его осенило: всё, хватит! Я теперь буду создавать новый блок вложенности, чтобы всё было явно прописано.
В моей же картине мира, противники continue — это либо такие старые бабки, которые учились на turbo pascal 2.0, где не было этой конструкции, и которые ворчат «не нужны нам ваши лямбды, и continue ваш сраный нам тоже не нужон!».
Либо такие математики-теоретики, адепты Вирта, которые любой код приводят к стандартным блокам «следования, ветвления, итерации». У них всё должно быть по строгим теоретическим схемам. Если уж пишем императивный код, то никакой декларативности, и наоборот.
Против break
никто не возражал, речь шла исключительно про continue
.
не нужны нам ваши лямбды
Если уж доводить до абсурда, то берите сразу машинное обучение и квантовые вычисления.
Если уж пишем императивный код, то никакой декларативности, и наоборот.
Где continue
, а где декларативность, не сравнивайте тёплое с мягким.
Против break никто не возражал, речь шла исключительно про continue.И то, и другое — скрытый goto. Есть рациональная причина, почему одно можно, а другое нельзя?
Если уж доводить до абсурдаПочему же? Лямбды — синтаксический сахар, как и continue, их можно выразить в старых конструкциях, но громоздким и избыточным кодом.
for (int k = 1; i + j + k < 9; ++k)
if (k == 5)
continue;
Кандидат знает, как работают процессоры.
Какая именно особенность работы процессора использована в том коде?
А ошибки в вашем решении зачем?
Ну и моё решение
А что 9 18 27 и тд не подходят ? Ваше решение их не выводит
Impress me или как решить задачу на интервью