1. JavaScript / Говнокод #24000

    +7

    1. 1
    console.log(24000);

    Запостил: 1024--, 26 Марта 2018

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

    • poor man's debug
      Ответить
    • (() => console.log)()(24000)
      Ответить
      • console.log((s=>(p=>(t=>t(n=>p(n)(p(s(t))(s(s(t)))))(t))(s(s(s(f=>x=>x)))))
          (n=>m=>f=>x=>n(a=>m(f)(a))(x)))(n=>f=>x=>f(n(f)(x)))(x=>x+1)(0));
        Ответить
        • https://www.youtube.com/watch?v=la1AN3k0NCs
          Ответить
        • OMFG. В чьих извращенных... Ах ты ж ёбанный по голове... Нет слов просто.

          Понятно что за счёт хитрый рекурсий ++x вызывается 24к раз. Но не могу это распарсить за приемлимое время.

          Это руками написано?
          Ответить
          • > Это руками написано?
            Руками, конечно.

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

            Очевидно, что для компактной записи надо как-то разложить число на множители (возможно, ложное впечатление для лямбда исчисления, но в машине Тьюринга оно работало). Далее подготовленную кашицу из числа стоит выражать через нумералы Чёрча. Приведу далее недостающие звенья:
            // 1. Простая запись нумералов Чёрча
            var succ = n => (f, x) => f(n(f, x));
            var prod = (n, m) => (f, x) => n(a => m(f, a), x);
            var three  = succ(succ(succ((f, x) => x)));
            var four = succ(three);
            var five = succ(four);
            var n = three(n=>prod(n, prod(four, five)), three); // 24000 = (4*5)**3 * 3
            console.log(n(x=>x+1, 0));
            
            // 2. Замена переменных на аргументы: var A = B; f(A) на (A => f(A))(B)
            console.log(
              (succ => (prod => (three =>
                three(n=>prod(n, prod(succ(three), succ(succ(three)))), three))
                  (succ(succ(succ((f, x) => x)))))
                    ((n, m) => (f, x) => n(a => m(f, a), x)))
                      (n => (f, x) => f(n(f, x)))
                        (x=>x+1, 0));
            
            // 3. Замена функций от двух аргументов на честные лямбды от одного аргумента
            // 4. Замена имён переменных на однобуквенные (s=succ, p=prod, t=three)
            Ответить
            • Возведение в степень тоже можно было как нумерал напесать.
              Ответить
              • Действительно.
                Оставим для следующего раза, когда сразу будут честные лямбды.

                А тут я и умножение записал громоздко:
                var prod = (n, m) => (f, x) => n(a => m(f, a), x); // у меня
                var prod = (n, m) => (f, x) => n(f, m(f, x)); // надо
                Ответить
                • А нет, с умножением всё нормально.
                  Надо n => m => f => n (m (f)), а не то, что я написал с пометкой "надо" (я там сложение написал).
                  При использовании функций от двух аргументов как раз неизбежно выходит то, что у меня.
                  Ответить
                • С учётом честной записи
                  var prod = n => m => f => n(m(f));
                  var pow = b => e => e(b);
                  var n = prod(pow(prod(succ(three))(succ(succ(three))))(three))(three);

                  Заинлайнив pow и сократив имена, получаем
                  console.log((s=>(p=>(t=>p(t(p(s(t))(s(s(t)))))(t))(s(s(s(f=>x=>x)))))
                    (n=>m=>f=>n(m(f))))(n=>f=>x=>f(n(f)(x)))(x=>x+1)(0));
                  Ответить
                  • >Заинлайнив pow
                    >Возведение в степень тоже можно было как нумерал напесать.

                    Думаю тут нужна гипероператорная функция Аккермана для того чтоб окончательно запутать читателя. pow и prod — частые её случаи.

                    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
                    Ответить
                    • Мне кажется, тут и так абстракция довольно любопытная. Питухи Чёрча производят аналогичные вычисления без читерской рекурсии и кобенаторов неподвижных вореций. Здесь как в Советской России число само считает выражение.

                      Особенно радует повышение дзена, когда с ростом питульности гипероператора из формулы выкидывается очередной лишний кусок, что на последней итерации даёт самую простую формулу из возможных:
                      PLUS := λn.λm.λf.λx.m f (n f x)
                      MULT := λn.λm.λf.   m   (n f)
                      POW  := λn.λm.      m    n

                      Хотя, на реализацию гипероператора в таких терминах интересно было бы посмотреть.
                      Ответить
                      • >Особенно радует повышение дзена, когда с ростом питульности гипероператора

                        Смысл очень простой: он применяет n раз ф-цию f над m.
                        То есть n раз инкремент 0 — n
                        То есть n раз сложение m — m*n
                        То есть n раз умножение m — m**т

                        Думаю реализация будет такая же во всех случаях.
                        > prod = (n, m) => (f, x) => n(f, m(f, x)); //

                        >H(op-1,a,H(op,a,b-1));

                        Только нужно делать декремент на функции:
                        POW-- = MUL
                        MUL-- = ADD
                        ADD-- = INC
                        Ответить
                      • >производят аналогичные вычисления без читерской рекурсии и кобенаторов неподвижных вореций

                        Так это оно и есть, только в частной форме.

                        >succ(succ(succ(

                        Рекурсия руками.

                        >f(n(f, x))
                        >(f, x) => x

                        Неподвижная точка руками.
                        Ответить
                        • Тогда 1+1+1+1 - цикл руками. Без бесконечного зацикливания рекурсия слабовата и пуста.

                          > Только нужно делать декремент на функции
                          Декремент не нужен. Тут же можно обойтись без этого, пользуясь не рекурсией, а корекурсией (если я правильно понимаю значения этих слов). Нумерал Чёрча сам отсчитает нужное количество итераций и сконструирует нужную питушню. Сумма - не разбор левого операнда для наращивания правого, а наращивание правого операнда левым; произведение - не разбор левого операнда ради набрасывания суммы на правый, а левооперандное наращивание нуля правым операндом, и так далее.

                          В мире нумералов Чёрча надо найти такую функцию f, которой можно подействовать k раз на hyper0, чтобы получился hyperk, никаких декрементов. Если k - нумерал Чёрча, hyperk = k(f, hyper0).

                          Смотрим. hyper0 - просто succ правого операнда; hyper1 - применение hyper1 m раз к m - сумма; hyper2 - применение m раз функции x => sum(n, x) (или x=>hyper1(n)(x)) к начальному значению 0 - произведение; и так далее. Сокращая здесь и далее hyper до h, получаем:
                          const h0 = n => m => succ(m);
                          const h1 = n => m => m(h0(n))(n);
                          const h2 = n => m => m(h1(n))(zero);
                          const h3 = n => m => m(h2(n))(one);
                          const h4 = n => m => m(h3(n))(one);

                          Видно, что каждый новый гипероператор h' получается из старого h и начального значения x по формуле
                          h' = n => m => m(h(n))(next(x))

                          Для гипероператора понадобится последовательность n, 0, 1, 1... Очевидно, что из-за начального n она не будет чистой функцией от одного аргумента. Я сначала в силу шаблонности мышления не придумал ничего лучше использования обычного бесконечного списка значений. Но для создания такого списка мне понадобилась богомерзкая рекурсия (Z кобенатор).

                          На самом деле, достаточно FIFO из двух элементов (x1, x2) = (n, 0), в конец которой добавляют 1.
                          Преобразование гипероператора - преобразование 3-кортежа (h, x1, x2):
                          h'  = n => m => m(h(n))(x1)
                          x1' = x2
                          x2' = one
                          Ответить
                          • В итоге имеем:
                            // стандартные лямбды
                            const zero = f => x => x;
                            const succ = n => f => x => f(n(f)(x));
                            const one = succ(zero);
                            const True = x => y => x, False = zero;
                            const pair = x => y => f => f(x)(y);
                            const first = p => p (True), second = p => p (False);
                            
                            // const h0 = n => m => succ(m);
                            // const h1 = n => m => m(h0(n))(n);
                            // const h2 = n => m => m(h1(n))(zero);
                            // const h3 = n => m => m(h2(n))(one);
                            // const h4 = n => m => m(h3(n))(one);
                            
                            // xs(n) = (n, 0)
                            const xs = n => pair(n)(zero);
                            
                            // следующий гипероператор: (h, xs) -> (h', tail(xs))
                            const hnext = p => {
                              const h = first(p), xs = second(p);
                              
                              // для гипероператора h и значения x следующий гипероператор h':
                              // h' = n => m => m(h(n))(next(x));
                              const h1 = n => m => m(h(n))(first(xs));
                              
                              // продавливание: (a, b) -> (b, 1)
                              const xs1 = pair(second(xs))(one);
                              
                              return pair(h1)(xs1);
                            };
                            
                            // гипероператор: hnext(...hnext((hnext(h0, xs)))...)
                            const hyper = k => n => m => first(k(hnext)(pair(_ => succ)(xs(n))))(n)(m);
                            
                            const two = succ(one);
                            const three = succ(two);
                            const four = succ(three);
                            
                            console.log('2.3= ', hyper(zero)(two)(three)(x=>x+1)(0));
                            console.log('2+3= ', hyper(one)(two)(three)(x=>x+1)(0));
                            console.log('2*3= ', hyper(two)(two)(three)(x=>x+1)(0));
                            console.log('2^3= ', hyper(three)(two)(three)(x=>x+1)(0));
                            console.log('2^^4=', hyper(four)(two)(three)(x=>x+1)(0));

                            С использованием стандартных функций zero, succ, pair, first, second, гипероператор можно переписать кратко как
                            const hyper = k => n => m => first(k
                              (p => pair(n => m => m(first(p)(n))(first(second(p))))(pair(second(second(p)))(succ(zero))))
                              (pair(_ => succ)(pair(n)(zero))))(n)(m);
                            Ответить
                            • Гипероператор, не требующий инклюдов:
                              const hyper = k=>n=>m=>(i=>(p=>(f=>(s=>f(k
                                (h=>p(n=>m=>m(f(h)(n))(f(s(h))))(p(s(s(h)))(i(f=>x=>x))))
                                (p(_=>i)(p(n)(f=>x=>x))))(n)(m))(p=>p(f=>x=>x)))
                                (p=>p(x=>y=>x)))(x=>y=>f=>f(x)(y)))(n=>f=>x=>f(n(f)(x)));
                              Ответить
                            • Бляя, ну ты сумасшедший, ёб твою мать, а...
                              Ответить
                          • >20 минут назад #
                            >19 минут назад #

                            Господи боже мой, за минуту два сверхупоротых (в хорошем смысле) поста. Теперь мне медитировать полдня, чтоб что-то по делу ответить.

                            Еще раз какая там у вас клавиатура?
                            Ответить
                            • Я думал, в наше время каждый пользуется подпространственной клавиатурой на чёрных дырах. Очень удобно, когда написать код нужно было ещё вчера.
                              Ответить
                              • Я смотрел по диагонали тред о клавиатурах, но и подумать не мог что они НАСТОЛЬКО ускоряют набор.
                                Ответить
                          • >const h1 = n => m => m(h0(n))(n);
                            >const h2 = n => m => m(h1(n))(zero);
                            >const h3 = n => m => m(h2(n))(one);
                            >const h4 = n => m => m(h3(n))(one);

                            Интересно можно ли как-то не хардкодить, но вывести из свойств гипероператора нейтральный элемент для каждого n. Для сложения это 0, для умножений и степени ­— 1.

                            В смысле убрать эту неэстетичную часть:
                            > b < (1+(op>1))
                            Ответить
                            • > вывести из свойств гипероператора
                              Чтобы построить новый гипероператор, нужен старый и нейтральный элемент старого. Из работающего гиператора нейтральный элемент можно найти подбором.

                              x @ x0 = x

                              x0(op) = solve(x0 => op(n, x0) == x0) // понадобятся isZero, pred
                              solve(e) = solve'(e, 0)
                              solve'(e, n) = if(e(n), n, solve'(n + 1)) // понадобится if, Z кобенатор

                              В теории тут можно и без кобенаторов, т.к. количество итераций не превышает n.

                              Единственное - с h0 будут проблемы.
                              h0(x, x-1) = x // а для моих формул надо не x-1, а x, чтобы h0(x, x) = x
                              h1(x,   0) = x
                              h2(x,   1) = x
                              h3(x,   1) = x

                              Не знаете, как этого избежать?

                              Ну и подбор будет всё равно использовать 0 и 1.
                              Ответить
                              • Описанное выше - через лямбда исчисление:
                                // стандартные лямбды
                                const succ = n => f => x => f(n(f)(x));
                                const zero = f => x => x;
                                const one = succ(zero);
                                const two = succ(one);
                                const three = succ(two);
                                const four = succ(three);
                                const True = x => y => x, False = zero;
                                const plus = n => m => f => x => n(f)(m(f)(x));
                                const iszero = n =>n (x => False) (True);
                                const pred = n => n (g => k => iszero (g (one)) (k) (plus (g (k)) (one))) (v => zero) (zero);
                                const sub = n => m => m(pred)(n);
                                const leq = a => b => iszero(sub(a)(b));
                                const and = p => q => p (q) (p);
                                const If = p => a => b => p (a) (b);
                                const Z = f => (x => f(v => x(x)(v)))(x => f(v => x(x)(v)));
                                
                                // полустандартные
                                const nothing = null;
                                const eq = a => b => and(leq(a)(b))(leq(b)(a));
                                const lazyIf = p => a => b => If(p)(a)(b)(nothing);
                                
                                // нейтральный элемент
                                const x0 = (h, n) => solve(x0 => eq(h(n)(x0))(n))(zero);
                                // solve(f, x) находит x: f(x)==True
                                const solve = Z(solve => f => x => lazyIf(f(x))(_=>x)(_=>solve(f)(succ(x))));
                                // новый гипероператор
                                const hnext = h => n => m => m(h(n))(x0(h, n));
                                
                                const h0 = _ => succ; // убрали из-за плохого нейтрального элемента
                                const h1 = plus;
                                const hyper = k => pred(k)(hnext)(h1);
                                
                                const num = n => n(x=>x+1)(0);
                                // console.log('2.3= ', hyper(zero)(two)(three)(x=>x+1)(0)); // утрачено
                                console.log('2+3= ', hyper(one)(two)(three)(x=>x+1)(0));
                                console.log('2*3= ', hyper(two)(two)(three)(x=>x+1)(0));
                                console.log('2^3= ', hyper(three)(two)(three)(x=>x+1)(0));
                                console.log('2^^3=', hyper(four)(two)(three)(x=>x+1)(0));
                                Ответить
                              • Я написал длинный коммент, но ГК его схавал и отвалился.

                                >нейтральный элемент можно найти подбором.
                                That's not how the Math works.


                                h0(x,  x) = x //надо не x-1, а x
                                h1(x,  0.) = x
                                h2(x,  1) = x



                                >Единственное - с h0 будут проблемы.
                                Никаких проблем нет: всё логично получается:
                                x+0=x
                                x*0=0
                                x⁰=1

                                Нейтральный эл-т (h_n), есть применение нуля к (h_n+1). Только круг какой-то замкнутный.
                                Ответить
                                • >>>"Только круг какой-то замкнутный"

                                  Так это кольцо твоего ануса.
                                  Ответить
                              • >Не знаете, как этого избежать?

                                Возможно h0 и не инкремент вовсе.
                                Ответить
                                • В каком смысле? На Википедии пишут, что это инкремент правого операнда. Кто ошибается - я, Википедия или математики?
                                  Ответить
                                  • >На Википедии пишут

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

                                    Все остальные операции бинарны, a+b, a*b, a^b;

                                    Инкремент же унарный. Отсюда и траблы при унификации.

                                    То есть я допускаю
                                    Что есть бинарная f(a,a), отличная от инкремента функция (возможно побитовая), которую можно применить b раз, и получить a+b.
                                    Ответить
                                  • Или я упоролся?
                                    Ответить
                                    • Если найдёте операцию с такими свойствами, можно писать научную статью. Не знаю, как насчёт славы и денег, но пара докторов наук руку точно пожмёт.
                                      Раз такую функцию настойчиво скрывают и либо выкидывают h0, либо вставляют богомерзкую унарщину, скорее всего ничего ценного не нашли.
                                      Питушня должна быть фундаментально проще сложения и умножения, и соответственно - разности и деления, а также должна работать на целых числах.

                                      Тут либо действительно инкремент оставлять, либо вводить R и читерствовать с делением, добавляя кусочек операнда по какой-нибудь экспоненциальной логике (f(a, b) = a+k(a,b)*b). Можно ещё вероятностные операции вводить: f(a,b) = b*random()<1 ? a+b : a; - в среднем за b таких сложений наберётся a+b, но всё из того, что придумывается - какая-то сомнительная питушня.
                                      Ответить
                                      • >в среднем за b таких сложений наберётся a+b

                                        Да-да, именно в этом направлении и мыслил.

                                        > либо вставляют богомерзкую унарщину, скорее всего ничего ценного не нашли

                                        Всё-таки я упоролся, в вечер пятницы странные мысли лезут в голову.

                                        Используя индукцию можно элементарно доказать что инкремент (или другая функция, которая ведёт себя абсолютно так же) - единственно возможна.

                                        f(a,f(a,a))=a+2
                                        f(a,f(a,f(a,a)))=a+3

                                        Или в общей питухаскельной форме.
                                        foldr $ inc $ replicate b a


                                        Никаких частичных штук тут не получается, поскольку все промежуточные результаты: инкременты.

                                        То есть доказываем для случая где b=1; f(a,a)=a+1

                                        Потом доказываем что f(a,a)☓b+1 раз = f(a,a)☓b+1

                                        И остаётся доказать кейсы что функция инкрементит a, даже если второй аргумент меньше чем а.
                                        Ответить
                              • > Из работающего гиператора нейтральный элемент можно найти подбором.

                                Думал и над этим.
                                Подбор не такая плохая штука, как может показаться на первый взгляд.

                                Вдруг код будет выполняться во вселенной, где 0 — нейтральный эл-т умножения? А нейтральный элемент сложения допустим -1.

                                В целом интересно получается.

                                Для H₀ нейтрального элемента нет вовсе. Второй аргумент функция игнорирует примерно в таком духе
                                (a,b)=> b+a+1-b //формально функция бинарна

                                Для H₁ нейтральный эл-т ­это . Однако нет инвариантного элементa, который при взаимодействии даёт констранту ради лулза назовём его нейтрализующим.

                                Для умножения H₂ нейтральный эл-т ­это 1. Нейтрализующий эл-т 0, он превращает любой другой элемент в себя.

                                Для степени и высших порядков H₃ всё практически так же. 1 в любой степени это 1. Только нуль превращает всё в 1. Насчёт 0⁰ спорят, и тем не менее.


                                PS. Как же меня бесят 500 на ГК. Как не напишу километровый пост, вечно получаю ошибку. ЧСХ на ворециях очень редко падает.
                                Ответить
                                • > Как же меня бесят 500 на ГК. Как не напишу километровый пост
                                  Пишите в отдельном редакторе, ну или Ctrl+A, Ctrl+C перед Ctrl+Enter.
                                  Отдельный редактор тем хорош, что по Ctrl+A показывает, сколько символов занято - в итоге можно оценить и подсократить/разбить пост.

                                  > ЧСХ на ворециях очень редко падает.
                                  А Вы случайно не хитрые юникодные символы вставляете в формулы? В ворециях их как раз нет, а в математических постах - вполне возможны (ГК учит ASCII-скромности).
                                  Ответить
                                  • > Пишите в отдельном редакторе

                                    Сказал король юзерскриптов. Можно сделать ЮС который сохраняет перед отправкой коммент в историю в localStorage и не даёт проебать.

                                    По поводу юникода, думаю дело не в нём. Пару раз сохранял текст перед отправкой и попадал на эксепшон, перезагрузка страницы и повторная попытка помогает. Если бы дело было в кодировке, не пропускало бы ни с какой попытки.

                                    Я думаю это что-то чуть более сложное, чем csrf verification error. Что-то протухает или какой-то таймаут превышается. Это объясняет и то, что медленно вручную написанный текст порой вызывает проблемы, а копи-паст вореции, которые генерируются и постятся за секунду — реже.
                                    Ответить
                                    • Помню, я даже какую-то такую питушню писать начинал.
                                      Впрочем, скрипты для себя пишутся тогда, когда без скрипта уже совсем плохо, т.к. лень. А в npp уже есть автоматический бэкап и автосохранение несохранённых файлов в специальной папке. Начал писать комментарий, другой, закрыл редактор, открыл через неделю, и тексты комментариев сами открываются. Всё те же несохранённые new 1 и new 2.
                                      Ответить
                                  • >А Вы случайно не хитрые юникодные символы вставляете в формулы?

                                    Да, похоже из-них не падает.
                                    Кстати я только сейчас оценил прикол с жырным нулём (http://govnokod.ru/24000#comment410458).
                                    Он тоже не поддерживается ГК.
                                    Ответить
                                • > Как не напишу километровый пост
                                  Как ни напишу…
                                  Ответить
                • как это умножение работает?

                  var two = x => 2;
                  var three = x => 3;
                  var prod = (n, m) => (f, x) => n(f, m(f, x));
                  prod(two, three)(); // выводит 2
                  Ответить
                  • Ты должен был числа нумералами чёрча передать, а не просто числами.
                    Ответить
                    • спс пофиксил
                      var succ = n => (f, x) => f(n(f, x));
                      var one = succ((f, x) => x);
                      var two = succ(one);
                      var three = succ(two);
                      var prod = (n, m) => (f, x) => n(a => m(f, a), x);
                      prod(two, three)(x=>x+1, 0); // 6
                      Ответить
                    • В haskell можно перегрузить numeric literals, чтобы они стали нумералами Чёрча. И строки, чтобы они были лямда-списками из чисел Чёрча...
                      Ответить
                      • >И строки, чтобы они были лямда-списками из чисел Чёрча...

                        Я вот как раз думал над этим.
                        Можно ведь написать и такой пример, который тайно сделает rm -rf.
                        Ответить
            • Сломал мозг над succ. Можешь расписать, в частности, что такое n, f?
              Ответить
              • succ здесь самый обычный, всё по канону, я ничего не привносил, это всё Чёрч придумал.

                Число n - функция, которая принимает функцию f и значение x, а возвращает n-кратное применение функции f к значению x.

                succ - функция, которая принимает n и возвращает n+1.
                Было: "N" = n(f, x) = f(f(...n раз...f(x)))
                Надо: "N+1" = n'(f, x) = f(f(...n+1 раз...f(x)))) = f(n(f, x))
                Ответить
            • >Руками, конечно.
              Просто я кажись видел на гитхабчике кодогенераторы похожей произвольной питушни.
              Ответить
              • Помню, CHayT что-то такое писал ещё.
                Ответить
                • https://gist.github.com/k32/84cc73f720a5ea116c92bbd715e1a963
                  Не уверен, что это последняя версия.
                  Ответить
        • ого, вот это функциональное программирование
          Ответить
    • 1024-- 24000
      Как символично )))
      Ответить

    • Ответить

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