До того, как прийти в ЕРАМ, я побывал примерно на 20 собеседованиях в питерских IT-компаниях, и во многих давали задачи. Я синтезировал свой опыт и придумал пять задач, которые похожи на те, что дают на онлайн-тестированиях и очных собеседованиях.

19-20 мая в Питере прошла конференция DotNext, где мы предложили участникам пройти квест, который и состоял из этих задач. Отвечая правильно на задачу, участник получал следующую.

С первыми тремя могут справиться джуниоры, им часто задают подобные вопросы на собеседованиях. Четвертую можно задать кому угодно, но я бы рассчитывал на специалистов уровня middle: далеко не все джуниоры разбираются в возрастаниях сложности алгоритмов.

С пятой задачей справились единицы. Ее сложность – не в том, чтобы вычислить, что будет в селекте (с этим как раз справились многие), а в том, чтобы найти следующее число в последовательности, а для этого требуются хорошие математические знания. Мне кажется, математическая база очень важна для программиста.

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

Итак, начнем.

1) Какой результат выведет на консоль данная программа?

    class Program
    {
        static void Main(string[] args)
        {
            var numbers = new int[] { 7, 2, 5, 5, 7, 6, 7 };
            var result = numbers.Sum() + numbers.Skip(2).Take(3).Sum();
            var y = numbers.GroupBy(x => x).Select(x =>
            {
                result += x.Key;
                return x.Key;
            });

            Console.WriteLine(result);
        }
    }

Ответ
56. Учитываем особенности LINQ. Двоичное представление: 111000.

Комментарий
Подобные задачи довольно часто дают на собеседованиях. Если говорить о квесте, то правильный ответ дали около 80% участников. Самая распространенная ошибка – люди не замечали, что здесь присутствует отложенное выполнение запроса. Почитать подробнее о нем можно вот тут.

2) Какой результат выведет на консоль данная программа?

    class Program
    {
        private static string GetNumber(int input)
        {
            try
            {
                throw new Exception(input.ToString());
            }
            catch (Exception e)
            {
                throw new Exception((int.Parse(e.Message) + 3).ToString());
            }
            finally
            {
                throw new Exception((++input).ToString());
            }

            return (input += 4).ToString();
        }

        static void Main(string[] args)
        {
            string result;
            try
            {
                result = GetNumber(1);
            }
            catch (Exception e)
            {
                result = e.Message;
            }

            Console.WriteLine(int.Parse(result) * 100);
        }
    }

Ответ
200. Учитываем специфику finally. Двоичное представление: 11001000.

Комментарий
Сам сталкивался с подобным вопросом на собеседовании. Если говорить об участниках квеста, правильно смогли ответить около 70%. Они оставляли отзывы и предложения, среди которых – уменьшить количество лишнего кода. Мы это обсудили и пришли к выводу, что все-таки лучше уменьшать читаемость кода для искусственного введения в заблуждение.

3) Какой результат выведет на консоль данная программа?

    class MagicValue
    {
        public int Left { get; set; }
        public int Right { get; set; }

        public MagicValue(int left, int right)
        {
            Left = left;
            Right = right;
        }

        public static void Apply(MagicValue magicValue)
        {
            magicValue.Left += 3;
            magicValue.Right += 4;
            magicValue = new MagicValue(5, 6);
        }

        public static void ApplyRef(ref MagicValue magicValue)
        {
            magicValue.Left += 7;
            magicValue.Right += 8;
            magicValue = new MagicValue(9, 10);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var magicValue = new MagicValue(1, 2);
            MagicValue.ApplyRef(ref magicValue);
            MagicValue.Apply(magicValue);

            Console.WriteLine(magicValue.Left * magicValue.Right);
        }
    }

Ответ
168. Учитываем особенности ref. Двоичное представление: 10101000.

Комментарий
Это очень популярный вопрос на собеседованиях. Я сам решал подобную задачу, наверное, на каждом втором. На эту тему можно почитать вот тут. Кстати, только 45% участников квеста смогли найти правильное решение. Зачастую ошибки были не в понимании принципа работы ref, а в математике.

