FizzBuzz на TensorFlow

Original author: Joel Grus
  • Translation

интервьюер: Приветствую, хотите кофе или что-нибудь еще? Нужен перерыв?


я: Нет, кажется я уже выпил достаточно кофе!


интервьюер: Отлично, отлично. Как вы относитесь к написанию кода на доске?


я: Я только так код и пишу!


интервьюер: ...


я: Это была шутка.


интервьюер: OK, итак, вам знакома задача "fizz buzz"?


я: ...


интервьюер: Это было да или нет?


я: Это что-то вроде "Не могу поверить, что вы меня об этом спрашиваете."


интервьюер: OK, значит, нужно напечатать числа от 1 до 100, только если число делится нацело на 3, напечатать слово "fizz", если на 5 — "buzz", а если делится на 15, то — "fizzbuzz".


я: Я знаю эту задачу.


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


я: ...


интервьюер: Вот маркер и губка.


я: [задумался на пару минут]


интервьюер: Вам нужна помощь, чтобы начать?


я: Нет, нет, все в порядке. Итак, начнем с пары стандартных импортов:


import numpy as np
import tensorflow as tf

интервьюер: Эм, вы же правильно поняли проблему в fizzbuzz, верно?


я: Так точно. Давайте обсудим модели. Я думаю тут подойдет простой многослойный перцептрон с одним скрытым слоем.


интервьюер: Перцептрон?


я: Или нейронная сеть, как вам угодно будет называть. Мы хотим чтобы на вход приходило число, а на выходе была корректное "fizzbuzz" представление этого числа. В частности, мы хотим превратить каждый вход в вектор "активаций". Одним из простых способов может быть конвертирование в двоичный вид.


интервьюер: Двоичный вид?


я: Да, ну, знаете, единицы и нули? Что-то вроде:


def binary_encode(i, num_digits):
    return np.array([i >> d & 1 for d in range(num_digits)])

интервьюер: [смотрит на доску с минуту]


я: И нашим выходом будет унитарное кодирование fizzbuzz представления числа, где первая позиция означает "напечатать как есть", второе означает "fizz" и так далее.


def fizz_buzz_encode(i):
    if   i % 15 == 0: return np.array([0, 0, 0, 1])
    elif i % 5  == 0: return np.array([0, 0, 1, 0])
    elif i % 3  == 0: return np.array([0, 1, 0, 0])
    else:             return np.array([1, 0, 0, 0])

интервьюер: OK, этого, кажется, достаточно.


я: Да, вы правы, этого достаточно для настройки. Теперь нам нужно сгенерировать данные для тренировки сети. Это будет нечестно использовать числа от 1 до 100 для тренировки, поэтому давайте натренируем на всех оставшихся числах вплоть до 1024:


NUM_DIGITS = 10
trX = np.array([binary_encode(i, NUM_DIGITS) for i in range(101, 2 ** NUM_DIGITS)])
trY = np.array([fizz_buzz_encode(i)          for i in range(101, 2 ** NUM_DIGITS)])

интервьюер: ...


я: Теперь нашу модель нужно адаптировать для tensorflow. Сходу я не сильно уверен какую толщину слоя взять, может 10?


интервьюер: ...


я: Да, пожалуй 100 будет лучше. Мы всегда можем изменить это позже:


NUM_HIDDEN = 100

Нам понадобится входная переменная шириной в NUM_DIGITS, и выходная переменная с шириной в 4:


X = tf.placeholder("float", [None, NUM_DIGITS])
Y = tf.placeholder("float", [None, 4])

интервьюер: Как далеко вы планируете зайти с этим?


я: Ах, всего два слоя — один скрытый слой и один слой для вывода. Давайте используем случайно-инициализированные веса для наших нейронов:


def init_weights(shape):
    return tf.Variable(tf.random_normal(shape, stddev=0.01))

w_h = init_weights([NUM_DIGITS, NUM_HIDDEN])
w_o = init_weights([NUM_HIDDEN, 4])

И мы готовы определить нашу модель. Как я сказал ранее, один скрытый слой, и, давайте используем, ну, не знаю, ReLU активацию:


def model(X, w_h, w_o):
    h = tf.nn.relu(tf.matmul(X, w_h))
    return tf.matmul(h, w_o)

Мы можем использоваться softmax кросс-энтропию как нашу функцию стоимости и попробовать минимизировать её:


py_x = model(X, w_h, w_o)

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(py_x, Y))
train_op = tf.train.GradientDescentOptimizer(0.05).minimize(cost)

интервьюер: ...


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


predict_op = tf.argmax(py_x, 1)

интервьюер: Пока вы не заблудились, проблема, которую вы должны были решить это генерация fizz buzz для чисел от 1 до 100.


я: Ох, отличное замечание, predict_op функция вернет число от 0 до 3, но мы же хотим "fizz buzz" вывод:


def fizz_buzz(i, prediction):
    return [str(i), "fizz", "buzz", "fizzbuzz"][prediction]

интервьюер: ...


я: Теперь мы готовы натренировать модель. Поднимем tensorflow сессию и проинициализируем переменные:


with tf.Session() as sess:
    tf.initialize_all_variables().run()

Запустим, скажем, 1000 эпох тренировки?


интервьюер: ...


я: Да, наверное этого будет мало — пусть будет 10000, чтобы наверняка.


Ещё, наши данные для тренировки последовательны, что мне не нравится, так что давайте размешаем их на каждой итерации:


for epoch in range(10000):
    p = np.random.permutation(range(len(trX)))
    trX, trY = trX[p], trY[p]

И, каждая эпоха будет тренировать в пачках по, я не знаю, ну пусть 128 входов.


