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

    +68

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    // Возвращает квадрат натурального числа
    // 4^2 = 1 + 3 + 5 + 7
    int sqr(int n) {
    	int result = 0;
    	for(int i = 1, a = 1; i <= n; i++, a = a + 2) result += a;
    	return result;
    }

    Нестандартные решения - залог успешности проекта.

    Запостил: Gouvere, 08 Декабря 2014

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

    • А ведь мог бы и ^ переопределить. А еще, как вариант, можно было бы просто сначала найти все простые множетели, а потом каждый из них удвоить.
      Ответить
      • > можно было бы просто сначала найти все простые множетели, а потом каждый из них удвоить.
        Какие простые множители? Можно поподробнее?
        Ответить
        • Разложить число на простые множители, удвоить порядок каждого, и перемножить всё это, чтобы получить квадрат.
          Ответить
          • >Разложить число на простые множители, удвоить порядок каждого,
            То есть возвести множетель в кважрат?
            Но ведь тогда задача сводится к предыдущей. Не понимаю.
            Ведь оп считает вторую степень числа через суммирование.
            Ответить
            • Ну а в этом случае мы:
              1. Получаем сверхэкспонентное время.
              2. Используем символьную арифметику для нахождения квадрата (мы же копируем выражение, а не значение).
              Ответить
              • >1. Получаем сверхэкспонентное время.
                Во. С такой точки зрения принимается.

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

                И. Важно сделать это парой функций, то есть обобщить для любой вложенности.
                Ответить
                • > обобщить для любой вложенности
                  Функция hyper(), которая при n=0 - инкремент, при n=1 - сложение, при n=2 - умножение, при n=3 - степень и т.п.? Забыл, как она правильно называется ;(
                  Ответить
                  • Вот она: https://ru.wikipedia.org/wiki/Гипероператор
                    Ответить
                    • Вот она, однострочная функция мечты с запредельной сложностью:
                      var H = function (op, a, b){
                          return op<1?b+1:b<(1+(op>1))?a:H(op-1,a,H(op,a,b-1));
                      };

                      H(0,3,9) // инкремент 9
                      H(1,3,5) // 3+5
                      H(2,3,5) // 3*5
                      H(3,3,5) // 3**5
                      Ответить
                      • Можно еще функцию аккермана пильнуть. У нее сложность запредельней запредельной запредельности. Вот только ее некуда применить в контексте этого треда.
                        Ответить
                        • >Можно еще функцию аккермана пильнуть. У нее сложность запредельней запредельной запредельности.
                          Блин. Так это практически она и есть, я там ниже в спойлере еще вчера её упоминал.
                          Только у Аккермана для джвух, а у меня для трёх:
                          >H(op-1,a,H(op,a,b-1))
                          Сравните, http://upload.wikimedia.org/math/f/8/2/f826ff51d40963b01fd8fee2dbe8ff0a.png

                          Проблема в том что стек быстро заканчивается.
                          Ответить
                        • Дано: интерпретатор Brainfuck, принимающий на вход битовый массив со входными данными, который также служит ЗУ. *
                          Сделать генератор кода, который будет вычислять гиперфункцию произвольных двух чисел и записывать ответ в переданный массив.

                          *Задача повышенной сложности (в O-нотации).Полагаю такой способ будет еще более ресурсоёмким.
                          Ответить
                          • "Остапа несло... Остап не ел три дня, и его красноречию не было предела" (ц)
                            Ответить
                          • > интерпретатор Brainfuck
                            Кстати, а почему до сих пор нет AES на брейнфаке?
                            Ответить
                            • А для Brainfuck есть какое-то пособие "как брейнфак превратить в язык", где подробно расписано хотя бы о том, как он соответствует ассемблеру? Я видел на Википедии несколько примеров, но они поверхностны (скажем, сложить два числа - не значит сложить два вектора или два числа в произвольных местах в памяти) и напоминают цитату с баша о методичке по C++, простых примерах и синхрофазотроне в качестве задания.

                              Если про пару десятков принципов ООП сложной жабы надо прочитать 0..2 книжки, а про философию простого хаскеля - 5..20 книжек, то про простейший брейнфак нужно читать 20..100 книг, чтобы писать одни и те же программы.

                              После #14528 можно ожидать и AES на брейнфаке.
                              Ответить
                              • Ну на то он и брейнфак, чтобы ебать моск.
                                Ответить
                              • > как он соответствует ассемблеру?
                                по специальности "математик, системный программист" машину Тьюринга изучают чуть ли не первой
                                Ответить
                              • > как он соответствует ассемблеру
                                [ ] while (*p) { ... }
                                +   ++(*p)
                                -   --(*p)
                                <   --p
                                >   ++p
                                .   putc(*p)
                                ,   *p = getc()
                                Как из этого собрать xor, shr и rol - думай сам :)
                                Ответить
                          • Дано: Hyper(f, x, n) — оператор, вычисляющий производную n-го порядка функции f по переменной x (при отрицательном n вычисляющий первообразную порядка (-n)).

                            Требуется: придумать непротиворечивое определение Hyper(f, x, n) на случай нецелых значений n и, пользуясь только интерпретатором Brainfuck, найти символьное выражение Hyper(f, x, √2̅) для основных тригонометрических функций.
                            Ответить
                            • Надо такую автокопчу на гк запиливать, в политотредах.
                              Ответить
                  • Да,
                    Блин, пример не в ту ветку попал:
                    http://govnokod.ru/17276#comment258717
                    Главное — то чтоб эта функция наиболее неоптимально реализована: через понижение порядка самой себя.
                    Ответить
            • Задача сводится не к предыдущей (возведению произвольного числа в квадрат), а к двум подзадачам:
              1) возведению простого числа в энную степень
              2) перемножению пачки взаимнопростых чисел
              Ответить
              • Проблема вашей с wvxvw идеи заключается в том что сверхэкспонентная сложность достигается не всегда.
                Нет ничего хуже чем нестабильный по сложности алгоритм. В оп коде сложность предсказуема.

                А вдруг злоумышленник будет присылать для возведения в степень специально подобранные простые числа.
                Что тогда? Ведь sqr тогда сведется к тривиальному возведению в квадрат.
                В этом случае будут простаивать проплаченные наперёд вычислительные мощности и теряться деньги.

                Чтобы не понести убыток, я рекомендую добавить элегантное решение добавить if и проверить n на простоту.
                if (isPrime(n)) использовать формулу n*n-1=(n-1)*(n+1)
                n-1 и n+1 — гарантированно составные числа (при n>4)
                и уже их разбить на множители и перемножать.

                Таким образом вы защититесь от prime-атак и минимизируете убытки.
                Ответить
        • Фундаментальная теорема теории чисел говорит, что любое число можно разложить на простые множители. Например 36 = 2 * 2 * 3 * 3. Квадрат любого числа в таком случае будет просто повторение этого произведения еще раз: 36^2 = (2 * 2 * 3 * 3) * (2 * 2 * 3 * 3) = 1296.
          Или по-русски это не простые множители (prime factors)?
          Ответить
          • >Фундаментальная теорема теории чисел говорит, что любое число можно разложить на простые множители.
            >Квадрат любого числа в таком случае будет просто повторение этого произведения еще раз: 36^2 = (2 * 2 * 3 * 3) * (2 * 2 * 3 * 3) = 1296.
            Ну это всё копетанство.

            Меня насторожило:
            > а потом каждый из них удвоить.
            Удвоить, по-русски, это обычно умножить на джва.
            Ответить
          • Что я хочу вызвать
            var calc=function(op, count){../*говняно-рекурсивная реализация через понижение count, when count=0 понижение порядка op*/...};
            Где op - операция.
            op = 1 - сложение с count
            op = 2 - умножение на count
            op = 3 - возведение в степень count

            var sqr=calc(3,2);
            f(5)=25;
            Блджад что-то похожее на Аккермана получается. Переизобрёл велосипед.
            Ответить
      • не мог, справа или слева должен быть класс
        Ответить
    • Вот, от безделья родился еще такой вариант:
      function logSquare(n) {
          var shift = Math.ceil(Math.log(n) / Math.log(2)), 
              upperBound = n << shift,
              diff = (1 << shift) - n;
          return upperBound - n * diff;
      }
      Ответить
    • Байтоебство..
      int sqr(int n) {
          int a = n;
          long long b = n;
          long long c = 0;
          for (int i=0; i<32; i++) {
              (a & 1) && (c += b<<32);
              a >>= 1;
              c >>= 1;
          }
          return c;
      }

      http://ideone.com/tMEsSq
      Ответить
      • Можно и не считать до 32:
        function shiftSquare(n) {
            var sum = 0, i = 0, copy = n, next;
            while (n) {
                next = n >> 1;
                (n & 1) && (sum += (copy << i));
                n = next;
                i++;
            }
            return sum;
        }
        Ответить
        • Точно. Черезчур уж я придерживался оригинального машинного алгоритма.
          Ответить
    • Где здесь C++, Gouvere?!
      Ответить
      • for(int i = 1, a = 1; i <= n; i++, a = a + 2) result += a;

        В этой строчке есть C++.
        Ответить
        • Скорее в этой строчке есть C99.
          Ответить
          • Видимо, я отстал от жизни. Думал, что в Си можно объявлять переменные только в начале блока. А тут оказывается еще в 2000 вышел стандарт, поддерживающий такую няшую вещь.
            Ответить
          • Орлы? Си поддерживает объявление с инициализацией переменной?
            Ответить
            • main() {
              	printf("Hello!");
              	int a = 123;
              	printf("%d", a);
              
              	return 0;
              }


              Во всяком случае Visual Studio 2013 не ругается на это.
              Ответить
              • Вот Visual Studio 2013 как раз С не поддерживает.
                Ответить
                • >Вот Visual Studio 2013 как раз С не поддерживает.
                  Наоборот же.
                  Это первая версия студии, которая худо-бедно поддерживает C99.
                  Ответить
                  • Лень качать, но там что - правда массивы переменной длины запилили? Тогда грац.
                    Ответить
                    • >Лень качать
                      Ёпты, ну погуглите
                      http://blogs.msdn.com/b/vcblog/archive/2013/07/19/c99-library-support-in-visual-studio-2013.aspx

                      >там что - правда массивы переменной длины запилили?
                      Конкретно эту фичу нет. Но хотя бы в хедеры внесли функции, и то радует.
                      http://msdn.microsoft.com/en-us/library/vstudio/zb1574zs(v=vs.120).aspx
                      Ответить
                      • Ссылку то я нагуглил, но там
                        >To summarize, we added declarations and implementations for missing functions in the following headers
                        чисто заголовки добавленные, а про функции языка ничего.
                        Насколько я знаю массивов переменной длины в VS нет, потому что в С++ они не нужны, а для VS важнее поддержка С++.

                        И в комментах к статье это вроде подтверждают. Так что нет, VS не поддерживает С99.
                        Ответить
                        • Ну да, они добавили их только из-за С++11.
                          >Так что нет, VS не поддерживает С99.
                          Я сказал "худо-бедно". Если так разобраться gcc тоже не все фичи C99 поддерживает.
                          Ответить
                          • >Я сказал "худо-бедно".
                            А я сказал "не поддерживает".
                            Поэтому использовать его для проверки совместимости со стандартом нет смысла.
                            В gcc может тоже не все поддерживается, но у VS вообще своя, особая атмосфера.
                            Ответить
                • Если бы она не поддерживала Си, мне бы компилятор все руки переломал за то, что я не указал тип возвращаемого значения main.
                  Ответить
                  • А, ну это кстати тоже не в его пользу - в С99 implicit int уже нет, должна ругаться.
                    Ответить
                    • C99 является большей частью обратно совместимым с C90, но вместе с тем в некоторых случаях является более жёстким. В частности, объявление без указания типа больше не подразумевает неявное задание типа int. Комитет по стандартизации языка Си решил, что для компиляторов будет более важным определять пропуск по невнимательности указания типа, чем «тихая» обработка старого кода, полагавшаяся на неявное указание int. На практике же, компиляторы могли определять неуказание, но также допускали, что это int и продолжали компиляцию программы.
                      https://ru.wikipedia.org/wiki/C99
                      Ответить
                      • >На практике же,
                        Ну мы что тут, практики что ли собрались?
                        Ответить
                      • А это опцией не отключалось?
                        Ответить
        • Тогда уж:
          for(int С = 1, a = 1; С <= n; С++, a = a + 2) result += a;
          Ответить
    • видимо метод еще не тестировали
      sql(-2) = 0
      отправить на доработку
      Ответить
      • Написано же: натурального. А -2 ∈ (ℤ\ℕ).
        Ответить
      • FIXED: http://codepad.org/bRvsD37a
        short чисто для ускорения - сервак не даёт проге достаточно времени, чтобы просчитать int (http://codepad.org/M9WfLzE8).
        Ответить
        • Главное теперь чтобы никто тест с -1 не придумал)))
          Ответить
    • int succ(int a){return a+1;}
      int ispred(int a,int b){
      	if(succ(b)==a)return b;
      	return ispred(a,succ(b));
      }
      int add(int a,int b){
      	if(!b)return a;
      	return add(succ(a),ispred(b,0));
      }
      
      int sqr(int n){
      	int o=0,i,a;
      	for(i=1,a=1; i<=n;i=succ(i),a=succ(succ(a))){
      		o=add(a,o);
      	}
      	return o;
      }
      Ответить

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