4) Даны 9 функций. Каждой функции соответствует номер от 1 до 9. Расположите функции в порядке возрастания сложности, после чего подставьте 9 номеров отсортированных функций последовательно в формулу _ _ _ — _ _ _ + _ _ _ = «?». Напишите, чему равно «?».

1. $log?(log(N))$
2. $N^{2/9}$
3. $log(N)$
4. $N$
5. $3^N$
6. $900^{10000000}$
7. $N!$
8. $N^3$
9. $N*log(N)$

Ответ
1221. Двоичное представление: 10011000101.
Решение:
6. $900^{10000000}$
1. $log?(log(N))$
3. $log(N)$
2. $N^{2/9}$
4. $N$
9. $N*log(N)$
8. $N^3$
5. $3^N$
7. $N!$
6 1 3 — 2 4 9 + 8 5 7 = 1221

Комментарий
Такая задача реже встречается на собеседованиях, но это – хороший старт для тех, кто изучает сложности алгоритмов. Есть много ресурсов с формулами, и найти их просто. Кроме того, задачу можно решить «подстановкой» на бумаге. На собеседовании могут задать вопрос, связанный со сложностью некоторых алгоритмов, и здорово, когда ответ подкреплен общими знаниями. Если говорить о квесте, с задачей справились только 30% участников.

5) Пусть таблица carTable содержит следующие значения:
id model price
1 Nissan 1000
2 BMW 2000
3 Toyota 1000
4 Renault 2000
5 Peugeot 1000
6 Opel 2000

Результатом представленного ниже SQL запроса будет 2 значения — <1> и <2>.

;WITH someTable AS
(SELECT 1 val
UNION ALL
SELECT val + 1 FROM someTable WHERE val BETWEEN 1 AND 3)
SELECT carTable.price / SUM(CASE WHEN carTable.price = 1000 THEN 1 ELSE 2 END) / 250 AS result
FROM someTable
INNER JOIN carTable ON carTable.id = someTable.val
GROUP BY carTable.price
ORDER BY carTable.price ASC

<1> и <2> — это первые числа последовательности <1>, <2>, 6, 34, 270, <?>.
Найдите следующее число последовательности.