BATCH_SIZE = 128

В итоге, каждый проход будет выглядеть так:


    for start in range(0, len(trX), BATCH_SIZE):
        end = start + BATCH_SIZE
        sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end]})

и потом мы можем вывести погрешность тренировочных данных, ведь почему бы и нет?


    print(epoch, np.mean(np.argmax(trY, axis=1) ==
                         sess.run(predict_op, feed_dict={X: trX, Y: trY})))

интервьюер: Вы серьёзно?


я: Да, мне кажется это очень полезно видеть, как прогрессирует точность.


интервьюер: ...


я: Итак, после того, как модель натренирована, время fizz buzz. Наш вход будет всего лишь двоичное кодирование числе от 1 до 100:


numbers = np.arange(1, 101)
teX = np.transpose(binary_encode(numbers, NUM_DIGITS))

И затем, наше вывод это просто fizz_buzz функция, применённая к выходной модели:


teY = sess.run(predict_op, feed_dict={X: teX})
output = np.vectorize(fizz_buzz)(numbers, teY)

print(output)

интервьюер: ...


я: И это будет ваш fizz buzz!


интервьюер: Этого достаточно, правда. Мы с вами свяжемся.


я: Свяжемся, звучит многообещающе.


интервьюер: ...


Постскриптум


Я не получил эту работу. Но я попробовал на самом деле запустить этот код (код на Github), и, оказалось, что он даёт несколько неправильный вывод! Большое спасибо, машинное обучение!


In [185]: output
Out[185]:
array(['1', '2', 'fizz', '4', 'buzz', 'fizz', '7', '8', 'fizz', 'buzz',
       '11', 'fizz', '13', '14', 'fizzbuzz', '16', '17', 'fizz', '19',
       'buzz', '21', '22', '23', 'fizz', 'buzz', '26', 'fizz', '28', '29',
       'fizzbuzz', '31', 'fizz', 'fizz', '34', 'buzz', 'fizz', '37', '38',
       'fizz', 'buzz', '41', '42', '43', '44', 'fizzbuzz', '46', '47',
       'fizz', '49', 'buzz', 'fizz', '52', 'fizz', 'fizz', 'buzz', '56',
       'fizz', '58', '59', 'fizzbuzz', '61', '62', 'fizz', '64', 'buzz',
       'fizz', '67', '68', '69', 'buzz', '71', 'fizz', '73', '74',
       'fizzbuzz', '76', '77', 'fizz', '79', 'buzz', '81', '82', '83',
       '84', 'buzz', '86', '87', '88', '89', 'fizzbuzz', '91', '92', '93',
       '94', 'buzz', 'fizz', '97', '98', 'fizz', 'fizz'],
      dtype='<U8')

