Няшная / Говнокод #16375 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
#include studio.h

main()
{
  uint16 final,num;
  printf(“enetr the unsigned integer 16bit number “);
  scanf(“%d”, &num);
  final= numbitset(num);
  printf(“%d”, final);
}

unit16 numbitset( unit16 x)
{
  int i, j,result, total=0;
  uint16 no,modify
  for(i=1;i<=4;i++)
  {
    j=pow(10,i);
    no= (x%(j))>>(i-1)*4;
    if(no==0)
    {
      result=0;
    }
    else if(no==1)
    {
      result=1;
    }
    else if(no==2)
    {
      result=1;
    }
    else if(no==3)
    {
      result=2;
    }
   else
   {
      result = othernum(no/4)+othernum(no%4);	
    }
    total = total+result;
  }
}

uint16 othernum( uint16 y)
{
  switch(y)
  {
    case 0:
      return(0);
      break;
  case 1:
      return(1);
     break;
  case 2:
    return(1);
    break;
   case 3:
      return(2);
      break;
   default:
    return;
    break;
  }
}

Посчитать количество значащиз битов в 16ти разрядном целом. Реальный тест на собеседовании дал такой вот результат. Угадайте откуда кандидат :)

Запостил: multilexa multilexa, (Updated )

Комментарии (116) RSS

  • > Посчитать количество значащиз битов
    Битоебы-битоебики...

    > studio.h
    > printf(
    > unit16
    > enetr
    ВОННИ, Т ПРНС?
    Ответить
  • > Угадайте откуда кандидат 🙂
    Да чего тут угадывать, все люди оттуда рождаются, не из пробирки же, право слово.
    Или ты до сих пор веришь в сказки про аиста и капусту? 🙂
    Ответить
        • Черепашка из лаб по информатике? Которая умела ползать и поднимать/опускать карандаш?
          Ответить
          • я вобще-то про аву ... но историю про инфолабчерепашку готов послушать 🙂
            Ответить
            • Если на аватарке изображен кот - значит ты говоришь с котом? А если на аватарке изображена девушка-пилот ОБЧР, то... oh shi...
              Ответить
      • > Посчитать количество значащиx битов
        int count = 0; while(num) num >>=1, ++count; return count;
        Ответить
        • >> Посчитать количество значащиx битов
          Я лох и обосрался 😉 Минусуйте коды ниже, они не ту задачу решают.
          Ответить
        • Сведем задачу к сдуру решенной:
          num |= num >> 1;
          num |= num >> 2;
          num |= num >> 4;
          num |= num >> 8;
          num |= num >> 16;
          return bit_count(num);
          Ответить
          • В 6 раз быстрее Цикла Хомячка, лол (тестил на всем диапазоне uint32_t).
            Ответить
            • ___________________________________________
              /  _____                                   \
              | /     \        ACHIEVEMENT ULOCKED       |
              | | 101 |       Битоёбству нет предела     |
              | \_____/                                  |
              \__________________________________________/
              Ответить
            • У ваших кодов есть один фатальный недостаток.
              num >>= 1;
              Число Тараса 1<<31 - 32 итерации. А можно за 1.
              Ответить
              • У кода без цикла этого недостатка нет. Он за фиксированное число тактов отрабатывает для любого N. И вообще у него логарифмическая зависимость от количества битов...

                P.S. Ну а если с циклом - согласен, от старших битов выгоднее начинать, т.к. старший бит у половины чисел установлен.
                Ответить
                    • просрать шанс всей жизни - бесценно
                      для всего остального есть национальная платёжная система
                      Ответить
                      • >для всего остального есть национальная платёжная система
                        она же только в Крыму работает
                        Ответить
                        • а зачем тебе где-либо ещё, когда крымнаш?
                          не на курорты северного кавказа же ехать, право слово
                          Ответить
                          • тут слышал, хотят мат.капитал разрешить на отдых детей в Крыму тратить
                            Ответить
                            • уже не знают в какую жопу засунуть маткапитал и крым
                              Ответить
          • Как жалко, что для размера регистра на хуй86 есть ассемблерная инструкция для сабжа, а для большего нету | за такт.
            Ответить
            • Ой, пардон, кажется, я с наибольшим значащим битом перепутал. Пусть сишкоёбы меня пофиксят.
              Ответить
          • 1) Битоёбский вариант со сведением к bit_count один хрен раза в 3 быстрее (на всём диапазоне uint32_t, т.е. фактически по матожиданию).
            2) Решает не ту задачу - считает количество ненулевых битов, а не значащих (но можно свести к нужной пачкой сдвигов, как я и поступил выше).
            Ответить
            • >битоёбский вариант со сведением к bit_count один хрен раза в 3 быстрее
              Тут нужно искать бинарным поиском, примерно так:
              if (num == 0) return 0;
                      int n = 14;
                      if (num >> 8 == 0)   { n -= 8; num <<= 8; }
                      if (num >> 12 == 0) { n -=  4; num <<=  4; }
                      if (num >> 14 == 0) { n -=  2; num <<=  2; }
                      n += num >> 15;
                      return n;
              Ответить
              • Ага, идея понятна...

                И, походу, это самый быстрый способ (3 секунды против 14 у <<240298 на всех uint32_t).
                Ответить
                • P.S. Ан нет, я криво условия записал. С правильными - 16 секунд. Все-таки branch'и не рулят ;(
                  Ответить
                  • > С правильными - 16 секунд. Все-таки branch'и не рулят ;(
                    Один можно убрать. Всё же в реальных условиях 0 может приходить чаще всего.
                    >if (num == 0) return 0;
                    Без этого должно быть быстрее.
                    Ответить
            • рискну показаться дураком, но все же - что есть значащий бит если не ненулевой?
              Ответить
              • Возьмем 0x01000001.
                Битов с единичкой тут всего 2. А значащих - аж 25 (все, кроме ведущих нулей).
                Ответить
                  • Тип того. Отбрасываешь бесполезные ведущие нули. Все остальные цифры - значащие.
                    Ответить
                    • я бы назвал это старшим разрядом. а теперь посмотрим на ваше байтоебство
                      Ответить
                      • Я бы назвал это log2 😉

                        [code language=cpp]
                        unsigned int v; // 32-bit value to find the log2 of
                        register unsigned int r; // result of log2(v) will go here
                        register unsigned int shift;

                        r = (v > 0xFFFF) << 4; v >>= r;
                        shift = (v > 0xFF ) << 3; v >>= shift; r |= shift;
                        shift = (v > 0xF ) << 2; v >>= shift; r |= shift;
                        shift = (v > 0x3 ) << 1; v >>= shift; r |= shift;
                        r |= (v >> 1);
                        [/code]

                        Источник: https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
                        Ответить
                          • [code=c++]

                            А код годный, спасибо, подрочил. Жаль, что я вчера тесты в /tmp делал и после ребута они стерлись, а заново писать лень...

                            Если у кого-то есть время и желание - сравните по скорости с другими вариантами из этого треда.
                            Ответить
  • А меня вылечат примете? 🙂
    uint32_t bit_count(uint32_t a) {
        a = (a & 0x55555555) + ((a & 0xAAAAAAAA) >> 1);
        a = (a & 0x33333333) + ((a & 0xCCCCCCCC) >> 2);
        a = (a & 0x0F0F0F0F) + ((a & 0xF0F0F0F0) >> 4);
        a = (a & 0x00FF00FF) + ((a & 0xFF00FF00) >> 8);
        a = (a & 0x0000FFFF) + ((a & 0xFFFF0000) >> 16);
        return a;
    }
    Ответить
    • P.S. А гугл подсказал более изящное решение:
      unsigned int count_1bits(unsigned int x)
      {
          x = x - ((x >> 1) & 0x55555555);
          x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
          x = x + (x >> 4);
          x = x + (x >> 8);
          x = x + (x >> 16);
          return x & 0x0000003F;
      }
      Ответить
      • И на добивание копипаста из hackers delight:
        a = a - ((a >> 1) & 0x55555555);
        a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
        a = ((a + (a >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
        Ответить
        • a = (((((a - ((a >> 1) & 0x55555555)) & 0x33333333) + (((a - ((a >> 1) & 0x55555555)) >> 2) & 0x33333333)) + ((((a - ((a >> 1) & 0x55555555)) & 0x33333333) + (((a - ((a >> 1) & 0x55555555)) >> 2) & 0x33333333)) >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
          Вроде fixed, проверьте кто-нибудь.
          Ответить
          • Ну да, тест проходит, по скорости ничем не отличается.

            Ты просто раскрыл выражение, или что-то поменял внутри?
            Ответить
            • Просто раскрыл, чтобы меня там что-то, нужно быть битоебом IV степени ;(
              Ответить
        • хорошее, годное байтоебство. мне до такого еще расти и расти
          Ответить
          • Мне тоже... hackers delight это все-таки вершины байтоёбства.
            Ответить
            • Это да. Но тут Кнут недавно выпустил том, у книжки Уоррена конкурент. Первая часть 4A как этому всецело посвящена.
              Ответить
            • http://www.cs.utsa.edu/~wagner/knuth/
              Скачать бесплатно без регистрации и смс.
              Удовлетворит ваши самые грязные битоебские фантазии и хаки. Так же в наличии описание генерации всевозможных извращённых позиций и сочетаний.
              Ответить
              • Четвёртый том? Я безнадёжно отстал от жизни... Уже думал, что дрочить больше не на что, а тут вдруг такой сюрприз.
                Ответить
                • >Четвёртый том?
                  Еще 4-5 лет назад. Я дждесять лет ждал от Кнута именно Bitwise tricks and techniques - тема совсем не была раскрыта.
                  Но по слухам он насобирал материала как минимум на семь томов (по три книги в томе - A,B,C) - человеческой жизни не хватит. Он в каком-то томе объяснял почему рано ушёл на пенсию - университетская работа отнимала много времени.
                  Видимо и после его смерти будут издавать новые. Просто лично мне теория языков, компиляторов и лексический анализ не настолько интересны/полезны.
                  Ответить
      • У нас есть 32 однобитных числа.

        > a = (a & 0x55555555) + ((a & 0xAAAAAAAA) >> 1);
        Разобьем на четные и нечетные половинки. Сложим их. Теперь у нас есть 16 джвухбитных чисел.

        > a = (a & 0x33333333) + ((a & 0xCCCCCCCC) >> 2);
        Опять бьем и складываем, получая 8 четырехбитных.

        и т.д.

        В итоге получается одно 16 битное число, в котором лежит сумма всех исходных 1 битных (т.е. то самое количество единичек).
        Ответить
        • Это понятно. Но с такими константами можно наверное подрезать на поворотах.
          Ответить
  • нет предела байтоебству
    unsigned long bits1(unsigned long num) {
      int float_order_le = 1;
      union { unsigned int u[2]; double d; } t;
      t.u[float_order_le] = 0x43300000;
      t.u[!float_order_le] = num;
      t.d -= 4503599627370496.0;	
      return ((t.u[float_order_le] >> 20) - 0x3FF) + 1;
    }
    Ответить
        • так нолик и единичку поменять можно, а это магическое число - константа Б-га - оно неизменно)
          Ответить
          • > а это магическое число - константа Б-га - оно неизменно
            Это всего лишь 2 в 52 степени.
            Ответить
      • Кармак нашей вселенной делал плавающую магию через целочисленную.
        Это Кармак из зеркальной вселенной!1адын
        Ответить
        • >Кармак нашей вселенной делал плавающую магию через целочисленную.
          Тарас тоже много чего делал. Но видать не в ту эпоху родился.
          И вообще заебали своим Кармаком. Быстрый квадратный корень и другие хаки придумал не он. Заслуга в другом: он просто ловко воспользовался этими всеми наработками при написании движков для крутых игр и смог поднять на этом кучу денег.
          А потом еще выложил движки в опен-сорс.
          Ответить
    • Дабл состоит из 1 бита знака, 11 бит порядка и 52 бита мантиссы.

      После сборки дабла из джвух половинок получаем 43300000 XXXXXXXX, где XXXXXXXX = num. Т.е. положительное число с мантиссой 1.<двадцать ноликов><num> и порядком 0x433 - 1023 = 52 т.е. 1.<двадцать ноликов><num> * pow(2, 52), что составляет... 2^52 + num.

      В шестой строке из этого числа вычитается 2^52 и FPU нормализует число так, чтобы старшая единичка стояла перед точкой в мантиссе. Например, из числа 0xFFFFFFF мы получим 2^31 * 1.11111... Порядок получится на единичку меньше, чем нужный нам ответ.

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

      Вот и вся магия 😉
      Ответить
      • Ради чего вообще всё это затевается? Ради скорости, верно?
        Так вот полагаю передача данных в FPU и обратно будет ооочень медленной.
        Ответить
        • #240295 (просто цикл) - 1m13.371s
          #240467 (даблоёбство) - 0m21.729s
          #240298 (сведение к подсчету ненулевых битов) - 0m14.605s
          #240308 (двоичный поиск с if'ами) - 0m15.908s
          #240403 (двоичный поиск без if'ов) - 0m27.734s

          Прога: http://pastebin.com/mXV6ESvm
          Ответить
          • Сей комментарий преисполнен занудства

            А мне интересно, сколько времени было потрачено на разработку каждого алгоритма подсчета количества значащих бит. Я на цикл потратил около 30 секунд.

            К тому же, имеет значение задача, под которую алгоритм можно применить. Предположим, принесли нам гигабайт статистических данных, для которых нужно подсчитать максимальное количество значащих бит. Весь массив можно поразрядным or "запаковать" в одно слово и подсчитать его биты; тут скорость алгоритма уже не имеет такого значения. А если сами данные состоят сплошняком из нулей и единиц, то цикл с линейной сложностью отработает быстрее.

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

            Не вижу смысла в битоёбстве, короче. Вот.
            Ответить
            • > А мне интересно, сколько времени было потрачено на разработку каждого алгоритма подсчета количества значащих бит. Я на цикл потратил около 30 секунд.
              На 32 - __builtin_clz(num) где-то столько же 😉
              Ответить
            • >А мне интересно, сколько времени было потрачено на разработку каждого алгоритма подсчета количества
              Минут 5 на двоичный поиск. Думаю циклом было бы короче/понятней. А компилер бы уже развернул сам.
              Ответить
          • >#240308 (двоичный поиск с if'ами) - 0m15.908s
            А если 1-й if убрать? //if (num == 0) return 0;
            Чёто не верю что ifы сливают. Правда я особо и не старался.
            >__builtin_clz
            Некросскомпилерно
            Ответить
            • > Чёто не верю что ifы сливают.
              Ну они всего несколько процентов сливают.

              > А если 1-й if убрать?
              Где-то полсекунды убавляло.
              Ответить
        • Победителем с результатом 0m4.919s объявляется:
          return 32 - __builtin_clz(num);
          P.S. Даже если попадется платформа, на которой такой операции нет аппаратно - всяко gcc'шники задрочили этот builtin как следует...
          Ответить
    • Как-то сложно. Длинные константы - говно.
      unsigned int bits1(unsigned int num) {
         union {unsigned int asInt[2];double asDouble;} t;
         t.asDouble = (double)num;
         int n = 0x41E - (t.asInt[LE] >> 20);
         return 32- (n & 31) + (n >> 9);
      }

      http://ideone.com/rL1PXA
      Ответить
      • О_о. Почти догнал __builtin_clz!

        6.5с без проверки на 0 (иначе при нуле выдает 4) и 7.5с с ней.
        Ответить
        • Там еще пару инструкций можно смело убрать.
          Но главное что я убрал загрузку больших констант и FPU-вычитание.
          Ответить
        • Большие и непонятные числа - только чтобы нубов пугать - оооо какое хитрое байтоебство.
          А всё можно свести к очевидному и интуитивно понятному коду:
          unsigned int bits1(unsigned int num) {
             union {unsigned int asInt[2];double asDouble;} t;
             t.asDouble = (double)num; //+0.5 для коррекции
             return  (t.asInt[LE] >> 20)-0x400+2;
          }
          http://ideone.com/Swd4TW
          Ответить
      • Ииии... у нас новый победитель: 4.6с (без проверки на 0 вообще 3.4с)
        uint32_t bits6(uint32_t num) {
            if (!num) return 0;
            union {uint32_t asInt[2];double asDouble;} t;
            t.asDouble = (double)num;
            return (t.asInt[1] >> 20) - 0x3FE;
        }
        Ответить
        • > FPU
          Авотхуй (благо на x86_64 SSE есть всегда и подразумевается даже без -march/-mtune).
          _Z5bits6j:
                  xorl    %eax, %eax
                  testl   %edi, %edi
                  je      .L26
                  movl    %edi, %edi
                  cvtsi2sdq       %rdi, %xmm0
                  movsd   %xmm0, -8(%rsp)
                  movq    -8(%rsp), %rax
                  shrq    $52, %rax
                  subl    $1022, %eax
          .L26:
                  rep ret
          Ответить
          • >всяко gcc'шники задрочили этот builtin как следует...
            Плохо, негодно задрочили.
            Я в принципе так и думал.

            Может до ночи чего еще придумаю. Мы ведь еще всякие таблицы не пробовали - а это сильный кандидат.
            Ответить
            • > таблицы
              Начнем:
              uint8_t first_bit[256];
              
              uint32_t bits9(uint32_t x) {
                  if (x & 0xFF000000)
                      return first_bit[x >> 24] + 24;
                  if (x & 0x00FF0000)
                      return first_bit[x >> 16] + 16;
                  if (x & 0x0000FF00)
                      return first_bit[x >> 8] + 8;
                  return first_bit[x];
              }
              0m10.235s
              Ответить
              • Мне от ваших обсуждений захотелось нарисовать картину "Программист на отдыхе ебет байты" маслом)
                Ответить
                • Ну на работе же байты не поебешь, там другие приоритеты 😉

                  P.S. Хотя в тех же контроллерах, где 2кб флеша, 128 байт оперативки и 20МГц еще есть шанс поебать байты...
                  Ответить
                  • Все самое приятное приходится делать тайком) Ебать байты, кодить Хаски, обсирать плюсы)
                    Ответить
              • При том что задача стоит "Посчитать количество значащиз битов в 16ти разрядном целом."
                Я бы сделал табличку на 64К, или выпилил ifы нахер.
                return (x & 0x0000FF00)? first_bit[x >> 8] + 8 : first_bit[x];
                Ответить
                • >Я бы сделал табличку на 64К, или выпилил ifы нахер.
                  Тогда обсуждение затрагивало бы тему формирования этой таблички 🙂
                  Ответить
                  • Она один раз формируется. Любой из способов с этой страницы проканает. Ну либо можно чуть более оптимальное заполнение замутить. Как-то так например:
                    first_bit[0] = 0;
                    for (uint32_t i = 1, m = 0, n = 0; i<65536; ++i) {
                        if ((i & m) == 0) // битов стало больше
                            m = (m << 1) | 1, ++n;
                        first_bit[i] = n;
                    }
                    Ответить
                    • first_bit[0] = 0;
                      uint32_t offset = 0;
                      for (uint32_t bits = 1; bits <= 16; ++bits) {
                          for (uint32_t i = 0; i < (1 << (bits - 1)); ++i)
                              first_bit[++offset] = bits;
                      }
                      Ответить
        • Тэкс. Ну я ж писал это чисто для лулзов. Не люблю я ёбанный fpu, unionы. И __builtin_clz тоже.
          Алгоритм должен быть таким чтоб я мог пользоваться им в жабе, жс, питоне и остальных языках.
          Хотя машине Борманда верить нельзя - у меня когда-то ifы оказались самым быстрым что я смог придумать, но попробуем без них.
          unsigned int bits1(unsigned int x) {
             int y, m=0, n=0;
          
             y = x - 0x100;      m = (y >> 16) & 8; n +=  m; x  <<=  m;
             y = x - 0x1000;    m = (y >> 16) & 4; n +=  m; x  <<=  m;
             y = x - 0x4000;    m = (y >> 16) & 2; n +=  m; x  <<=  m;
             y = x >> 14; m = y & ~(y >> 1);
             return 14 - n + m;
          }

          http://ideone.com/scwkXl
          Ответить
  • Лично я считаю этот код оптимальным.
    Трейдофф между скоростью, читабельностью, краткостью и портабельностью (на другие языки и размеры чисел).
    int binarySearch(int x) {
       int y=0, n=1,  c=8; // поставить sizeof/2 для универсальности
       do {
          y = x >> c; 
          if (y != 0) {n += c; x = y;}
          c >>= 1;
       } while (c != 0);
       return n;
    }
    http://ideone.com/luUZxM
    Ответить
  • Ничего не понимаю. Каждый второй на сайте, неибаца хацкелист и теоретик, а это говно приходится постить мне.
    int ln(int x, int shift, int n) {
        int y = x >> shift; 
        if (y != 0) {x=y;n += shift;}
        return (shift!=0) ? ln(x,shift>>1,n): n;
    }
    int ln1(int x, int shift, int n) {
        int y = x >> shift; 
        if (y != 0) {x=y;n += shift;}
        return (shift!=2) ? ln(x,shift>>1,n): n+(x>>1);
    }
    Впрочем хотя бы один вариант должен уложится в 17 сек.
    http://ideone.com/XsIR3q
    Ответить
    • Во втором методе он тоже вызывает сам себя.
      return (shift!=2) ? ln1(x,shift>>1,n): n+(x>>1);
      fix
      Ответить
  • не думал, что тема вызовет столько интереса! а кандидат был таки из индии.
    Ответить

Добавить комментарий

Где здесь C++, guest?!

    А не использовать ли нам bbcode?


    8