singlepost

Головоломка от Intel (первым решил Anton RichDad Kononov) << На главную или назад  

Intel разослали вот такую вот головоломку:

Дано число состоящее из n битов. Нужно выяснить является ли это число целой степенью двойки.
У вас есть все элементарные действия, такие как сложение, вычитание, сдвиг, and, or, xor, nand, not и т.д. и т.п. Все эти действия делаются за О(1) сразу на все n битов. Умножение и деление в этот список не входят.

Предложите оптимальный по скорости алгоритм.

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

67 ответов в теме “Головоломка от Intel (первым решил Anton RichDad Kononov)”

  1. 42
    Павел Потапов ответил:

    Самый простой варинат:

    ((x – 1) & x) == 0

  2. 41
    Борис Нишлюк ответил:

    это один из простых вариантов. Приведённый здесь вариант ничуть не хуже.

  3. 40
    Борис Нишлюк ответил:

    не понял вопроса.

  4. 39
    Денис Товстык ответил:

    Если задача математическая и не связана с процессорами зачем брать и проверять 0100 ?

  5. 38
    Борис Нишлюк ответил:

    Anton RichDad Kononov: Да, это верное и оптимальное решение :) Пздравляю!

  6. 37
    Антон Кононов ответил:

    легкотня какая.

    вот если узнать является ли число суммой двух чисел-степеней двойки…
    ;) там чуть посложнее

  7. 36
    Борис Нишлюк ответил:

    Ты не против того как я изменил название темы?

  8. 35
    Антон Кононов ответил:

    :D

    хех) не против. еще есть загадочки?

  9. 34
    Борис Нишлюк ответил:

    Есть. Сейчас создам топик.

  10. 33
    Антон Кононов ответил:

    Владимир, ты перебираешь?

    хотя мой алгоритм сложился бы так:
    ((not x)+1) AND x = x
    условие для степеней двойки

  11. 32
    Борис Нишлюк ответил:

    Anton RichDad Kononov, я не понял, 111100000 and 000100000 = 000100000?

  12. 31
    Владимир Щербина ответил:

    #28
    если угодно называть ответы перебором, то да.
    да, мой последний вариант по сути идентичен

  13. 30
    Борис Нишлюк ответил:

    Vladimir Sherbina, это опять не верно. Например для числа из 5 битов равного 8. Проверяй алгоритмы прежде чем постишь их.

  14. 29
    Антон Кононов ответил:

    >Anton RichDad Kononov, я не понял, 111100000 and 000100000 = 000100000?

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

  15. 28
    Антон Кононов ответил:

    >да, мой последний вариант по сути идентичен

    не совсем. берем число 0100 и прогоняем твой алгоритм (not x) + 1 == x

    получаем not x = 1011
    1011 + 1 = 1100

    это явно не равно 0100

  16. 27
    Борис Нишлюк ответил:

    а… чтото я погнал :) Смотрю на and, а думаю об or.

    Так, секунду…

  17. 26
    Владимир Щербина ответил:

    (x!=1) and ((x<<1)==0)
    х – это наше число

  18. 25
    Борис Нишлюк ответил:

    #20, у тебя есть любое число. Взять число это элементарное действие.

    #21, неверно. Например, если х=1, х=8.

    ps: Никакой перегрузки или отрицательных чисел тут нет. Если вы сдвигаете число 16 в лево то получите число 32, даже если изначально было только 4 бита.

  19. 24
    Антон Кононов ответил:

    ладно, допустим число ноль у меня есть (в любом процессоре оно есть просто потому что есть)
    тогда мой алгоритм будет в 4 шага:
    1) B = NOT 0 (получим все 1 в разрядах, но на некоторых процессорах на целочисленных операциях можно делать ноль минус один и опять получим все 1, только не спрашивайте где взять 1)
    2) Y = X xor B
    3) Z = Y – 1
    4) ANS = Z AND X
    если ANS=X тогда – число степень двойки

  20. 23
    Борис Нишлюк ответил:

    #20, кстати операция not делает то, что ты хотел сделать с хоr 11111…1

  21. 22
    Борис Нишлюк ответил:

    Алгоритм ещё не проверял, но нет никакой связи с процессорами. Это математическая задача.

  22. 21
    Антон Кононов ответил:

    #22 тогда если я могу взять любое число, то три шага

    поясняю суть алгоритма:

    если число – это степень двойки, то все разряды нули кроме одного
    например 000100000

    теперь инвертируем его (например как я через XOR, ну или через NOT)
    получим 111011111

    теперь прибавим 1
    получим 111100000

    теперь к полученному сделаем AND с исходным числом
    получим 000100000
    ;)

  23. 20
    Владимир Щербина ответил:

    а если вот так:
    (not x) + 1 == x
    ?

  24. 19
    Борис Нишлюк ответил:

    Я пока плохо представляю как будет работать бинарный поиск в этом случаи, но даже если это и возможно то мы имеем О(log(n)). Не плохо… но может ктото придумает алгоритм по оптимальней?

  25. 18
    Сильвестр Сталлоне ответил:

    Это понятно, скорее всего есть какая-то операция типа xor или nand (вот я уже не помню, что это значит даже), которая дает какой-то результат лишь если только одна единица среди n. Соответственно её надо ко всем применить за O(1), может быть пару таких операций – и сверить результат с нужным.

  26. 17
    Антон Кононов ответил:

    я бы делал так (допустим X – это наше число):
    1) Y = X XOR 111…111 (все разряды 1) – так мы инвертируем число
    2) Z = Y + 1
    3) ANS = Z AND X
    если ANS=X тогда это число – степень двойки
    три шага получается O(3)

  27. 16
    Борис Нишлюк ответил:

    Три шага – это О(1), оптимальней не возможно. Но где ты возьмёшь число 1111….1? Чтобы составить его тебе нужно О(n) шагов. Правильность алгоритма, кстати, не проверял. Желательно объяснить почему алгоритм должен работать, т.к. проверять чужие идеи всегда очень сложно.

  28. 15
    Антон Кононов ответил:

    ну хорошо, а число ноль у меня хоть есть?

    если есть, то нет проблем сделать из него все единицы

  29. 14
    Павел Потапов ответил:

    #10 Есть такие числа, которые делятся на 2, но не являются степенями двойки…

    ЗЫ Задача достаточно тривиальная, надо только немного подумать :)

  30. 13
    Леонид Максимов ответил:

    #11 это модно – разговаривать с собой?

  31. 12
    Борис Нишлюк ответил:

    Более того число 1 не делиться на два, младший бит равен 1, а всё равно это целая степень двойки.

    Задача эта может и тривиальная, но не простая :)

  32. 11
    Владимир Щербина ответил:

    видимо, #10 – это ответ мне. я запостил сообщение и сразу удалил, потому что пришло озарение и я понял, что написал чушь :)

  33. 10
    Борис Нишлюк ответил:

    Ну, уже прогресс :) Ладно, небольшой намёк. Оптимальный алгоритм работает быстрее чем О(n) :)

  34. 9
    Леонид Максимов ответил:

    >> Предложите оптимальный по скорости алгоритм.

    самое простое – бинарный поиск. то есть использовать для поиска выражения вида 1<<(n>>p)-1<<o

  35. 8
    Борис Нишлюк ответил:

    Да, подправил задачку. Все элементарные действия выполняются за О(1) сразу на все n битов.

  36. 7
    Сильвестр Сталлоне ответил:

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

  37. 6
    Борис Нишлюк ответил:

    О! Это уже верно. Пол задачи щитай решил, осталось предложить оптимальный алгоритм.

  38. 5
    Сильвестр Сталлоне ответил:

    Правильный ответ – первый бит единица, а остальные нули %)
    Доказательство элементарное =) Хотя наверняка это не решение, а только "указание".
    Хз как побитово работать с числами и какой из способов быстрее. На проверку каждого бита по условию задачи уйдет O(1), а всего O(n), но я не уверен, что нет способа быстрее)

  39. 4
    Борис Нишлюк ответил:

    На самом деле MSB равный еденице это не обязательное условие, но ты на верном пути :)

  40. 3
    Ричард Столлман ответил:

    Если младший бит установлен в 0 значит является. :)

  41. 2
    Сильвестр Сталлоне ответил:

    По-моему, младший бит покажет лишь, делится ли число на 2, а не является ли степенью 2х)

  42. 1
    Сильвестр Сталлоне ответил:

    Т.е. младший бит – 0 – это необходимое, но недостаточное

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