Ответ
2698. Двоичное представление: 101010001010.
Решение:
Результатом запроса будут числа 2 и 2 (BETWEEN даст выборку 1,2,3,4. Join сработает на первые 4 записи, GROUP BY их сгруппирует, SELECT вычислится как $1000 / (1 + 1) / 250 = 2$, $2000 / (2 + 2) / 250 = 2$. Последовательность вычисляется как $x_{n+1}=x_{n}*2*n - 2$, где $n$ – число уже полученных элементов.
Т.е.:
$2*2*1 - 2 = 2$
$2*2*2 - 2 = 6$
$6*2*3 - 2 = 34$
$34*2*4 - 2 = 270$
$270*2*5 - 2 = 2698$

Комментарий
Это, безусловно, самая сложная задача. С ней справились только 15% участников квеста.

Заключение


Спасибо всем, кто решал задачи, а особенно тем, кто смог дойти до конца! Было интересно читать ваши отзывы и комментарии. А те, кто внимательно читал условия и давал ответы в двоичной форме – вдвойне молодцы!

Фото взято из архива конференции DotNext.
Поделиться с друзьями
-->

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


  1. corr256
    01.06.2017 16:54
    +11

    Кто-то пишет код, а кто-то сочиняет задачки.


    1. AndreiZhigulin
      01.06.2017 16:56
      -1

      А как одно мешает другому?


      1. kekekeks
        01.06.2017 17:08
        +8

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


        1. AndreiZhigulin
          01.06.2017 17:18
          -2

          Как раз подобный вопрос мы и обсуждали на конференции с участниками квеста: главные цели подобных задач — запутать, проверить внимательность, заставить сомневаться. Некоторые торопятся и дают неправильный ответ, некоторые не вчитываются в условие, некоторые ошибаются в подсчетах. Если бы здесь было меньше лишнего, некрасивого или трудно читаемого кода, скорее всего почти все отвечали бы правильно, из-за чего квест наскучил бы очень быстро :) Да и просто здорово, когда человек приносит неправильный ответ, говорит «как неправильно??», потом замечает ошибку и радуется, что теперь все правильно — это очень приятные чувства :)


      1. helvar
        01.06.2017 19:12
        +3

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


  1. Nahrimet
    01.06.2017 18:09
    +6

    Иногда складывается впечатление, что программистами рекрутеры признают только гиков… Поймите меня правильно.


    1. AndreiZhigulin
      01.06.2017 18:16
      -2

      На самом деле, исходя из тех заданий, которые мне давали на собеседованиях, нельзя сказать, что рекрутеры так уж категоричны. Много кто пытается подготовить общий набор вопросов (которые, кстати, покрываются тем же Рихтером + Тепляковым почти целиком) и иногда несколько заданий, проверяющих мышление. Программисты бывают с разным опытом, и вполне нормально, что кто-то не способен решить те несколько «особых» заданий. Иногда тебе везет, иногда знаешь ответ, иногда открывается «третий глаз», и ты просто вычисляешь правильный ответ. Собеседования — это вообще скорее лотерея, чем проверка на гика :)


  1. fzn7
    01.06.2017 18:24
    +6

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


  1. aftertherainbow
    01.06.2017 18:38
    +1

    Везде завалил арифметику. Давайте уж и шестнадцатеричное представление ответов, а то выглядит дискриминацией.


    1. AndreiZhigulin
      01.06.2017 18:43
      -2

      На самом деле, ответы в двоичном представлении принесло человек 20 :)
      Идея с двоичным представлением была рождена, когда думали на ноуты слать запароленные архивы с задачками, а паролем к ним — конкатенацию ответов на все предыдущие задания, чтобы и пароль был непростым для подбирания, и решение всех предыдущих задач требовалось для открытия каждого из архивов. Потом решили, что нехорошо завязываться на технику, и сделали карточки, но двоичное представление оставили :)


  1. v_bogdanov
    01.06.2017 18:44
    +6

    Сложность функции — это что вообще?


    1. AndreiZhigulin
      01.06.2017 19:17
      -4

      Вот навскидку статья на хабре


      1. i_user
        01.06.2017 19:48
        +6

        Сложность алгоритма — функция от объема входных данных (и еще некоторых параметров)
        Сложность функции — эммм…?

        Скорее задача должна звучать как — расположите данные функции по эммм… ну я даже не знаю, по скорости роста на больших N…

        Слабенько, на самом деле для задач, которые должны что-то показать на собеседовании.
        Для tricky задач — слишком прямолинейны, для вопросов на искусство программирования — не то.

        Итого — подойдет чтобы отсеять слабых джуниоров и найти джуниоров посерьезнее. Для практикующих программистов, увы, не репрезентативно.


      1. v_bogdanov
        01.06.2017 22:47
        +1

        Что такое сложность алгоритма я представляю, но в условии задачи 4 про алгоритмы ни слова. И да, если не читать предисловие и комментарий к задаче, то далеко не очевидно, что же там имеется в виду.


  1. yarric
    01.06.2017 19:50
    +4

    А зачем спрашивать про вывод на консоль? Запустил — посмотрел.



  1. PapaBubaDiop
    01.06.2017 20:03
    +3

    Решил только 4 и 5, первые три вообще не понял набора букв — это что, такое современное программирование?

    Никогда мне не стать программистом. Выпью. Тоже не стану.


  1. SergeyVoyteshonok
    01.06.2017 20:31
    +8

    И так, человек пришел на собеседование. На собеседованиях логично спрашивать задачи, которыми занимается компания. Ну т.е. пришел человек в геймдев, ему сразу там задачки на векторную алгебру там, пересечения плоскостей векторов в 3D и тд. Пришел человек в dev банка, ему сразу там вопросы про безопасность, транзакции и тд.
    Пришел человек на собеседование и видит вот ЭТО. Да еще и написано уберужасным стилем ( реально увидев такое в продакшене я бы уволил). Реакция нормального человека сказать — досвидания, я пошел.


    1. avost
      01.06.2017 23:35
      +2

      Расслабьтесь. Поищите здесь статью про неспособность "программистов" написать реализацию алгоритма пузырьковой сортировки. Там очень смешные комментарии. Как только "программисты" не отмазывались, каких только нелепостей не придумывали для оправдания своей неспособности написать три строчки кода. И даже когда им дали эти три строчки они продолжали настаивать, что "настоящие программисты" вовсе не обязаны уметь написать трёхстрочную реализацию по формальному описанию простейшего алгоритма, поскольку это задача офигенной сложности. Они действительно считают себя программистами и сеньорами и прочими крутыми словами. И они в реальности приходят на собеседования. И их процентов 95. Или 96. Поэтому я абсолютно спокойно отношусь к таким заданиям. С пониманием. А все эти хлопанья дверями, "я бы за такой код уволил", — ну, этим вв покажите свою неадекватность, не более. А я напишу эту пузырьковую стртировку или бинарный поиск за пару минут и перейду к обсуждению более интересных вещей.


      1. SergeyVoyteshonok
        02.06.2017 00:30
        +4

        Да я стараюсь в принципе не напрягаться ))). Насчет баблсорта другой вопрос (хотя тоже спорный), все-таки это алгоритм, вы просите человека написать свое видение этого алгоритма. В обобщенном виде можно даже назвать это тестовым заданием. Здесь же человек просит соискателя поработать компилятором/рантаймом для ужасного, корявого кода. Уходить надо спокойно, без хлопаний дверьми, просто — спасибо, до свидания, я все понял. Показаться кому-то неадекватным — абсолютно не страшно, большинство людей, которые чего-то в этой жизни добились, казались кому-то неадекватными.


        1. avost
          02.06.2017 17:56

          Насчет баблсорта другой вопрос (хотя тоже спорный),

          Да ладно, чего там спорного. Если человек не может написать трёх строк кода, то можно выставлять его за дверь.


          Здесь же человек просит соискателя поработать компилятором/рантаймом

          Если у вас работа — не быдлокодинг прямолинейного кода по отображению страничек, то вы периодически работаете и компилятором и рантаймом. При отладке. А при разработке многопоточного кода ещё и немного процессором и контроллером кэш-памяти :). По-моему, нормально.


          для ужасного, корявого кода

          Ну, это вообще офигенная возможность обсудить ужасность и корявость кода.


          Уходить надо спокойно, без хлопаний дверьми, просто — спасибо, до свидания, я все понял.

          Но ваша воля не пользоваться такой прекрасной возможностью ;)


          большинство людей, которые чего-то в этой жизни добились, казались кому-то неадекватными.

          Да, мы все знаем этих трёх человек. Остальные неадекваты так неадекватами и остались и имя им — легион.


    1. petuhov_k
      02.06.2017 04:13

      С такой логикой, будет сложно найти сотрудника. Получается, начал работать в банке — всё, теперь только банки. Связался с 1С.., ладно про 1С неудачный пример. Если серьёзно, мне не принципиально, чем занимался разработчик. Если он хорошо знает свой инструмент (язык) и хорошо соображает — значит сможет освоить и нашу область. Как оценить знания соискателя кажый выбирает по своему — кто-то такие вот задачки даёт. Впринципе, и по ним можно оценить, например, даже если человек ошибся, но смог объяснить где и почему — значит разбирается. Хотя, мы делаем проще — спрашиваем прямо, что-то вроде: «как работает LINQ», или «как работает yield return» (если не джуниор, конечно).


      1. SergeyVoyteshonok
        02.06.2017 14:06

        С такой логикой, будет сложно найти сотрудника.

        Ну как бы так в жизни и бывает, человек начал работать в бэк-энде банка, вряд ли он придет на геймдева куда-то еще, а если и придет, то только с понижением в ЗП пока до всего не дойдет. Ваш подход подходит для подбора человека «на вырост». Этим приходится заниматься, когда не нашел того, кого нужно сразу, и понимаешь что человечка нужно будет растить =).
        Хотя, мы делаем проще — спрашиваем прямо, что-то вроде: «как работает LINQ», или «как работает yield return» (если не джуниор, конечно).

        Вам когда ремонт в квартире надо сделать, вы рабочих тоже спрашиваете — как шуруповёрт работает?
        Понятно, что нужно знать где применять и во что это обойдется, но вопрос «как» — странный, вы еще может и на бумажке просите написать IL код, в который компилируется например yield?


  1. GDXRepo
    01.06.2017 23:02
    +5

    Сугубо имхо — подобные задачи в непрофильной отрасли (не связанной напрямую с постоянной работой над математическими алгоритмами) — это пережиток институтского воспитания. Этакий экзамен, где тебе запрещено пользоваться всем, и ты обязан все помнить (закрыли учебники, убрали мобильники, решайте; здесь — убрали IDE, вот вам бумажка, решайте). В нормальной разработке я за свои 6 с лишним лет работы ни разу не встречал ситуации, когда бы мне пригодилось «крайне полезное» умение прогнать задачу на бумажке, не имея под рукой IDE (потому что она у меня всегда под рукой, я же на работе, а не в поле, в конце концов). Правильное собеседование (имхо) — это правильные теоретические вопросы, имеющие прямое приложение в практике данной компании, а также предложение тестового задания, чтобы оценить практические умения. Компания (нормальная компания) нанимает сотрудника, чтобы он решил ее практические задачи, а не прогонял задачи на бумажках. У вас же получаются «вопросы ради вопросов». Я бы не ответил ни на один. Хотя пишу достаточно тяжелые и мощные приложения вроде банковского ПО, биржевого ПО и так далее. Вот верите-нет — ни разу подобные задачи не пригодились. Зато практических сложностей — хоть отбавляй, и у любого специалиста так, я уверен. На «бумажке» умеют решать максимум заточенные на это выпускники ВУЗов. Настоящий специалист, как правильно писали выше, увидев такое, просто развернется и уйдет, поняв, что в компании с такими принципами отбора сотрудников делать явно нечего. Еще раз, математические и алгоритмические задачи нужны там и только там, где они напрямую используются постоянно, — аналитика, геймдев, физические движки, криптография, сжатие данных, и тому подобные области. Если же вы этого не касаетесь — то «программист должен иметь математическую базу» — это один из худших подходов к оценке способностей специалиста, коих я повидал немало.


    1. GDXRepo
      01.06.2017 23:07
      +3

      Кстати, да, за второй код — убил бы. И моя реакция на такой код была бы «разобраться, как оно работает, затем настучать по рукам тому, кто это написал, и провести рефакторинг». И, естественно, не на бумажке, а в IDE, с отладкой и вдумчивым изучением ситуации. Надуманные задачи, не имеющие ничего общего с практикой, находят лишь специалистов, готовых решать только теорию, без практической явной пользы. За редкими исключениями.


      1. JIghtuse
        02.06.2017 06:09

        Согласен. С таким же успехом можно генерировать задачи с помощью какого-нибудь csmith (ну и обфусцировать ещё для надёжности) и просить рассказать, что оно там будет делать. Множество всех программ бесконечно, зачем же давать адекватные? Нагенерил тысячу строк, которые компилятор едва собрал — отдавай кандидату.


  1. crea7or
    01.06.2017 23:54
    +3

    Про epam вообще много на ebanoe.it.


    1. Deosis
      02.06.2017 07:36
      +2

      До такой желтизны даже ализар не опускался.


  1. vyatsek
    02.06.2017 18:37
    -1

    Если честно от таких задач блевать тянет. В упор не понятно какие навыки выявляют подобные задачи и кого вы ищете на собеседованиях?
    Если уж собеседование на C# то спросите про кругозор и глубину знаний. Какие задачи решались с применением C#, почему было выбрано именно такое решение.

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

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


    1. mnepohyi
      08.06.2017 11:54

      Почему обычных людей? Конечно последние мне показались немного е*нутые, но мб это я что-то не понимаю. Первые, вроде, легкие.


      1. vyatsek
        08.06.2017 17:41

        Код, который приведен в первых двух постах, должен напроч отсуствовать в проде, либо быть переписанным в рамках следующей задачи которая его коснется.
        За весь опыт разработки ПО, основная сложность найти адекватного человека. Такие вопросы на собеседовании ни разу не помогают его выявить. Эти задачи показывают лишь что человек как-то знает инструмент, а потом выясняется, что пользоваться им не умеет.
        Я бы понял, если бы были задачи еще переписать код на более понятный.


  1. usharik
    08.06.2017 11:54

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

    Кстати, а есть ли аналог книги «Java puzzlers» Джошуа Блоха, но про C#?