Если у вас нет плюсов

    Мой друг Алексей ищет работу и ходит на собеседования. После которых интересуется, как бы я ответил на некоторые из заданных вопросов.

    Отвечая на один такой вопрос, я слегка увлёкся, и материала набралось на целую статью. Впрочем, небольшую и несерьёзную - пятничного формата.

    Хотите немного развлечься? Вопрос лёгкий. Надеюсь, вы попытаетесь ответить на него самостоятельно, прежде чем читать дальше. Итак:

    "Сложить два целых числа (от 1 до 99) без использования оператора 'плюс'. Дайте пять разных ответов"


    Ну как? Придумали пять ответов? Давайте сравним. Если будет что-то такое, до чего я не додумался - добавляйте в комментарии.

    Дальше - художественно обработанная "стенограмма" моего общения с другом.


    Первое, что приходит в голову - "минус на минус даёт плюс":

    plus1 = lambda a,b: a - (-b)
    
    >>> plus1(22,6)
    28

    Видишь ошибку? Она здесь есть. И на интервью её заметят. Но не будем пока отвлекаться - в конце объясню.

    Второй вариант, думаю, очевиден:

    import math
    plus2  = lambda a,b: int(math.log10(10**a * 10**b))
    Пояснение для читателей

    Используется равенство an+m = an * am

    Соответственно, логарифм от an+m равен n+m

    С помощью модуля operator:

    import operator
    plus3 = lambda a,b: operator.add(a,b)

    Но можно и напрямую, без этого модуля:

    plus4 = lambda a,b: a.__add__(b)

    Впрочем, есть готовая встроенная функция:

    plus5 = lambda a,b: sum([a,b])

    И даже вот так можно:

    plus6 = lambda a,b: list(range(a, 200, b))[1]

    Или через длину строки:

    plus7 = lambda a,b: len(''.join([a*'#', b*'*']))

    Python вообще богат на варианты:

    plus8 = lambda a,b: eval('a + b')

    Тут мой товарищ возмутился, что видит плюс, а плюс использовать нельзя. Спорный вопрос. В условии говорится про оператор '+', а здесь он просто символ. Хотя eval его, конечно, исполняет как оператор.

    Впрочем, не буду спорить с другом:

    plus9 = lambda a,b: eval('a \N{PLUS SIGN} b')
    Пояснение для читателей

    Используется символ плюса через его название в Unicode

    Друг: "Мне кажется, меня тут пытаются обмануть. Что это ещё за PLUS SIGN?"

    Ладно! Сейчас не будет никаких плюсов:

    plus10 = lambda a,b: eval("".join(map(chr, [97, 32, 43, 32, 98])))
    Пояснение для читателей

    С помощью join из отдельных символов собирается строка 'a + b'

    "Так! Никаких больше eval!"

    Хорошо. Кстати, я тут придумал ещё пару вариантов. Правда, с плюсом, но Python даже не будет этот плюс исполнять. Вариант первый:

    import sqlite3
    conn = sqlite3.connect(':memory:')
    cursor = conn.cursor()
    plus11 = lambda a,b: cursor.execute('select ? + ?', (a,b)).fetchone()[0]

    Вариант второй (для Linux, FreeBSD и т.п.):

    import os
    plus12 = lambda a,b: int(os.popen(f'expr {a} + {b}').read().strip())

    "Э-э-э, нет... Давай вот без этого. Только встроенными средствами Питона. А то так можно в каком-нибудь онлайн-калькуляторе два числа сложить, а потом распарсить ответ"

    Эх... А я только собирался предложить что-нибудь эдакое. Что-ж... Придётся вспомнить детство. Складываем "в столбик" двоичные представления чисел:

    def plus13(aa,bb):
        a = f'{aa:0>8b}'
        b = f'{bb:0>8b}'
        result = ['0'] * 8
        carry_bit = '0'
        for i in range(7, -1, -1):
            if a[i]=='1' and b[i]=='1':
                result[i] = carry_bit
                carry_bit = '1'
            elif (a[i]=='1' and b[i]=='0') or (a[i]=='0' and b[i]=='1'):
                if carry_bit == '0':
                    result[i] = '1'
            else:
                if carry_bit == '1':
                    result[i] = '1'
                    carry_bit = '0'
        return int(''.join(result),2)
    Пояснение на примере

    22 + 6 = 10110 + 00110 (считаем справа налево, всего пять шагов)

      1    |    2    |    3    |    4    |    5
           |    ▼1   |   ▼1    |         | 
    10110  |  10110  |  10110  |  10110  |  10110
    00110  |  00110  |  00110  |  00110  |  00110
    -----  |  -----  |  -----  |  -----  |  -----
        0  |     00  |    100  |   1100  |  11100 = 28

    Шаг 2) 1 + 1 = 10. Что не вмещается в двоичный разряд. Поэтому 0 пишем, а не вместившийся бит (бит переноса, carry bit) переходит в следующий разряд.

    Шаг 3) 1 + 1 = 10 плюс бит переноса = 11. Пишем один и один переносим.

    А собственно... Что это я в бирюльки играюсь? Можно обрабатывать все разряды одновременно:

    def plus14(a, b):
        while b != 0:
            carry_bits = a & b
            a = a ^ b
            b = carry_bits << 1
        return a
    Пояснение для читателей

    Сначала используем битовое И (&). Так мы узнаем разряды, в которых появится переполнение. Соответственно, на разряд левее нужно будет добавить биты переноса. Для этого сдвигаем полученное число на бит влево (00110 << 1 = 01100). И получаем первое слагаемое для следующего цикла. Или выходим из цикла, если битов переноса нет (одно из слагаемых стало равно нулю, значит вычисление завершено).

    10110
    00110
    ----- &
    00110 << 1 = 01100

    С помощью исключающего ИЛИ (^) устанавливаем в 0 переполненные разряды и оставляем неизменными непереполненные. Это будет второе слагаемое для следующего цикла или конечный результат, если вычисления завершены.

    10110
    00110
    ----- ^
    10000

    Можно даже сделать рекурсивный вариант:

    def plus15(a, b):
        if b == 0:
            return a
        else:
            return plus15(a ^ b, (a & b) << 1)

    А теперь - внимание! Барабанная дробь... Смертельный номер! Закат Солнца вручную:

    import types
    co = types.CodeType(2, 0, 0, 2, 0, 0, b'|\x00|\x01\x17\x00S\x00', (), (),
                        ('a','b'), '', '', 1, b'')
    plus16 = types.FunctionType(co, globals())

    "Так... Секундочку... Что это сейчас было?"

    Ты-же в курсе, что внутри функции есть CodeObject, который состоит из байт-кода Питона и нескольких параметров (определение переменных, размер стека и т.п.). Этот объект можно сгенерировать вручную и получить из него работающую функцию.

    "Ну да. Ты ещё скажи, что в голове питоновские программы в байт-код компилируешь :)"

    Нет, конечно. Просто я это пару дней назад смотрел и пока ещё помню.

    На самом деле там несложно
    >>> import dis
    >>> dis.dis(co)
      1           0 LOAD_FAST                0 (a)
                  2 LOAD_FAST                1 (b)
                  4 BINARY_ADD
                  6 RETURN_VALUE

    То есть, это обычное сложение через стек.

    Вообще, к байткоду функции легко добраться:

    >>> bytecode = plus16.__code__.co_code
    >>> bytecode
    b'|\x00|\x01\x17\x00S\x00'
    
    >>> list(bytecode)
    [124, 0, 124, 1, 23, 0, 83, 0]

    Видно, что операции в байткоде состоят из кодов команд (opcode) и аргументов (oparg). Вот команды:

    124 - LOAD_FAST    # |
    23 - BINARY_ADD    # \x17
    83 - RETURN_VALUE  # S

    С помощью dis.opmap и dis.opname их можно преобразовывать туда-сюда:

    >>> dis.opname[124]
    'LOAD_FAST'
    
    >>> dis.opmap('LOAD_CONST')
    100

    Аргумент операции - это номер в списке переменных. В нашем случае список состоит из двух переменных a и b, которые загоняются в стек и складываются.

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

    Кстати, без модуля types можно обойтись. Переменные типа "функция" и "объект кода" можно клонировать из других объектов:

    f = lambda: ...
    function = type(f)
    code = type(f.__code__)
    co = code(2, 0, 0, 2, 0, 0, b'|\x00|\x01\x17\x00S\x00', (), (), 
              ('a','b'), '', '', 1, b'')
    plus17 = function(co, globals() )

    "Три точки в первой строке - это Ellipsis?"

    Да. Объект-заполнитель, который здесь используется вместо pass. Появился в последних версиях.

    О! Насчёт последних версий. Если у тебя Python версии 3.8+, там есть замена кодового объекта:

    def plus18(a,b): ...
    plus18.__code__ = plus18.__code__.replace(
      co_code=b'|\x00|\x01\x17\x00S\x00')

    Видал, какая чёрная магия? Весь "обвес" остаётся от исходной функции, а меняется только нужная часть (в этом примере - байт-код).

    Вообще, там не обязательно должен быть байткод в явном виде. Можно не заморачиваться с преобразованием и писать вот так:

    plus18.__code__ = plus18.__code__.replace(
      co_code=(lambda a,b: a + b).__code__.co_code)

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

    def plus19(a,b):
        lst = []
        value = 0
        before = sys.getrefcount(value)
        for i in range(a):
            lst.append(value)
        for i in range(b):
            lst.append(value)
        return sys.getrefcount(value) - before

    Вот, как-то так...

    . . .

    {прошло несколько минут}

    . . .

    "Что молчишь? Нет больше вариантов?"

    Один ещё есть. Только я формулу забыл. Пришлось в интернете посмотреть. Через разложение косинуса суммы углов:

    from math import cos, sin, acos
    def plus20(a,b):
        a = a / 200
        b = b / 200
        result = acos(cos(a)*cos(b) - sin(a)*sin(b)) * 200
        return int(round(result, 0))
    Пояснение для читателей

    Используется формула cos(a+b) = cos(a)*cos(b) - sin(a)*sin(b)

    Максимально возможная сумма в этой задаче - 198. А тригонометрия считается в радианах. Чтобы исключить неоднозначность и гарантированно остаться в пределах четверти круга (около полутора радиан) - я просто делю и умножаю на 200.

    А пока я мысленно представлял транспортир, вспомнилась ещё и функция enumerate, которая нумерует элементы:

    plus21 = lambda a,b: list(enumerate([*range(-1,a), *range(b)]))[-1][0]

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

    "Вопрос я выдам. Не вопрос. Что там с первым ответом? Где ошибка?"

    Ошибка в том, что по PEP 8 не рекомендуется присваивать лямбды. Надо использовать обычное определение функции через def, т.к. это "more useful for tracebacks and string representations".

    То есть, неправильно писать

    fun1 = lambda a: a**2

    надо использовать так:

    def fun2(a): return a**2

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

    >>> fun1
    <function <lambda> at 0x0000024FEE36F1F0>	
    
    >>> fun3 = lambda a: 2 * a
    >>> fun3
    <function <lambda> at 0x000001A7571BA550>
    
    >>> fun2
    <function fun2 at 0x0000024FEE36F3A0>

    Видишь? У всех лямбд одинаковое имя - <lambda>. Когда я тебе однострочные примеры пишу - это неважно. А на собеседовании лучше делать так, как рекомендуют.

    "А можно лямбде имя присвоить?"

    Да без проблем!

    >>> fun1.__qualname__ = 'fun1'
    >>> fun1
    <function fun1 at 0x0000024FEE36F1F0>

    Только зачем такие сложности, если можно сразу через def объявить. Кроме того, всё ещё видно, что это лямбда:

    >>> fun1.__code__.co_name
    '<lambda>'

    В отличие от

    >>> fun2.__code__.co_name
    'fun2'

    При этом параметр co_name - readonly, т.е. напрямую имя не поменять. Надо использовать __code__.replace (но это только в Python 3.8+):

    >>> fun1.__code__ = fun1.__code__.replace(co_name='fun1')

    И ещё в одном месте:

    >>> fun1.__name__ = 'fun1'

    Теперь она не отличается от обычной функции:

    >>> fun1.__code__.co_name
    'fun1'
    >>> fun1.__qualname__
    'fun1'
    >>> fun1.__name__
    'fun1'
    >>> fun1
    <function fun1 at 0x0000024FEE36F1F0>

    Реально проще использовать def.

    И я всё ещё жду новый вопрос...

    Впрочем... Забавно у вас там на собеседованиях. Самому, что-ли, сходить? Ни разу не был.

    Комментарии 131

      +63
      Бежать надо от таких вопросов и работодателей.
      Хотите разузнать о моих математических навыках? Спросите, а не делайте спектакль безумия.

      Заметил, что только в ИТ сфере есть такие дебильные собеседования.

      — Как вы доставите пиццу, если у вас откажут ноги?
      — Как вы почините кран, если у вас будет шесть пальцев?
      — Как провести трахеотомию при помощи пвх трубы и зажигалки?
      — У вас есть пластилин, кинетический песок и жвачка. Постройте 9-этажный дом. Не забудьте про СНИПы.
        +1

        Забавно, что иногда такие задачи в ИТ встречаются: например, как на лету прочитать дамп ffmpeg vstats при условии, что он пишется исключительно в файл (в стандартный выхлоп не умеет).


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


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

          +8
          Ну так предлагайте реальные задачи, а не «не используйте операцию сложения». Нет в природе ситуаций, когда нельзя использовать сложение.

          Само-собой, бывает, что нужно провести операцию в лифте, отрезать ногу в поле, замотать трубу тряпкой в эпоксидке, отбиться от гопников перед подъездом клиента. Но никто не нападает на кандидатов перед собеседованием и не запирает в лифте с больным. Когда-то давно были только люки от гугла, теперь вот пошло в массы.
            +1
            Конечно же в природе есть ситуации, когда нельзя использовать сложение.
            Например, когда ваша задача реализовать сложение в архитектуре процессора который вы разрабатываете.
              +13
              На питоне? :)
                +6
                В природе.
                +8
                При разработке архитектуры, наверное будет невыгодно реализовывать сложение через логарифмы или вычитание. Иначе это будет очень очень медленный и плохой процессор.
                0
                На объяснение «реальной задачи» может уйти 10 минут. И если я уже знаю, что «реальная задача» сводится к «найти наибольший элемент в массиве без использования оператора сравнения» — то я сэкономлю 10 минут и дам сразу задачу в сжатом виде. Потому что на собесе время ограничено. И если кандидат успеет быстро решить задачу — то поясню, откуда она такая взялась и как она относится к нашей деятельности. Но только если времени хватит.
                  +3
                  Если вы не можете придумать реальную задачу, которую можно объяснить быстрее чем за 10 минут, это не проблема задач.
                  Если ваша реальная задача сводится к тому, чтобы заниматься таким вот извращением, возможно вам стоит отойти на шаг подальше, и понять где именно вы свернули не туда, а не собеседования устраивать.
                    +1
                    Если вы не можете придумать реальную задачу

                    Я вижу тут какое-то противоречие: если вы придумываете задачу — она уже по определению не реальная.

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

                    Кажется, вы забываете о том, что не всё программирование делается по шаблону. И иногда приходится обрабатывать терабайты неструктурированных данных для которых оператор сравнения не определён (точки на графе, например).
                    0
                    На объяснение «реальной задачи» может уйти 10 минут. И если я уже знаю, что «реальная задача» сводится к «найти наибольший элемент в массиве без использования оператора сравнения» — то я сэкономлю 10 минут и дам сразу задачу в сжатом виде.
                    Способность декомпозировать задачу до уровня простых алгоритмов так явно не проверить. Джунов имеет смысл так проверять, но только их, кмк.
                      0
                      Способность декомпозировать задачу до уровня простых алгоритмов так явно не проверить. Джунов имеет смысл так проверять, но только их, кмк.

                      Я согласен, что декомпозицию так не проверить. Но когда я провожу собеседование — я сначала проверяю, что человек тянет хотя бы на джуна, а потом уже даю мидловские/сениорские задачи.
                        0
                        Если собеседовать «по матрице», то подход верен. А если на конкретную позицию, требующую левел, то я бы сразу переходил к вопросам повыше (слегка странно на сеньора слышать вопросы а-ля «как создать класс исключения и потом использовать его в коде», причем кейс — реальный). Максимум — это вопросы, тянущие на полгрейда ниже — все-таки резюме интервьюер перед собесом видит. Так и время сэкономится, и качество отбора повыше будет. Имхо.
                          0
                          Не всё то правда, что в резюме. Не каждый претендент на сеньора — джун. А вообще проще надо всем быть. А то одни изображают из себя супер профессионалов и считают, что алгоритмические задачи недостойны того, чтобы их решать, я ведь не джун какой-то. А потом выясняется что решить то эту «задачку» не так-то просто. А другие придумавают такие «задачки», которые чтобы решить надо быть Вассерманом в программировании, а потом выясняется, что на работе надо домашний страницы делать. В общем баланс должен быть везде и гармония :)
                            0
                            Конечно, в резюме много чего можно встретить. Но я немного не о том.
                            Идея в том, чтобы на собесе на сеньора сразу спросить вопросы, по ответам на которые человек либо явно сеньор, либо скорее мидл, либо точно джун. Эдакие маячки. Вряд ли по ответу на вопрос «что такое декоратор» можно такое предполагать (ну разве что кандидат, увлекшись, начнет декоратор сразу в байткоде набрасывать :) ).

                            А баланса, да, побольше бы. :)
                            0
                            Да, тут локальная специфика — я примерно никогда не собеседую людей на конкретную позицию. Очень часто провожу предварительные секции, на которых нужно оценить общий уровень кандидата и дальше с ним уже будут общаться по конкретным позициям.

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

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

                      +2

                      Ну вообще-то, такая программа как tail именно это и делает, читает в свой stdout всё что валится в файл.

                        +1

                        А еще есть именованные каналы

                        0
                        в стандартный выхлоп не умеет

                        Он не не умеет, а сделано это целенаправленно.
                        ffmpeg в stdout может выводить видео или аудио поток, и тогда этот поток можно принимать другой программой обработки.

                        Именно по этому, ffmpeg делает текстовый вывод в stderr. Но ни кто не мешает stderr перенаправить в stdout средствами операционной системы:
                        fmpeg -i input.mp3 2>&1
                          0

                          Почитайте документацию, посмотрите код. Vstats пишется исключительно в файл.

                        +10
                        ИМХО, самое ужасное в этих вопросах — зачастую очень плохо задаются условия задачи и ограничения.
                        В статье это тоже есть. Язык — только в тегах, можно ли использовать библиотеки, которые используют "+" под капотом — не сказано.

                        Иногда из-за этого получается забавный эффект — «правильно» задачку могут решить только те, кто знают одни вещи, и не знают другие. Потому что если знаешь слишком много — отвергнешь «правильное» решение.
                          +6
                          Что ещё плохо — непонятно, что именно от тебя хотят. Проверить знание математики? Алгоритмов? Стандартной библиотеки? Встроенных возможностей языка? Или просто ищут повод, чтобы отказать чем-то не понравившемуся кандидату.
                            +2
                            Обычно если прямо спросить — ответят «мы хотим увидеть, как вы мыслите». Но объяснить, что же именно в этом мышлении они анализируют, обычно не могут.
                            То есть у них самих нет готового алгоритма типа «если кандидат использовал библиотеку — то он относится к группе людей 1, если кандидат сформировал плюс из символов — то он относится к группе людей 2».

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

                            Так что по факту это просто ИБД — имитация бурной деятельности. С тем же успехом человека можно посадить проходить тест Люшера.
                              0
                              Так что по факту это просто ИБД

                              Кстати да. Я вполне могу представить ситуацию, когда кандидат уже подходит, но по процессам компании собеседование всё равно нужно провести. Спрашивать элементарщину тоже вариант, но придумывать свои задачки-головоломки тупо интереснее, а слышать в 20 раз о том, как работает хеш-таблица — тупо скучнее.
                                0
                                А на практике из 20 раз услышать один-два вменяемых ответа — вполне норма. А уж как работает хеш джойн — и того куда реже.
                                  0
                                  Если кандидат подходит, а собес нужно для галочки, то проблема в процессах, ведь, пока человека ищут/собеседуют, компания теряет время, а время=деньги. В конце-концов, просто сократить время собеса до 15 минут и поговорить с человеком о задачах, которые ему действительно придется решать на проекте — так и интересно, и с пользой. А все эти задачи вроде «сосчитать до бесконечности» или «сколько жирафов поместится в лондонский автобус» — это либо пустая трата времени, либо садизм по отношению к кандидату (и себе, если делается без удовольствия).

                                  З.Ы: особенно ярко проявляется в конторах, как из этого примера.
                                    0

                                    К сожалению, даже я, практически не имеющий опыта "боевой" разработки, сталкивался с ситуациями, когда кандидату нельзя показывать боевые примеры кодинга. Безопасность через неясность — всё ещё популярный механизм. Увы.

                                      0
                                      Так код и нельзя показывать, а то «придут люди, умеющие убеждать» — злой дядя Начальник-Безопасности и неумолимая тетя NDA.

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

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

                                Если 5 разных способов на самом деле разные, то ок.

                                Если 5 способов это почти копии одного (5 вычислений через минусы со сменой знака в конце, например), то не ок.

                                Ну и промежуточные вариации.

                              +4
                              «Нам угрожает начинённый атомными бомбами инопланетный космический корабль. У нас есть транспортир» — Нил Стивенсон, «Анафем»
                                +2

                                Правильный ответ на вопрос "как?" не может быть дан при неимении ответа на вопрос "зачем?".

                                  0
                                  Задача очень даже интересная, если бы собеседовал разработчиков вероятно тоже бы задавал.
                                  Хотя по мне интереснее слушать как бы кандидат написал алгоритм поиска решения для игры в 15ки. Еще надо понимать на какой грейд берут специалиста.
                                    +1

                                    "Задача - удалить гланды. Условие - через рот нельзя."

                                      0
                                      Ответ выше был: «трахеотомия с помощью пвх-трубы и зажигалки».
                                    –1
                                    сильно…
                                      +11
                                      Сложить два целых числа (от 1 до 99) без использования оператора 'плюс'

                                      А самый тупой вариант — таблица с вариантами для каждого случая? Типа if (a == 1) { if (b == 1) return 2;… }…
                                        +2
                                        Почему тупой? Так и программируют индусы, между прочим. И не стесняются.
                                          0
                                          Массивом проще
                                            0
                                            Но это уже будет не самый тупой вариант :)
                                          +13

                                          Правильный ответ - после первого вопроса встать и уйти. Не дай Б-г еще возьмут на саппорт уже написанного в этом духе.

                                            +1
                                            Вот так они и заманивают.
                                            +3
                                            Имхо, есть ещё 4 решения намного проще:

                                            1) a+b === 2a-x, где x = a-b
                                            2) a+b = c === c-a == b… a, b in [0, 99] => c < 200….
                                            a = 15
                                            b = 24
                                            for bv in range(200, 0, -1):
                                                if bv-a == b: 
                                                    break
                                            print(bv)
                                            

                                            3. табличное сложение — предварительно в коде размещаем таблицу 99x99 — где каждый элемент является сложением индеска.
                                            4. сложение генератором — if и switch наше всё…

                                            но это не так весело…
                                              +3
                                              Это самые разумные общеалгоритмические подходы, но автору захотелось поупражняться в хаканьи Python internals. Кама-сутра по вызову python opcode add через нетрадиционные места.
                                                +3
                                                А как можно было бы развернуться на C++ с использованием template metaprogramming!
                                                  0
                                                  Ну, классическому компилируемому в нативный бинарный код языку на самом деле труднее конкурировать с обфускацией внутренних вызовов чем скрипту с развитой рефлексией и built-in eval. Вот JavaScript-хацкеры тут повоюют.
                                                    +1
                                                    Возможность прямого доступа в память и выполнения ассемблерных вставок вряд ли побивается любой самой развитой рефлексией.
                                                      0
                                                      Ну, рефлексией, наверно, не перебивается. Но против eval-а приемов нет, потому что с исходным кодом как вычисляемым ресурсом в рантайме можно нагенерить вообще все что угодно. Темплейты хотя и полны по Тьюрингу, но выразительно гораздо менее гибки чем родной исходный текст.
                                                +1

                                                3. табличное сложение — предварительно в коде размещаем таблицу 99x99 — где каждый элемент является сложением индеска.

                                                Можно отсортировать аргументы (if (a > b) swap(a, b);) и оптимизировать таблицу.

                                                +1
                                                «Сложить два целых числа (от 1 до 99) без использования оператора 'плюс'. Дайте пять разных ответов»

                                                plus1 = 100 — (100 — a — b);
                                                  +4
                                                  100 не нужно. Просто умножение на -1
                                                  +1
                                                  А показалось… ладно, неважно, вот мои 3 (недо)решения:

                                                  1) 100 — (100 — a — b)
                                                  2) (0 — a — b) * (-1)
                                                  3) Используем что a**2 — b**2 = (a — b)(a + b), соответственно (a**2 — b**2)/(a — b), a — b != 0
                                                    0
                                                    А зачем во втором случае ноль? Почему не просто (-a-b)*(-1)?
                                                      0
                                                      недочет, действительно)
                                                      Спасибо за поправку)
                                                        0

                                                        Потому что без нуля будет уже следующий способ решения, о нём уже писали :))

                                                        0

                                                        Первый вариант сразу пришел в голову, только не 100 использовал а 198 (потому что числа от 1 до 99, т.е оба могут быть 99) 8-)

                                                      +9
                                                      А можно было на первый вопрос сразу ответ написать? Ну, чтобы те, кто с питоном не знаком, не чувствовали себя дураками, пытаясь найти ошибку в
                                                      спойлер
                                                      использовании синтаксиса

                                                      (Или я единственный, кто упорно думал над этим случаем?:))
                                                        +1

                                                        Там нету ошибок. PEP8 — это набор рекомендаций, не более. Его нарушение является ошибкой настолько же, насколько является ошибкой


                                                        for(...)
                                                        {
                                                           do_stuff()
                                                        }

                                                        вместо


                                                        for(...) {
                                                           do_stuff()
                                                        }
                                                        0

                                                        Сложить два целых числа (от 1 до 99) без использования оператора 'плюс'

                                                        Потом скажут пиши код без использования компьютера

                                                          0

                                                          Ну на листе бумаги же заставляют

                                                            0
                                                            Не знаю насколько это распространённая вещь, но экзамен в техническом вузе нас так заставляли сдавать. На С.
                                                            +5
                                                            if a<>b then
                                                              writeln((a*a-b*b) div (a-b))
                                                            else
                                                              writeln(a*2);
                                                              0
                                                              Ух, с решением на основе разности квадратов опередили, пардон.
                                                              Тогда так:
                                                              writeln(a*2 - (a-b));
                                                                0
                                                                Но это же тоже самое что и первое решение в посте.
                                                                Так можно до бесконечности продолжать
                                                                print(a*3 - (a*2-b))
                                                                  0
                                                                  Формально — нет, идейно — да.
                                                                  Заодно плюс повод подискутировать с интервьюером и оценить глубину его шибанутости :)
                                                                0

                                                                Ну так неинтересно. Вот если бы у вас не было ADD/SUB в доступном подмножестве ассемблера...

                                                                  0
                                                                  1. Цикл с INC a, DEC b и выходом когда b = 0
                                                                  2. Полный сумматор (побитовый)
                                                                  3. Через сумму логарифмов (углов синусов, квадратов или любым другим математическим фокусом)
                                                                  4. Через память (массив 100*100 с ответами)
                                                                  5. ???
                                                                  +1

                                                                  Есть такие задачки, до сих пор помню code challenge 15-летней давности, который меня выбил на неделю

                                                                  язык: asm

                                                                  набор инструкций: I 386**

                                                                  цель: написать DOS программу (.com), которая принимает на стандартный вход 1 байт (число 0-255) и выводит в стандартный вывод N знаков $, где N - число на входе, после чего завершается с кодом 0

                                                                  критерий оценивания: побеждает программа минимального размера

                                                                  ** ну, и маленький нюанс: нельзя использовать команды условного перехода (jz, je, jne и т.п.), нельзя использовать арифметику (add, sub, inc, dec, mul, div), в том числе адресную арифметику (lea, dword ptr [eax + 4] и т.п.)

                                                                  Победила программа размером (кажется) 19 байт

                                                                    0

                                                                    Сдается мне, там был разрешен loop. Тогда читаешь в CX, выводишь бакс через int21, loop, int20. Иначе никак в 19 байт не уложиться.

                                                                      +1

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

                                                                        0

                                                                        Подтверждаю — это — кратчайший путь. Когда писал io.tpu, crt.tpu и dos.tpu именно так и поступал (ну, любил я Паскаль, а "дистрибутив" достался без turbo.tpl)

                                                                    0
                                                                    сразу видна позиция программиста в крупной компании (может даже корпорации). Сверху сказали не использовать плюс в рассчетах — значит не использовать плюс в рассчетах.
                                                                      0

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

                                                                        +11
                                                                        Сверху сказали отказаться от С++, то есть буквально такой приказ:

                                                                        — Перестаньте использовать плюсы!

                                                                        Сотрудники всё запомнили и теперь программируют без сложения.
                                                                          +1
                                                                          Сверху сказали отказаться от С++

                                                                          Дело было так, пришел новый chief architect в компанию и сказал «У нас на прошлой работе плюсов небыло». Ну все и завертелось.
                                                                        +17
                                                                        auto start = now();
                                                                        sleep(a);
                                                                        sleep(b);
                                                                        return now() - start;

                                                                        Правда, я использую аж два плюса, потому что C++
                                                                          0

                                                                          Вот вы смеётесь, а у нас был китаец, который так и писал. Как увидел код, так вздрогнул.

                                                                            0
                                                                            Лучше сделать раз 10 и взять среднее, для большей стабильности.
                                                                            +1
                                                                            Прятание плюса в строки — скучно. Фокусы с логарифмами, синусами и пр — забавно, но за преобразование целых чисел в float и обратно нужно наказывать.
                                                                              0

                                                                              Не соглашусь. Есть ситуации и их много, когда нужно float преобразовать в int32 к примеру. Записать в EEPROM результат с точностью до сотых -- float * 100 и отбрасываем дробную часть. Не вижу никаких проблем. Может поделитесь опытом почему нельзя?

                                                                                0

                                                                                Во первых погрешности 2 преобразований. Во вторых - обе операции достаточно сложные.

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

                                                                              0

                                                                              Вот вам задачка для собеседования:
                                                                              Попробуйте объяснить с точки зрения здравого смысла, почему разработчик системы поставил ограничение на длину пароля сверху:

                                                                                +9
                                                                                почему разработчик системы поставил ограничение на длину пароля сверху


                                                                                а) так повелось с тех древних времен, когда пароли сохранялись в таблицу
                                                                                б) пароли до сих пор сохраняются в таблицу
                                                                                  0

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

                                                                                  +4

                                                                                  Длина СМС?

                                                                                    +1
                                                                                    При этом, когда вводишь пароль, все эти требования не высвечиваются и ты не можешь вспомнить, как именно ты угождал этим затейникам.
                                                                                      0
                                                                                      И вспоминаешь пароль только когда отчаялся, запросил смену — и вдруг видишь эту подсказку
                                                                                      +3
                                                                                      Попробуйте объяснить с точки зрения здравого смысла, почему разработчик системы поставил ограничение на длину пароля сверху:

                                                                                      Намекает на то, что разработчик системы замыслил хранение пароля в открытом строковом виде, и за это его надо пинать, — возможно даже ногами.
                                                                                        +1

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

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

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

                                                                                            Боится SQL injection :D с учетом "не пихайте пробелы в пароль"

                                                                                              0
                                                                                              На одном из предыдущих проектов у клиента упорно выбрасывалась ошибка при попытке ввести почтовый адрес в формочку. Как выяснилось, в базе под поле «номер дома» было отведено 15 символов, а на фронтенде это не проверялось.
                                                                                                0

                                                                                                Это что ж за номер был, что не влазил в 15 символов?

                                                                                                  0
                                                                                                  Клиент был из Питербурга и в поле номера дома он написал что-то вроде «Дом №7, литера А»
                                                                                                +1

                                                                                                Про 120 не знаю, знаю про 72 из своего дивного доисторического опыта в php :) Blowfish и bcrypt игнорируют остальные символы. Может что-то подобное и про 120 есть.

                                                                                                  +2

                                                                                                  Кажется, на польском тикетмастере, ограничение на длину пароля при регистрации - 20 символов, но на самом деле запоминает он только 16. Об этом он тебе любезно сообщает аж на странице смены пароля, когда ты его сбросишь, потому что не можешь залогиниться с _только что_ заведённым аккаунтом. Очень увлекательный UX

                                                                                                    0
                                                                                                    похоже, что пароль хранится в открытом виде в поле varchar(255)
                                                                                                    +2

                                                                                                    Универсальное правило для подобных головоломок и собеседований:

                                                                                                    В любой непонятной ситуации говори: «lookup-таблица»! (И начинай думать, как её применить).

                                                                                                      0

                                                                                                      Сделать список из чисел от 1 до 189 и итерироваться по нему b раз, начиная с позиции а :)
                                                                                                      (типа сложение по аксиомам Пеано)

                                                                                                        +1

                                                                                                        Вот мои решения, несколько из которых, правда, есть здесь.


                                                                                                        Заголовок спойлера
                                                                                                        def add0(a, b):
                                                                                                            return a - (-b)
                                                                                                        
                                                                                                        # =======================================
                                                                                                        
                                                                                                        def add1(a, b):
                                                                                                            return a.__add__(b) # a.__radd__(b)
                                                                                                        
                                                                                                        # =======================================
                                                                                                        
                                                                                                        def add2(a, b):
                                                                                                            def inc(a):
                                                                                                                return -(a ^ (-1))
                                                                                                        
                                                                                                            bin_a, bin_b = bin(a)[:1:-1], bin(b)[:1:-1]
                                                                                                            res_len = inc(max(len(bin_a), len(bin_b)))
                                                                                                            res = '0' * res_len
                                                                                                            bin_a = f'{bin_a}{"0" * (res_len - len(bin_a))}'
                                                                                                            bin_b = f'{bin_b}{"0" * (res_len - len(bin_b))}'
                                                                                                            zz, zos, oo = ('0', '0'), [('1', '0'), ('0', '1')], ('1', '1')
                                                                                                        
                                                                                                            for (i, (ba, bb)) in enumerate(zip(bin_a, bin_b)):
                                                                                                                if (ba, bb) == zz:
                                                                                                                    continue
                                                                                                                elif (ba, bb) in zos:
                                                                                                                    if res[i] == '0': 
                                                                                                                        res = f'{res[:i]}1{res[inc(i):]}'
                                                                                                                    else:
                                                                                                                        res = f'{res[:i]}01{res[inc(inc(i)):]}'
                                                                                                                elif (ba, bb) == oo:
                                                                                                                    res = f'{res[:inc(i)]}1{res[inc(inc(i)):]}'
                                                                                                        
                                                                                                            res = res[::-1]
                                                                                                            return int(res, 2)
                                                                                                        
                                                                                                        # =======================================
                                                                                                        
                                                                                                        def add3(a, b):
                                                                                                            if a == b:
                                                                                                                return 2 * a
                                                                                                        
                                                                                                            m = max(a, b)
                                                                                                            for z in range(m ** 2):
                                                                                                                if z - a - b == 0:
                                                                                                                    return z
                                                                                                        
                                                                                                        # =======================================
                                                                                                        
                                                                                                        def add4(a, b):
                                                                                                            if a == b:
                                                                                                                return a * 2
                                                                                                        
                                                                                                            import math
                                                                                                            a, b = min(a, b), max(a, b)
                                                                                                            c2 = round((b / math.cos(math.atan(a/b)))**2)
                                                                                                            a2b2 = c2 - 2 * a**2
                                                                                                            return a2b2 // (b - a)
                                                                                                        
                                                                                                        # =======================================
                                                                                                        
                                                                                                        def add5(a, b):
                                                                                                            # Свернул для комментария, для ответа развернуть в
                                                                                                            # {(1, 1): 2, (1, 2): 3, (1, 3): 4, (1, 4): 5, (1, 5): 6, ...}
                                                                                                            all_results = {(a, b): a + b for a in range(1, 100) for b in range(1, 100)}
                                                                                                            return all_results[(a, b)]
                                                                                                        
                                                                                                        def test(f):
                                                                                                            test_flag = True
                                                                                                            for a in range(1, 100):
                                                                                                                for b in range(1, 100):
                                                                                                                    if f(a, b) != a + b:
                                                                                                                        test_flag = False
                                                                                                                        print('error in ', a, b, f.__qualname__)
                                                                                                            return test_flag
                                                                                                        
                                                                                                        for f in [add0, add1, add2, add3, add4]:
                                                                                                            if test(f):
                                                                                                               print(f.__qualname__, 'is good') 
                                                                                                        
                                                                                                          +7
                                                                                                          Круто!
                                                                                                          Кстати, в первое мгновение я понял заголовок поста как «Как проходить собеседование если у вас нет достоинств (== положительных сторон)».
                                                                                                            0
                                                                                                            Уже было: my_first_calculator.py
                                                                                                              +2
                                                                                                              выбираем из двух чисел большее
                                                                                                              умножаем на два
                                                                                                              вычитаем из большего меньшее
                                                                                                              вычитаем из произведения разность

                                                                                                              пример:
                                                                                                              21+37=58

                                                                                                              37*2 = 74
                                                                                                              37 -21 = 16
                                                                                                              74 -16 =58
                                                                                                                0
                                                                                                                Был у меня такой вариант, но я его даже не стал писать. Т.к. он сводится к первому решению.
                                                                                                                Допустим, a > b. Тогда a * 2 = a + a
                                                                                                                сокращаем:
                                                                                                                a + a — (a — b) => a — (-b)
                                                                                                                  0
                                                                                                                  Легко заметить, что это решение работает и без выбора большего из двух слагаемых.
                                                                                                                  2а-(a-b) = a+b независимо от того, что больше — a или b.
                                                                                                                  0

                                                                                                                  @sukhe Круто было бы на GitHub сделать репозиторий и в нем папочки для разных языков. И принимать туда pr)

                                                                                                                    +1
                                                                                                                    range(max(a,b),a*b*2)[min(a,b)]
                                                                                                                      0
                                                                                                                      from time import sleep, time
                                                                                                                      
                                                                                                                      left, right = map(int, (input(), input()))
                                                                                                                      
                                                                                                                      now = time()
                                                                                                                      sleep(left)
                                                                                                                      sleep(right)
                                                                                                                      new = time()
                                                                                                                      
                                                                                                                      print(int(new - now))
                                                                                                                      
                                                                                                                        +1
                                                                                                                        Второй вариант, думаю, очевиден

                                                                                                                        Зря вы так все человечество под математиков подписали )

                                                                                                                          0

                                                                                                                          Подумал про три варианта, один - через побитовые операции автор описал, спасибо, + а ведь ещё есть

                                                                                                                          Модулярная арифметика, вангую, что можно через деление.

                                                                                                                          И еще регулярные выражения суть разложить число на цифры и собрать новое число. В принципе это можно сделать и без регулярное, токо много if или case будет

                                                                                                                            0
                                                                                                                            можно перевести в двоичный вид и по разрядам логическими операциями просуммировать как в АЛУ
                                                                                                                              0

                                                                                                                              while (a--) b-=-1;

                                                                                                                                +4

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

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

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

                                                                                                                                2. Lookup-таблица с вычисленными заранее результатами.

                                                                                                                                3. Сокрытие вызова. Здесь мы на самом деле вызываем всё тот же add что и при использовании оператора "плюс", но делаем это без использования оператора. Решений также несколько, все они сильно зависят от конкретного ЯП.

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

                                                                                                                                5. Использование внешнего источника. Реализация нужной операции берётся из среды выполнения — окружения или библиотек.

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

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

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

                                                                                                                                  0
                                                                                                                                  четвертый пункт это подвариант первого пункта
                                                                                                                                  0
                                                                                                                                  plus = lambda a,b: (a==b) and  2*a or int((a**2-b**2)/(a-b))
                                                                                                                                    0

                                                                                                                                    Вероятно "правильными" вариантами являются "минус на минус", сложение степеней, sum и, например, operator или eval, хотя мне больше нравится по длине строки. Это натолкнуло на ещё один простой ответ - цикл по b и a += 1, ведь это же другой оператор?

                                                                                                                                    А если так, то можно и ещё проще: a += b

                                                                                                                                      0
                                                                                                                                      Ребята, мы тут в корпорации тоже решили оказаться от плюсов. Подскажите, какой из вариантов самый быстрый и жрет мало памяти???
                                                                                                                                        +1
                                                                                                                                        Видишь ошибку? Она здесь есть. И на интервью её заметят. Но не будем пока отвлекаться — в конце объясню.
                                                                                                                                        Это тестирование кратковременной памяти, или будет вторая статья в цикле?
                                                                                                                                          +2

                                                                                                                                          Без плюса? Ха! Можно сложение сделать даже без самих чисел! :)


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


                                                                                                                                          Навскидку:


                                                                                                                                          # Вспомогательная функция
                                                                                                                                          rec = lambda f: f(f)
                                                                                                                                          
                                                                                                                                          # Определение «числа»
                                                                                                                                          zero = lambda: None
                                                                                                                                          succ = lambda x: lambda: x
                                                                                                                                          
                                                                                                                                          # Сложение «чисел»
                                                                                                                                          add_num = rec(lambda r: lambda x, y: x if not y() else r(r)(succ(x), y()))
                                                                                                                                          
                                                                                                                                          # Преобразование в «число»
                                                                                                                                          to_num = lambda n: (lambda l: rec(lambda r: lambda a: succ(a) if not next(l) else r(r)(succ(a))))(iter(reversed(range(n))))(zero)
                                                                                                                                          
                                                                                                                                          # Преобразование из «числа»
                                                                                                                                          ln = lambda i: next(iter(next(iter(reversed(list(enumerate(i)))))))
                                                                                                                                          from_num = lambda num: ln(rec(lambda r: lambda n, l: l if not n() else r(r)(n(), [*l, []]))(num, [[]]))
                                                                                                                                          
                                                                                                                                          # Сложение
                                                                                                                                          add = lambda x, y: from_num(add_num(to_num(x), to_num(y)))
                                                                                                                                          
                                                                                                                                          # Проверяем
                                                                                                                                          add(5, 3) # выведет 8

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

                                                                                                                                            0
                                                                                                                                            Разве что этого работодателя будут звать David Beazley.

                                                                                                                                            Вообще, конечно, впечатляет.
                                                                                                                                            +1

                                                                                                                                            Сходу вспомнилось

                                                                                                                                            abs(-a-b)

                                                                                                                                            ~(-a-b)+1

                                                                                                                                              0
                                                                                                                                              Python — это язык программирования, с помощью которого в начале 21 века складывали два целых числа.
                                                                                                                                              На всякий случай
                                                                                                                                              Барометр — это прибор, с помощью которого в конце 20 века измеряли высоту башен. (с)
                                                                                                                                                +1
                                                                                                                                                a = 7
                                                                                                                                                b = 9
                                                                                                                                                while a:
                                                                                                                                                  a = ~-a
                                                                                                                                                  b = -~b
                                                                                                                                                print(b)
                                                                                                                                                # 16
                                                                                                                                                  0
                                                                                                                                                  Великолепно!
                                                                                                                                                  0
                                                                                                                                                  Вариант использовать список предвыделенных интов (которые от -5 до 256), взять адрес a и пробежаться по списку циклом из b раз уже был? :)
                                                                                                                                                    0
                                                                                                                                                    «Три точки в первой строке — это Ellipsis?»
                                                                                                                                                    Да. Объект-заполнитель, который здесь используется вместо pass. Появился в последних версиях.

                                                                                                                                                    Интересно, начиная с какой?
                                                                                                                                                      0

                                                                                                                                                      Точно версию не скажу, но в Python 2.7 многоточие уже было, но можно было использовать только при индексирования. Начиная с Python 3.0 (декабрь 2008 года) многоточие уже можно использовать как самостоятельный объект.

                                                                                                                                                      Ну и стоит добавить, конечно, что многоточие (объект) конечно же не является заменой pass (элемент синтаксиса) и вводился совсем для других целей.

                                                                                                                                                      0

                                                                                                                                                      Если у вас нету плюсов - пишите на чистом Си. Ну или собирайте компилятор плюсов самостоятельно)

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

                                                                                                                                                      Самое читаемое