Как стать автором
Обновить

Как я проходил отбор на стажировку бекэнд — разработчиком (C++) в Яндекс по программе Deep Dive (в формате буткемпа)

Время на прочтение 6 мин
Количество просмотров 29K
Всего голосов 22: ↑17 и ↓5 +12
Комментарии 31

Комментарии 31

Поздравляю! Летом тоже пробовал попасть на стажировку, но второе собеседование завалил.
По поводу

for (int i = 0; i < s.size(); i++)

Возможно придирка была к постфиксной записи инкремента. Давно когда-то встречал заметки на тему, что i++ дольше работает, чем ++i. Сейчас компиляторы вроде как сами оптимизируют эту конструкцию под капотом. Также может быть тема с int и size_t - что из-за разного типа может гипотетически произойти некорректное сравнение. Либо вообще хотели увидеть range based loop.

Я не пишу на C++ и не в курсе как именно размер строки хранится. Вопрос — s.size() будет вычисляться при каждой итерации или просто однократно берётся из структуры данных? Может быть имелось в виду, что нужно размер строки поместить во временную переменную?

size() имеет константную сложность для большинтсва контейнеров, скорее все же дело в int и size_t

Компиляторы сейчас очень умные. Вероятно, нужно было что-то типа s.length()

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

Похожие чувства возникают, когда вижу как на современных версиях C продолжают писать как 30 лет назад. Принципиально объявляют переменные отдельно в начале функций, игнорируют существование const и т.п., хотя код всё равно не совместим с C89.

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

https://en.cppreference.com/w/cpp/language/operator_incdec

Pre-increment and pre-decrement operators increments or decrements the value of the object and returns a reference to the result.

Post-increment and post-decrement creates a copy of the object, increments or decrements the value of the object and returns the copy from before the increment or decrement.

Принципиально объявляют переменные отдельно в начале функций

Иногда так удобнее высвобождать ресурсы.

В данном случае результат операции все равно выкидывается, так что цитата хорошая,и но толку от нее 0.

Так речь конкретно про типовые циклы и смежные случаи, где форма записи не имеет значения, но многие без объективных причин зациклены именно на префиксной, аргументируя это тем, что «ну так вроде быстрее».

В С++ нельзя вручную освобождать ресурсы, потому что за это нужно по рукам бить

ТОЧНО НЕТ. Включайте логику.

for (int i = 0; i < s.size(); i++)

s.size() - это функция. Как думаете, если строчка мутирует ВНУТРИ цикла for - что мы получим? Я бы размер определял изначально, потом уже фигачил. Конечно, может быть супер оптимизирующий компилятор... но такое себе. Я уж не говорю о том, что такие штуки через итераторы пишут, потому что размер символа в байтах не определен точно...

Первое: int - это да, неправильно однозначно, там ещё и warning будет.

Второе: Если длина строки изменяется внутри цикла, то нужно использовать именно i < s.size(), или типа того.

Если длина строки изменяется внутри цикла

в этом случае можно получить любые приключения, включая неявный бесконечный цикл :-)

В том случае, с большой долей вероятности, получишь выход за границу массива

и так, вы определелили изначально размер строки, которая мутировала внутри цикла и стала меньге, если бы сравнение было с s.size(), цикл бы завершился и все было бы хорошо, а вот в вашем случае, мы продолжим индексироваться уже за пределами массива (строки), а это уже очень трагичное UB

Постарайтесь меньше думать вместо компилятора, начните с аналога foreach, котрый и быстрее и лучше

for(auto const& item :s)

скорее разговор идет про s.size() если вспомнить про строки (обещанные аж в 5гб)... не знаю как в с++ но если при каждой итерации вычислять....

в том же паскале например ограничивающе значения вычисляются только при входе в цикл, помоему у си по другому

(могу ошибаться)

опять же в чем проблема с вычислениями? какая ассимптокика у этого метода? в целом бля большинства контейнеров она константная

Это лишнее время занимает в каждой итерации?

Я отчего-то уверен, что константаная сложность для этого метода приблизительно такая же, как из переменой прочитать)) что там за потери времени такие на вызов, близкий к О(1)? Все таки это не std::list или std::forward_list, где она будет линейной и будет отбирать время

Тем временем ниже автор признался, что дело в несоответствии знакового int и беззнакогового size_t

Год спустя я бы топил за for (auto i = 0; i < s.size(); i++)

Как минимум, длина строки неотрицательна, значит unsigned int.

Еще, она может быть (в теории) больше 2**32 символов

Исключительноль проблема в сравненние знакового и беззнакового типа. Вообще, по-хорошему, для большинства задач хватает встроенных функцией std:string и стандартной библиотеки.

программирования все нет и нет, а есть одна иженерия)

no comments. Будто программирование - не инженерия... Или хочется быть тупым кодером?

резковато конечно, но в целом верно )

Все же хотелось бы увидеть больше внимания на "кодерские предметы".
У нас же идут по нескольку семестров химия, физика, начертательная геометрия, электротехника и т.д. Я не против таких предметов, но неприятно, когда на них делается акцент, например, электронику делают экзаменом, а какой-нибудь курс по алгоритмам и структурам данных - зачетом на полсеместра. 

На мой скромный взгляд цикл с подвохом, вместо него нужен range based for, тогда мы будем перемещаться от begin к end, а не заводить счётчики позиции.

Учитывая, что условие задачи не приведено, возможно, есть необходимость знать конкретный номер итерации. Кто его знает...

Мало кто ща хочет кодить на плюсах, поэтому яндекс наверное сбавил входные требования

for (int i = 0; i < s.size(); i++)

Самая серьёзная тут ошибка - это int. Там целая куча проблем всплывает:

например, size_t(8) больше int(4) в два раза и что будет когда size_t перевалит int или

например, i=-1 < s.size - тут i будет больше, если в size_t велечина в диапазоне int.

Правильная запись:

for (size_t i = 0; i < s.size(); ++i)

Ещё лучше использовать итераторы или for(auto const& ch:s).

Благодарю модераторов и комментаторов за указание ошибок в тексте, писал по ночам в основном :)
По поводу ошибки в цикле. Как многие заметили, дело было как раз в несоответствии типов. int и size_t.

Насчёт кода со строкой. Может быть потому что s.size() long unsigned int. Хотя не думаю что это большая проблема.int На 5 гб памяти хватит или нет не знаю

В цикле возможна проблема из-за int и size_t. Потенциально это UB, если размер строки будет равен значению, которое не может быть хранимо в int. В этом случае произойдет переполнение переменной i и как следствие (для знаковых целых) UB.

Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории