Насколько правомерно утверждение, что 199 из 200 соискателей вакансий в сфере программирования по факту программировать не умеют? Откуда взялось это утверждение, и какие основания под собой имеет?

Заголовок получился громоздкий, но в его основу легло более лаконичное название статьи «Why Can’t Programmers…Program?», в начале которой автор приводит выдержку из ещё одного поста:

Как и я, его автор столкнулся с тем, что 199 из 200 соискателей на любую вакансию программиста не умеют писать код. Повторюсь: они не могут писать код ни в каком виде.

И хотя Джефф разместил эту статью в 2007 году, она по-прежнему широко обсуждается. Вот её обсуждение из 2020 года, вот её перепост в HackerNews в 2021 году, а вот цитирование этой статьи на корпоративном сайте.

Меня как-то просили писать более сжато, так что приведу короткую версию моей статьи. Надеюсь, она убедит вас, что:

  • Статистика «199 из 200» не имеет под собой оснований.
  • Даже если бы основания у неё были, она бы применялась только к соискателям, а не к программистам в целом.
  • Если вы можете решить FizzBuzz, это ещё не означает, что вы готовы к собеседованиям по программированию.

▍ Что меня подтолкнуло к написанию


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

Я уже писал о статье Джеффа Атвуда ранее, на что получил довольно критический ответ. И вместо того, чтобы отвечать напрямую, я решил сфокусироваться конкретно на утверждении про «199 из 200 соискателей». Если бы существовало твёрдое доказательство того, что в 2007 году 199 из 200 соискателей на любую вакансию программиста вообще не умели писать код, о чём заявил Реджинальд Брейтвейт (Raganwald), то мои личные чувства в отношении элитаризма и зашоренности оказались бы неуместны перед лицом холодных и неоспоримых фактов.

Немного истории:

  • 27 января 2005 года сооснователь StackOverflow Джоэл Спольски написал статью, названную им просто «News».
  • В январе 2007 года разработчик ПО Имран Гхори (сегодня занимается венчурными вложениями) написал, что большинство выпускников факультетов компьютерных наук не могут решить задачку FizzBuzz.
  • Тогда же в январе 2007 года Raganwald, являющийся разработчиком ПО и писателем, заявил, что 199 из 200 соискателей на любую вакансию программиста не умеют писать код. В качестве источника он указал ссылку на вышеупомянутую статью Джоэла Спольски.
  • В феврале 2007 года сооснователь StackOverflow, наконец, написал статью «Why Can’t Programmers…Program?», в которой связал всё воедино. Он процитировал Raganwald, который, в свою очередь, ссылался на Джоэла Спольски.

Почему я не стал обсуждать статью Джоэла Спольски? Потому что по факту в ней не утверждается то, что утверждает Raganwald. Вот выдержка из неё:

Все считают, что нанимают лучший 1% специалистов.

Мартин Фаулер: «Мы по-прежнему усердно стремимся нанимать только топовых разработчиков (наша цель – это лучшие 0,5 – 1%).

Я: «Мы получаем от 100 до 200 резюме на вакансию».

Помню, когда я начал работать на Дэвида Шоу, он сказал нам, что их компания наняла только «1 из 200».

И я слышу это практически из каждой компании по разработке ПО: «Мы нанимаем лучший 1% или ещё меньше».

Источник

Спольски не приводит никаких свидетельств того, что 199 из 200 соискателей не могут программировать, как и не утверждает этого. В своей статье он размышляет о том, что если все будут стремиться нанимать лучшие 0,5%, то самые грамотные кандидаты с рынка труда исчезнут. И тут нет чего-то неправильного, это просто интересно. Но сей факт также подтверждает, что указанное число было гипотетическим. Позднее Raganwald написал ответ, в котором объяснил свои расчёты, но по факту он описал мысленный эксперимент о том, что большинство лучших «кандидатов», как и в случае со свиданиями, просто не ищут собеседований. Это размышление не вызывает противоречий, но оно очень далеко от статистики «199 из 200 соискателей».

▍ Прочие обсуждения


И я не единственный, кого это смутило. На эту статью был опубликован короткий и ясный ответ на Quora:

Я прочёл все три указанных автором источника и сделал вывод, что он ошибается или неверно толкует их смысл. Однако при этом он не связывает все те три статьи. Так что, возможно, вы просто неверно поняли суть, которую он пытался донести.
В первом источнике говорится, что 199/200 людей не получают работу, и что компании нанимают этого 1 из 200 не потому, что нанимают лучший 1%, а потому что нанимают 1% соискателей, которые не находятся постоянно без работы. Здесь ничего не говорится относительно FizzBuzz.

— Дэвид Ши, взято из этого обсуждения.

А на StackExchange пользователь с ником DJClayworth написал:

