Но разработчики TrapC уверяют, что их компилятор минимизирует накладные расходы, выполняя большинство проверок во время компиляции, а не работы программы.
А это как, простите? В этих искусственных примерах - верю, но в них и любой линтер вроде cppcheck ругнётся. А если у меня в функцию передан указатель на начало массива и из совершенно другой переменной выводится его длина, то компилятор же хрен докажет что длина корректная, это нужно анализировать всю программу.
отсутствуют макросы: упрощение синтаксиса и устранение ошибок, связанных с их использованием;
Замена того что делалось макросами на примерно эквивалентные им шаблоны упростит синтаксис? Ну-ну.
Но (код) сохраняет высокую производительность благодаря оптимизации работы компилятора.
Какой-то словесный салат. Работающий эффективно компилятор и компилятор, порождающий эффективный код - это очевидно разные вещи. "Автоматически освобождает память" - программа/среда исполнения, а не компилятор. Если компилятор вставил в код проверку, а не надо ли "автоматически" освободить память - эта проверка съела минимум одну ассемблерную инструкцию, чудес не будет. (А в многопоточной программе такие проверки на произвольную память делать больно, многопоточные структуры стараются разнести во времени работу с данными и выделение памяти.)
При каких-то условиях (не знаю могу хорошо сформулировать каких, не тестировщик) ссылка на комментарии (с /comments/) не позволяет видеть текст поста, в то время как ссылка на пост при прокрутке вниз отображает комментарии.
Желание получить 99/100% времени и что-нибудь хорошее по памяти понятно, но не должно быть частью использования LeetCode как инструмента отбора кандидатов. Если вас мало интересует оптимизация - потому что интересует мало и нефиг отбирать людей по тому что вас интересует мало, если вас сильно интересует оптимизация - потому что нормальная оптимизация делается профилировщиком, а не на глаз. Опять же, результаты LeetCode не отличаются хорошей повторяемостью, особенно по памяти.
Не существует идеала, но можно делать лучше. В исходном описании задачи FizzBuzz для собеседований подчёркивается, что её суть не в
Кандидатам даётся функциональная задача, и они должны выработать идеальное решение.
а в том чтобы человек произвёл на свет хоть какое-нибудь решение. (Замечу что стандарты именно LeetCode на большинстве задач тоже очень мягкие: вы можете написать сильно неоптимальный код и он всё ещё впишется в ограничения.)
Затем, задачи должны быть неожиданными. В частности, даже для HR выглядит несложным попросить программистов компании написать три-четыре элементарных задачи с нуля вместо извлечения их из базы. Это заведомо уберёт проблему
Как насчёт разницы между кандидатами, уже встречавшими эту задачу викторины, и теми, кто ещё её не встречал?
HR может понимать специфику деятельности... несколько превратно.
Сказано: "Наша компания занимается разведением слонопотамов. Вы будете работать над программой мониторинга слонопотамьего здоровья."
На самом деле - вариант А: есть задача анализа слонопотамьих популяций в десяти разных заповедниках, в четырёх из них уже кем-то сделаны свои системы с которыми надо интегрироваться, для остальных шести нужно сделать аналогичное решение и свести всё это в единую систему представления данных.
На самом деле - вариант Б: есть фермы разведения слонопотамов; в промышленном разведении слонопотамов нужна программа, которая учитывает анализы и рекомендует как подстраивать рацион. Решение уже написано, но его надо поддерживать в актуальном состоянии, вносить в его логику поправки на основе новых статей по медицине слонопотамов, добавлять полезные фичи в интерфейс и т.д.
Так вот, HR может иметь смутное представление, а кто вообще такие слонопотамы про которых постоянно говорят в офисе и в принципе не понимать разницы между А и Б. А с точки зрения разработки задачи ну очень разные.
1) батарея автоматических тестов по прошлым багам является инструментом защиты от регрессий и, по совместительству, хранилищем странных краевых случаев;
2) писанный протокол ручного тестирования позволяет быть уверенным что по крайней мере функциональность основных, оптимистичных путей выполнения не сломана совсем;
С моей точки зрения это вполне себе практически полезные, достижимые разумными усилиями гарантии.
Если есть 1) "старшие товарищи" и 2) способность сказать "возможно тут проблема" вместо двадцати железобетонных аргументов "это так и надо" (к сожалению, она есть не у всех), то хорошо. А если нет ни того ни другого, то приходится рекомендовать клиентам использовать Firefox, потому что приложение кушает гигабайт в десять минут, а ответственный за фронт программист считает что так и надо.
Я могу быть пристрастен, лично мне как раз было неплохим отвлечением поупихивать вчерашний LeetCode в 7 мс времени, но от полного игнора производительности я проблемы в задачах за которые платят деньги вижу достаточно регулярно.
И в реальном энтерпрайзе редко заморачиваешься, например, производительностью.
Моё развлечение прошлой недели: попытки отлаживать код, исполнение которого занимает 18 часов. После пары часов медитации с инструментами анализа, без изменения базового алгоритма, время уменьшается до 75 минут. Да, это относительно экзотичный сценарий, но не то чтобы нулевой.
А самое главное, как раз если в норме команда разработки "не заморачивается" производительностью, то оценка асимптотик должна быть на уровне спинного мозга: логика "если окажется медленно, поправим" работает только если кто-то post factum тратит время и силы на оценку не медленно ли оно. А без этого отдел маркетинга поможет клиентам свыкнуться с мыслью что с этой скоростью надо жить, и мир в целом станет немного хуже.
Я всегда понимал эту задачу как упражнение на рефлексию над моделями. Достаточно ли того упрощения реального люка которое у меня в голове? Какие особенности я забыл?
Реально я видел и квадратные люки крышки, и я довольно сильно ожидаю что даже такую крышку в закрываемое ей отверстие вы нарочно-то замучаетесь просовывать, с шестиугольной миссия становится практически невыполнима (потому что а) крышка толстая и б) она закрывает люк потому что размер дырки меньше размера крышки, она лежит на "полочке"; численное соотношение между этими параметрами при котором задача для шестиугольника становится нерешаемой даже теоретически читатель может вывести самостоятельно, для люка метрового диаметра это единицы сантиметров).
Я в основном хотел обратить внимание что ответы даже в хорошем случае показывают не "как кандидат мыслит", а некоторую сумму "как он мыслит" + "как он вербально рефлексирует" + "как у него получается вести себя в обстановке собеседования".
Если вас как раз интересует что-то близкое к этой сумме, то и хорошо. Но это не универсальное предпочтение.
Оно показывает хорошо если человек а) умеет вслух рассказывать как он мыслит, б) либо умеет это делать в стрессовой ситуации, либо не нервничает на интервью. Проблема в том, что хорошие программисты... не обязательно обладают этими свойствами.
Проблема в том, что "есть 12 типов людей, по 12 знакам Зодиака [забывая про Змееносца]" - это современное попсовое изложение. "Во времена магии и драконов" астрология была большим искусством, всякие натальные карты, привязка ко времени первого крика младенца, etc. Поэтому вряд ли дело в сезонности, просто старое доброе "люди не умеют не искать закономерности".
Затем что истинный вопрос X, на который хочется ответ - "будет ли группе разработки хорошо, если этот человек проработает в ней полгода". Самый очевидный способ ответа требует полгода.
Поэтому все пытаются найти такой индикатор Y, который а) вычислим за разумное время и б) коррелирует с X. Поскольку задача примерно одна и та же, разные агенты приходят к очень похожим индикаторам.
А дальше приходит Гудхарт и говорит "а хрен, в окружении где многие оптимизируют Y, он больше не коррелирует с X". Люди пытаются решать проблему, в первую очередь поиском какого-то волшебного индикатора который бы был устойчив к этому эффекту, "истинного имени" X. Как ни странно, это не получается.
(Как известно людям, соприкасающимся со вступительными экзаменами, более-менее универсальный способ - задавать простые, коррелирующие с желаемой характеристикой, но при этом неожиданные вопросы. Но массовый рынок неизбежно трактует "неожиданный вопрос" как "вопрос из сборника неожиданных вопросов".)
Я усложняю чтобы получить точный ответ. (Не то чтобы сильно усложняю: задаче "посчитать остаток от деления миллиардного числа Фибоначчи на 10*9+7" сто лет в обед, она решается так же.)
Интуитивно, при случайном блуждании вы будете чаще оказываться в узлах степени 3, поэтому ожидание числа вариантов перехода больше среднего арифметического степеней узлов. (Близкий родственник этого наблюдения - "парадокс дружбы" a.k.a. "у ваших друзей в среднем больше друзей чем у вас".) Как можно видеть, в данном случае поправка около 10%, не так уж мало.
Значит существует такое число ходов для каждой цифры при котором любые последовательности ходов будут приводить обратно к ней и ситуация будет повторятся.
Не существует, хотя бы потому что мы можем разворачиваться: 6-7-6, 6-1-8-1-6, 6-1-8-1-8-1-6.
Ну и наконец, можно посмотреть на граф переходов и сообразить решение за логарифмическое время.
В силу симметрии, есть шесть видов кнопок (плюс бесполезная 5): {{0}, {2}, {8}, {1,3}, {4,6}, {7,9}}. Обозначая число ходов начиная с кнопки этого класса за A-F(n), имеем:
A(n+1) = 2*E(n)
B(n+1) = 2*F(n)
C(n+1) = 2*D(n)
D(n+1) = C(n) + E(n)
E(n+1) = A(n) + E(n) + F(n)
F(n+1) = B(n) + E(n)
Это линейное преобразование, размерность пространства 6. Иными словами, результат N преобразований - некоторая матрица в N-ной степени умноженная на единичный вектор. Быстрое возведение в степень справится за O(log(N)), а также можно прикинуть порядок результата за постоянное время по доминирующему собственному значению (~2.43828).
То есть просто лжи вам мало, хотите добавить ещё и ложь о том что Х "казнён за лож гражданам"?
А это как, простите? В этих искусственных примерах - верю, но в них и любой линтер вроде cppcheck ругнётся. А если у меня в функцию передан указатель на начало массива и из совершенно другой переменной выводится его длина, то компилятор же хрен докажет что длина корректная, это нужно анализировать всю программу.
Замена того что делалось макросами на примерно эквивалентные им шаблоны упростит синтаксис? Ну-ну.
Какой-то словесный салат. Работающий эффективно компилятор и компилятор, порождающий эффективный код - это очевидно разные вещи. "Автоматически освобождает память" - программа/среда исполнения, а не компилятор. Если компилятор вставил в код проверку, а не надо ли "автоматически" освободить память - эта проверка съела минимум одну ассемблерную инструкцию, чудес не будет. (А в многопоточной программе такие проверки на произвольную память делать больно, многопоточные структуры стараются разнести во времени работу с данными и выделение памяти.)
При каких-то условиях (не
знаюмогу хорошо сформулировать каких, не тестировщик) ссылка на комментарии (с/comments/
) не позволяет видеть текст поста, в то время как ссылка на пост при прокрутке вниз отображает комментарии.Желание получить 99/100% времени и что-нибудь хорошее по памяти понятно, но не должно быть частью использования LeetCode как инструмента отбора кандидатов. Если вас мало интересует оптимизация - потому что интересует мало и нефиг отбирать людей по тому что вас интересует мало, если вас сильно интересует оптимизация - потому что нормальная оптимизация делается профилировщиком, а не на глаз. Опять же, результаты LeetCode не отличаются хорошей повторяемостью, особенно по памяти.
Не существует идеала, но можно делать лучше. В исходном описании задачи FizzBuzz для собеседований подчёркивается, что её суть не в
а в том чтобы человек произвёл на свет хоть какое-нибудь решение. (Замечу что стандарты именно LeetCode на большинстве задач тоже очень мягкие: вы можете написать сильно неоптимальный код и он всё ещё впишется в ограничения.)
Затем, задачи должны быть неожиданными. В частности, даже для HR выглядит несложным попросить программистов компании написать три-четыре элементарных задачи с нуля вместо извлечения их из базы. Это заведомо уберёт проблему
HR может понимать специфику деятельности... несколько превратно.
Сказано: "Наша компания занимается разведением слонопотамов. Вы будете работать над программой мониторинга слонопотамьего здоровья."
На самом деле - вариант А: есть задача анализа слонопотамьих популяций в десяти разных заповедниках, в четырёх из них уже кем-то сделаны свои системы с которыми надо интегрироваться, для остальных шести нужно сделать аналогичное решение и свести всё это в единую систему представления данных.
На самом деле - вариант Б: есть фермы разведения слонопотамов; в промышленном разведении слонопотамов нужна программа, которая учитывает анализы и рекомендует как подстраивать рацион. Решение уже написано, но его надо поддерживать в актуальном состоянии, вносить в его логику поправки на основе новых статей по медицине слонопотамов, добавлять полезные фичи в интерфейс и т.д.
Так вот, HR может иметь смутное представление, а кто вообще такие слонопотамы про которых постоянно говорят в офисе и в принципе не понимать разницы между А и Б. А с точки зрения разработки задачи ну очень разные.
Как минимум:
1) батарея автоматических тестов по прошлым багам является инструментом защиты от регрессий и, по совместительству, хранилищем странных краевых случаев;
2) писанный протокол ручного тестирования позволяет быть уверенным что по крайней мере функциональность основных, оптимистичных путей выполнения не сломана совсем;
С моей точки зрения это вполне себе практически полезные, достижимые разумными усилиями гарантии.
Если есть 1) "старшие товарищи" и 2) способность сказать "возможно тут проблема" вместо двадцати железобетонных аргументов "это так и надо" (к сожалению, она есть не у всех), то хорошо. А если нет ни того ни другого, то приходится рекомендовать клиентам использовать Firefox, потому что приложение кушает гигабайт в десять минут, а ответственный за фронт программист считает что так и надо.
Я могу быть пристрастен, лично мне как раз было неплохим отвлечением поупихивать вчерашний LeetCode в 7 мс времени, но от полного игнора производительности я проблемы в задачах за которые платят деньги вижу достаточно регулярно.
Моё развлечение прошлой недели: попытки отлаживать код, исполнение которого занимает 18 часов. После пары часов медитации с инструментами анализа, без изменения базового алгоритма, время уменьшается до 75 минут. Да, это относительно экзотичный сценарий, но не то чтобы нулевой.
А самое главное, как раз если в норме команда разработки "не заморачивается" производительностью, то оценка асимптотик должна быть на уровне спинного мозга: логика "если окажется медленно, поправим" работает только если кто-то post factum тратит время и силы на оценку не медленно ли оно. А без этого отдел маркетинга поможет клиентам свыкнуться с мыслью что с этой скоростью надо жить, и мир в целом станет немного хуже.
Я всегда понимал эту задачу как упражнение на рефлексию над моделями. Достаточно ли того упрощения реального люка которое у меня в голове? Какие особенности я забыл?
Реально я видел и квадратные
люкикрышки, и я довольно сильно ожидаю что даже такую крышку в закрываемое ей отверстие вы нарочно-то замучаетесь просовывать, с шестиугольной миссия становится практически невыполнима (потому что а) крышка толстая и б) она закрывает люк потому что размер дырки меньше размера крышки, она лежит на "полочке"; численное соотношение между этими параметрами при котором задача для шестиугольника становится нерешаемой даже теоретически читатель может вывести самостоятельно, для люка метрового диаметра это единицы сантиметров).Я в основном хотел обратить внимание что ответы даже в хорошем случае показывают не "как кандидат мыслит", а некоторую сумму "как он мыслит" + "как он вербально рефлексирует" + "как у него получается вести себя в обстановке собеседования".
Если вас как раз интересует что-то близкое к этой сумме, то и хорошо. Но это не универсальное предпочтение.
Оно показывает хорошо если человек а) умеет вслух рассказывать как он мыслит, б) либо умеет это делать в стрессовой ситуации, либо не нервничает на интервью. Проблема в том, что хорошие программисты... не обязательно обладают этими свойствами.
Проблема в том, что "есть 12 типов людей, по 12 знакам Зодиака [забывая про Змееносца]" - это современное попсовое изложение. "Во времена магии и драконов" астрология была большим искусством, всякие натальные карты, привязка ко времени первого крика младенца, etc. Поэтому вряд ли дело в сезонности, просто старое доброе "люди не умеют не искать закономерности".
Затем что истинный вопрос X, на который хочется ответ - "будет ли группе разработки хорошо, если этот человек проработает в ней полгода". Самый очевидный способ ответа требует полгода.
Поэтому все пытаются найти такой индикатор Y, который а) вычислим за разумное время и б) коррелирует с X. Поскольку задача примерно одна и та же, разные агенты приходят к очень похожим индикаторам.
А дальше приходит Гудхарт и говорит "а хрен, в окружении где многие оптимизируют Y, он больше не коррелирует с X". Люди пытаются решать проблему, в первую очередь поиском какого-то волшебного индикатора который бы был устойчив к этому эффекту, "истинного имени" X. Как ни странно, это не получается.
(Как известно людям, соприкасающимся со вступительными экзаменами, более-менее универсальный способ - задавать простые, коррелирующие с желаемой характеристикой, но при этом неожиданные вопросы. Но массовый рынок неизбежно трактует "неожиданный вопрос" как "вопрос из сборника неожиданных вопросов".)
Я усложняю чтобы получить точный ответ. (Не то чтобы сильно усложняю: задаче "посчитать остаток от деления миллиардного числа Фибоначчи на 10*9+7" сто лет в обед, она решается так же.)
Интуитивно, при случайном блуждании вы будете чаще оказываться в узлах степени 3, поэтому ожидание числа вариантов перехода больше среднего арифметического степеней узлов. (Близкий родственник этого наблюдения - "парадокс дружбы" a.k.a. "у ваших друзей в среднем больше друзей чем у вас".) Как можно видеть, в данном случае поправка около 10%, не так уж мало.
Максимальный корень уравнения λ^6 - λ^5 - 7 λ^4 + 4 λ^3 + 14 λ^2 - 4 λ - 8 = 0
Аналитически это (1 + √5 + √(38+2√5))/4.
Я выше посчитал (с помощью Wolfram Alpha), основание чуть больше: 2.43828 ~ 22/9.
Не существует, хотя бы потому что мы можем разворачиваться: 6-7-6, 6-1-8-1-6, 6-1-8-1-8-1-6.
Ну и наконец, можно посмотреть на граф переходов и сообразить решение за логарифмическое время.
В силу симметрии, есть шесть видов кнопок (плюс бесполезная 5): {{0}, {2}, {8}, {1,3}, {4,6}, {7,9}}. Обозначая число ходов начиная с кнопки этого класса за A-F(n), имеем:
A(n+1) = 2*E(n)
B(n+1) = 2*F(n)
C(n+1) = 2*D(n)
D(n+1) = C(n) + E(n)
E(n+1) = A(n) + E(n) + F(n)
F(n+1) = B(n) + E(n)
Это линейное преобразование, размерность пространства 6. Иными словами, результат N преобразований - некоторая матрица в N-ной степени умноженная на единичный вектор. Быстрое возведение в степень справится за O(log(N)), а также можно прикинуть порядок результата за постоянное время по доминирующему собственному значению (~2.43828).
"Гугол" - это вполне "официальное" число, 10^100.