0,0
рейтинг
14 января 2011 в 11:42

Управление → FizzBuzz, или почему программисты не умеют программировать

[Автор этой статьи — Джеф Этвуд (Jeff Atwood), один из основателей stackoverflow.com. Сама же статья, несмотря на довольно приличный возраст (она написана в 2007 году) до сих пор популярна, а введенный в ней термин «FizzBuzz question» стал общеупотребительным. Оригинал можно найти здесь.]

Я весьма скептически отнесся к следующему наблюдению Реджинальда Брейтвайта (Reginald Braithwaite):

«Меня немного удручает тот факт, что 199 из 200 соискателей программистских вакансий не умеют программировать. Повторю: они не умеют писать код. Вообще.»

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

«Проведя достаточно собеседований, я понял, что при написании кода неопытные люди спотыкаются вовсе не на сложных и неочевидных задачах, и даже не на мелких задачах (например, реализовать связный список). Больше всего проблем у них вызывают совершенно тривиальные задачи.

Я решил разработать набор вопросов, которые позволили бы мне быстро идентифицировать таких «недопрограммистов». Вопросам такого рода я дал название «FizzBuzz questions», в честь игры, в которую играют британские школьники. Типичный FizzBuzz question выглядит следующим образом:

Напишите программу, которая выводит на экран числа от 1 до 100. При этом вместо чисел, кратных трем, программа должна выводить слово «Fizz», а вместо чисел, кратных пяти — слово «Buzz». Если число кратно и 3, и 5, то программа должна выводить слово «FizzBuzz»

Нормальный программист должен написать такую программу на бумажке за пару минут. Но вот что интересно: многие люди с профильным образованием вообще не могут справится с этой задачей. Были даже случаи, когда кандидаты, подававшие резюме на вакансию «Senior developer» тратили на эту программу больше 15 минут.»

Дэн Кигель (Dan Kegel) рассказывает о похожих впечатлениях при приеме на работу начинающих программистов:

«Неожиданно много соискателей (в том числе имеющих магистерские степени и PhD по информатике!) затрудняются ответить на простейшие вопросы. Я сам видел, как люди на собеседованиях не могут написать цикл, итерирующий от 1 до 10 или не знают, какое число в шестнадцатеричной системе идет после F. Что до менее очевидных примеров, то довольно много кандидатов не знают, как применить рекурсию для решения какой-либо практической задачи. Согласитесь, всё это совершенно базовые вещи, и если человек затрудняется с ответом на подобные вопросы, значит у него попросту нет опыта программирования.

Возьму на себя смелость говорить от лица всех программистов, которым приходится проводить собеседования: мы страшно устали общаться с людьми, которые в программировании ни в зуб ногой. Поверьте, если вы можете написать цикл от 1 до 10 на всех языках, указанных в вашем резюме, если вы можете решить в уме несложный арифметический пример и если вы знаете, как применить рекурсию в несложной (но взятой из реальной жизни) задаче — то вы уже на голову выше большей части людей, вращающихся в нашей индустрии.»

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

Известно, что между состояниями «я учусь программировать» и «я умею программировать» лежит огромная пропасть. Я полагал, что у каждого, кто хоть раз подавал резюме на вакансию программиста, эта пропасть уже позади. Но практика показывает, что это совсем не так. Более того, я прихожу к выводу, что предварительное отсеивание кандидатов вопросами типа FizzBuzz просто необходимо, иначе мы будем бездарно тратить кучу времени на собеседования с программистами, которые таковыми не являются.

Для тех из вас, кто считает задачу о FizzBuzz чересчур простой (она, впрочем, намеренно тривиальна), я приведу комментарий из поста о собеседованиях, на который мы ссылались в начале статьи:

«Я бы не советовал людям, проводящим собеседования, отметать задачу о FizzBuzz как слишком примитивную. Положитесь на нее, и вы (как и я в свое время) будете неприятно удивлены, увидев, насколько много соискателей не имеют даже базовых навыков программирования»

Я считаю, что глупо проводить собеседование с человеком, не посмотрев сначала его код. Процесс собеседований в нашей фирме требует, чтобы кандидат предоставил нам фрагмент своего кода еще до телефонного собеседования. А если дело доходит до личного собеседования, то мы обязательно даем кандидату небольшую задачу по программированию, которую он должен решить при нас. Ничего сверхсложного, просто небольшое упражнение на час-полтора, позволяющее проследить все этапы создания работающего приложения. Должен вам сказать, что такая стратегия великолепно работает. Благодаря ей на собеседованиях мы разговариваем о программировании, а не погрязаем в сотнях задачек на сообразительность.

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

UPDATE:
Лучшие реализации FizzBuzz в комментах:
Семён Факторович @chebureque
карма
63,2
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Управление