Это просто смесь утверждений. В первичном источнике (Имран) сказано лишь, что «Большинство выпускников факультетов компьютерных наук не могут реализовать FizzBuzz за пару минут». Это сильно расходится с утверждением, что 199 из 200 программистов вообще не могут её реализовать. Соотношение 199/200 взято из проведённого Джоэлом абсолютно гипотетического анализа найма, и в нём нет ни слова про FizzBuzz.

Источник

Ещё один пользователь, Джимми, написал следом за предыдущим:

Последовавшее за статьёй «объяснение» расчётов никак не стремится эти расчёты в действительности прояснить, а лишь использует «мысленный эксперимент», сводящийся к тому, что «хорошие программисты уже при деле, поэтому работу ищут только те, кто не умеет программировать». Таким образом, автор оправдывает своё утверждение про 199 неспособных соискателей из 200. Без возможности просмотреть оригинальные результаты теста по реализации FizzBuzz это утверждение выглядит подозрительным или как минимум не поддающимся проверке.

Источник

▍ Альтернативы FizzBuzz


Когда я впервые об этом написал, к моей статье оставил комментарий пользователь под именем Джеймс. Он сказал (я немного перефразирую):

«Если вы считаете, что умение решить FizzBuzz говорит о ваших высоких навыках, то неверно понимаете смысл теста. Его задача — не увидеть степень квалификации, а отсеять тех, кто не квалифицирован в принципе. Если вы решаете FizzBuzz, то мне это говорит немногое, но если вы не можете этого сделать, то с вами всё ясно».

Как человек, который закончил университет в 2016 году, лично мне не доводилось видеть FizzBuzz, но я встречал много похожих задачек. Например:

  • Сжатие строк (string compression). Я вижу, что на LeetCode эта задача имеет среднюю сложность, но это, скорее всего, из-за того, что её надо решать на месте. В противном случае она бы идеально соответствовала Cracking The Coding Interview 1.6 (и неважно, что на LeetCode условие задачи сформулировано столь запутанно).
  • Правильные скобки (valid parenthesis) (подсказка: какая структура данных окажется полезной для решения этой задачи?)
  • Сопоставление строк (string question). Не помню точно условий этой задачи, но, по-моему, в ней нужно взять две равных по длине строки и возвращать True, если их буквы совпадают, и False в противном случае. Хотя это вопрос с собеседования для технического писателя, так что к нашей теме он, возможно, не подходит.

Что такое FizzBuzz в наше время? Возможно, «задача по инвертированию бинарного дерева», но только потому, что сейчас она уже стала чем-то вроде мема.

▍ Заключение


На собеседованиях вас не всегда спрашивают по части программирования. Я получал уточняющие вопросы о проектах, тематические вопросы вроде «Чем отличаются dynamic_cast и reinterpret_cast?». Было ещё несколько тестов, в которых мне не позволяли выбирать язык программирования. А один раз собеседующий даже предоставил файлы HTML/CSS/JavaScript и попросил при нём реализовать новую функциональность UI.

Вот ещё несколько головоломок, которые я встречал на собеседованиях:

  • 3 1 3 6 = 8. Расставьте операторы (только + — * /) и скобки так, чтобы равенство оказалось верно. Я уже публиковал этот вопрос ранее, поэтому сразу уточню: порядок значений менять нельзя https://www.careercup.com/question?id=1691
  • «Дано три ящика. В одном находятся только яблоки, в другом только апельсины, а в третьем и яблоки, и апельсины. Эти ящики ошибочно подписали так, что ни одна из надписей не отражает содержимое своего ящика правильно. Вы открываете один из ящиков и, не глядя в него, достаёте один фрукт. Как, взглянув только на этот фрукт, вы можете сразу правильно подписать все ящики?» (Источник)

