1. Си / Говнокод #16375

    +136

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    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, 18 Июля 2014

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

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

      > studio.h
      > printf(
      > unit16
      > enetr
      ВОННИ, Т ПРНС?
      Ответить
    • > Угадайте откуда кандидат :)
      Да чего тут угадывать, все люди оттуда рождаются, не из пробирки же, право слово.
      Или ты до сих пор веришь в сказки про аиста и капусту? :-)
      Ответить
      • Автор не говорил, что кандидат - человек.
        Ответить
        • автор сам черепашка
          Ответить
          • Черепашка из лаб по информатике? Которая умела ползать и поднимать/опускать карандаш?
            Ответить
            • я вобще-то про аву ... но историю про инфолабчерепашку готов послушать :)
              Ответить
              • Если на аватарке изображен кот - значит ты говоришь с котом? А если на аватарке изображена девушка-пилот ОБЧР, то... oh shi...
                Ответить
                • >значит ты говоришь с котом?
                  так интереснее же
                  Ответить
              • Мы не жалкие букашки, инфолабочерепашки!
                Ответить
                • Мы не делаем какашки
                  Мы круги рисуем
                  Оу е!
                  Ответить
    • for (int i=0; i<16; count += (num>>i++) & 0x1);
      Ответить
      • Ну тогда уж while (num) { count += num & 1; num >>= 1; }
        Ответить
        • > Посчитать количество значащи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. Ну а если с циклом - согласен, от старших битов выгоднее начинать, т.к. старший бит у половины чисел установлен.
                  Ответить
                  • Тьфу блин смотрел на коды борманда и тоже написал popcnt
                    Ответить
                    • Нас не возьмут в контору multilexa ;(
                      Ответить
                      • просрать шанс всей жизни - бесценно
                        для всего остального есть национальная платёжная система
                        Ответить
                        • >для всего остального есть национальная платёжная система
                          она же только в Крыму работает
                          Ответить
                          • а зачем тебе где-либо ещё, когда крымнаш?
                            не на курорты северного кавказа же ехать, право слово
                            Ответить
                            • тут слышал, хотят мат.капитал разрешить на отдых детей в Крыму тратить
                              Ответить
                              • уже не знают в какую жопу засунуть маткапитал и крым
                                Ответить
            • Как жалко, что для размера регистра на хуй86 есть ассемблерная инструкция для сабжа, а для большего нету | за такт.
              Ответить
              • Ой, пардон, кажется, я с наибольшим значащим битом перепутал. Пусть сишкоёбы меня пофиксят.
                Ответить
          • int count = 0;
             while(num) num&=num-1, ++count; 
            return count;

            fixed
            Ответить
            • 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 это все-таки вершины байтоёбства.
              Ответить
              • 80ый левел?)
                Ответить
              • Это да. Но тут Кнут недавно выпустил том, у книжки Уоррена конкурент. Первая часть 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;
      }
      Ответить
      • http://ideone.com/RHbogP
        Ответить
      • и магии твоих чисел

        4503599627370496.0
        Ответить
        • Зато единичку и нолик в переменную вынес.
          Ответить
          • так нолик и единичку поменять можно, а это магическое число - константа Б-га - оно неизменно)
            Ответить
            • > а это магическое число - константа Б-га - оно неизменно
              Это всего лишь 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];
                  Ответить
                  • return (x > 0xFF)? first_bit[x >> 8] + 8 : first_bit[x];

                    fix
                    Ответить
                  • >Я бы сделал табличку на 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
            Ответить
        • А под DOS код рабочий?
          Ответить
    • Лично я считаю этот код оптимальным.
      Трейдофф между скоростью, читабельностью, краткостью и портабельностью (на другие языки и размеры чисел).
      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
      Ответить
      • Вполне достойная скорость - 0m16.516s
        Ответить
        • А http://govnokod.ru/16375#comment240502?
          Ответить
          • Там ответ неправильный был, лень было выяснять где именно... Поэтому на скорость не тестил.
            Ответить
            • >Там ответ неправильный был,
              До 64К - правильный.
              Ответить
    • Ничего не понимаю. Каждый второй на сайте, неибаца хацкелист и теоретик, а это говно приходится постить мне.
      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
      Ответить
      • unsigned int j=1<<1,i=0;

        а 2 не проще было написать?
        Ответить
      • Во втором методе он тоже вызывает сам себя.
        return (shift!=2) ? ln1(x,shift>>1,n): n+(x>>1);
        fix
        Ответить
    • не думал, что тема вызовет столько интереса! а кандидат был таки из индии.
      Ответить
    • s
      Ответить

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