1. C++ / Говнокод #13852

    +81

    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
    #include <iostream>
    #include <cstdlib>
    using namespace std;
    
    int bin_search(int *A, int key, int low, int high){
      if (low > high){
          return 0;
      }
      int mid = ( low + high ) / 2;
      if (A[mid] == key)
        return mid+1;
      else if( A[mid] < key)
        bin_search(A, key, mid + 1, high);
      else if (A[mid] > key)
        bin_search(A, key, low, mid - 1);
    }
    
    int main()
    {
        int n, k;
        cin >> k >> n;
        int A[n-1];
        for (int i = 0; i < n; i++)
        {
            cin >> A[i];
        }
            cout << bin_search(A, k, 0, n);
    }

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

    Запостил: aesc_smirnov, 26 Сентября 2013

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

    • int n, k;
          cin >> k >> n;
          int A[n-1];
      Нестандартное (пока) говно.

      А в чём баг заключается?

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

      Не работает на не отсортированных массивах?
      Так и не должен.

      Ну и еботня с индексами и указателем на оригинальный массив вместо двух указателей — тоже говно.
      Ответить
      • Он просто по тестам не проходит, я не пойму почему :(
        Ответить
      • и не будет стандартным же
        Ответить
        • Потому что опасно и ненужно ;)

          Оно, конечно, иногда дает копеечку перфоманса, если на n наложены ограничения, и оно невелико, да и покороче, чем вызов alloca... Но толпы обезьян, которые побегут это юзать (т.к. короче чем std::vector), а потом начнут вопить что у них порвало стек, нивелируют все преимущества ;)
          Ответить
        • Так обрезанные VLA в C++14 же вводят
          Ответить
    • Требуется найти число K в упорядоченном массиве из N элементов и
      определить чему равен номер соответствующего элемента массива.
      Если элемент не найден, то вывести 0.

      Входные данные
      В первой строке расположено искомое число К.
      Во второй - количество элементов в массиве N <= 10000.
      Далее расположены N целых чисел, упорядоченных по возрастанию.

      Выходные данные
      Выведите наименьший номер найденного значения, или 0, если элемент не найден.
      Ответить
    • 1. A - это не массив из n элементов, это питушня какая-то.
      2. mid принимает питушарские значения.
      Ответить
      • как это исправить?
        Ответить
        • 2. Понять, при каких условиях mid выходит за границы массива. Искоренить эти ситуации.
          Ответить
          • Что-то сомнительно, что он выйдет (если учитывать, что в строке 27 баг уже пофиксили, и там n-1, а не n)...

            Переполнение и залет в минус будет только на 16-битном компилере при n в районе 32к, или на 32-битном при n в районе двух лярдов. Оба случая маловероятны.

            Или я совсем туплю?
            Ответить
            • вы не видите где может быть баг? потому что он на первом тесте валится (
              Ответить
              • Ну за исключением того что нашли ниже - не вижу. В упор.

                Значит, скорее всего, или ввод или вывод багует. На контрольном примере, который в задании, все работает?
                Ответить
                • ага
                  Ответить
                  • А ну да. На выхлопе нет перевода строки. std::endl добавляй, должно пролететь :)

                    P.S. Что-то косяки настолько простые, что я уже давным-давно не видел их в коде, с которым работаю, и из-за этого потерял на них нюх, и тупо в упор не вижу... Что этот endl, что return, что A[n-1]... А может просто пора спать...
                    Ответить
                    • То есть cout << endl << bin_search?
                      Ответить
                      • Наоборот же ;) Блин, посмотри на выхлоп проги в нормальной консоли, поймешь куда его засунуть.
                        Ответить
                        • cout << bin_search(A, k, 0, n) << endl;
                          Ответить
                          • > n
                            n-1 же... обсуждалось же ниже.

                            Прошел?
                            Ответить
                            • ну в ручную да, но на сервере нет.
                              Ответить
                              • Откуда ты опять n выкопал?
                                Ответить
                                • int A[n-1];
                                  for (int i = 0; i < n; i++)
                                  {
                                  cin >> A[i];
                                  }
                                  cout << bin_search(A, k, 0, n-1) << endl;
                                  }
                                  Ответить
                                • int bin_search(int *A, int key, int low, int high){
                                  if (low > high){
                                  return 0;
                                  }
                                  int mid = ( low + high ) / 2;
                                  if (A[mid] == key)
                                  return mid+1;
                                  else if( A[mid] < key)
                                  return bin_search(A, key, mid + 1, high);
                                  else if (A[mid] > key)
                                  return bin_search(A, key, low, mid - 1);
                                  }

                                  int main()
                                  {
                                  int n, k;
                                  cin >> k >> n;
                                  int A[n-1];
                                  for (int i = 0; i < n; i++)
                                  {
                                  cin >> A[i];
                                  }
                                  cout << bin_search(A, k, 0, n-1) << endl;
                                  }
                                  Ответить
                                  • int A[n] же.
                                    Ответить
                                  • int A[n-1]; //Правильно A[n]

                                    Проверь на данных:
                                    4
                                    8
                                    1 4 4 4 4 4 4 9
                                    и ты обнаружишь, что твоя программа не выдаёт 2, как должна.

                                    Это цена велосипедостроительства.
                                    Ответить
                                    • она и с A[n] выдает 4 а не 2
                                      Ответить
                                      • Я починил возможную причину повреждения стека и указал на недоработку алгоритма в целом
                                        Ответить
                                    • > как должна
                                      Если там есть такой тест - то условие, имхо, неполное. Тут же не сказано upper bound искать, lower bound, или же вообще любое подходящее:

                                      найти число K в упорядоченном массиве из N элементов и
                                      определить чему равен номер соответствующего элемента массива
                                      Ответить
                                      • > Выходные данные
                                        > Выведите наименьший номер найденного значения, или 0, если элемент не найден.
                                        Ответить
                                        • а как осуществить проверку прям в рекурсии?
                                          Ответить
                                          • http://en.cppreference.com/w/cpp/algorithm/lower_bound#Possible_implementation
                                            Разберись с принципом работы алгоритма, переделай итерацию в рекурсию и всё заработает.
                                            Ответить
                                        • > наименьший
                                          Тьфу ёпт. Точно. Всё, я пошел спать, невнимательность прёт изо всех щелей ;)
                                          Ответить
                            • завтра спрошу у препода, может сервер не заточен под такое?
                              Ответить
                              • Ну тут еще у main'а return'а нет. Но это не повлияет.
                                Ответить
            • После того, как исправили 27ю, с индексом вроде бы всё нормально.
              Ответить
      • > это питушня какая-то.
        В крестах это гццизм: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Variable-Length.html. Если хочется портабельности - лучше не юзать VLA за пределами чистой сишки ;)
        Ответить
        • int A[n-1];
          for (int i = 0; i < n; i++)

          Если int A[n-1] будет иметь n элементов, то этот гццизм - питушня. Если int A[n-1] не будет иметь n элементов, то код - питушня.
          Ответить
          • А, да про n-1 я только потом заметил, сорри. Питушня, конечно, массив на 1 элемент меньше чем надо.
            Ответить
          • выхода нет?
            Ответить
            • std::vector

              Это заодно ответ на вопрос о n>100000 и даже о n>100000000.
              Ответить
    • По идее трабла в том, что ты в строке 27 передал n, вместо n-1. А весь остальной код в bin_search рассчитан на закрытые интервалы [low; high], а не на полуоткрытые [low; high), которые получаются из-за этого бага.

      P.S. ГК это не место для исправления лаб.
      Ответить
    • Если бы все так просто!
      Ответить
      • Все проще: int A[n-1]; Тут надо n.

        Ибо сишка, а не пасцаль. Ты только что словил buffer overflow, запилив массив на один элемент меньше, чем положено :)
        Ответить
        • спасип
          Ответить
          • > спасип
            Спасибо в карман не положишь ;)

            Тест то прошел, или дальше мучаем?
            Ответить
            • хахаха, нет)
              Ответить
              • В 13 и 15 ты return проебал. Внимательней надо быть ;)

                P.S. Все, мне пора спать, таких очевидных косяков не вижу. С тебя пиво ;)
                Ответить
                • зачем там return???
                  Ответить
                  • Затем, что это не perl и не ruby какое-нибудь, где результат последнего стейтмента автоматом считается результатом функции ;)

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

                    Функция, которая должна была вернуть int, но завершилась, не сделав этого, имеет полное право вернуть мусор... Или вернуть правильный ответ... Никто не знает что именно произойдет. Это UB.
                    Ответить
            • видимо есть еще баги (
              Ответить
    • Она что с n, что с n-1 не робит
      Ответить
      • Бля, опять у вас тут питушки анскильные кукарекают. Гоните их в шею!
        Ответить
    • Алексей, задания в СУНЦ задаются для того, чтобы их делать самостоятельно. В крайнем случае можно было спросить одноклассников.
      На лекциях вам рассказывалось, какой в правом и левом бинпоиске должен быть инвариант, и что строки "if (A[mid] == key) return mid+1;" быть не должно, если нужен не произвольный элемент, равный заданному, а самый правый или самый левый.
      Ответить
    • Не твоя личная армия.
      Ответить
    • Развели стековерфловочку, понимаешь. У нас и так школьников перебор.
      Ответить

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