Узнавайте о новых акциях и промокодах первыми из нашего Telegram-канала ????

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


  1. Krawler
    12.11.2023 12:21

    Третья задача про ящики - это просто законы де Моргана

    Начнем с третьего ящика - O - oranges, A - Apples

    \overline{O \land A} = \overline{O}\lor\overline{A}

    Стало быть, там будут только либо яблоки, либо апельсины
    В первом не яблоки:

    \overline{A} = O \lor (OA)

    Во втором не апельсины:

    \overline{O} = A\lor AO

    Ну и все, дальше элементарно. Идем к третьему, достаем фрукт - если это апельсин, значит там лежат только апельсины, если яблоко - только яблоки.

    Стало быть вторые ящики меняют свои метки на Апельсины или Яблоки и Яблоки соответственно. Все


    1. saboteur_kiev
      12.11.2023 12:21
      +2

      Не понял вашего решения. По условию нужно достать только из одного ящика, или из каждого? Если только из одного (а так в условии), и вы попали на ящик в котором и яблоки и апельсины, то как?

      Hidden text

      я думаю так

      надо взять фрукт из ящика ЯО

      если взяли яблоко, значит
      ЯО - > Я
      Я -> О
      О -> ЯО

      если взяли апельсин, значит
      ЯО - > О
      О -> Я
      Я -> ЯО


      1. Squoworode
        12.11.2023 12:21

        и вы попали на ящик в котором и яблоки и апельсины

        Так мы открываем ящик, на котором написано "яблоки и апельсины". Там не могут быть яблоки и апельсины.


      1. olivera507224
        12.11.2023 12:21
        +6

        Всё же апельсины пишутся через А :)


        1. funca
          12.11.2023 12:21
          +3

          Как вариант там импортные Orange, либо в тех ящиках лежит местное Ядерное Оружие.


          1. RichardMerlock
            12.11.2023 12:21

            Это тов майор решал про ящики с огнестрелом и ОМП и чатом ошибся.


      1. Krawler
        12.11.2023 12:21

        Так и есть. Там 2 варианта, просто я их схлопнул. Вы их расписали до конца.


  1. HEXFFFFFFFF
    12.11.2023 12:21
    +7

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

    Вообще верно то что 99.9% программистов не понимают конечных задач. Хороший программист это тот кто напишет мне библиотеку. Но классный специалист это тот кто скажет мне - "давай сделаем вот так, упростим этот кусок, тогда эта библиотека вообще будет не нужна"))))

    Когда я руководил программистами главный мой лозунг был -" не надо откладывать на завтра то что можно не делать вообще"))) И применяя этот подход нам удвалось делать проекты в очень сжатые сроки.


    1. GospodinKolhoznik
      12.11.2023 12:21
      +4

      верно то что 99.9% программистов не понимают конечных задач

      А вы входите в их число, или вы относитесь к 0.1% уникальных специалистов экстра класса?


      1. RichardMerlock
        12.11.2023 12:21
        +2

        Когда я руководил программистами...

        Руководитель обязан понимать конечную задачу, а уникальными специалистами экстра класса желательно быть подчинённым.


        1. funca
          12.11.2023 12:21
          +1

          Когда специалист экстра класса понимает конечную задачу своего руководителя, то руководителю приходится с ним либо на полном серьёзе делиться, либо прощаться. 0.01% это видимо те, руководители которых застыли в ожидании чуда (но это быстро проходит).


          1. RichardMerlock
            12.11.2023 12:21

            Делиться - это хорошо, говорят, это делает мир во всех отношениях лучше.


    1. codecity
      12.11.2023 12:21
      +2

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

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

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


      1. voltag
        12.11.2023 12:21
        +1

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

        Для крайнего примера, представьте что работаете с ML(AI), который генерит код по ТЗ. В его задачу, скорее всего, не будет включено "читаемость человеком". Мы напишем архитектуру так, чтобы всё свободно собиралось и тестировалось - такая конструкция и будет решением.


        1. funca
          12.11.2023 12:21

          ML(AI), который генерит код по ТЗ. В его задачу, скорее всего, не будет включено "читаемость человеком".

          На практике требуется не только читаемость, но и понятность, иначе такое решение никому не нужно. Может код помимо ТЗ по ночам биткойны майнит или котиков обижает, или нет - чём докажете?


          1. voltag
            12.11.2023 12:21

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

            И если Вы опишите ML ,что надо помимо программы ещё и майнить... то как минимум он может не пройти человеческие тесты, по причине усложнения простого задания

            p/s пожалуйста без "а если они сговорились" =))


    1. profFortran
      12.11.2023 12:21
      +5

      нужна библиотека, которая...

      Ну если Вы так ставите задачу, то чего тогда жалуетесь, что Вам написали эту библиотеку?

      Нужна библиотека? Получите, распишитесь.

      Нужно решить задачу? Сформулируйте задачу, подумаем, как решать.


      1. Fedorkov
        12.11.2023 12:21
        +4

        Так он и говорит, что хороший программист решает поставленные задачи.

        А 0.1% — это те, кто умеет вычленять из задач реальные потребности.


  1. Arakel
    12.11.2023 12:21

    Я раньше на собеседование просто выводить все простые числа до 1 млн. Логика была такая. Что можно написать быстро просто перебором, что зачёт и наводящие вопросы. Можно подумать и выкинуть все четные числа, а поиск корней ограничить корнем квадратным от числа. То есть можно на простом примере посмотреть как думает человек. Но это оказалось очень сложно. Даже люди позиционирующие себя как мидлы не могли выполнить. Я сдался и перешёл на fizzbuzz.


    1. Reallamos
      12.11.2023 12:21

      Беспощадные и бессмысленные собесы, именно то что нам надо.


  1. Alexandroppolus
    12.11.2023 12:21
    +3

    Надо полагать, задача с расстановкой знаков "3 1 3 6 = 8" - это на программирование?

    Ну ок.

    Кодъ
    const funcs = ['+', '-', '*', '/'];
    
    const wrap = (n) => typeof n === 'number' ? n : `(${n})`;
    
    function each(values, callback) {
        if (values.length < 2) {
            callback(values[0]);
            return;
        }
        for (let i = 1; i < values.length; ++i) {
            const lv = values.slice(0, i);
            const rv = values.slice(i, values.length);
            each(lv, (s1) => {
                each(rv, (s2) => {
                    for(let f of funcs) {
                        callback(wrap(s1) + f + wrap(s2));
                    }
                });
            });
        }
    }
    
    function find(values, r) {
        const arr = [];
        each(values, (str) => {
            if ((0, eval)(str) === r) {
                arr.push(str);
            }
        });
        return arr;
    }
    
    console.log(find([3, 1, 3, 6], 8)); // ['(3+1)/(3/6)', '((3+1)/3)*6']


    1. aamonster
      12.11.2023 12:21
      +5

      Ой... А почему не просто console.log("(3+1)/3*6")?


      1. Alexandroppolus
        12.11.2023 12:21

        лишние скобки не убирал - лень допиливать)


      1. Alexandroppolus
        12.11.2023 12:21

        Вообще, конечно, из-за лишних скобок бывают дубликаты, потому всё-таки надо их выкинуть.

        code
        const funcsData = {
            '+': {pr: 1, a: true},
            '-': {pr: 1, a: false},
            '*': {pr: 2, a: true},
            '/': {pr: 2, a: false},
        };
        
        const needPar = (fi, fo, first) => fi.pr < fo.pr || (!first && fi.pr === fo.pr && !fo.a); 
        
        const wrap = (v, f, first) => typeof v === 'number' ? v : !needPar(funcsData[v[1]], funcsData[f], first) ? v[0] : `(${v[0]})`;
        
        function each(values, callback) {
            if (values.length < 2) {
                callback(values[0]);
                return;
            }
            const funcs = Object.keys(funcsData);
            for (let i = 1; i < values.length; ++i) {
                const lv = values.slice(0, i);
                const rv = values.slice(i, values.length);
        
                each(lv, (s1) => {
                    each(rv, (s2) => {
                        for(let f of funcs) {
                            callback([wrap(s1, f, true) + f + wrap(s2, f, false), f]);
                        }
                    });
                });
            }
        }
        
        function find(values, r) {
            const set = new Set();
            each(values, (str) => {
                if (!set.has(str[0]) && (0, eval)(str[0]) === r) {
                    set.add(str[0]);
                }
            });
            return [...set];
        }
        
        console.log(find([3, 1, 3, 6], 8)); // ['(3+1)/(3/6)', '(3+1)/3*6']
        console.log(find([6, 1, 3, 4], 24)); // ['6/(1-3/4)']
        console.log(find([1, 1, 1, 1], 4)); // ['1+1+1+1', '(1+1)*(1+1)']


  1. alan008
    12.11.2023 12:21
    +10

    Для людей (таких, как я), изучавших программирование лет 20 назад, вся основная суть программирования на тот момент была в алгоритмах и жонглировании структурами данных. Поэтому для меня наличие алгоритмических вопросов на собеседованиях на вакансию программиста вполне ожидаемо и логично. Однако, за последние годы, программирование уже стало чем-то другим: умением построить некую архитектуру из разрозненных взаимодействующих компонентов, умение связать технологии X и Y, умение отличать плохие решения от хороших (ну или подходящие от неподходящих в конкретной ситуации), умение найти популярный фреймворк и обосновать, почему для конкретной задачи подходит именно он. Редко требуется начинать велосипедить с нуля, потому что даже если в компании сильный NIH синдром (not invented here), на момент прихода соискателя в компанию там уже есть пара-тройка миллионов строк собственного библиотечного кода, покрывающего большинство кейсов, возникающих при разработке в данной компании, и всё что останется соискателю - строить на основе этой кучи библиотечного кода БИЗНЕС ЛОГИКУ. Так не стОит ли на собеседованиях обсуждать, насколько хорошо и быстро соискатель может разобраться в пользовательских требованиях, ТЗ (если они есть) и уже существующей в проекте бизнес-логике, которую ему предстоит отлаживать и модифицировать в процессе развития продукта? А не эти ваши физзбаззы решать, которые ему в работе может вообще не потребуются.


    1. funca
      12.11.2023 12:21

      Редко требуется начинать велосипедить с нуля, потому что даже если в компании сильный NIH синдром (not invented here), на момент прихода соискателя в компанию там уже есть пара-тройка миллионов строк собственного библиотечного кода, покрывающего большинство кейсов

      Если в компании NIH синдром, то вы скорее всего будете пилить свое, даже если внутри тех миллионов строк. Бюджет сам себя не обоснует, а пытаться строить из себя нормального в дурдоме это плыть против денег в направлении за ворота, под дружное улюлюкание санитаров руководства.


      1. alan008
        12.11.2023 12:21

        Я имел в виду NIH синдром в адекватном его проявлении. Например, у Яндекса почти всё своё.


  1. aragaer
    12.11.2023 12:21
    +4

    Если "задачку FizzBuzz" нужно "решать", то что-то уже не то. Когда я проводил собеседования, то просил людей написать FizzBuzz вот прям сейчас. Если в тех 10-15 (максимум) строчках, которые человек написал, содержится что-то непонятное, то это уже звоночек. Иногда можно увидить попытки сразу что-то соптимизировать и усложнить. Я же хочу просто увидеть цикл и ветвление -- т.е. совершенно стандартные вещи.

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

    В конце концов, мне с этим человеком работать и мне бы не хотелось ему в будущем объяснять, что именно я имею в виду, когда говорю о каких-то вроде бы тривиальных конструкциях типа цикла или ветвления.


    1. FlyingDutchman2
      12.11.2023 12:21

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

      Я хочу у вас спросить, как у специалиста по FizzBuzz: какое ваше мнение по поводу моего решения для FizzBuzz? Если бы я у вас собеседовался и представил свое решение этой задачи. Удовлетворяет ли оно вашим требованиям?

      Теперь само решение:

      Сначала проведем анализ задачи и представим логику получения результата для числа N в виде таблицы решений:

      +---------------------------------+-----------------+
      |           Conditions            |     Actions     |
      +----------------+----------------+-----------------+
      | N is divisible | N is divisible |  What to print  |
      |      by 3      |      by 5      |                 |
      +================+================+=================+
      |     Yes        |      Yes       | 'FizzBuzz'      |
      |                +----------------+-----------------+
      |                |      No        + 'Fizz'          |
      +----------------+----------------+-----------------+
      |     No         |      Yes       | 'Buzz'          |
      |                +----------------+-----------------+
      |                |      No        +  N              |
      +----------------+----------------+-----------------+
      

      Теперь напишем реализацию таблицы решений на языке Python:

      '''
          FizzBuzz demonstration
      '''
      
      def fizz_buzz(n):
          ''' Evaluate FizzBuzz for the given n '''
      
          isDivBy3 = n%3 == 0
          isDivBy5 = n%5 == 0
      
          if(isDivBy3 and isDivBy5):
              result = 'FizzBuzz'
          elif(isDivBy3 and not isDivBy5):
              result = 'Fizz'
          elif(not isDivBy3 and isDivBy5):
              result = 'Buzz'
          elif(not isDivBy3 and not isDivBy5):
              result = str(n)
          else:
              raise Exception(f'Error processing number {n}')
      
          return result
      
      max_number = 100
      for n in range(1, max_number + 1):
          print(fizz_buzz(n))
      

      Что вы думаете по поводу моего решения?


      1. mayorovp
        12.11.2023 12:21

        Неплохое решение. Одновременно и продемонстрировали общий подход, и код не усложнили.


        1. Alexandroppolus
          12.11.2023 12:21

          общий подход

          Это смотря куда "обобщать". Если у нас N независимых делителей (и прикрепленных к ним слов), то такой подход получается 2^N в "высоту". Для такого обобщения лучше конкатенировать (но конкатенация не подойдет для других обобщений).


          1. mayorovp
            12.11.2023 12:21
            -1

            Обычно бизнес-логика "обобщается" в сторону появления новых правил, совершенно не предусмотренных более старыми обобщениями :-)


            1. Kergan88
              12.11.2023 12:21

              Ну так работа программиста как раз в том и состоит чтобы предсказать правильные обобщения исходя из имеющейся бизнес логики)


      1. wataru
        12.11.2023 12:21
        +1

        Нормальное решение. Чувствуется немного сраказм с налетом enterprise подхода и оскорбленное самомнение. Бросание исключения в очевидно недостижимой ветке кода и лишние комментарии идут сюда. Но это все придирки. Ваше решение 100% удовлетворит любого вопрошающего интервьювера.


        1. FlyingDutchman2
          12.11.2023 12:21

          Бросание исключения в очевидно недостижимой ветке кода

          Это сделано специально. Догадываетесь почему?


          1. wataru
            12.11.2023 12:21

            Есть несколько догадок: Потроллить интервьювера? Показать, что вы умеете бросать исключения и не забываете про крайние случаи? Более безопасный к опечаткам код? Что-то питоноспецифичное из-за того, что result появляется только в условных ветках?


            1. FlyingDutchman2
              12.11.2023 12:21

              Более безопасный к опечаткам код?

              Да


              1. wataru
                12.11.2023 12:21

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


                1. FlyingDutchman2
                  12.11.2023 12:21

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

                  Я бы так не сказал. Такое случается чаще, чем мы думаем.

                  Я уже после многих лет работы стал немного параноидальным и в этих случаях всегда бросаю исключение в последней ветке if. Точно так же я в операторе switch перечисляю все варианты и обязательно добавляю выброс исключения в ветке default.

                  В общем, как говаривал начальник Первого Отдела из института ИРЭ АН УССР, в котором я работал в советское время: "Лучше перебдеть, чем недобдеть".

                  Тут я подумал, что было бы неплохо, если бы компилятор сам проверял бы, что все условия написаны без ошибок (т.е. были бы исчерпывающе полными). Но с Python это точно не получится.

                  Может быть, это удастся сделать при помощи механизма Pattern Matching из последней версии C#? Я провел небольшое исследование, и получилось. Отпала необходимость в выбрасывании исключения, да и код стал выглядеть понятнее, чем написанный на Python:

                  const int MaxNumber = 100;
                  for (int i = 1; i <= MaxNumber; i++)
                  {
                    Console.WriteLine(FizzBuzz(i));
                  }
                  
                  static string FizzBuzz(int n)
                  {
                    var isDivBy3 = n % 3 == 0;
                    var isDivBy5 = n % 5 == 0;
                  
                    var result = (isDivBy3, isDivBy5) switch
                    {
                      (true, true) => "FizzBuzz",
                      (true, false) => "Fizz",
                      (false, true) => "Buzz",
                      (false, false) => n.ToString()
                    };
                  
                    return result;
                  }
                  

                  Если здесь убрать одно из выражений из switch (например, первое), то Visual Studio выдаст предупреждение: CS8509 The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern '(true, true)' is not covered.

                  Это предупреждение можно превратить в ошибку, и тогда код просто не скомпилируется (чтобы это сделать, нужно зайти в свойства проекта C#, раздел Build -> Errors and Warnings, секция Treat specific warnings as errors и внести в поле текст "CS8509").


      1. saboteur_kiev
        12.11.2023 12:21

        Имхо накидали много ентерпрайз кода. Ведь можно так

        for i in {1..100}; do unset r;[ $(($i%3)) -eq 0 ] && r=fizz;[ $(($i%5)) -eq 0 ] && r="${r}buzz"; echo ${r:-$i}; done


        1. FlyingDutchman2
          12.11.2023 12:21

          А что это за язык? Какой-то shell?


  1. sva89
    12.11.2023 12:21

    "3 1 3 6 = 8. Расставьте операторы..."

    Вот бы мне такие задачки на собеседованиях попадались :)


  1. wataru
    12.11.2023 12:21
    +6

    Статистика, конечно, сильно преувеличенна. Но сам факт существования FizzBuzz означает, что очень ненулевое количество соискателей действительно вообще не умеют писать код.


    1. saboteur_kiev
      12.11.2023 12:21

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


      1. wataru
        12.11.2023 12:21
        +2

        Ну FizzBuzz то завалить это никакой невнимательность не объяснить. Потом, проблема не в ошибках типа напутанных условий, а в том, что вот вообще подобие решения за 30 минут выдавить из себя не получается. Некоторые люди, которые считают себя программистами, могут только случайным образом менять код, пока он не заработает.


        1. saboteur_kiev
          12.11.2023 12:21

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


      1. dom1n1k
        12.11.2023 12:21
        +2

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

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

        Так что соглашусь с комментатором выше - 199 из 200 это наверняка большое преувеличение, но доля истины там есть.


  1. nronnie
    12.11.2023 12:21
    +4

    Про физбeз сразу приходит на ум тупо сделать массив из 15 элементов с null, fizz, buzz, и fizzbuzz в нужных местах. Потом просто деление входящего числа по модулю 15 и вывод по элементу из массива. По-моему это самое быстрое и простое решение.


    1. Alexsey
      12.11.2023 12:21

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


      1. nronnie
        12.11.2023 12:21

        Что тут олимпиадного-то?

        if(args.Length != 1 || !int.TryParse(args[0], out var n) || n < 1)
        {
            Console.Error.WriteLine("Provide a single integer argument greater than zero.");
            return 1;
        }
        
        var fizzBuzz = new string?[] {
            null, null, "fizz", null, null, "fizz",
            null, null, "fizz", "buzz", null, "fizz",
            null, null, "fizzbuzz"
        };
        
        Enumerable.Range(1, n)
            .Select(i => fizzBuzz[(i - 1) % fizzBuzz.Length] ?? i.ToString())
            .ToList().ForEach(s => Console.WriteLine(s));
        
        return 0;
        

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


        1. Timofeuz
          12.11.2023 12:21
          +2

          Зачем ToList, вдруг n под два лярда окажется? )


          1. mayorovp
            12.11.2023 12:21
            +3

            Чтобы сделать ForEach, очевидно же :-)

            На что только люди не идут лишь бы оператор цикла не использовать...


          1. nronnie
            12.11.2023 12:21

            Да, согласен, конечно. Написал просто как короче.


        1. wataru
          12.11.2023 12:21
          +6

          У вас тут ошибка. Для числа 5 у вас там null вместо "buzz". И эта ошибка прямо вызвана вашим подходом, ибо вместо понятных читабельных условий, тут какая-то магическая константа. Кроме того, в этом решении очень непонятно, а почему там i-1 береться по модулю. Это еще один вариант допустить ошибку.

          Вы сильно перемудрили. Любого задающего это задание удовлетворит сильно более короткое и тупое наивное решение с четырьмя if-then-else ветками.


          1. nronnie
            12.11.2023 12:21
            -2

            Правильно заметили. В реальности все равно к коду был бы тест, который бы это сразу выявил.На мой взгляд, как раз решение с if-then-else оно лобовое и будет тяжело тестироваться из-за "cyclomatic complexity" (такой код всегда плохо тестируется из-за необходимости проходить все возможные ветки) впрочем, тут все равно не та задача чтобы этим заморачиваться - мне бы было стыдно такую на интервью давать.


            1. mayorovp
              12.11.2023 12:21
              +1

              Ваш массив из 15 элементов - это замаскированный switch на 15 позиций. Тестировать его куда тяжелее тех if-then-else.

              Кстати, а как вообще его тестировать-то? Перечислять в тесте все 15 ответов бесполезно, потому что вы их уже перечислили (тест не должен совпадать с проверяемым кодом, иначе можно допустить одну и ту же ошибку дважды). Получается, надо писать какие-нибудь более общие проверки, то есть... в тесте вам придётся написать нормальный FizzBuzz через if-then-else?


              1. nronnie
                12.11.2023 12:21

                Тестировать элементарно:

                public string FizzBuzz(int n)
                {
                    // ....
                }
                
                // Как-то так:
                [Theory]
                [MemberData(nameof(GetFizzBuzzTestData))]
                public void FizzBuzz_returns_correct_fizz_buzz_or_number(int n)
                {
                    var actual = FizzBuzz(n);
                    string expected;
                
                    if(n % 3 == 0 && n % 5 == 0)
                    { 
                         expected = "fizzbuzz";
                    }
                    else if(n% 3 == 0)
                    {
                        expected = "fizz";
                    }
                    else if(n % 5) 
                   {
                       expected = "buzz";
                   }
                   else 
                   {
                      expected = $"{n}";
                   }
                
                   actual.Should().Be(expected);   
                }
                


                1. mayorovp
                  12.11.2023 12:21
                  -1

                  Вот именно при этом я и писал. Чтобы протестировать свой код на массиве, вам понадобился нормальный FizzBuzz через if-else


                  1. nronnie
                    12.11.2023 12:21
                    -1

                    Да. А что тут некорректного. В данном случае тест "blackbox" - сам тест это описание на ЯП спецификации задачи - т.е. "если делится на ..., то ...". Реализация может быть какой угодно - тестом мы проверяем что данная реализация соответствует спецификации (по крайней мере, в рамках тех case-ов, которые мы тесту при этом скармливаем)


                    1. mayorovp
                      12.11.2023 12:21

                      Да всё корректно, просто вам не удалось избежать написания нормального понятного FizzBuzz через if-else.


            1. Kergan88
              12.11.2023 12:21

              >В реальности все равно к коду был бы тест, который бы это сразу выявил.

              Нет, не выявил бы. В реальности вы в тесте проверяли бы на соответствие той же таблице)


        1. dom1n1k
          12.11.2023 12:21
          +2

          А потом константы 3 и 5 немного меняются и таблицу нужно всю перестраивать, неизбежно внося туда ошибки и опечатки. Да, можно сгенерировать её автоматически, но тогда... ой, алгоритм генерации таблицы - и есть решение исходной задачи.


          1. nronnie
            12.11.2023 12:21

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


            1. mayorovp
              12.11.2023 12:21

              Это алгоритм КМП, и там КА лишний, достаточно построить таблицу префиксных ссылок (они же суффиксные).


              1. Fedorkov
                12.11.2023 12:21
                -1

                Так и знал, что в enterprise edition чего-то не хватает.


              1. wataru
                12.11.2023 12:21

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


                1. mayorovp
                  12.11.2023 12:21

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

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

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


                  1. wataru
                    12.11.2023 12:21
                    -1

                    Ну этот бор по сути и является КА. Те же самые состояния. Переходы вперед те же самые. Переходы по префиксным ссылкам - некоторое сжатие представления автомата в памяти. Еще можно эти префиксные переходы считать эпсилон переходами. Уже не совсем детерменированный КА получается, тогда, да, но все еще КА.


              1. nronnie
                12.11.2023 12:21

                Я толком не помню, т.к. я говнокодер с JSON-ом наперевес, но там, кажись, всё-таки, получается КА, может быть просто не такой явный - где записи в таблице префиксов/суффиксов это как бы, типа, и есть его состояния. Можно было бы память освежить, но, тут, б*ть, сегодня поручили написать тесты на ветвление из полусотни веток - чтоб тому, кто его написал было так же хорошо, как мне плохо :)))


    1. Alexandroppolus
      12.11.2023 12:21

      Мне тоже как-то задали эту странную zzадачу, года 4 назад. Решил через конкатенацию

      for (let i = 1; i < 20; ++i) {
          console.log(`${i % 3 ? '' : 'fizz'}${i % 5 ? '' : 'buzz'}` || `${i}`)
      }


      1. saboteur_kiev
        12.11.2023 12:21

        не решили, ошибка элементарная.


        1. Alexandroppolus
          12.11.2023 12:21

          в чем баг? Проверял, печатает всё правильно


          1. saboteur_kiev
            12.11.2023 12:21

            по условиям задачи от 1 до 100 ;)


  1. Angelchik
    12.11.2023 12:21
    +2

    Основная проблема всех этих современных собеседований в том, что интервьюер упускает цель задачи собеседования: поиска человека, способного выполнять определённые задачи (1) в определённом качестве (2) с определёнными сроками (3). Для этого нужно выявлять не только способности, которые позволят выполнять определённые задачи (не только п.1). Но почти все собесы сводятся к выявлению только п.1 )))) что уже само по себе тупость. Важны ещё 2 следующих пункта + оценка обучаемости человека. Именно поэтому вот эти бедненькие вышеуказанные в статье люди могу выполнить свои поставленные задачи лишь на 0.5-1% от рынка людей )))))) Это говорит о том, какие они "отличные" руководители )))))


  1. CorwinH
    12.11.2023 12:21
    +2

    ((3 + 1) * 3)6 = 8

    12 по основанию 6 (12 в шестеричной системе счисления) = 8 :)


  1. bullgare
    12.11.2023 12:21

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

    Не помню точно условий этой задачи, но, по-моему, в ней нужно взять две равных по длине строки и возвращать True, если их встречные буквы совпадают, и False в противном случае.


    1. nronnie
      12.11.2023 12:21

      Я бы, наверное, предположил, что речь о палиндроме.

      Мне как-то на собесе дали отличную задачу на соображалку, на которой я стормозил и не решил. Дано: чемодан с "барабанным" замком - четыре цилиндра с цифрами от 0 до 9, открывается определенной комбинацией цифр. Вопрос: Какое максимальное число комбинаций нам может потребоваться перебрать, чтобы узнать правильную. Ответ не так очевиден, как может показаться :))


      1. Alexandroppolus
        12.11.2023 12:21

        Неужели можно менее чем за 10000 попыток?


        1. nronnie
          12.11.2023 12:21

          Да, можно. Особенно если внимательно условия прочитать :))

          Подсказка

          В условии написано не "открыть", а "узнать правильную комбинацию".


          1. Alexandroppolus
            12.11.2023 12:21

            А, ну тогда максимум за 9999 неудачных попыток. В этом идея?


            1. nronnie
              12.11.2023 12:21
              -1

              Почти верно

              За 9998. В наихудшем случае (ведь требуется определить именно _максимальное_ число переборов) не нужно перебирать первую (которая уже стоит) и последнюю (потому что если перебрали все остальные, а оно так и не открылось, то последняя и есть правильная).


              1. bullgare
                12.11.2023 12:21

                Я думаю, что Вы не очень расстроились, что не решили эту задачу.
                Ну это ж докапывание до столба. С ними же работать потом :)


                1. nronnie
                  12.11.2023 12:21
                  +3

                  Да я на интервью вообще никогда не расстраиваюсь уже давно. Если чего-то не знаю, то так и говорю: "Вообще в душе не знаю", или "Не знаю, но могу предположить, что ...". А бывает еще и так, что вариант ответа, который предлагает интервьюер какой-то сомнительный, тогда тоже можно сказать: "При всем уважении, но ...". Какое тут расстройство, или тем более стресс - возраст не 20 лет ведь уже давно :)


                  1. bullgare
                    12.11.2023 12:21

                    Полностью согласен.
                    Это как на свидании - просто не подошли друг другу, чего время тратить


                    1. nronnie
                      12.11.2023 12:21

                      Да, не, тут дело не в совместимости - просто ведь нет людей кто знает абсолютно всё. Ну не знаешь и не знаешь, ничего страшного поехали дальше. Интервьюер тоже, наверняка, что-то не знает. Можно даже немножко и похохмить - тебя спрашивают как работает GC в .NET, а ты типа: "Ой-вэй, а ви, кстати, знаете сколько, на самом деле, SOH и LOH в процессе .NET CLR?" :))


              1. Alexandroppolus
                12.11.2023 12:21
                +1

                не нужно перебирать первую (которая уже стоит)

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


            1. Fedorkov
              12.11.2023 12:21
              -1

              На практике 9999 неудачных попыток скорее всего означают, что замок сломан.


  1. myhambr
    12.11.2023 12:21
    +1

    Все вопросы ерунда, программистам это нахрен не нужно.

    Собеседуйте математиков и своё ЧСВ такими вопросами.