Pull to refresh

Comments 96

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

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

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

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

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

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

\overline{O} = A\lor AO

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

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

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

Hidden text

я думаю так

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Надо полагать, задача с расстановкой знаков "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']

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

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

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)']

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

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

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

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

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

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

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

Я давно занимаюсь 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))

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

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

общий подход

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

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

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

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

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

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

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

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

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

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

Я уже после многих лет работы стал немного параноидальным и в этих случаях всегда бросаю исключение в последней ветке 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").

С исключением код обычно лучше читается. Я тоже часто так пишу, только еще с комментарием, типа // На самом деле мы сюда никогда не попадём.. На мой взгляд, например, в switch отсутствующий или пустой default: при чтении сразу начинает какие-то вопросы вызывать.

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

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

Еще одно решение на Python с использованием словаря и лямбда-функций:

'''
    FizzBuzz demonstration using dictionary and lambda functions.
'''

d_config = {
    (True, True)   : lambda x : 'FizzBuzz',
    (True, False)  : lambda x : 'Fizz',
    (False, True)  : lambda x : 'Buzz',
    (False, False) : lambda x : str(x)
    }

def fizz_buzz(n):
    isDivBy3 = n%3 == 0
    isDivBy5 = n%5 == 0
    key = (isDivBy3, isDivBy5)

    if(key in d_config):
        return d_config[key](n)
    else:
        raise Exception(f'Error processing number {n}')

max_number = 100
for n in range(1, max_number + 1):
    print(fizz_buzz(n))

Если вспомнить, что True и False это просто 1 и 0, то можно сделать еще проще:

for x in range(1, 101):
    print([x, "Fizz", "Buzz", "FizzBuzz"][(x % 5 == 0)*2 + (x % 3 == 0)])

Еще одно решение на Python с использованием механизма Pattern Matching:

'''
    FizzBuzz demonstration using pattern matching
'''

def fizz_buzz(n):
    isDivBy3 = n%3 == 0
    isDivBy5 = n%5 == 0

    match isDivBy3, isDivBy5:
        case True, True:
            result = 'FizzBuzz'
        case True, False:
            result = 'Fizz'
        case False, True:
            result = 'Buzz'
        case False, False:
            result = str(n)
        case _:
            raise Exception(f'Error processing number {n}')

    return result

max_number = 100
for n in range(1, max_number + 1):
    print(fizz_buzz(n))

Но, в отличие от Pattern Matching в C#, здесь нет проверки на логическую полноту условий. То есть, если убрать какое-либо из условий case, то не будет выдано никакого сообщения об ошибке.

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

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

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

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

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

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

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

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

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

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

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

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

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;

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

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

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

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

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

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

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

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

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

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

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

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);   
}

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

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

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

Господи, так это ведь тест, а не "рабочий " код. Но, ладно, проехали.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Подсказка

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

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

Почти верно

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

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

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

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

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

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

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

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

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

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

Sign up to leave a comment.