Наверное, нужно взять более глубокую нейронную сеть.

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 140

    +7

    Надо было делать на brainfuck. Тогда бы взяли

      –50
      Идея fizz buzz — проверить умение логически мыслить и читать тело задачи.
      Задача решается в два if. Если число делится на 3 и на 5, значит оно делится и на 15. Написать в два if не так просто, учитывая output. Но надо сделать именно в два if (else стейтмент можно вводить).

      Именно так задача давалась в оригинале.
      Попробуйте решить строго в два if
        +48

        Вы это серьёзно? (Или ваш комментарий настолько тонок, что я не понимаю?)

          –31
          Еще раз условие задачи для тех кто не понял:
          есть понятие пробы. Проба позволяет узнать значение.
          есть if () — в скобках мы пробируем значение.
          нам надо написать программу, которая:
          1. если число делится на 3 выводит «fizz»
          2. если число делится на 5 выводит «buzz»
          3. если число делится на 3 и на 5 выводит «fizzbuzz».
          4. если число не делится на 3, на 5, на 3 и на 5 НЕ выводит ни fizz, ни buzz, а выводит само число

          Example output:
          1 2 fizz 4 buzz 6 7… 14 fizzbuzz 16 17

          Попробуйте Randl, не знаю С++, что у вас выведется на экране.

          Можно написать
          for { if else; if else }
          можно
          for { if; if }
          можно
          for { if else; if}
          и т.п.
          оператор print()
          Попробуйте честно решить
            +3
            Вангую, что вам опять посыпятся минусы, но вместо этого я встречно предложу вам решить эту задачку вообще без проб, проверок и условий. Раз уж вы так настаиваете. Попробуйте честно решить (С).
            алгоритм под спойлером :)
            Заводим мутабельный массив, заполняем числами, потом пробегаемся по нему с 3 с шагом 3 — пишем в значение элемента физз, вторая пробежка — с 5 с шагом 5 — пишем базз, третья — с 15 с шагом 15 — пишем физзбазз.
              +6
              ЗЫ и похоже, ваш алгоритм как и у героя статьи, тоже эвристический :)
              Example output:
              … 6 ....
                0
                Формально будут проверки на выход из цикла. Ну и третья пробежка излишняя, если инициировать значения пустой строкой, а на второй и третьей не устанавливать новые значения, а конкатенировать с имеющимися.
                  +1
                  Если заполнять пустой строкой, то потом все равно придется делать проверку — на пустоту строки, и выводить индекс. А у нас надо же без проверок :) Ну, кроме проверки на прекращение цикла — но ее и постановщик ограничений за проверку не считает. А так, я уже под впечатлением от обсуждения создал тему на одном форуме — с ограничениями без единого if, switch / case, тернарного оператора, любых циклов for, while, do, goto, foreach и прочих функциональных мапов, фолдов и фильтров (допустим, на С++) — решить эту задачку.
                    +4
                    print(«1 2 fizz 4 buzz fizz 7 8 fizz buzz 11 fizz 13 14 fizzbuzz ...»);
                    так сойдет?
                    +1

                    Хм, а если делать на шаблонах? Работа компилятора считается? =)

                  +6

                  ну что же так, массив, числа какие-то: только рекурсия темплейтов, только хардкор

                    +1
                    Чуть упростил принтер https://gist.github.com/k06a/f3cbc6533dec54bb301a880c8f231aa4
                      +2

                      а я тряхнул стариной и зафигачил на дефайнах, раскрывающихся в сто тернарных операторов (каждый из которых может быть вычислен компилятором): http://codepad.org/5t1na6Rs

                        –2
                        Давайте зачетку
                  • UFO just landed and posted this here
                      0
                      я встречно предложу вам решить эту задачку вообще без проб, проверок и условий.
                        0
                        Так если уж есть переменная цикла («пробегаемся»), то можно в теле цикла посчитать 3-4 производных (от неё) индекса.
                        let a = [];
                        for(let i = 0; i < 105; i++){
                          a[i] = i;
                          a[i*3%102] = 'fizz';
                          a[i*5%105] = 'buzz';
                          a[i*15%90] = 'fizzbuzz';
                        }
                        console.log(a.slice(1,101));
                      –3
                      // Могу решить вообще без if-else!

                      // Достаточно подготовить массив и обращаться по индексу.

                      #include
                      #include

                      char *arr[]={«1», «2», «fizz», «4», «buzz», «fizz», «7», «8», «fizz», «buzz», «11», «fizz», «13», «14», «fizzbuzz», «16», «17», «fizz», «19», «buzz», «fizz», «22», «23», «fizz», «buzz», «26», «fizz», «28», «29», «fizzbuzz», «31», «32», «fizz», «34», «buzz», «fizz», «37», «38», «fizz», «buzz», «41», «fizz», «43», «44», «fizzbuzz», «46», «47», «fizz», «49», «buzz», «fizz», «52», «53», «fizz», «buzz», «56», «fizz», «58», «59», «fizzbuzz», «61», «62», «fizz», «64», «buzz», «fizz», «67», «68», «fizz», «buzz», «71», «fizz», «73», «74», «fizzbuzz», «76», «77», «fizz», «79», «buzz», «fizz», «82», «83», «fizz», «buzz», «86», «fizz», «88», «89», «fizzbuzz», «91», «92», «fizz», «94», «buzz», «fizz», «97», «98», «fizz»};

                      void echo(int i)
                      {
                      printf("%i -> %s\n", i, arr[i-1]);
                      }

                      int main(void) {
                      echo(rand()%100 + 1);
                      return 0;
                      }

                      // жаль, за мой ответ голосовать нельзя ))
                        +1
                        Немного более универсальный подход с массивом:

                        // 0,1,2… 14
                        string array a[15]={«fizzbuzz»,«num»,«num»,«fizz»,«num»,«buzz»,«fizz»,«num»,«num»,«fizz»,«buzz»,«num»,«buzz»,«num»,«num»};

                        string func(int n){
                        int i=n%15;
                        if (a[i]==«num») then return string(n);
                        else return a[i];
                        }

                        язык описания немного намешан, но думаю что принцип ясен, если использовать подмену (скрытая проверка условия)
                        можно избавиться от явного условия «if». Необходимо только на вход подавать целое число больше нуля.
                          0
                          Чуть позже дошло что нужно в первом присваивании получать сразу строку из массива для того чтобы второй раз по массиву не елозить.
                          *
                          string s=a[n%15];
                          if(s==«num») then return string(n);
                          else return s;
                          *
                      +29

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

                        +1
                        пост совсем не о том, как решать FizzBuzz. Вообще.

                        Это-то понятно, но дело в том, что настоящий программист просто физически не способен пройти мимо интересной задачи!

                        +1
                        Без if

                        import math

                        def fizzbuzz(i):
                          return [str(i), 'fizz', 'buzz', 'fizzbuzz'][3 — math.ceil((i % 3) / 2) * 2 — math.ceil((i % 5) / 4)]

                        for i in range(1, 100):
                          print(fizzbuzz(i))
                          +3
                          вы тестировали код?)
                            0
                            Одним глазком
                              0

                              Моё почтение, Михаил Илларионович!

                                +1
                                Не намекаете ли вы на то, что у меня 'fizz' и 'buzz' поменялись местами?
                                  0

                                  Нет, это старая шутка из серии "весь вечер Кутузов строил девушкам глазки глазок" ;)

                      +4

                      Идея FizzBuzz — отсеять совсем неумеющих программировать совсем.
                      Написать его даже в 2 if без else несложно.


                      С++. Может подумаете самостоятельно?
                        for (uint8_t i = 1;  i <= 100; ++i) {
                          std::string s = std::to_string(i);
                          if (!(i%3)) {
                            std::cout << "fizz";
                            s = "";
                          }
                          if (!(i%5)) {
                            std::cout << "buzz";
                            s= "";
                          }
                          std::cout << s << std::endl;
                        }
                        +6
                        По-моему тут куда лучше было бы условие написать честно, i%3 == 0. Читаемость значительно повысится, а символов печатать всего на два пробела больше.
                          +7
                          Да вообще эти сишные хаки в стиле «я знаю, что 0 это тоже самое, что NULL и тоже самое что false» — раздражают. if тестирует условие, так будьте добры — пишите в if условия!
                            +1

                            Верно. Просто сначала написал i%3, а потом изменил на противоположное условие и добавил !. Вот и вышло не очень красиво

                            +1
                            Задача давалась Джоном Холландом отцом генетических алгоритмов, в 70-х годах.

                            Ключевой момент вашего решения — операция s = ""

                            Обычно схема fizzbuzz идет следующим образом:
                            1. Напишите fizzbuzz — написал в 3 if.
                            2. Напишите fizzbuzz в 2 if. Пишут что и вы.
                            3. Избавьтесь от изменения переменных. Тут продолжите свои размышления.
                            Если вы считаете, что в условиях 3 задача не решается — докажите что решений нет. Если решается — решите.

                            Неумеющий программировать — уходит на пункте 1
                            Умеющий программировать — решает пункт 2
                            Математик — решает пункт 3.

                            Правило следующие:
                            if { block } then { block } else { block}; if {block} then {block} else {block} — два if
                            if; if — два if
                            if then else if; if — недопустимо. Три if

                            промежуточные результаты можно сохранить в неизменяюю переменную.
                            Нельзя менять переменную, в вашем случае s = "" недопустимо для пункта 3.
                            можно вычислять любые выражения, битовые сдвиги, числа — все допустимо.
                            Обрамляющий цикл — классический for или while.
                              0
                              В такой формулировке не понятно зачем там второй if.
                                0
                                Ну у нас максимум два if. Задача Холланда, не моя.
                                максимум два раза можно узнать результат — это значит пробу сделать.
                                if (i mod 3 = 0) — опробировали 1 раз
                                if (i mod 3 = 0 && i mod 5 = 0) — опробировали 1 раз.
                                Результат первой пробы можно использовать во второй пробе.
                                  0
                                  но результат первой пробы — надо сохранить в переменную, разве нет?
                                    0
                                    И как вы с такими if отличите fizz от fizzbuzz?
                                    i == 3:
                                    i mod 3 = 0 == true
                                    i mod 3 = 0 && i mod 5 = 0 == true
                                    i == 15
                                    i mod 3 = 0 == true
                                    i mod 3 = 0 && i mod 5 = 0 == true
                                      +1
                                      > i == 3:
                                      >…
                                      > i mod 3 = 0 && i mod 5 = 0 == true

                                      это неверно
                                        0
                                        Действительно. Там же &&, а не || — перепутал.
                                        Тогда тот же вопрос про n vs buzz: 2 — false, false; 5 — false, false. Суть не изменилась.
                                          0
                                          Ну да, автор комментария показывал пример того, что он понимает под двумя if-ами, он не предлагал рабочее решение для задачи.
                                          Я подозреваю, что в задаче подразумевается ответ «решения нет», который доказывается как-нибудь через то, что у нас грубо говоря есть только три листа в дереве ветвлений, а надо четыре. Но задачу надо очень сильно формализовать, чтобы убить всякие решения с масками, индексами в массивы итд.
                                            0
                                            На самом деле gena_glot просто несет что-то странное. Выше решение с 2 if привели. Убрать из него изменяемые переменные — задача чисто механическая (просто понадобится переменная s2): тыц, тыц.
                                      0
                                      if (i mod 3 = 0) — fizz
                                      if (i mod 3 = 0 && i mod 5 = 0) — fizzbuzz
                                      buzz?
                                    +2

                                    Вот вам вариант вообще без if-ов.


                                    object FizzBuzz {
                                      def main(args: Array[String]) = {
                                        val fb = Array[String](
                                          "fizzbuzz", "fizz", "fizz", "fizz", "fizz",
                                          "buzz", "a", "a", "a", "a",
                                          "buzz", "a", "a", "a", "a")
                                        for (i <- 1 to 100) {
                                          println(fb(5 * (i % 3) + i % 5).replace("a", i.toString))
                                        }
                                      }
                                    }
                                      –1
                                      очень плохой ответ. Элегантный, хакерский, но такой код должен идти с нормальным текстом в комментарии и объяснении, зачем был выбран такой сложный алгоритм
                                        +1
                                        Можно добавить один if чтобы не выводить пустые строки, и сократить массив.
                                        variants = ('', 'fizz', 'buzz', 'fizzbuzz')
                                        for i in range(101):
                                            v = variants[(i % 3 == 0) + (i % 5 == 0) * 2]
                                            if v != '':
                                                print("{0}: {1}".format(i, v))
                                        
                                          0

                                          Какие такие пустые строки? Мой вариант пустрых строк не выводит…
                                          Но про неявную конверсию bool -> int — хорошая идея.

                                            +2
                                            Да, прошу прощения, недочитал задачу, решил что нужно вывести только если делятся, а не с заменой.
                                            Соответственно решение с поправкой будет еще короче:
                                            variants = ('{}', 'fizz', 'buzz', 'fizzbuzz')
                                            print("\n".join([variants[(i % 3 == 0) + (i % 5 == 0) * 2].format(i) for i in range(101)]))
                                            
                                              0

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


                                              def fizzbuzz_iter():
                                              
                                                  variants = ('{}',
                                                      '{} делится без остатка на 3',
                                                      '{} делится без остатка на 5',
                                                      '{} делится без остатка и на 3, и на 5')
                                              
                                                  for i in range(1, 101):
                                                      yield variants[int(i % 3 == 0) + (int(i % 5 == 0) * 2)].format(i) 
                                              
                                              for fb in fizzbuzz_iter():
                                                  print(fb)

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

                                            0

                                            О, совсем забыл — в скале нет имплиситных конвертаций булеана в инт. Не С++ все же.

                                              +1
                                              C 1 if'ом можно вообще без хитрых алгоритмов:

                                              var test=(e)=>{
                                              	var q={
                                              		3: 'fizz',
                                              		5: 'buzz',
                                              		15: 'fizzbuzz'
                                              	};
                                              
                                              	var result=e;
                                              	for(var i in q){
                                              	   if(e%i==0){
                                              		 result=q[i];
                                              	   }
                                              	}
                                              	return result;
                                              };
                                              
                                              var t=[];
                                              for(var i=0; i<100; i++) t.push(test(i));
                                              console.log(t.join(' '))
                                              


                                              Вот без — изящно.
                                            +3
                                            На правах наркомании и отсутствия чувства юмора…

                                            console.clear();
                                            // что бы совсем без if'ов и пустых строк...
                                            var a = [
                                            	function(){},
                                            	console.log.bind(null, 'fizz'),
                                            	console.log.bind(null, 'buzz'),
                                            	console.log.bind(null, 'fizz buzz'),
                                            ];
                                            for(var i=1; i<=100; ++i){
                                                    // получаем в виде битов, через черную магию -> складываем a+b*2 -> и соотвественно выводим [ничего,1е,2е,оба]
                                            	a[Math.floor(((i-1)%3)/2) + Math.floor(((i-1)%5)/4)*2](i);
                                            }
                                            
                                              +2

                                              Без if'ов вообще:


                                              Зато с массивом
                                                for (uint8_t i = 1;  i <= 100; ++i) {
                                                  std::array<std::string, 4> print = {std::to_string(i), "fizz", "buzz", "fizzbuzz"};
                                                  bool three = i % 3 == 0, five = i % 5 == 0;
                                                  std::cout << print[three +five * 2] << std::endl;
                                                }

                                              Я принят? ;)
                                              Или будет следующий этап — отказаться от массивов? Мы играем в игру "найди мое решение", а она мне не нравится, особенно в программировании.

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

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

                                            Но статья очень смешная.
                                              +1
                                              А если человека берут работать с нейросетями? Тогда логично ведь делать описанным в статье способом.
                                                +2
                                                Даже если человека берут работать с нейросетями, ему придётся решать вот такие физзбаззы, а человек, который на такие физзбаззы будет городить нейросети, нахрен не нужен.
                                              +6
                                              interviewer detected
                                                0
                                                Почему на ваш ответ столько минусов?
                                                  0
                                                  Проблема в том, что статья-то совсем не про физзбазз, это такое введение в тензорфлоу. Да и вообще-то задачка-то нужна только для того, чтобы выяснить умеет ли человек код писать.
                                                    0
                                                    и вообще-то задачка-то нужна только для того, чтобы выяснить умеет ли человек код писать.

                                                    Вспомнилось:


                                                    Мужик в лесу заблудился, орёт "Ау! Ау!"
                                                    Подходит медведь: "Мужик, чего орешь?"
                                                    Мужик: "Заблудился, может кто услышит."
                                                    Медведь: "Ну я услышал. Тебе легче стало?"

                                                    Человек явно умеет решать задачи при помощи TensorFlow. Вам легче стало? ;)

                                                +29
                                                Без go, nodejs и микросервисов — не тру ;)
                                                  +16
                                                  Это была великолепная статья. Чаще бы такое попадалось:(
                                                    0

                                                    del

                                                      +24
                                                      Правильно, что не взяли на работу — требовался детерминированный алгоритм, а не эвристика, которая в результате ошиблась :)
                                                        –21
                                                        на js в одну строку
                                                        for(let s, i = 0; i < 100; i++) s = '', (i % 3 || (s += 'Fizz')), (i % 5 || (s += 'Buzz')), console.log(s || i);
                                                        

                                                        и незачем мудрить
                                                          +8
                                                          У вас он с нуля считает ;)
                                                          Статья кстати была не про это, в интернете и так вариантов куча, от красивых до производительных.
                                                            0
                                                            нужно напечатать числа от 1 до 100
                                                              +11

                                                              Вы пробелы убрать забыли.

                                                                +7

                                                                Ваш код не соответствует вашему же призыву ("и незачем мудрить").

                                                                  0
                                                                  Раз уж на то пошло, то почему бы и нет…
                                                                  input([ "FizzBuzz" if not x%3 and not x%5 else "Fizz" if not x%3 else "Buzz" if not x%5 else x for x in range(1, 101)])
                                                                  


                                                                  как то писал и C++ однострочник, но там настоящий ужас
                                                                    0
                                                                    И да, у вас тело на одной строке с условием цикла — это не совсем кошерный однострочник
                                                                    +1
                                                                    Не, на самом деле герой статьи молодец :) За мой опыт устройства на работу меня тоже далеко не во все места брали, но как я потом радовался, что меня не взяли в те места! Если это реальная история, то все закончилось лучшим исходом — и для героя, и для компании :)
                                                                    • UFO just landed and posted this here
                                                                        +13
                                                                        А вывод простой: хочешь провалить интервью — покажи интервьюеру, что он ламер.
                                                                          +6
                                                                          Правда, но не совсем. Тут немного другое. Не «покажи интервьюеру, что он ламер», а «покажи интервьюеру, что ты на него плевать хотел».

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

                                                                          А вот когда кандидат сознательно манкирует вопросами интервьюера и вместо решения задачи, о которой его просили, демонстрирует какой он умный и хороший, но не порождает решения, которого от него ждут… это чистый «No Hire».

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

                                                                            ИМХО давать FizzBuzz на интервью — это дурной тон. Ещё б спросили сколько настройщиков пианино в мире.

                                                                              +4

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

                                                                                0

                                                                                Во первых, вопрос в том, на какую позицию интервью. Одно дело джуниор, другое — миддл или сениор.
                                                                                Во вторых, я имел ввиду не сложность задачи, а её разрекламированность. Ну серьёно, о FizzBuzz знают все. Имейте совесть придумать аналогичную простую задачу если это то, что вам нужно. Сам факт вопроса "вам знакома задача "fizz buzz"?" означает, что интервьюер ожидает, что задача мне знакома.

                                                                                  +3
                                                                                  Сам факт вопроса «вам знакома задача „fizz buzz“?» означает, что интервьюер ожидает, что задача мне знакома.
                                                                                  И что? Вам теперь сложно её написать?

                                                                                  Задача может быть сколько угодно «широко разрекламированной», но даже при всём при этом соискатели, в большинстве своём — неспособны её написать. Вы можете? Отлично — возьмите и напишите, а не ломайте комедию.

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

                                                                                  Ибо встречал я таких «сениоров»: могут часами песни петь про всякие разные супер-пупер технологии (я и словей-то таких не знаю), рассказывать как у них команда «бороздит просторы Большого театра»… написать FuzzBuzz — не могут. Вот никак.

                                                                                  Обычно дальнейший разговор показывает, что человек последние N лет код не пишет от слова совсем и только «руководит проектами». Ну и на что он претендует, пытаясь устроиться на инженерную должность? Что? У нас не было вакансий «чистого менеджера?»… Действительно не было — потому что подобных должностей у нас нет, извините.

                                                                                  P.S. Я был бы счастлив перенестись как-нибудь ночью в мир где FuzzBuzz на собеседовании реально смысла не имеет ибо все соискатели способны его написать за 2 минуты. В нашем, реальном, мире — всё не так. Увы.
                                                                                    0
                                                                                    И что? Вам теперь сложно её написать?

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


                                                                                    Вот как раз для сениора — эта задачка в самый раз.

                                                                                    Так дайте ему сложную задачу. Кто не разбирается — одинаково обе не решит.

                                                                                      +1

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


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

                                                                                        0
                                                                                        Но я ожидаю задачи своего уровня на собеседовании.

                                                                                        Это вы знаете свой уровень (думаете, что знаете). Его задача — объективно его выяснить/проверить. Поэтому начинается от простого к сложному. Можно и наоборот, можно и методом дихотомии, не суть важно.
                                                                                          0

                                                                                          Нет, его задача не выяснить мой уровень, а проверить, соответствует ли он должности, на которую я претендую. Если нужен доктор математики, нет смысла начинать с 7*8. Тем более, что доктор математики может в уме и не посчитать :)

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


                                                                                            Его задача — объективно его выяснить/проверить

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

                                                                                            Если нужен доктор математики, нет смысла начинать с 7*8.

                                                                                            Если человек — «доктор математики», он ответит на этот вопрос без истерик. А вот гражданин, начинающий брызгать слюной и бить себя в грудь на тему «да как вы смеете, да вы знаете, кто я такой» — подозрителен. Да, он может быть просто слишком впечатлительным, а может быть и пустышкой.
                                                                                              0
                                                                                              А вот гражданин, начинающий брызгать слюной и бить себя в грудь на тему «да как вы смеете, да вы знаете, кто я такой» — подозрителен.

                                                                                              Никто и не спорит. Я только говорю, что


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

                                                                                              и


                                                                                              Разработчики особенно толковые, могут позволить себе выбирать. И издеваясь так над интервьюером человек обычно отдает себе отчёт, что это no hire.
                                                                                        0
                                                                                        Я дизайнер интерфейсов и могу написать FizzBuzz (go):

                                                                                        package main
                                                                                        
                                                                                        import "fmt"
                                                                                        
                                                                                        func main() {
                                                                                            for i := 1; i <= 100; i++ {
                                                                                                if i % 3 == 0 && i % 5 > 0 {
                                                                                                    fmt.Println("Fizz")
                                                                                                } else if i % 3 > 0 && i % 5 == 0 {
                                                                                                    fmt.Println("Buzz")                
                                                                                                } else if i % 3 == 0 && i % 5 == 0 {
                                                                                                    fmt.Println("FizzBuzz")
                                                                                                } else {
                                                                                                    fmt.Println(i)
                                                                                                }
                                                                                            }   
                                                                                        }
                                                                                        

                                                                                        Писал два года назад, и, вроде, сразу без ошибок получилось…

                                                                                        Как-то не верится, что такое не может сделать опытный разработчик. Я же вообще ничего не программирую, просто для развлечения иногда занимаюсь.
                                                                                          +4
                                                                                          Вы абсолютно правы: такое может написать типичный разработчик. Такое не может написать типичный соискатель.

                                                                                          Всё просто: хороший разработчик, после увольнения, пройдёт собеседование в 2-3 компании, выберет подходящую и всё. «Опытный разработчик» не умеющий написать FuzzBuzz сходу будет подавать заявления в 10, 20, 100 компаний — пока, наконец, не «проскочит» и не попадёт на кого-то, что не проверит банальное умение писать тривиальный код.

                                                                                          Потому-то уровень «неадекватов» приходящих на собеседование резко повышен по сравнению со «средней температурой по больнице» и потому-то FuzzBuzz на собеседовании имеет смысл…
                                                                                        0
                                                                                        Вы много людей собеседовали? Я вот достаточно, и обычно как раз миддл и сеньор. Минимум две трети людей, прошедших даже через скайп интервтью, на очном такую задачу адекватно решить не могут. Серьёзно, об этой задаче знает подавляюще малое число миддлов даже. И если человек не понимает, почему его такое спрашивает и начинает строить сильно умного — это no hire, неумение общаться. Нам с ним не по пути (по крайней мере, в крупных и уважаемых компаниях ему врядли работать).
                                                                              +1
                                                                              Не люблю эту задачу. Зато у меня тоже есть свое «аналогичное решение» — на SQL…
                                                                                0
                                                                                Спасибо, было смешно :D
                                                                                  +14
                                                                                  Интересная статья! О том как нужно ввести себя, если компания разочаровала:)
                                                                                  • UFO just landed and posted this here
                                                                                      +58

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

                                                                                        +2
                                                                                        Да и вообще: нужно было обогатить тестовые данные остатками от деления на 3 и 5 да делать решающее дерево. Работать быстрее будет! Ох уж эти любители перцептронов…
                                                                                          +6
                                                                                          Уоу уоу, полегче! Он тренирует на 101-1024, а тестирует на 1-100. Как можно оферфититься на примеры, которые никогда не видел?
                                                                                            +3

                                                                                            О, кто-то прочитал внимательно, круто!

                                                                                          +9
                                                                                          За это отдельное спасибо:
                                                                                          интервьюер: Отлично, отлично. Как вы относитесь к написанию кода на доске?
                                                                                          я: Я только так код и пишу!

                                                                                          Порадовали, отличный пост!
                                                                                          А на точке
                                                                                          интервьюер: [смотрит на доску с минуту]

                                                                                          бедный интервьюер понял, что либо он идиот, либо его тролят )))
                                                                                            +8
                                                                                            Если кто не понял, эта замечательная статья — про введение в TensorFlow, а не про то, на каком языке круче писать FizzBuzz'ы.
                                                                                              0
                                                                                              Странно что я не заметил у статьи тега «Юмор».
                                                                                                +26
                                                                                                Да, он необходим.
                                                                                                Так же как закадровый смех в американских ситкомах.
                                                                                                А то непонятно, что пост — это сарказм
                                                                                                  +23
                                                                                                  Я оценил Ваш сарказм.
                                                                                                  Тег — это не указатель на эмоции, какие должен вызывать пост, а инструмент поиска и организации.
                                                                                                +2

                                                                                                Выводы:


                                                                                                • Либо ищут человека способного рубить леса пилочкой для ногтей, везде лепят популярные решения, без понимания их ограничений и целевых задач
                                                                                                • Либо задача давалась для того что бы соискатель сказал пару ласковых интервьюеру, написал саму простую реализацию на питоне, и не пытался гнуть ель резинкой от трусов
                                                                                                  +3
                                                                                                  и не пытался гнуть ель резинкой от трусов

                                                                                                  Но согнул ведь! А победителей не судят.

                                                                                                    +1
                                                                                                    Не согнул, его алгоритм ошибался.
                                                                                                      –2

                                                                                                      Это не NP полная задача, соответственно нейросети — неуместны.

                                                                                                        0

                                                                                                        Сеть недостаточно натренировалась, чо. :)

                                                                                                      +3
                                                                                                      Вывод здесь другой совершенно. А именно — ещё никогда не было так просто замутить нейронную сеть…
                                                                                                      +10
                                                                                                      Отличный алгоритм. Напомнило сферический Enterprise FizzBuzz
                                                                                                        –2
                                                                                                        Спасибо, автор! Возьму на вооружение. А то реально бесит, когда суют всякие олимпиадно-школьные задачки на интервью (не смотря на то, на какую позицию ты идешь).
                                                                                                          0
                                                                                                          Начало было замечательным. Но видимо интервьюер расколол любителя нейросетей, найдя у него ошибку)
                                                                                                          • UFO just landed and posted this here
                                                                                                              +3
                                                                                                              Старая шутка про программиста, проблему и регулярные выражения обретает новое дыхание с появлением TensorFlow.
                                                                                                                +6
                                                                                                                Впрочем, до Нильса Бора, измеряющего высоту дома барометром, всё равно далеко.
                                                                                                                  –4

                                                                                                                  Во-первых не Бор, а Паскаль. Во-вторых — метод до сих пор много где применяется (навскидку — авиация, измерение глубины пещер).

                                                                                                                0
                                                                                                                ты вдохновил меня написать fizzbuzz на регулярных выражениях :) (см ниже)
                                                                                                                0
                                                                                                                и все же… для не умеющих сходу решать задачу в два if(готов яростно ловить минусы, но я не кодер от природы) статья была про красивый троллинг или про ксрасивый кейс нейросети?
                                                                                                                  0

                                                                                                                  Про нейросети.

                                                                                                                  +3
                                                                                                                  Сразу вспоминается поговорка «Когда у тебя есть только молоток, все похоже на гвоздь» :)
                                                                                                                    0
                                                                                                                    К вопросу о затроллении интервьюера, может, кто еще не видел классический пост о функции копирования файла.
                                                                                                                      0

                                                                                                                      Он мне так понравился, что я его Вам (и остальным хабравчанам) художественно перевёл

                                                                                                                        0
                                                                                                                        Вот еще мне нравится интервью с кандидатом на должность бизнес-аналитика о том, как передвинуть гору Фудзи: https://angryaussie.wordpress.com/2007/11/01/pointless-interview-questions/

                                                                                                                        Ну и про дизайн велосипеда для слепых тоже отлично придумано (в самом низу, где про вентилятор):
                                                                                                                        http://thedailywtf.com/articles/Riddle-Me-An-Interview
                                                                                                                      +3
                                                                                                                      хехе. а я вчера на регулярных выражениях написал по приколу :)
                                                                                                                      Слабо?
                                                                                                                      seq 0 30 | sed -r 's/^(([0369]|[147][0369]*[258 ]|([258]|[147][0369]*[147])([0369]|[258][0369]*[147])*([147]|[258][0369]*[258]))*(([147]|[258][0369]*[258])([0369]|[147 ][0369]*[258])*5|0))$/\1\tFizzBuzz/; s/^(([0369]|[147][0369]*[258]|([258]|[147][0369]*[147])([0369]|[258][0369]*[147])* ([147]|[258][0369]*[258]))*)$/\1\tFizz/; s/^([0-9]*[05])$/\1\tBuzz/'
                                                                                                                      


                                                                                                                        +1
                                                                                                                          0

                                                                                                                          Где-то ошибка — должно быть 21 Fizz, а регулярка выводит просто 21.


                                                                                                                          sed (GNU sed) 4.2.2

                                                                                                                            0
                                                                                                                            хм. у меня работает. я, видимо, неправильно скопировал из терминала — я вижу, там лишние пробелы есть, которых быть не должно. сейчас скопирую еще раз:
                                                                                                                            seq 0 30 | sed -r 's/^(([0369]|[147][0369]*[258]|([258]|[147][0369]*[147])([0369]|[258][0369]*[147])*([147]|[258][0369]*[258]))*(([147]|[258][0369]*[258])([0369]|[147][0369]*[258])*5|0))$/\1\tFizzBuzz/; s/^(([0369]|[147][0369]*[258]|([258]|[147][0369]*[147])([0369]|[258][0369]*[147])*([147]|[258][0369]*[258]))*)$/\1\tFizz/; s/^([0-9]*[05])$/\1\tBuzz/'
                                                                                                                            

                                                                                                                            это должно работать
                                                                                                                              0

                                                                                                                              Да, так лучше.

                                                                                                                          0
                                                                                                                          >>Наш вход будет всего лишь двоичное кодирование числе от 1 до 100

                                                                                                                          А вот тут проблема: а почему числа от 1 до 100 должны генериться? А как же постулат о атомарности и сохранности данных? По хорошему, эту последовательность лучше хранить в таблице базы данных. Соответственно, на доске надо бы еще привести скрипты для генерации таблицы. А для чего? Ну для SQL Server конечно, мы ж взрослы люди, в конце концов. Но мы же в 2016-ом? Поэтому нужна человеческие вьюшка. А куда ж без нее? Затем, раз мы все уж храним в базе, то автору б не мешало все его коды оформить в виде CLR модуля, написать команду компиляции оного куда? В какую-то dll, наверное. Дальше на доске скрипты разрешения CLR, подключения dll. Ну и конечно, создать пользовательские функцией с вызовом всего обвяза из ранее подключенной сборки (обучение, выводы — вот это все). И только потом, как написал коллега выше — go, nodejs и микросервисы.

                                                                                                                          Где это всё, автор? Почему архитектуру не продумал? Почему сразу стал код писать? Что это? Вопиющая некомпетентность? Спешка? Слабость характера?

                                                                                                                          Правильно сделали, что не взяли.

                                                                                                                          ;)
                                                                                                                            0
                                                                                                                            проблема в том, что на РЕАЛЬНОМ производстве, к которому интернет имеет косвенное отношение и задачи там совсем другие, проблем в том, что там такие вопросы для школьников не задают, так ценятся люди совсем другие — умеющие проектировать и реализовывать до уровня железа стенды, системы управления оборудованием и т.д.

                                                                                                                            Собственно говоря одна из причин, почему в России не могут решить проблемы с импортозамещением или проще — осуществить новую ре — индустриализацию, состоит как раз в том, что в стране тех. специалистов (согласно статистике) только 10%, при этом специалистов занимающихся железом возможно сотые доли процента среди всех специалистов…
                                                                                                                              0
                                                                                                                              Даже такой замудреный вариант решения задачи — через перцептрон, можно было решить куда проще — в первую очередь используя используя sklearn, вместо tensorflow. Он лаконичнее решает простые задачи по машинному обучению.

                                                                                                                              При этом сама конструкция перцептрона вызывает сомнение. На вход нет нужды подавать весь этот мусор. Это создает лишние шумы. Лучше подавать сразу остаток от деления на 3 и 5. Только 2 инпута.

                                                                                                                              Ну и использовать softmax тоже нет нужды. Он хорош для multi-class аутпута. А это не тот случай. Правильнее было бы просто linear.

                                                                                                                              Может тогда взяли бы на работу? А точность уж наверняка была бы 100% :)
                                                                                                                                –2
                                                                                                                                Вот еще вариант решения без использования временной переменной

                                                                                                                                for (int i = 1; i < 101; i++)
                                                                                                                                {
                                                                                                                                Console.WriteLine((«fizzbuzz» + i.ToString())
                                                                                                                                .Replace((i%3 != 0)? «fizz»: i.ToString(), "")
                                                                                                                                .Replace((i%5 != 0)? «buzz»: i.ToString(), ""));
                                                                                                                                }

                                                                                                                                Мопед не мой, попросили разместить)))
                                                                                                                                  +2
                                                                                                                                  Правильно не взяли, он неправильно использует инструмент. 100 слоев на такой маленькой выборке не обучить. При том, что деление на пять тривиально проверяется двухслойной сеткой, да и деление на три наверняка можно сделать при помощи двухслойной-трехслойной рекуррентной сети.
                                                                                                                                    0
                                                                                                                                    Где Вы 100 слоёв усмотрели? Скрытый слой там всего один. Если речь про нейроны, то мне не очевидно, как в 2 нейрона проверить число в двоичной записи на делимость на 5 или 3.
                                                                                                                                      0
                                                                                                                                      Да, вы правы. Читать не умею, прочитал толщину слоя 100 как 100 слоев.
                                                                                                                                      Нет, не в два нейрона, а в два слоя, конечно. В два нейрона не выйдет, вероятно.
                                                                                                                                    0
                                                                                                                                    осознал, что не пособен быть программистом, даже если бы из кожи вон вылез. грёбаный гуманитарий (

                                                                                                                                    Only users with full accounts can post comments. Log in, please.