Комментарии (568)

  • +83
    Смысл всей статьи в одном предложении: «При приёме на работу нового программиста дайте ему тестовое задание»
    • +9
      Кратк. — сес. тал.! Ловите плюс :)
      • +2
        Краткость — сестра нашего брата.
        • 0
          По слухам, автор этого выражения скатился в УГ… :(
          • 0
            Тут есть несколько различных мнений.
            Скажем, 4duk.ru/ местами очень неплох.
    • НЛО прилетело и опубликовало эту надпись здесь
    • +16
      Смысл всей статьи — дайте ему ПРОСТЕЙШЕЕ тестовое задание.
      • +4
        … прежде, чем давать более сложное.
        • 0
          … и кто тогда будет работать?
    • –1
      хуже бывает, когда тестовое задание дают на несколько дней домой. если на собеседовании, то это отличная практика.
    • –3
      Знаете, помоему даже всё проще. Если у человека опыт работы 2-3 года по CV, но при этом там PHP/JavaScript/Python/Ruby/Java — уже можно пропускать CV :)

      Я лично ненавижу задания на собеседовании, и этому несколько причин:
      1. Я человек работающий, и как правило вырываюсь или на обеде, или вечером к 18. У меня нету лишних 4-х часов (или пары дней как в некоторых случаях).
      2. Я не помню алгоритмы из головы (ну сортировку пузырьком конечно напишу :) ), а математику так и подавно (те вещи, которые по сложнее. Не лежит у меня к вышке).

      Эти два пункта как правило то, из-за чего я просто не иду на некоторые собеседования, хотя по критериям подхожу на ура.

      Прислать кусок кода если честно меня обычно тоже коробит. Просто потому, что ну пришлю я вам файл контроллера, или модели. И что? Половина там будет по стандартам фреймворка, вторая половина кастомного кода тоже в стиле фреймворка. Всё это будет завязано на события и хуки в связанных моделях и скорее всего толком ничего понятно не будет. А выслать вам целый модуль я не могу, потому что это чужой код и мне за него отвалили кучу бабла (мелочевкой я не занимаюсь, натягиванием сайтов на CMS тоже не занимаюсь).

      Гораздо больше мне нравиться, когда просто спрашивают те или иные вещи и нужно просто дать ответы. Поинтересуются что я думаю по поводу тех или иных технологий, спросят о приведущих проектах, проблемах которые решал. Спросят пару базовых вещей по профилю. Всё это отвечается за 5-20 минут в зависимости от кол-ва вопросов и желания инвертирующего пообщаться по человечески. Последние 2 собеседования у меня выливались почти по часу, были очень интересные дискуссии и обмен опытом помимо стандартного интервью. Уходил с приятными ощущениями о работающих там людях и компании как таковой. Другое дело что не сложилось из-за некоторых обстоятельств (а на последнее место очень хотелось).
      • НЛО прилетело и опубликовало эту надпись здесь
        • +4
          Даже если ищите кандидата на должность php программиста, которому все эти ваши биты и адреса до фени и он с ними никогда не сталкивается? Вообще это бредовый способ. Ответ гуглится без особых сложностей, если хотя бы примерно представлять себе суть вопроса.
          • НЛО прилетело и опубликовало эту надпись здесь
        • 0
          По адресу или в числе 1234567?
          • НЛО прилетело и опубликовало эту надпись здесь
        • +3
          mov dx, 1234567
          mov al, [dx]
          xor al, 64
          mov [dx], al

          так? :) (15 лет на асме не писал и честно не гуглил синтаксис)

          • +2
            чёрт, 1234567 это больше максимально адресуемой памяти в 8086, не говоря о том что больше размера сегмента
          • НЛО прилетело и опубликовало эту надпись здесь
            • +2
              char *ptr = (char*)1234567;
              *ptr ^= 1 << 7;
              • 0
                Это восьмой бит.
                • 0
                  Ни хрена себе! Биты принято нумеровать справа и с нуля FYI.
                  • +1
                    С нуля? Лично никогда не слышал термина «нулевой бит».
                    Под «первым битом» всегда имелся ввиду самый наименее значимый бит. Аналогично первый байт, а не нулевой.
                    • 0
                      • 0
                        Но нумерация бит в байте, бит и байт в слове и в других многобайтовых объек-тах в различных вычислительных системах может быть различной.


                        www.kailib.ru/part2?start=3 — третий результат на момент написания коммента (страховка от сеошников :) ) по вашей ссылке

                        Вообще, всю жизнь воспринимал нормально как нумерацию битов (и байтов, и слов различной длины) как с нуля, так и с единицы (очень часто приходилось кодить параллельно на разных языках), но если по контексту не ясно, что нумерация конкретной сущности начинается с нуля, то всегда подразумевал нумерацию с единицы. Даже фраза «первый элемент массива имеет индекс ноль, а значит нулевой элемент равен первому» не вызывает диссонанса :D
                        • 0
                          Да не, понятно, что это вопрос обозначений. Можно хоть ёлочкой из середины нумеровать — главное договориться заранее. Речь идёт о том, что общепринятым обозначением является нумерация с младших битов и с нуля. Если соискатель ищет работу системного программиста и не знает, что в 99% литературы по процессорам, регистрам, портам и прочим железкам нумерация битов с нуля, то сразу делается вывод, что практики в низкоуровневом программировании у него нет. Кстати, в сетевых RFC точно такая же нумерация.

                          По сути, это не значит, что это плохой программист, и его надо сразу прогонять. Просто именно в данных вопросах он неопытен, надо это помнить.
            • –1
              Не уверен, что конструкция типа *p ^= 64; не выкинет BSOD для char *p = 1234567; (тоже по памяти), тем более не уверен, что сработает *1234567 ^= 64… :(
              • 0
                И про приведение типа забыл за 10 лет :( Не быть мне Си программистом, да собственно и не стремлюсь :)
        • +3
          Плохая задача, придумайте что-то чтобы 200 из 200 отсеивались :)
        • –2
          А какое правильное решение???
          Лобовое решение вида:
          #include <stdio.h>
          int main (int argc, char **argv)
          {
              unsigned char *address = (unsigned char*)1234567;
              unsigned char was = address[0];
              printf("was %i\n",was);
              unsigned char became;
              if (was < 250){
                  became = was + 2;
              }
              else{
                  became = was - 2;
              }
              printf("became %i\n",became);
              return 0;
          }

          не годится, это понятно: будет Segmentation Fault.
      • +18
        О том и речь — задача не должна требовать больше нескольких минут на решение, поэтому и достаточно давать тривиальную, просто чтобы посмотреть как человек умеет взять и написать код. Если он это сделать умеет — то в реальной работе ничто не мешает ему смотреть алгоритмы/формулы/best practices, не экзамен же сдается.

        Кстати некоторые мудрые преподаватели сложных дисциплин разрешают пользоваться любыми материалами во время сдачи, т.к. в реальной жизни намного важнее умение быстро найти ответ, чем помнить его наизусть
        • +3
          Я бы сказал, что среди хороших преподавателей дисциплин, связанных с ИТ, таковых подавляющее большинство.
        • +1
          Верное замечание! Такое ощущение, что образование отметает все инструментальные достижения, требуя как и в средние века находить решение полностью из головы. Как будто готовят не специалистов в реальные условия, а игроков в интеллект-шоу
      • 0
        «приведущих»
        Наконец-то я нашел человека, который пишет так же как я слышу!
    • 0
      Зато какой резонанс — бурные обсуждения!
    • 0
      Этвуд всегда так пишет, можно только выделенное жирным читать
  • +10
    Интересно, где обучают программистов которые не могут решить задачу FizzBuzz, или сколько они заплатили за свой диплом?
    • +27
      У нас в университете выпускали программистов, которые платили мне, чтобы я решал FizzBuzz за них.
      • +8
        У нас тоже такое было, но все-таки эти люди не шли работать программистами после ВУЗа
        • 0
          Аналогично! Причём, непонятно зачем они вообще шли учиться «программистами», если не собирались ими работать. По логике они должны были ещё на первом курсе поняв что не тянут перевестись на другой факультет.

          PS только я тогда брал не деньгами (и нет не борзыми щенками), а дискетами. Так как дискеты от Verbatim часто дохли чуть ли не при первой попытке с них что-нибудь считать.
          • 0

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

            • 0
              У меня самыми живучими были FujuFilm и FujiKawa (FujiFilm проработал более 10 лет до самого выхода дискет из обращения, а на FujiKawa через 10 лет появился бад-сектор). А вот Verbatim — часто дох.
      • 0
        о! Коллега :) На первом курсе аналогично зарабатывал себе на обед.

        Знаю некоторых вечерников-выпускников МИРЭА IT специальностей. Вопрос про шаблоны проектирования вешает мозг. :)
        • +10
          Я до четвертого курса так зарабатывал :)
          На втором курсе мой «заготовок для курсача по C++» купило 15 человек. Из них только шестеро додумались его хотя бы запустить на досуге, хотя я заранее говорил, что это полуфабрикат, который нужно будет самому доделать под себя. Остальные пришли с невинным лицом с день сдачи и обнаружили, что там в разделе About написано Made by Vasya Pupkin, чему препод был несказанно рад…
          • +6
            Если уж продавали, можно было выдать персональные лицензии )
            • +1
              За те деньги, которые стоит индивидуальная домашняя работа, ее только один человек захотел купить )
        • +1
          IT специальность != программирование, и про шаблоны проектирования они ничего знать не должны.
          • 0
            уточните, пожалуйста, термин «IT специальность»
            • +1
              Наверное: системник пропылесосить и картридж в принтере заменить :)
    • 0
      Есть некоторые лицеи, которые выпускают 3-4 человек с выпуска, которые это могут решить :)
      • 0
        А из лицеев или институтов вообще выгоняют, если не за огромные прогулы или неуплату?
        У меня сложилось мнение, что в России сколько человек пришло учиться, столько и будет выпущено с дипломами в итоге — главное хоть иногда появляться.
        • +1
          Ну, у меня, например, с пятого курса отчислили одногруппницу, которая получала президентскую стипендию и заняла первое место в республике по высшей математике, но при всём при этом продолжают учиться люди, для которых создать объект в С++ — проблема.
          • –1
            Это у вас приличное учебное заведение еще.

            Я в свое время бросил НГТУ, специальность «Защита информации» (http://ciu.nstu.ru/kaf/zi) — работать нужно было. А мой одногруппник, успешно закончивший и получивший диплом инженера, недавно спросил меня, что такое SHA1. При этом он несколько лет работает в сфере webdev (правда, на ActionScript в основном, но не суть). Другие ребята, которые ушли от информатики дальше, боюсь, и того меньше знают. Печально это все.
          • 0
            За что отчислили, не скажете? Просто интересно.
            • +1
              Просто на нашей кафедре очень много вахтёров. Например, один вообще издевается, доводит людей, что они уже плачут: один человек, защищая лабу стоял перед ним, и у него уже руки тряслись (так перенервничал), а этот вахтёр — улыбался(и это хорошо всем было видно), шутил по-своему над ним, унижал, но при этом напрямую не оскорбляя. Мог назначить время пересдачи, прийти за пять минут до конца, принять у кого-то одну лабу и сразу свалить домой, при том что больше 20-ти человек висит. Он у нас 1С вёл.
              • +8
                Ощущение, что у него комплексы от того, что он ведет неполноценный ЯП и он их на студентах вымещает.
                • 0
                  Нет, на самом деле он очень умный человек(постоянно ездит на конференции заграницу по нейронным сетям и занимает на них призовые места), но с ним даже другие молодые преподы не дружат и не разговаривают, ну и если он с ними первым не поздоровается, то с ним никто первым здороваться не будет(по крайней мере я такого ни разу не видел за все 5 курсов).
                • 0
                  У него не комплексы, у него звездочка загорелась
          • +2
            Мне на 3-м или 4-м курсе (специальность 220100) поставили неуд на экзамене по «C++ и объектно-ориентированное программирование» за использование конструкции x?a:b; Препод сказал что такого вообще нет и это я сам всё придумал :-D

            А так как это была последняя капля то через некоторое время я из универа отчслился. 2 года армии (там итшники очень востребованы), а потом работаю по специальности. Админ, программер и т.д.
            • +2
              В армии востребованы айтишники? Оо
              • +2
                Компы везде есть. Так что да.
              • +1
                Был связистом. Сетка довольно немаленькая. Видеонаблюдение (Videonet), охранная сигнализация и много ещё в этом духе.
                • 0
                  Речь наверное даже не об администрировании сеток и т. п., а о «печатных машинках» где-нибудь на КП роты или в штабе батальона.
                  • +1
                    Ну, «печатные машинки» это отдельная тема. Я имел в виду именно более интересное: протяжка сетки, настройка, серваки, интернет. Серваки видеонаблюдения и охранки. Плюс начальство тоже люди — одному дома помочь что-то настроить, другому :-) Я в связисты попал когда у комбата кто-то пароль поставил на биос, он спросил у взвода «кто могёт убрать?». Ну я вызвался, быстренько сбросил парой командой в debug (на том компе DOS стояла). В результате чуть ли не карьеру там сделал :-D Но слава богу хватило ума по контракту не остаться.
              • 0
                Да. Любой умеющий нормально обращаться с компьютером человек может получать поблажки.
                Но это всё равно армия с дисциплиной и идиотами )
                • +1
                  Кстати дисциплина не есть плохо :-) Идиотов да, хватало.
            • 0
              Мне на 3-м или 4-м курсе (специальность 220100) поставили неуд на экзамене по «C++ и объектно-ориентированное программирование» за использование конструкции x?a:b; Препод сказал что такого вообще нет и это я сам всё придумал :-D

              Что-то мне анекдот про крысу, хомяка и пиар вспомнился. :-)
              Ни одному препаду не приходило в голову сомневаться в моих знаниях.
        • 0
          У меня на курс был набор 125 чел., вышло примерно 80(2 группы из 5 сократили ибо слишком маленькие группы получались).
          Правда приходилось преподам помогать понять почему не работают те или иные программки из задачника на паскале :)
          А на самых модных факультетах вообще был бейсик :)
    • +1
      Не поверишь, я когда искал людей с такими встречался каждый божий день (иногда 12-ти летние пацанята с форумов, бывает дадут фору «соискателям» с высшими образованиями и кучей страшных слов в «резюме»)
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        «Нормальный программист должен написать такую программу на бумажке за пару минут. „
        наверное 5 минут было по их мнению слишком долго:) А может им ваш почерк не понравился, прическа или еще что-нибудь в этом роде.
        • 0
          Мой бывший шеф несколько лет назад размещал вакансии в службе занятости из-за каких то льгот или освобождения от какого-то налога (Украина). Вакансии естественно были липовыми. Но люди звонили, даже приходили на собеседование… Так что всякое бывает.
    • 0
      В СПбГУ например, у нас на кафедре Технологии Программирования, где-то четверть бы не справилась
      • 0
        очень странно, что с этой задачей можно вообще не справиться.
        всего два условия на кратность, тут надо либо не знать про цикл for, либо не знать синтаксиса определения остатка/кратности какому-либо числу.
        нет, неужели 199 из 200?
        • +1
          запороться можно на двойной кратности и на else, как только решишь оптимизировать (а на собеседовании же не хочется выглядеть неэффективно кодирующим) программу, чтобы не писать 4 взаимоисключающих if в лоб, ежу понятно, что раз условия взаимоисключающие, то как минимум без одного условия можно обойтись, но начинаются трудности с определением какого. Плюс явная подсказка на ещё одну оптимизацию, что FizzBuzz состоит из Fizz+Buzz и начинается путаница с двумя одновременными оптимизациями в уме. Вообще хороший тест на выявление не только тех, кто синтаксис не знает, но и на любителей преждевременной оптимизации или писать сильно вложенный код там, где можно обойтись плоским (пускай и не таким эффективным)

          Даже здесь в комментах выложили нерабочие решения, что уж говорить…
    • +1
      у меня в группе 27 человек и из всех, помимо меня, код могут писать еще человека 4.
      а в дипломе всем напишут: «профессионал в области программирования»
    • +1
      У нас препод вообще говорил «Чем меньше вы знаете, тем больше я стою как специалист» :)
  • +4
    В трех фирмах принимал людей. Солгласен. Если берете людей с опытом, то около половины не умеют писать код. Именно поэтому не задаю задачи на сообразительность (стиля микрософт), а
    1. Задача на минимальное программирование (чуть посложнее чем приведенные тут). Причем можно в превдо коде, а не на каком то языке
    2. Технологческая задача — придумать как что то делать — без написания кода — например придумать свою сериализацию для какой то цели

    Основная причина — люди не интересуются. Пишут свой кусочек, им код ревью не делают, их вся система, технологии, качество кода не интересует. И получаются люди с опытом в 3-5-7 лет пишущие ооочень плохо и ничего не знающие.

    50% заваливаются на вопросе «опишите архитектуру продукта в котором вы работали последние Х лет»
  • +7
    А я, честно сказать, сперва напрягся. Но проверил и уложился в минуту.
  • –16
    На груви. За 53 секунды :)

    for (n in 1..100) {
    if (n%3 == 0 && n%5 != 0) println 'Fizz'
    else if (n%5 == 0 && n%3 != 0) println 'Buzz' else
    if (n%5 == 0 && n%3 == 0) println 'FizzBuzz' else
    println n
    }
    • 0
      На Haskell:
      fizzbuzz x | divides x 3 && divides x 5 = "FizzBuzz"
                 | divides x 3 = "Fizz"
                 | divides x 5 = "Buzz"
                 | otherwise = show x
        where
        divides x n = x `mod` n == 0
      
      main = mapM (putStrLn . fizzbuzz) [1..100]
      
      • +40
        у вас обоих первое условие лишнее
        — если кратно трем выведем Fizz
        — если кратно пяти выведем Buzz

        а если кратно и трем, и пяти — FizzBuzz получится само)
        • +6
          В Хаскелле, чтобы оно само так получилось, надо несколько по-другому написать.
          Можно конечно, но никто не может сказать, что этот вариант неправильный.
          Он как раз видится мне тру-функциональным :)
          • –1
            возможно, я говорил о логике
            • 0
              С точки зрения логики тут все нормально, выполняются оба условия -> выводим FizzBuzz, а то что все условия надо проверять не более одного раза — это подразумевается в нестрогой семантике Haskell'я. И компилятор все сделает как надо.
              Это лишь декларативное описание соответствия входных данных желаемым выходным не отражающее то, как оно будет вычисляться в реальности.
        • +11
          Простите, но ваше утверждение верно только для императивных языков.
          То есть в Хаскелле, конечно, можно присобачить эту императивщину и получить грязную функцию. Но это быдлокодинг и неуважение к такому языку.
          • +4
            +1 такого рода оптимизации это вообще задача компилятора — надо писать максимально близко к формулировке задачи.
            • 0
              «надо» каждый сам для себя определяет
              мне вот надо писать максимально минимально, при этом чтобы задача была решена
              • +5
                >> максимально минимально
                o_O
              • +2
                Писать надо в первую очередь понятно. Минимально писать конечно круто — можно быть уверенным что вас никто не уволит, т.к. фиг кто когда то разберется в том, что вы там накодили, но это не дело.
              • 0
                >мне вот надо писать максимально минимально, при этом чтобы задача была решена

                «Спасибо, вы нам не подходите».

                В тот момент, когда количество разработчиков проекта переваливает отметку «1», писать надо не «максимально минимально», а максимально понятно. Причём без понтов вида «на самом деле это понятно, а если кому-то непонятно, то он сам идиот, а я умный».
          • 0
            опять же, возможно
            я с хаскеллом не знаком, может быть в двух словах скажете в чем выражается «императивность» языка?
            • +3
              Команды выполняются последовательно, есть присваивания.

              В чисто функциональных языках принципиально по другому — программа описывается, как математическая функция.
            • +1
              Вкратце:
              императивное программирование — это когда вы описываете какие нужно выполнить действия и в каком порядке.
              декларативное программирование — вы описываете что вы хотите получить задавая правила/формулы преобразования входных данных в выходные. Компилятор сам решает какие действия нужно выполнять и в каком порядке.

              Почитайте все таки про Haskell — полезно для развития кругозора.
        • +5
          но также нужно вывести число если условия не работают
          • –3
            в задаче такого не было
          • +1
            сорри, было)
        • +4
          Да, кстати, даже если мы используем императивный язык. Если вы выбросите первое условие, вы лишитесь взаимоисключающей конструкции. И в этом случае вам все равно перед выводом числа придется дополнительно проверять, а не было ли уже что-то выведено для этого числа. Иначе ваша программа выплюнет что-то типа «FizzBuzz15».

          Вот благодаря своим оптимизациям вы бы и не попали туда на работу. ;)
          • –3
            а зачем выводить число? я не нашел такого в задаче
          • 0
            уже нашел. но мне кажется что суть не меняется все-таки — число выводим отдельно, физбазз — отдельно
          • +6
            блин. вы победили, а я — невнимательный, не увидел слово «вместо»
            • +1
              Хорошо отношусь к людям, признающим свой промах, посему плюс вам. :)
              Жаль, не могу добраться до того стада, которое бездумно плюсовало, не думая своей головой. ]:->
              • +2
                А чего до них добираться? У них и без вас будет куча провальных собеседований.
        • 0
          я после первого прочтения задачи подумал, что подвох будет именно в этом. Хотя, похоже, задачка вообще не задумывалась как задача с подвохом)
        • 0
          А куда тогда девать условие 'не кратно 3 и 5'?
          По плюсам сразу видно что тема актуальна )
        • 0
          Fizz\nBuzz получится, а нее FizzBuzz.
        • 0
          функция вызывается один раз для одного x. если несколько клоз удовлетворяют условию, будет использована первая. так что код правильный
      • +7
        perl -le '$_ % 3 ? $_ % 5 ? $_ : "Buzz" : $_ % 5 ? "Fizz" : "FizzBuzz" for 1 .. 100'
        • +6
          Вот за такой код в реальном проекте я готов оторвать руки, у меня нет ни малейшего желания распутывать хитросплетения воспаленного мозга автора кода, когда нужно что-то исправить или просто понять, что код делает. Сравните

          foreach my $i (1..100) {
          unless($i % 3) {
          print «Fizz»;
          }
          unless($i % 5) {
          print «Buzz»;
          }
          if($i % 3 && $i % 5) {
          print $i;
          }
          print "\n";
          }
          • +5
            А вы расслабьтесь, FizzBuzz это не реальный проект :)
            • +4
              Одна из целей FizzBuzz как раз в том, чтобы увидеть пример кода кандидата.
              Если бы вы пришли ко мне на собеседование и написали решение в таком виде — вы бы не прошли :)
              • +3
                Цель FizzBuzz — увидеть, способен ли человек думать мозгами. Кода в этой задаче маловато для того, чтобы оценивать его красоту.
                • +2
                  >Цель FizzBuzz — увидеть, способен ли человек думать мозгами.

                  А может вы недостаточно глубоко смотрите?

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

                  Для того, чтобы оценить стиль кода — вполне достаточно. По крайней мере ваш стиль я уже «оценил» :)
                  • +5
                    Это вообщет шутка старого перловика была.
          • +1
            Мдэ, все пробелы съелись

            foreach my $i (1..100) {
              unless($i % 3) {
                print «Fizz»;
              }
              unless($i % 5) {
                print «Buzz»;
              }
              if($i % 3 && $i % 5) {
                print $i;
              }
              print "\n";
            }
            
          • +2
            Ну что вы так близко к сердцу принимаете. Это всего лишь вопрос договоренностей.

            Я вот, например, за unless руки отрываю :)
            • 0
              почему?
              • +1
                Потому что это тоже хитросплетения мозга. Потому что приводит к unless(! $a)

                Посмотрите, например, Perl::Critic::Policy::ControlStructures::ProhibitUnlessBlocks.
                • +1
                  Я использую unless только в одном единственном случае — в качестве замены простого условия if с отрицанием, т.к. в простом условии можно знак восклицания не заметить при беглом взгляде на код.
                  Т.е. вместо if(!$a) пишу unless($a) или вместо if(!($a > 5)) пишу unless($a > 5).
                  • 0
                    Я перл не знаю, но почему вместо if(!($a > 5)) нельзя написать if($a <= 5)?
                • 0
                  За описанную выше конструкцию убивать надо, да. А за unless — зачем? Я её при валидации использую, очень удобно.
                  • 0
                    Ну, я, конечно, маленько шучу… но вообще-то не люблю unless. Избегаю. В целях неувеличения энтропии :)
                    • 0
                      unless(энтропия не увеличена)… ;)
        • +4
          Ваша программа ничего не выводит :)
          • 0
            Ах, да, я print в самом начале забыл
        • –1
          Вот за это я люблю перл :)
        • 0
          Думаю всё же где-то так будет лучше:
          perl -le 'print join "\n", map { ($_,«Fizz»,«Buzz»,«FizzBuzz»)[!($_%3)+2*!($_%5)] } 1..100'
    • +13
      зачем делать отдельное условие для FizzBuzz?
      • +1
        Да, тоже так подумал :)
        На Ruby(не бейте больно, второй день трогаю — уверен, есть более лаконичный вариант)
        def fizzbuzz
        res=""
        (1..100).to_a.each do |elem|
        res+=«Fizz» if (elem%3).zero?
        res+=«Buzz» if (elem%5).zero?
        res+="#{elem}" unless ((elem%3).zero? or (elem%5).zero?);
        res+=","
        end
        res
        end
        puts fizzbuzz
        • +2
          def fizzbuzz
            res=""
            (1..100).to_a.each do |elem|
              res+="Fizz" if (elem%3).zero?
              res+="Buzz" if (elem%5).zero?
              res+="#{elem}" unless ((elem%3).zero? or (elem%5).zero?);
              res+=","
            end
            res
          end
          

          puts fizzbuzz
          • –1
            res=""
            100.times do |num|
              elem = num+1
              res+="#{elem}" unless ((elem%3).zero? or (elem%5).zero?)
              res+="Fizz" if (elem%3).zero?
              res+="Buzz" if (elem%5).zero?
              res+=","
            end
            puts res
            
          • +1
                  (1..100).map do |i|
                    puts i, [
                            (i % 3).zero? ? "Fizz" : nil,
                            (i % 5).zero? ? "Buzz" : nil
                    ].compact.join
                  end.compact
            


            Можно и еще более извращенными способами.
            • –1
              Эх, поспешил
                    (1..100).each do |i|
                      puts i, [
                              (i % 3).zero? ? "Fizz" : nil,
                              (i % 5).zero? ? "Buzz" : nil
                      ].compact.join
                    end
              
              • 0
                Не катит. Выводит числа 3, 5, 15 и т.д.
                100.times do |i|
                  num=i+1
                  [ (num % 3).zero? ? "Fizz" : nil,
                    (num % 5).zero? ? "Buzz" : nil
                    ].compact.join.display
                  num.display unless (num % 3).zero? or (num % 5).zero?
                  puts
                end
                
                • +4
                  Да, невнимательно прочитал условие

                        (1..100).each do |i|
                          puts (a = [
                                  (i % 3).zero? ? "Fizz" : nil,
                                  (i % 5).zero? ? "Buzz" : nil
                          ].compact.join).empty? ? i : a
                        end
                  


                  100.times, в вашем случае, начнет отсчет с нуля и закончит на 99.
                  • +1
                    в коде используется переменная на 1 больше счетчика.
                  • 0
                    Извиняюсь, пропустил вторую строку. Пойду спать
                  • +1
                    Обалденный вариант :)
                    • 0
                      Его можно записать с одну сроку, превратив Руби в плохой Перл :)
                      puts (1..100).map { |i| (a = [(i % 3).zero? ? "Fizz" : nil, (i % 5).zero? ? "Buzz" : nil].compact.join).empty? ? i : a }
                      
                      • 0
                        Похожий вариант у меня написался. Только не плохой Перл, а плохой… (подставить название функционального языка)

                        • +1
                          puts (1..100).map{|x| ((x % 15 == 0) && 'FizzBuzz') || ((x % 3 == 0) && 'Fizz') || ((x % 5 == 0) && 'Buzz') || x}
                        • 0
                          Вот на Scala

                          println(1 to 100 map( i => if (i%3==0) "Fizz" else if (i%5==0) "Buzz" else if (i%15==0) "FizzBuzz" else i ))

                      • +1
                        У меня тоже похоже вышло. Читаемости правда никакой, зато коротко:)
                        1.upto(100){|i|s=i%3==0?'fizz': '';s+='buzz'if i%5==0;puts s==''?i: s}
              • 0
                Довел до конца ваш вариант.
                100.times do |i|
                  num=i+1
                  [ (num % 3).zero? ? "Fizz" : nil,
                    (num % 5).zero? ? "Buzz" : nil,
                    ((num % 3).zero? or (num % 5).zero?) ? nil : num,
                    ","
                    ].compact.join.display  
                end
                
                • +1
                  А я так сделал:

                  (1..100).each do |i|  
                    puts (s = "#{"Fizz" if (i % 3).zero?}#{"Buzz" if (i % 5).zero?}").empty? ? i : s 
                  end
                  
                • 0
                  Так это че за язык? Пишите все язык, плиз.
                  • 0
                    Класс у подсветки синтаксиса — ruby
                    • 0
                      Вы считаете нормальным изучать исходники страницы, для выяснения того, на каком языке написан фрагмент одного из сотен комментов? Я-то ruby опознал, но вот не уверен, что, например, отличу Scheme от CommonLisp (вернее уверен, что не отличу).

                      Если вы просто подсказали человеку, на каком языке этот тред, не имея в виду, что он мог сам посмотреть исходники, приношу свои искренние извинения.
              • +1
                вот это синтаксис! код сразу понятен и при этом очень коротко записан!
            • +5
              Например вот так, на перле:
              for (1..100)
              {
                print (  (!($_%3) && !($_%5))?'FizzBuzz':(!($_%3)?'Fizz':(!($_%5)?'Buzz':$_)) );
              }


              • +15
                PHP — это маленькое зло, созданное некомпетентными новичками, в то время как Perl — это большое и коварное зло, созданное умелыми, но извращёнными профессионалами.
              • +1
                0_o Блин. Теперь perl у меня ассоциируется со смайликами $_%
                • +1
                  Можно сделать красивее, как например тут.
                  А я добавил скобок, для большей читаемости %).
                • +3
                  Эти смайлики плачут кровавыми слезами.
      • 0
        ну вот) опередили
      • 0
        Вот-вот. :) Я полагаю, именно это и имелось ввиду, когда автор говорит о том, что люди не умеют программировать…
        • +3
          Упомянутая недооптимизация требует дополнительной проверки того, что мы не вывели уже эти физы-базы. Из-за этого код становится менее читабельным, чем если бы содержал 4 условия.

          Если бы меня не приняли из-за этого на работу, то я был бы только рад: нахер нужна ТАКАЯ работа?!
          • +3
            действительно — пааадумаешь, что условие задачи не выполнено :-) важно ж, чтобы красиво.
      • +8
        Условий вообще тут нужно ноль:
        print [$_,"Fizz","Buzz","FizzBuzz"]->[!($_%3)+!($_%5)*2]."\n" foreach(1..100)

        (Перл, на других языках аналогично)
        • 0
          А толку? Переложить условную логику (которая тут гораздо более понятно выглядит) на доступ по индексу? Так в таком случае можно писать любой код вообще без условий, только зачем?
          • +1
            А зачем избавляться от условия на FizzBuzz? Если цель меньше условий, то держите. А если нет такой цели, а цель просто написать работающую программу, то суть вышеуказанной претензии неясна.
            • 0
              Незачем избавляться вообще ни от каких условий тут, должно быть 3 условия и в итоге 4 ветки.

              Просто подумал что описанный вами подход вы считаете правильным (исходя из слова «нужно» в каменте), если это была ирония, гиперболизирующая ответ предыдущего комментатора — прошу прощения, не уловил.
              • 0
                Я сперва тоже с тремя условиями написал, но мне тут в чате стали говорить, мол, одно условие лишнее :-)
                • 0
                  Даже если и найдется рабочий вариант с двумя условиями — это всё равно хуже чем топорный вариант с 3-мя. Так что вам в чате врут.
        • +1
          По-моему, это чудесно!
        • 0
          Хех, сначала написал чуть выше, а потом Ваш коментарий увидел. Мысли сходны :) Тоже подумалось о том что в минимализме можно условия убрать
      • 0
        Если не делать отдельный if, то все равно перед выводом числа нужно будет делать проверку:
        for (int i = 0; i < 100; i++) {
        	bool byThree = (!(i % 3));
        	bool byFive = (!(i % 6));
        	
        	if (byThree) std::cout << "Fizz";
        	if (byFive) std::cout << "Buzz";
        	if (!byThree && !byFive) std::cout << i;
        	std::cout << std::endl;
        }
        

        • 0
          bool byFive = (!(i % 5));
    • 0
      пых

      • +11
        … и программа напишет себя сама.
        • 0
          Промахнуля:)
    • –9
      пэхапэ

      for ($i = 0; $i < 100; $i++) {
      if ($i % 5 == 0 && $i % 3 == 0) print «FizzBuzz».PHP_EOL;
      elseif ($i % 5 == 0) print «Buzz».PHP_EOL;
      elseif ($i % 3 == 0) print «Fizz».PHP_EOL;
      else print $i.PHP_EOL;
      }
      • +2
        в условии от 1 до 100, а не от 0 до 99
        • –12
          это мелкая ошибочка
          • +5
            А потом в Африке самолеты падают!
      • –1
        Если пожертвовать красотой и несколькими строчками, то можно решить задачу вот так.
        В Вашем варианте отдельное условие для вывода FizzBuzz необосновано.
        for ($i = 1; $i <= 30; $i++)
        {
            if (($i % 3 != 0) AND ($i % 5 != 0)) echo $i;
            else
            {
                if ($i % 3 == 0) echo 'Fizz';
                if ($i % 5 == 0) echo 'Buzz';
            }
            echo '
        ';
        }
        
        • 0
          Парсер лох… Там в конце был br.
          А в начале 30 вместо 100 — это у меня экран на ноуте маленький, на 100 записях скролл появится...))
        • 0
          Мне мой вариант кажется более человекочитаем, при том что для того чтобы поменять физзбазз на что-нибудь другое ненужно менять логику. А по производительности условия те же.
      • +4
        for($i = 1; $i <= 100; $i++) {
        	echo ((($s = (($i%3 == 0) ? 'Fizz' : '') . (($i%5 == 0) ? 'Buzz' : '')) == '') ? $i : $s) . '<br />';
        }
        
        • 0
          А, если твой скрипт вывести на консоль, задача будет решена неправильно, т.к.
          никто не просил :-р
          • 0
            br никто не просил)
            • +4
              На похапе тоже ни кто не просил ^_^
    • 0
      Я не пойму, почему все так упрямо минусуют этот мой пост!? И никто мне не написал, за что собственно…

      //////// пост ////

  • +10
    Задача решена и код нечитабельный, два зайца убиты :)

    Console.WriteLine(
                    string.Join(
                        Environment.NewLine,
                        Enumerable.Range(1, 100)
                            .Select(num =>
                                num % 5 == 0 && num % 3 == 0 ? "FizzBuzz" :
                                num % 3 == 0 ? "Fizz" :
                                num % 5 == 0 ? "Buzz" :
                                Convert.ToString(num)
                            )
                    )
     );
    • +4
      Классно Вы F# в C# запихнули :)
      • –6
        Я не знаком с языком, но это может быть Nemerle. Говорят, интересный язык.
        • +4
          Не, я не о том, это был чистый C#, но программирование не в стиле C#.
      • 0
        генерализованный FB на F#

        
        let divs = [(3, "Fizz"); (5, "Buzz")]
        
        let prefix i = 
            divs 
            |> Seq.filter (fun (d, _) -> (i % d) = 0) 
            |> Seq.map snd 
            |> String.concat ""
        
        let convert i = 
            let special = prefix i
            if special = "" then
                string i
            else
                special
             
        {1..100} 
        |> Seq.map convert 
        |> Seq.iter (fun x -> printfn "%A" x)
        
  • +4
    почитав вопросы на том же stackoverflow.com приходишь в ужОс.
    не говоря уже о недостатках логики, которая закладывается ещё в школе
    • +3
      Ага, что то типа «Я тут пишу свою социальную сеть, подскажите пожалуйста регулярку чтоб валидировать имя пользователя» регулярно встречается.
  • 0
    По моему личному опыту не более 20% выпускников, пришедших на собеседование, могут написать например поиск в бинарном дереве или перевернуть односвязный список на бумажке.
    • 0
      Ну тут главное не слишком углубляться все же :).

      Структуру красно-черного дерева в коде напишет 5-10%.
      Алгоритм построения суффиксного дерева, который тут недавно постили — напишет по памяти думаю 0.001 процент.
      • 0
        Хотя эти задачки решаются в несколько строчек мы потом еще упростили и уже просили например перевернуть строку или просто скопировать строку без использования библиотечных функций — но картина стала не особо лучше.
      • 0
        Переоцениваете. 5-10% будут знать о существовании красно-черных деревьев, а толком объяснить что они и с чем их едят сможет меньше 1%.
        Знаю по опыту, проводил собеседования.
        • 0
          На какой уровень, если не секрет? Стоит ли гуглить на эту тему, если претендуешь на джуниора? :)
          • +1
            Если в ходе подготовки к собеседованию — однозначно не стоит. Даже на синьора. Задач такого уровня на собеседованиях не дают: ни смысла, ни нужды нет. 5-10% и <1% эмпирически выведенные числа, по общему впечатлению о кандидатах. Требовать красно-чёрные деревья есть смысл только на очень специфические вакансии, которых в наши дни раз, два и обчёлся. А если вы будете идти на собеседование по такой вакансии — не бойтесь, вас предупредят.

            Хотя для собственного общего развития тема интересная. Могу посоветовать почитать отличную книгу Кормена о деревьях и не только.

            Ну и если очень грубо — хороший джуниор должен удовлетворять первому уровню Programmer Competency Matrix.
            • 0
              Спасибо, еще одно подтверждение того что не зря ищу эту книгу, жаль только что 2-е издание уже не переиздается и через озон не купить, а третье будет только в 2012 (
              Придется читать PDF.
            • 0
              На собеседование в яндекс знакомого спрашивали про красно-черные деревья. Рассказал мало, послали подучиться.
              • 0
                Послали думаю не через красно-черные деревья. Если конечно брали не на работу в ядро поиска, или что-нибудь другое столь же серьезное в плане производительности и вообще алгоритмов. А если именно потому — то это как раз та специфическая вакансия которых раз, два и обчелся. И ваш друг наверное был в курсе о том, куда и на какую позицию идет.
    • +17
      Знаете, я лично на собеседовании не напишу. В WEB такие вещи используются редко, так что вспоминаешь быстрым гуглением и реализовываешь.

      ИМХО, алгоритмами нужно именно заниматься, что бы быть в состоянии их написать с ходу по памяти. А когда оно тебе надо раз в 2 года — согласитесь, без гугла или документации/книги по алгоритмам нереально :)
      Главное уметь найти и быстро вспомнить! :)
      • +2
        Я и сам не напишу красно-черное дерево по памяти без гугла за час :) Потому и призываю адекватно смотреть.

        Если только это не какой нибудь Google/ MS Research :)
        • +1
          Был месяц назад в гугле на собеседованиях (проводится 5 штук по 45 минут, с разными людьми) на вакансию девелопера.
          Никаких задач «на сообразительность» там не было.
          Задачи, конечно, сложней, чем этот FizzBuzz, но без красно-черных деревьев.
          По уровню сложности типа написания двоичной сортировки, но более практичные — т.е. не надо писать функции, которые есть в стандартных библиотеках.
      • 0
        Да, конечно, есть такие алгоритмы, которые тяжело написать, если не знать.
        Но конкретно в этих случаях можно придумать ответ самому довольно быстро, даже если не знать наперед. Вся необходимая информация давалась.
        • –1
          Не стоит так передёргивать :) Вам задать какой-нибудь вопрос по школьной химии, на который вы не ответите? А ведь вся информация, ну вы поняли…
          • 0
            Это вы передёргиваете, кандидатам было подробно обьяснено, что такое бинарное дерево или односвязный список, также была описана структура на С.
            Этого и знания С в рамках любого учебника вполне достаточно, чтобы этот код написать, времени тоже давалось достаточно.
            • 0
              Я подумал, вы имеете в виду что «вся информация по бинарным деревьям в институтах давалась». Виноват :)
    • +1
      Это ерундистика. Я не занимался программированием уже года два и все забыл напрочь, но решение этих «задач», что вы тут написали можно найти за 5 минут. Дело совсем не в том, чтобы помнить наизусть кучу алгоритмов.
  • +1
    На Python
    • +9
      for i in range(1,100):
      print ['fizz','',''][i%3] + ['buzz','','','',''][i%5] or i
      • +4
        чуть более длинный, но гораздо более неадекватный вариант :D
        print' '.join(''.join(['fizz']*(1-x%3)+['buzz']*(1-x%5)or str(x))
        for x in range(1,100))
        
        • 0
          [(not i%3 and 'Fizz' or '')+(not i%5 and 'Buzz' or '') or i for i in range(1,101)]
          • 0
            Ну, тут я, конечно, несознательно урезал длину в угоду красивому выводу. Если требуются просто числа
            
            print ' '.join([(not i%3)*'Fizz'+(not i%5)*'Buzz' or str(i) for i in range(1,101)])
            
      • 0
        в данном примере выведет до 99 ))
        • 0
          n=map(str, range(101))
          n[::3]=['fizz']*34
          n[::5]=['buzz']*21
          n[::15]=['fizzbuzz']*7
          print '\n'.join(n[1:])
          • 0
            Память расходуется неэкономно.
            • +1
              for x in range(100): print x%3/2*'fizz'+x%5/4*'buzz' or x+1
              • 0
                Проверяете число x, а выводите x+1.
              • +1
                Оптимальнее написать range(1,101) и выводить x, вместо того, чтобы применять 100 раз сложение
                • 0
                  Понял, туплю…
  • +8
    Поддерживаю подход автора.

    За декабрь просмотрел тестовые задания (написание калькулятора, вычисляющего расстояния между парами городов, с веб-интерфейсом) 3-4 кандидатов, после чего предполагалось что их будут собеседовать «вживую». К сожалению, ни один не дошел до этого собеседования :(

    Я добавлю еще от себя один момент. Ощущение, что многие люди в подробном тестовом задании на 2/3 страницы читают только первый абзац (или первые два). Т.е. в их работе нет ни следа того, что в задании указано как обязательный компонент.

    Если будет интерес, могу потом написать топик на тему, какие ошибки и антипаттерны встречал чаще всего в тестовом задании на знание Java / J2EE / MySQL.

    • +5
      Если можете писать — пишите. Вы же не Толстой…
    • +3
      Напишите, интересно.
    • +4
      Как интересно. Кратчайшее расстояние по сфере между точками? Или по эллипсоиду Красовского? Или по какому-то другому приближению формы Земли? Или задача минимизации расстояния с использованием заданной сети автодорог?
    • 0
      «Обещанного три года ждут.»

      Время вышло.
  • 0
    Я вот тоже как-то давал кандидатам задание — написать связанный список. Около половины не справляются.
  • +1
    После прочтения почувствовал себя гением.
    Нечго таким людям в программировании делать.
    • +1
      Ага. Я вот лично считаю себя где-то средним программистом, но при этом пробные тесты SCJP прохожу на ура (увы, платить за сертификат пока не могу себе позволить), да и калькулятор выражений за пару часов напишу.
      • –1
        Калькулятор выражений? :D
        print eval <>

        (Перл)
        • 0
          Программирование не ограничивается перлом.
  • +7
    «Почему» в заголовке — вопрос риторический? А то я пришел за ответом… =)
    • 0
      Конечно риторический:)

      Наверное, всё-таки не стоило переводить заголовок дословно, по-английски он звучит как-то более естественно
  • +5
    > FizzBuzz, или почему программисты не умеют программировать

    А где, собственно, ответ на вопрос «почему?» :)
  • 0
    Дурацкий заголовок, так и непонятно почему программисты не умеют программировать. А вообще на собеседовании большинство начинающих могут просто испытывать дикий стресс и не справиться…
    • +2
      блин, надо было обновлять топик перед ответом :)
  • +5
    Поверьте, если вы можете написать цикл от 1 до 10 на всех языках, указанных в вашем резюме, если вы можете решить в уме несложный арифметический пример и если вы знаете, как применить рекурсию в несложной (но взятой из реальной жизни) задаче — то вы уже на голову выше большей части людей, вращающихся в нашей индустрии.

    Хм, честно говоря, даже умея спокойно решить такие задачки, я не считаю себя программистом. Такие базовые знания алгоритмов, имхо, необходимы сейчас практически в любой области ИТ. Все таки в моем понимании программист — это человек глубоко знающий алгоритмы, математику, парадигмы и паттерны программирования.
    • +13
      не считать себя программистом — вообще хороший подход. А то как только начнешь себя им считать — бах — и остановился в развитии, начало распухать самооценка, и вообще превратился в незнамо что =)
      уж лучше тихо скромно писать код да учиться =)
  • +2
    Угу согласен у нас в универе из группы програмисто 2\3 не решат эту задачу
    • +3
      >2\3

      За обратный слэш я готов убить МС: уже и при делении его вместо прямого ставят %)
      • 0
        ааа… ну да… ^^' тут всетаки 2/3 хорошее замечание
  • 0
    я бы вообще агитировал студентов участвовать в опен сорс проектах.
    • +2
      Ага, чтобы эти проекты канули в лету )
      • 0
        Да кто ж пустит в основной репозиторий такой страшный код?
  • –1
    Вот интересная задачка ещё на тестирование:
    Сделать кольцевой сдвиг строки из M символов на N позиций, при этом используя минимальное количество памяти и минимальное количество операций чтения/записи из строки.
    • +1
      Если мне сейчас не изменяет память, там для ассемблера было 7 переменных, для C — 6 переменных (размера разрядности платформы), M операций чтения из строки и M операций записи.
      • 0
        Интересно для чего 6. По-моему 4 хватает:
        public class Main {
            static private long NOD(long n1, long n2) {
                if (n2 == 0)
                    return n1;
                return NOD(n2, n1 % n2);
            }
            
            static private void shr(char[] arr, int N) {
                for (int i = 0; i < NOD(arr.length, N); i++) {
                    int j = i;
                    char saved = arr[j];
                    do {
                        j = (j + N) % arr.length;
                        char nextVal = arr[j];
                        arr[j] = saved;
                        saved = nextVal;
                    } while (i != j);
                }
            }
            
            public static void main(String[] args) {
                char[] test = {'e', '2', 'i', '/', 'o', 'e', 'u', 'i', '/', 'o'};
                shr(test, 2);
                System.out.println(test);
            }
        }

        • 0
          Указатель на начало массива
          Длина массива
          N
          i
          j
          saved
          nextVal
          Итого — 7.
          • 0
            Тогда всё сходится. Хотя, всё же, общепринято не учитывать размер входных данных при оценке требований к памяти.
            • 0
              Возможно.
              Вообще на практике — не вижу особого смысла оценивать требования к памяти побайтно, обычно достаточно оценок «линейно», «квадратично», «константно», большой множитель зачастую скрывает в себе косвенную зависимость на непосредственно размер данных или другие характеристики, связанные с входными данными (как в radix сортировке).
    • +8
      Задачка на тестирование чего?
      Наймешь такого, а потом внезапно у тебя куча очень быстрого кода в одной функции на 2000000 строк, а разработчика сбил автобус)
      • 0
        На тестирование сообразительности. Правильное решение достаточно красиво и без грязных хаков, плюс это показывает умение мыслить логически и понимание математики отчасти.
        А одним тестом нельзя измерить всех параметров, так что на стиль кодирование и умение проектировать нужны свои тесты.
        • +2
          Тут имеет смысл не получение решения а наблюдение за его получением, к вашему правильному решению не прийдет за разумное для одного вопроса время думаю большинство нормальных программистов. Просто потому что современные программисты редко работают на таком низком уровне.
          • 0
            Ну вопрос к специфике работы, если не нужно тестировать такие знания — то и тесты такие не нужны, а если нужно протестировать понимание математики, а не зазубривание известных алгоритмов — задача вполне адекватная. Я пришел к решению за 30 минут, раньше никаких подобных задач не решал, никаких готовых алгоритмов для этого тоже не знал. Так что вполне для теста пойдет.
            • 0
              Попробуйте лучше определить, нет ли на конце односвязного списка (о-очень большого) кольца, не используя дополнительной памяти (читай: массивов), не копируя элементы списка. Сложность алгоритма должна быть O(n).

              P.S. Список заканчивается кольцом, если последний элемент списка указывает на один из элементов в середине списка.
              • 0
                Т.е. проверить, куда указывает конец списка, и потом пробежаться по списку, проверяя указатели? Или я что-то не понял?
                • 0
                  При сложности же указывается порядок и O(n) == O(2n) (последний вариант обычно не пишут).
                • 0
                  Ах, да, ступил, исправлюсь)
                  • 0
                    Решение 1 (верное) — абстрагировать список за объектом, который всегда хранит кол-во элементов в нем и использовать метод описанный выше (я сразу и подумал, что список — целостный объект)
                    Решение 2 — Можно пройти кареткой K=N, запомнить адрес останова, пройти K=2N, запомнить адрес останова (в той же переменной), потом K=4N K=8N и т.д. Тогда если список закольцован, как только мы попадем в кольцо и K будет равно длине кольца — мы обнаружим совпадение.
                    Сложность зависит от длины списка n линейно, т.к. когда мы дойдем до конца списка (+ максимум n-1 сверху) следующий K будет больше списка. Т.о. сделаем меньше 4n операций, что укладывается в линейные ограничения. Используем 1 ячейку памяти.
                    • 0
                      >Можно пройти кареткой K=N, запомнить адрес останова, пройти K=2N, запомнить адрес останова (в той же переменной), потом K=4N K=8N и т.д. Тогда если список закольцован, как только мы попадем в кольцо и K будет равно длине кольца — мы обнаружим совпадение

                      У меня 2 вопроса:
                      а) что такое N?
                      б) что если K никогда не будет равно длине кольца (скажем, кольцо длины 11)?
                      • 0
                        Не стал сразу исправлять:
                        N — начальный «шаг», можно взять равным 1 для простоты
                        Для К конечно же «больше или равно».
                        И тогда уж исправлюсь с максимальной сложностью, она равна 3n.

                        Как работает:
                        Представим что у нас список длины n, n+1 вершина — это уже середина списка, т.е. кольцо.
                        Будем двигаться по указанной схеме, на каждом шаге запоминая вершину, в которой мы находимся
                        Возьмём тот шаг, когда мы ещё не прошли n вершин в сумме, но на следующем шаге пройдем, следовательно — попадем в кольцо.
                        Возьмем худший случай «оверхеда», предположим что на предыдущем шаге мы находились на самой последней вершине и (т.к. следующий шаг равен сумме всех предыдущих + 1) сделаем таким образом n+1 лишних переходов по списку.
                        Затем запоминаем текущее положение и делаем следующий «проход», т.к. он будет очевидно больше размера списка (т.к. мы уже прошли список, а каждый следующих ход больше всех предыдущих), то он и больше размера кольца
                        А раз ход больше размера кольца — то мы на нем то и наткнемся на нашу «помеченную» вершину. В данном случае худший вариант — если список закольцован на начало, тогда мы должны будем пройти весь список (n переходов), до того, как можем констатировать закольцованность.
                        Таким образом худший случай — 3n+1 операций чтения. Лучший случай — n операций чтения, когда при первом прохождении списка мы попадаем с последней вершины сразу на помеченную.
                        • 0
                          Ок, теперь понятно. Да, такое сработает. У меня в своё время было другое решение: запустить одновременно два «бегунка» по списку: один бежит с шагом 1, второй с шагом 2. Если они в какой-то момент втречаются — список закольцован, т.к. изначально более быстрый удаляется от медленного со скоростью 2 элемент за шаг, а при выходе обоих на кольцо он начинает догонять более медленного со скоростью 1 элемент за шаг, т.е. в конце концов догонит.
                          • 0
                            Тоже задачка на собеседовании была, или попался реальный код?
                            • 0
                              На собеседовании. За реальный код я бы «оторвал руки разработчику» и далее по тексту… :)

                              Хотя при использовании высокоуровневых классов/библиотек тоже нужно думать и хорошо понимать, что происходит у них внутри. Вот, буквально час назад попался шедевр (Java):

                                  public void setResults(long[] uids) {
                                      if (uids != null) {
                                          int length = uids.length;
                                          if (length > 0) {
                                              User user;
                                              User[] users = new User[0];
                                              for (int i = 0; i < length; i++) {
                                                  user = UserStorageAccessor.getUser(uids[i]);
                                                  Arrays.add(users, user);
                                              }
                                              setResults(users, true);
                                          }
                                      }
                                  }
                              


                              вместо простого

                                  public void setResults(long[] uids) {
                                      if (uids != null) {
                                          int length = uids.length;
                                          if (length > 0) {
                                              User[] users = new User[length];
                                              for (int i = 0; i < length; i++) {
                                                  users[i] = UserStorageAccessor.getUser(uids[i]);
                                              }
                                              setResults(users, true);
                                          }
                                      }
                                  }
                              


                              Что происходит внутри Arrays.add(...) — догадываетесь? :)
                              • 0
                                Да уж. Экономить на создании объектов этого разработчика явно не учили. Плачевно.
                                • 0
                                  Хотя стоп… Тут вообще не будет работать )
                                  Из Arrays.add() ведь нельзя изменить ссылку )
                                  • 0
                                    Не-не, всё работает (как раз потому, что массив передаётся по ссылке). Просто внутри Arrays.add(..) массив каждый раз пересоздаётся заново (размером +1), копируя имеющиеся элементы и добавляя ещё один. И после отработки функции ссылка указывает на валидный массив (просто он уже лежит по другому адресу). Вот так вместо того, чтобы создать массив один раз, он пересоздаётся в цикле на каждой итерации :)
                                • 0
                                  Ну хоть на создании ссылок экономить научили (и тем самым немного отсрочить пробуждение GC) — и то хлеб. Видите, объявление User user; вынесено за пределы цикла? А ведь могло быть

                                  for (int i = 0; i < length; i++) {
                                      User user = UserStorageAccessor.getUser(uids[i]);
                                      Arrays.add(users, user);
                                  }
                    • 0
                      Решение 1 не подходит, т.к. список дается внешним образом, т.е. над структурой этого объекта мы не властны.
                      Решение 2 сработает :-)
                      • 0
                        Под первым решением я имел ввиду выделить абстракцию не в данном участке кода, а вообще по системе.
                • 0
                  Каким образом вы «проверите, куда указывает конец списка»? На каком элементе вы остановитесь и скажете «это конец, давайте проверим, куда он указывает»?
                  • 0
                    Я выше указал ответ, просто я как-то не привык к тому, что кому-то в голову взбредёт работать сразу с начинкой списка (т.е. с лист-нодами) без абстрагирующей оболочки. А когда есть абстрагирующая оболочка — у ней чуть ли не в первую очередь будет число элементов в списке, а зачастую и указатель на начало/конец списка + указатель на «текущий» элемент.
                    А если кто-то написал код, работающий с начинкой списка напрямую — то советую в первую очередь оторвать ему руки, и только потом садиться решать подобные задачи.
                    • 0
                      Если кто-то написал код, работающий с начинкой списка напрямую — то советую в первую очередь оторвать ему руки, и только потом садиться решать подобные задачи

                      Это очень хороший ответ, за него я поставлю мысленный плюс и скажу примерно следующее: «Да, действительно, это плохая практика, поэтому давайте мысленно перенесёмся в тот момент, когда руки автору уже оторвали, и теперь нужно решить задачу, когда у вас есть „сырой“ список, где каждый элемент содержит своё значение и указатель на следующий элемент. Исходные данные — указатель на головной элемент списка».
                      • 0
                        Я понял задачу, и вроде решил её несколькими каментами выше. Мой ответ здесь был собственно объяснением моей первой реакции, с непривычки к такому вопиющему надругательству.
                        А решить всё-таки при наличии времени я бы посоветовал введением уровня абстракции целостного списка.
                        • 0
                          В данном случае это все-таки не реальная, а академическая задача. Как раз для случаев, когда нужно проверить, насколько у разработчика работают мозги. В реальной жизни оно вряд ли встретится при нормальном подходе к программированию (объект-оболочка + запоминание длины списка).
    • 0
      ага, хороший пример плохого тестового задания для выполнения на собеседовании. гораздо больше толку от приведённых в топике и пары вопросов типа что бы вы сделали если стали президентом или выиграли сто тыщ мильёнов.
      • 0
        Чем оно так плохо? Если стоит задача протестировать способность человека понимать математику и разрабатывать свои алгоритмы на работе?
        • 0
          В общем случае плохо. Мне вот например нужен разработчик на pl/sql или на php, а не для разработки драйверов, откуда у них знания про экономию памяти?

          Способность более-менее алгоритмически формулировать свои мысли замечательно проверяют простенькие примеры с одним циклом и одним условием, за минуту и вне зависимости от специализации. Если ищется реально спец, то и вопросы к нему реально специальные, да и находятся они обычно адресно.
          • +1
            Вообще задача не на экономию памяти по сути (т.к. это зачастую абсолютное зло при цене 20$ за планку RAM), если нужен человек, от которого не требуется создание алгоритмов — то и тесты другие.
    • НЛО прилетело и опубликовало эту надпись здесь
  • +7
    Всегда было интересно: при решении тестового занятия в присутствии собеседующих можно ли пользоваться Гуглем? С одной стороны, если человек полез в поисковик — значит, он не помнит\не знает точной команды\синтаксиса. С другой стороны, раз полез — значит, может найти и применить…
    • +5
      по некоторым своим знакомым могу сказать, что владение Гуглем имеет смысл тестировать отдельно :)
    • +1
      У меня один товарищ (5 курс факультета программирования Бауманки в Калуге) в ответ на просьбу написать сортировку любым известным ему алгоритмом попросил справочник по синтаксису PHP. Мне было даже интересно, что он с ним делать будет. Дал. Он долго листал, потом нашёл синтаксис объявления массива и феерически обосрался, не сумев перепечатать из книжки без ошибки.
      • 0
        Просто в Пхп настолько нереально все запомнить, что многие даже не пытаются. Ничего удивительного в этом нет.
        • 0
          Условие задачи ставилось так: «Реализовать любой алгоритм сортировки на любом известном вам языке. Вылизывать программу не надо, нюансы синтаксиса неважны, мы её даже компилировать не будем. Хочу просто посмотреть, как вы программируете». PHP был выбран соискателем :)
  • 0
    Процесс собеседований в нашей фирме требует, чтобы кандидат предоставил нам фрагмент своего кода еще до телефонного собеседования.

    Абсолютно согласен по поводу тестовых заданий, но вот что мне не очень понятно, так это зачем нужно просить прислать образец кода. Что по этому образцу можно понять кроме стиля (отступов, фигурных скобок и т.д.)?
    • +3
      Мой код весь практически закрыт NDA, уверен как и у большинства enterprize-ников.
      • 0
        Дело даже не в NDA, просто когда ты посылаеш образец кода, ты не можешь послать целый проект, посылаешь какие то файлы или куски файлов с определемием классов, какие то куски с логикой. Во всех этих кусках кода вряд ли кто то будет разбираться, а если и будут, то могут и не найти реализации рекурсии или патерна.

        Так что мне действительно интересно что люди хотят увидеть в образцах кода присланных даже до телефонного собеседования. Намой взгля кроме стиля форматирования там ничего увидеть нельзя.
        • +1
          Собственно, одного взгляда на код достаточно, чтобы понять:
          — пользуется ли собеседуемый каким-либо распространенным стилем кодирования;
          — умеет ли более-менее сносно проводить декомпозицию;

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

            Но за ответ спасибо, вы мне открыли глаза на логику которой пользуются когда практикуют подобную шему при принятии на работу.
            • 0
              Я лично не собеседую, поэтому комментарий выше — это мое мнение, зачем это могло бы понадобиться.
          • 0
            А почему просите именно образцы кода, а не даёте тестовое задание? Во втором случае у вас же уже будет «идеальное» решение с которым можно реально сравнивать код собеседуемого? Сможете понять учёл ли он, например, все требования, граничные условия и т. п.
            • 0
              Удалённое тестовое задание не гарантирует, что его писал сам соискатель. Всё равно придётся перепроверять знания при личной встрече. Образцы кода в этом смысле — это элемент уважения к соискателю.
              • +1
                Так же как образцы кода не гарантируют, что его писал сам соискатель. Они это ещё меньше гарантируют. В чём уважение не понимаю. Я бы понял, если бы требовали или образцы кода, или выполнить тестовое задание, но требуют, как правило, что-то одно, а то и обязательно оба варианта, а вот честное «или» не встречал.
                • 0
                  > Так же как образцы кода не гарантируют, что его писал сам соискатель. Они это ещё меньше гарантируют.
                  Естественно, не гарантируют. Всё равно придётся на собеседовании выяснять, что он из себя представляет. Образцы кода, тестовые задания (когда их программист удалённо делает) — это быстрый отсев программистов от непрограммистов. И требовать трудозатрат от соискателя ещё до того, как обязался платить ему зарплату, я считаю некорректным. Вы для соискателя не один такой. Если каждый будет просить потратить часок времени, это создаст много неудобств кандидату.
                  • 0
                    Требовать, да, некорректно (тем более известны случаи мошенничества, когда соискатели под видом тестовых заданий целые проекты выполняли), но так же некорректно, имхо, требовать образцов кода. Написать в вакансии: «плюсом будут образцы вашего хорошего кода и/или выполнение тестового задания + линк на задание» — и корректно, и работодателю удобно, и соискатель может показать себя с той стороны, которую он считает лучшей. Ну, например, не было принято на предыдущей работе покрывать код тестами, а он тестовое задание покроет. Это не говоря о том, что вообще код с работы отдавать потенциальным конкурентам как минимум не очень этично.
                    • 0
                      Предложить на выбор — вполне разумно. Что касается «покрыть тестами или не покрыть», вы видимо не представляете, какого качества 90% приходящих примеров кода. Там такое, что волосы под мышками шевелятся. Одного взгляда достаточно, чтобы отсеять бОльшую часть кандидатов и сэкономить кучу времени на собеседования. Если там что-то вменяемое, это сразу видно, и человека можно в офис звать. О том, чтобы код был покрыт тестами, можно и не мечтать. А если уж кто-то покроет, то всё равно это пустая трата времени, т.к. заведомо неизвестно, он сам писал или нет.
      • 0
        Кода «для себя» вы не пишите в принципе?
        Оный вполне может подойти в качестве примера.
        • 0
          Верите-нет, но на том языке, на котором больше всего писал непрерывно на работе и, видимо, как следствие, на котором я заработал больше всего денег, ни строчки для себя или на своём компе не написал. Мне тот язык показался наиболее подходящим для решения поставленной задачи, я его изучил с нуля (ну, если не считать, что практически все языки на которых я писал большее, чем «hello world», кроме семейства ведущего род от SGML, были императивными, хотя не все реализовывали даже цикл — приходилось применять IF и GOTO), задачу решил в обозначенные сроки (поэтапно, шаг ~2-3 недели, да и задача уточнялась с шагом ~2 месяца), заказчик доволен до сих пор.

          Похожая ситуация с языком на среднее владение которым я претендую в резюме: для себя писал только прототипы, которые сам увидев на продакшене назвал бы «быдлокодом» ещё 10 лет назад (пускай такого термина и не было тогда) — никакой проверки пользовательских данных, никакой проверки на результаты операций с внешними сервисами типа БД или чужих сайтов, про архитектуру или хайлоад вообще молчу, мне были интересны либо практическая возможность реализации моих идей, либо привлечение инвестиций (то, что с некоторых пор в рунете стал модно называть «стартап»). Всегда подразумевалось, что в конечной реализации останется, максимум, то, что я сейчас называю «сценарии пользования». Всегда подразумевался корректный ввод и ожидаемая по типичному сценарию реакция (вплоть до того, что запрос к БД не может не вернуть хотя бы одну запись, а запрос к чужому сайту что-то отличное от того, что я вижу в браузере, заходя как реальный пользователь).

          Что мне слать в качестве образца кода — то, что я сам считаю быдлокодом не только теперь, но и на момент написания?
  • 0
    Интересно, сколько пройдет такое собеседование, если попросить написать FizzBuzz на прологе?
    • +1
      А вот и решение на SWI-Prolog:
      
      fizzBuzz(100).
      fizzBuzz(N) :-
      	I3 is N mod 3,
      	I5 is N mod 5,
      	print( I3, I5, N ), nl,
      	N2 is N + 1,
      	fizzBuzz(N2).
      
      print( 0, 0, _ ) :-
      	write( 'FizzBuzz' ).
      print( 0, _, _ ) :-
      	write( 'Fizz' ).
      print( _, 0, _ ) :-
      	write( 'Buzz' ).
      print( _, _, N ) :-
      	write(N).
      


      Запускать: fizzBuzz(1).
      • +3
        Через write как-то не слишком по-прологовски :) Вариант на gprolog:

        fizzlist(0, [], M).
        fizzlist(N, [H|T], M) :- N > 0, N1 is N - 1, M1 is M - N + 1, fizzbuzz(M1, H), fizzlist(N1, T, M).
        fizzlist(N, L) :- fizzlist(N, L, N).

        fizzbuzz(N, N) :- N mod 3 > 0, N mod 5 > 0.
        fizzbuzz(N, 'Fizz') :- 0 is N mod 3, N mod 5 > 0.
        fizzbuzz(N, 'Buzz') :- 0 is N mod 5, N mod 3 > 0.
        fizzbuzz(N, 'FizzBuzz') :- 0 is N mod 3, 0 is N mod 5.


        Соответственно,

        ?- fizzlist(100, L).
        • 0
          Если через список, то так проще ;)

          
          fizzBuzz(100, []).
          fizzBuzz(N, [H|T]) :-
          	I3 is N mod 3,
          	I5 is N mod 5,
          	val( I3, I5, N, H ),
          	N2 is N + 1,
          	fizzBuzz(N2, T).
          
          val( 0, 0, _, 'FizzBuzz' ).
          val( 0, _, _, 'Fizz' ).
          val( _, 0, _, 'Buzz' ).
          val( _, _, N, N ).
          


          ? fizzBuzz(1, L).
          • 0
            Проще, но я сохранил возможность сформировать список произвольной длины.
        • +2
          :-0
      • +2
        тогда вот на mercury

        :- module fizzbuzz.
        
        :- interface.
        
        :- import_module io.
        
        :- pred main(io, io).
        :- mode main(di, uo) is det.
        
        :- implementation.
        
        :- import_module int.
        
        main --> fizzbuzz(1).
        
        fizzbuzz(N) --> 
        	( {N =< 100} ->
        		print_fizzbuzz(N),
        		print(" "),
        		fizzbuzz(N + 1)
        	; []
        	).
        	
        print_fizzbuzz(N) --> 
        	( {N mod 3 = 0} ->
        		( {N mod 5 = 0} ->
        			print("fizzbuzz")
        		; print("fizz")
        		)
        	; {N mod 5 = 0} ->
        		print("buzz")
        	; print(N)
        	).
        


        D:\TEST\mercury>mercury --infer-all fizzbuzz.m
        fizzbuzz.m:016: Inferred :- pred fizzbuzz(int, io.state, io.state).
        fizzbuzz.m:016: Inferred :- mode fizzbuzz(di, di, uo) is det.
        fizzbuzz.m:024: Inferred :- pred print_fizzbuzz(int, io.state, io.state).
        fizzbuzz.m:024: Inferred :- mode print_fizzbuzz(in, di, uo) is det.
        D:\TEST\mercury>fizzbuzz.exe
        1 2 fizz 4 buzz fizz 7 8 fizz buzz 11 fizz 13 14 fizzbuzz 16 17 fizz 19 buzz fiz
        z 22 23 fizz buzz 26 fizz 28 29 fizzbuzz 31 32 fizz 34 buzz fizz 37 38 fizz buzz
        41 fizz 43 44 fizzbuzz 46 47 fizz 49 buzz fizz 52 53 fizz buzz 56 fizz 58 59 fi
        zzbuzz 61 62 fizz 64 buzz fizz 67 68 fizz buzz 71 fizz 73 74 fizzbuzz 76 77 fizz
        79 buzz fizz 82 83 fizz buzz 86 fizz 88 89 fizzbuzz 91 92 fizz 94 buzz fizz 97
        98 fizz buzz
  • +11
    Еще такое замечание — очень, ОЧЕНЬ много людей не разбираются в трех типах вещей. Не то, чтобы это была труъ Computer Science, но опытный программист… ну можно ожидать, что он это будет знать.

    1) Это внутренности той платформы, с которой человек проработал 3-5-7 лет. Вызвано тем, что нет мотивации и интереса копаться, или тем, что человек не сталкивался с сложными багами, проблемами при high-load, инфраструктурными задачами.

    Например, (примеры из мира Java) мало кто внятно рассказывает следующее:

    — Класслоадеры
    — Сборка мусора подробнее, чем «это отслеживание мертвых ссылок и очистка памяти». Алгоритмы, generation-based подход.
    — hot-swop кода
    — чуть-чуть про архитектуру JVM и как она вообще работает (байткод, стековая машина, фреймы, стек операндов, пул констант и прочее)
    — Некоторые ключи запуска JVM, из популярных (для управления памятью, например)
    — из каких компонентов состоит сервер приложений? Тот, который использовал в своем резюме соискатель. Какие фичи появились в его последнем крупном релизе?

    2) Язык / стандартная библиотека в тех частях, которые не используются в простом коде и простых проектах, и которые не описаны в некоторые книгах типа «Освой за 21 день».

    Пример из Java:

    — что такое soft / weak / phantom references?
    — аннотации и их процессинг
    — generics (вот это вообще kill-question)
    — что такое неблокируюший (lock-free, wait-free) ввод-вывод?
    — и т.д.

    3) Инструменты, используемые в проектах и инфраструктура. Системы контроля версий, Ant, Maven, Continuous Integration серверы, скриптинг (простейший!) для Windows CMD / unix bash, профайлеры, инструменты для мониторинга и прочее.

    — Что такое распределенная / централизованная система контроля версий?
    — Что такое бранчевание, как сделать бранч / бекмерж в той системе, про которую вы написали, что вы с — ней работали?
    — Что такое трехстороннее разрешение конфликта при коммите?

    — Что такое антовский таск, таджет. Можете ли вы написать собственный таск, который делает что-то примитивное.

    — Что такое управление зависимостями, что такое артефакт, репозиторий.

    — Какие CI серверы их использовали? Если человек пишет про них в резюме, спросить про них.

    — Пользовались ли вы когда-либо профайлером (каким?), какие результаты вы получали? Попросить рассказать об этом.

    • –1
      Плюсую стоя!

      С PHP та же ситуация. Только у нас вообще наверно 99.99% смотрят на тебя огромными лемурными глазами, когда начинаешь спрашивать особенности работы. Про внутренности я вообще молчу.
      Вопрос 2^7 вообще повергает народ в шок, а должно от зубов автоматом отскакивать :)
      • 0
        Т.е. вы думаете, большинство людей кто пишет на PHP 3-5 лет, ничего не могут сказать о внутренностях апача, о реализации PHP и прочее?
        • 0
          Многие даже не знают нормально ООП PHP, его особенностей и если спросить правила приведения типов в PHP — будут тупить. Это реальность :)
          • 0
            Как человек может знать особенности ООП в PHP (или вообще особенности чего-то), если он на других языках не писал или писал не ОО код (C, ASM — самые банальные примеры)?

            Навскидку для меня особенности ООП в PHP — нет перегрузки методов по сигнатуре и нет переопределения операторов. Ну и нет множественного наследования, не так давно это частично компенсировано интерфейсами, равно как и появились абстрактные классы/методы (в php4 их, кажется, не было). Наконец-то появилось позднее связывание. Какие ещё там особенности?
          • 0
            Я вам даже больше скажу — многие даже не знают, как устроен HTTP, как например, происходит GET или POST запрос.
            • 0
              Я тоже, 7-й уровень OSI более-менее знаю (хотя все заголовки и методы HTTP наизусть не помню, только простенький запрос и без кодирования урла и тела запроса смогу написать в телнете), 6-й и 5-й как-то оказываются выше 7-го, 4-й смутно представляю, 3-й ещё более смутно, а уж 2-й и 1-й очень-очень смутное представление и то, всё это только для частного случая HTTP over Ethernet
            • +2
              Я кстати с некоторых пор не спрашиваю таких вещей. Они настолько базовые и фундаментальные, что я удивлялся, как может человек идти работать веб-программистом, не зная их. Оказывается, что есть много талантливых программистов, которые не знают, потому что ни разу не приходилось знать. Эти знания можно получить в общих чертах за 5 минут, а детально — за час чтения RFC, если мозги на месте. А вот если человек не может выбрать максимальный элемент их массива, это уже клиника. Таких лучше подальше посылать.
              • 0
                Это скорее вопросы, чтобы посмотретЬ, чего стоит опыт, описанный в резюме. И как сам человек его оценивает.

                В этот раз пример из мира БД и оракла.

                Если человек сдал на 5 курс по разработке БД, и прочитал книжку о программировании под оракл, и пишет в резюме «Имею опыт работы с оракл, разработка схемы бд, написание стандартных запросов» — очень хорошо.

                Если человек сдал на 5 курс по разработке БД, и прочитал книжку о программировании под оракл, и пишет в резюме — «знаю оракл, или владею ораклом» — плохо. Он не понимает, что его знания — это 0.1 процент того, что в оракле есть. завышенное ЧСВ.

                Если человек пишет в резюме, что был ведущим Oracle-разработчиком / главным админом в проекте для крупного банка / какой то иной нагруженной и сложной системы, и пишет об этом факте — хорошо. Но это он должен подтвердить. Сертификатами и / или на собеседовании.

                Знакомый техлид рассказывал об одном случае, пришедший «ораклоид» в возрасте 40 лет, с указанным опытом работы с ораклом 5 лет, на собеседовании не смог написать умеренно-сложный запрос с having.
                • 0
                  Это да. В резюме такого понаписать могут… Проверять надо, конечно. Обычно после вопроса «что конкретно вы делали на ***», соискатель признаётся «в институте на лабах у нас было». Пара вопросов после этого ставит все точки над i.
                  • 0
                    Как представитель работодателей посоветуйте, пожалуйста, стоит ли упоминать в резюме языки, которые «на лабах были», «писал just for fun», «писал коммерчески, но с первой строчки за код стыдно было», «как-то пришлось» и т. п.? В общем те языки, знания основного синтаксиса которых можно восстановить буквально за один взгляд на произвольный листинг, в котором употребляются общепринятые конструкции хорошо знакомой парадигмы программирования? А если стоит, то как?
                    • +1
                      Однозначно стоит. Так и пометьте, что «just for fun». Это вас охарактеризует как человека, интересующегося программированием не просто в рамках работы от звонка до звонка, а желающего постоянно развиваться и профессионально расти.

                      Вообще, по моему скромному мнению, лучше для каждой технологии, перечисленной в резюме добавлять пару слов — что конкретно на этой технологии делали и в какой роли. Например:
                      Visual Basic — разработал архитектуру CRM для компании в 300 человек, потом реализовали проект коллективом в 5 человек;
                      Oracle — лабы в институте.
                      Это куда информативнее, чем просто Oracle, VB. Если написать «Oracle, VB», вас пригласят на собеседования по Ораклу, где вы провалитесь. А если распишете подробно, то даже пусть там VB, который никому нахрен не нужен, вас запросто могут взять. Очередной императивный язык выучить — дело нехитрое, а умение проектировать большие коммерческие системы на дороге не валяется. Мне вот нужны перловые программисты, но если написать в требованиях «Perl», соискателей мало. А если не писать, а приглашать всех, то оказывается, что хороших программистов в разы больше, а Perl изучается по ходу дела на ура. И если у соискателя будет много-много всего перечислено в резюме с пометкой «just for fun», он 100% легко разберётся с любой незнакомой ему технологией.
                      • 0
                        Спасибо за подробный ответ
    • 0
      Очень хороший набор вопросов, именно их мне в основном на собеседованиях и задавали, и именно поэтому я на них со временем «натаскалась» и других натаскивала:)
      Поэтому, к сожалению, хорошие ответы на такие вопросы тоже не всегда показатель — разве что того, что человек к собеседованию готовился.
  • 0
    Быстро, в общем:
    • –1
      window.onload = function () {
      for (var i = 1; i < 101; i++) {
      document.write(((q=((0==i%3?'fizz':'')+(0==i%5?'buzz':'')))?q:i)+'<br>');
      }
      };
      • 0
        да чтож такое-то… чего минусите?
        • 0
          <br> в задании не было — может поэтому? :)
          • +1
            \n тоже в задаче не было. И пробелов тоже. Но все же как-то форматируют перед выводом…
            • 0
              я только предположил, может код не отформатировали…

              <source lang=«javascript»>ваш код</source> дал бы
              window.onload = function () {
                for (var i = 1; i < 101; i++) {
                  document.write(((q=((0==i%3?'fizz':'')+(0==i%5?'buzz':'')))?q:i+'<br>'));
                }
              };
              • 0
                И не поэтому… Тут полно вообще без <code>...</code> Ладно, забейте :-)
                Это больше риторический вопрос… Тем ленивцам, которым поставить минус не влом, а написать почему — влом.
              • +1
                Опа, вот я и узнал, как на хабре нативно форматировать код.
                Об этом было написано где-нибудь в справке? Когда нужно было — не нашёл.
                • +1
                  Над формой комментария есть ссылка «можно использовать html-теги»
                  Там с самого начала:
                  <source lang="язык"></source>
                  подсвечивает код программы (поддерживается bash, cpp, cs, xml, html, java, javascript, lisp, lua, php, perl, python, ruby, sql, scala, tex)
                • 0
                  burdakovd, ну лично я с легкостью ориентируюсь по пиктограммам в редакторе текста, если мне нужно выполнить какое-либо действие. А вы разве нет?
  • +1
    Хорошо себя зарекомендовали 2 задачи, которые я предлагал претендентам на вакансию:

    1. Придумать алгоритм отрисовки «прямой» линии, соединяющей 2 точки на растре.
    1.1. Для тех кто вспоминал про тангенс объяснялось что это как минимум медленно и предлагалось отказатся о тригонометрии.
    2. Даны одномерные координаты N отрезков на прямой. Придумать алгоритм нахождения количества наложений отрезков и оценить его сложность.

    Не вижу смысла иметь дело с людьми не способных попытаться решить подобные задачи. Многие даже не пытались. Так и говорили, что не могу, пробовать не буду.

    Только после этого шёл разговор о технологиях и высоких материях.
    • 0
      Я конечно не супер гений, но при чём тут тангенс в 1.1? o_O Может вы имели ввиду что числа с точкой это медленно и просили написать целочисленный алгоритм (Брезенхемом)? :)
      • +1
        Потому что самое часто предлагаемое решение — посчитать угол через арктангенс, а потом пройтись в цикле по координатам одной из сторон треугольника и найти координаты точек на гипотенузе как произведение текущей координаты на тангенс найденного угла.

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

        И что касается целочисленного алгоритма то знание конкретного алгоритма (Брезенхемом) не важно, важно начать думать и предлагать идеи.
        <