Перейти к содержимому

ECS

Гуру
  • Публикации

    533
  • Зарегистрирован

  • Посещение

  • Победитель дней

    203

Сообщения, опубликованные пользователем ECS


  1. 5 часов назад, Doob сказал:

    Хотелось, чтобы была загадка

     

    Спасибо, Алексейюрич, примерно в том же ключе вы меня отправили на пересдачу хд

     

    5 часов назад, Doob сказал:

    Там вроде все ясно, нить рассуждений не прерывается, есть формула из кода, мы берем обратные функции и получаем формулу для извлечения неизвестного значения. Знак равенства пропал, т. к. это функция f(x) и мы не можем пока записать результат, иначе можно запутаться.

     

    Мне было совсем не ясно, т.к. в нити рассуждения отсутствует инфа о том, какое именно неизвестное значение мы желаем получить. Да, сделать предположение методом исключения - это не сложно. Однако не знаю, как у других, но у меня процесс додумывания смысла в готовом учебнике/уроке/гайде/статье вызывает припекание седалища

     

    А почему мы не можем записать результат? Именованные переменные ушли на забастовку? И давно ли знак равенства для функций не указывается? Я пропустил всемирный апокалипсис? А если это так, то почему он присутствовал здесь?

     

    В 06.01.2021 в 14:58, Doob сказал:

    R = G(RANDOM_BYTE / 128 / 33) * D * N + H

     

    Видимо, апокалипсис на данную запись не распространился? Какая стойкая, однако, запись, уважаю! Кроме того, в программировании (как и в физике, в отличие от математики), мы оперируем не абстрактными функциями, а фактическими формулами, т.к. всегда работаем с набором фактических данных или группой абстрактных, подчинённых фактическому правилу. Если бы твоя формула была человеком, то выглядела бы так:

     

    GPe5XX9.png

     

    5 часов назад, Doob сказал:

    Далее по тексту это проясняется

     

    Спасибо, прям как в кирпиче по матанализу от Виноградовой: ща пойду почитаю следующую главу, не дочитав текущую. Гениальная многоходовочка от автора, ставлю 5/5 на литресе!

     

    5 часов назад, Doob сказал:

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

     

    Но... но... половина вопросов так и осталась без ответа. Какая часть графика указывает на плотность, а какая на расстояние? За что отвечают цвета точек? За состояние "угаданности" и "неугаданности"? Ты ж, блин, автор статьи в разделе "уроки", ты ж, блин, строил этот график, ты ж, блин, знаешь, что там за исходные данные были. Ну подпиши их, ну интересно же! А еще почему в реальной проекции и масштабе аналогичную зависимость не получится? "Скукожь" график, наплевав на масштаб - и все получится, разве нет?

     

    5 часов назад, Doob сказал:

    Да, все так. Целый абзац потерялся. Чтобы компенсировать ошибку округления вводим магические константы. Они бы не понадобились, если в формуле получения рандомного байта подставить множитель, превращающий результат в целое число, но там тоже пришлось бы избавляться от ошибки округления, что добавит лишних операций.

     

    Фух, хоть это я угадал. А каким образом читатель должен допереть, не имея графиков и исходных данных о геосканировании, что максимальная близость RANDOM_BYTE к целому числу означает "угаданность" плотности? Гипотетически это действительно будет так, и в идеальном случае, когда геосканер вернул результат без шума, RANDOM_BYTE будет целым, т.к. переменные из формулы оказали на результат минимальное влияние. Но чёрт возьми, это ж просто предположение, а вдруг нет! *кусаю ногти*

     

    5 часов назад, Doob сказал:

    Так это результат работы нашей магической формулы для всех рандомных байт и расстояний. Вроде-бы очевидно, что у правильно распознанного блока результат в диапазоне рандомных байт, а у остальных шатает так, что в реальном масштабе и не разглядеть. Там еще полное совпадение по некоторым координатам, но его так совсем не получится показать. Результат работы геосканера намного наглядней - круги из ошибочных блоков ясно показывают неполноценность однократного сканирования.

     

    Ага, значит, догадка была близка к истине. Хотя это было вовсе не очевидно, т.к. диапазон signed byte в [-127; 127) противоречит этой очевидности. Да, глянув на код и условие по отсечению данных, у меня возникла мысль, что возвращаемое значение функции magic() может находиться в ином диапазоне, но, блин, даже в коде "ошибочный" диапазон просто игнорируется. А на графике - нет. Магия! Неужели рисовалка графиков не имеет фичи именования координатных осей для упрощения понимания?

     

    5 часов назад, Doob сказал:

    Ха, у меня еще со школы проблемы с усвоением материала, так как он везде подается в этой манере. Да и у кого таких проблем нет? Разве кому-то нравится математический язык?

    Лучший способ научиться чему-то новому - метод Сократа, ученик должен все пощупать своими руками и понять своим языком. А так, имеем то, что имеем - читаешь докторскую или препринт вроде-бы научной статьи, а там лютый бред, от банальных опечаток, до нарушения базовых законов логики, аж глаза кровоточат.

     

    О-о-о, на сократщину можно такую дискуссию развернуть, что счетчик PK БД форума выйдет за допустимые пределы. С методикой и подходом к самостоятельному обучению и личной интерпретации я полностью согласен, однако в данной ситуации мы имеем уже завершённый материал. Материал интересный, на актуальную тему, с хорошей науч. базой и даже наличием исследований с практическим опытом - это ж золотая жила знаний, пускай и в кубаче! Но... исходные данные только у автора. Упс.

     

    Я, может быть, очень хочу "пощупать руками и понять своим языком", открыть консольку, подставить исходники в формулу, рассчитать, порадоваться, что результат изящно сходится. А не могу. Ну то есть да, конечно, я могу запустить кубач, воссоздать исследовательскую среду, понатыкать руд, поставить пайтон и матплотлиб, построить график - но чёрт побери, за меня это уже сделали! Зачем тратить столько времени на подтверждение рабочей теории? Лучше потрачу время на срач))0


  2. Спасибо за статью, прямо в шараге себя ощутил: очень интересно, но ни хрена не понятно. И очень за это стыдно. А когда мне стыдно, то ладошки сами чешутся докопаться! Ну и заодно поинтересоваться, как же эта вундервафля работает.

     

    В 06.01.2021 в 14:58, Doob сказал:

    Нам известны все значения, кроме H и RANDOM_BYTE, что нам это дает?
    Мы можем предположить значение H и обратить всю формулу.
    (R - H) / D / N * 128 * 33
    Для стандартного конфига можно сократить до:
    2112 * (R - H) / D

     

    Я даже на этом шаге "завис" на минуту. Во что мы обращаем формулу? Что мы вычисляем в итоге, где знак равенства, черт побери? Методом исключения предположу, что мы вычисляем тот самый байт, который выдал нам ГСПЧ, а логика сокращения формулы была следующая:

     

    RANDOM_BYTE = (R - H) / D / N * 128 * 33

    RANDOM_BYTE = (R - H) / D / 2 * 128 * 33

    RANDOM_BYTE = (R - H) / D * 2112

     

    Ага, понятно! Теперь я провожу своё первое сканирование, передаю параметры желаемой плотности и расстояния, получаю заветный шумовой байт в дробном виде. И что мне с ним делать?

     

    В 06.01.2021 в 14:58, Doob сказал:

    А теперь тайное знание для тех, кто не понял самостоятельно.


    Мы взяли желаемую плотность блока (например 3 для руды).
    Подставили вместо H.
    Получили случайное значение.
    Можем легко определить, угадали ли плотность или нет.

     

    Да как определить-то? Нет, я понял, что при написании статьи это было легко, но я тоже хочу определить! *злобно топаю ножкой*

    Что мне даёт этот срандомленный байт? Ну 15, ну 120, а что дальше? Какова именно логика определения, угадали мы плотность или нет?

     

    В 06.01.2021 в 14:58, Doob сказал:

    Из-за дискретности случайных значений генератора, распределение вероятностей для блоков с разной плотностью не одинаковое.

    cbdzk30.png

     

    Вах, красота какая... у меня бабушка похожие платочки шила, очень мягкие. А что это? "Распределение вероятностей"... вероятностей чего? Если это график, то зависимость какой величины от какой тут продемонстрирована? За что отвечают синие точки, а за что оранжевые? Напрягу последнюю неатрофированную извилину и предположу, что каждый цвет отвечает за блок с определённой плотностью. Но с какой именно? Если для статьи плотность несущественна, то насчёт того, что представляют собой координатные оси, я вообще могу лишь догадываться. Ладно, хрен с ним, пропускаю этот момент.

     

    Далее идёт исходник. Ага, ну тут-то наверняка должна быть логика из предыдущего шага, по которой можно понять, "угадали мы плотность или нет":

    local function magic(R, H, D)
      return 2112 * (R - H) / D % 1
    end
    
    result = magic(blocks[i_y], hardness, distance(x, i_y+elevation-1, z))
    if blocks[i_y] ~= 0 and (result > 0.9998 or result < 0.00005) then
      ...

    Берем результат сканирования, вычисляем на его основе RANDOM_BYTE, берём от него дробную часть... А зачем? Откуда взялись магические константы 0.9998 и 0.00005? Что означает это сравнение? Пытаюсь перевести на человеческий: "если RANDOM_BYTE является целым или почти целым числом, то плотность блока валидна".

     

    Но почему именно так? Почему сравнение с "близостью к единице" менее точно, чем сравнение с "близостью к нулю"? Почему мы вообще анализируем дробную часть байта, который по определению является целым числом? Как она вообще отражает соответствие искомой плотности блока? Я понимаю, что у тебя были некие исходные данные, по которым это можно было легко понять, но в статье-то их нет. Сложна, оч сложна!

     

    8xis8Hv.png

     

    Пытаюсь читать дальше...

     

    В 06.01.2021 в 14:58, Doob сказал:

    Результаты обратного вычисления для разных плотностей хорошо это демонстрируют.

    onqp1Vm.png

     

    Якорь мне в гузно, опять зависимость *магии* от *магии*! В порядке бреда можно предположить, что ось абсцисс олицетворяет расстояние до блока, но что за что тогда отвечает ось ординат? Стопудова не за плотность блока. Вероятно, за RANDOM_BYTE? Да вроде не, нижняя точка графика в -300 и диапазон signed byte в [-127, 127) как бы намекают... или по какой-то причине график построен в ином масштабе. Ой, всё, я сдаюсь

     

    Аж вьетнамские флешбеки пошли с первого курса, где многие преподы имели милую манеру подавать материал в аналогичном "сокращённом" виде без разжёвывания. Надеюсь, каждый из них получит в аду личный котелок с антипригарным покрытием, хе-хе

     

    Но если не трудно, то не мог бы ты прояснить момент хотя бы с логикой сравнения остатка от деления? Мне правда очень интересно


  3. 15 минут назад, Grobovshik5121 сказал:

    Я полнейший валянок, что значит определена?

    Это значит, что она где-то создана в проге. Ты в этой жизни определен в свидетельстве о рождении под какую-то конкретную дату с сопутствующей инфой о месте регистрации. С функциями (командами) та же история: они имеют имя, тело (код, который они выполняют) и место определения в проге (номер строки)

     

    15 минут назад, Grobovshik5121 сказал:

    Эта команда вроде как одна из встроеных в компах

    Да, но это консольная команда, а не команда для обращения к редстоун-модулю из кода. Чтобы заставить свою прогу работать, ты можешь глянуть на исходный код redpulse.lua и модифицировать его под свои нужды:

    while true do
      F = redstone.getInput("front")
      
      if F then
        -- Либо используешь собственный код
        redstone.setOutput("back", true)
        sleep(3)
        
        redstone.setOutput("back", false)
        sleep(3)
        
        -- Либо запускаешь оригинальный redpulse, без разницы
        shell.run("redpulse back 1 6" )
      end
      
      sleep(1)
    end

     

    • Одобряю 2

  4. 14 минуты назад, hohserg сказал:

    Это тесты без индексации. Как на счет тестов с ней?

    Хе-хе, я ждал этого вопроса. Как говорится, пути компиляторов неисповедимы: к примеру, если каким-либо образом обрабатывать элементы таблицы, создавая иллюзию реальной деятельности в теле цикла, то ipairs, разумеется, проигрывает, т.к. это функция-итератор, которая чисто технически не может быть быстрее простого цикла с числовым лимитом:

    Bench()
    :Add("for i = 1, #tbl do", function()
        for i = 1, #tbl do
            local var = math.floor(#tbl[i])
        end
    end)
    :Add("for i, v in ipairs(tbl) do", function()
        for i, v in ipairs(tbl) do
            local var = math.floor(#v)
        end
    end)
    :Start(100000000)

    fnnf3Ev.png

     

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

    Bench()
    :Add("for i = 1, #tbl do", function()
        for i = 1, #tbl do
            local var = tbl[i]
        end
    end)
    :Add("for i, v in ipairs(tbl) do", function()
        for i, v in ipairs(tbl) do
            local var = v
        end
    end)
    :Start(100000000)

    yzgbOEM.png

     

    А вот в этом случае ipairs опять в пролёте даже несмотря на дополнительную индексацию по таблице в теле первого цикла, т.к. накладные расходы на вызов функции-итератора превышают расходы на индексацию таблиц:

    Bench()
    :Add("for i = 1, #tbl do", function()
        for i = 1, #tbl do
            local var = #tbl[i] + math.floor(i)
        end
    end)
    :Add("for i, v in ipairs(tbl) do", function()
        for i, v in ipairs(tbl) do
            local var = #v + math.floor(i)
        end
    end)
    :Start(100000000)

    HWn0ywP.png

    • Нравится 1

  5. 2 часа назад, Belzebub сказал:

    Индексация, не индесация - один фиг с любым телом цикла ipairs на luajit работает быстрее

    Не-а. Специально даже скомпилил LuaJIT из интереса, а для честности оба тела цикла сделал максимально простыми, дабы тестить исключительно итерационную составляющую:

    Bench()
    :Add("for i = 1, #tbl do", function()
        for i = 1, #tbl do
            local var = 1
        end
    end)
    :Add("for i, v in ipairs(tbl) do", function()
        for i, v in ipairs(tbl) do
            local var = 1
        end
    end)
    :Start(10000000)

    Y3yT5HZ.png


  6. 27 минут назад, eu_tomat сказал:

    При этом использование ipairs позволяет писать более читаемый код, позволяя отказаться как от использования индексов, так и от объявления локальной переменной внутри цикла

    Согласен, я и сам предпочитаю использовать ipairs в простых скриптах, где производительность не играет роли. Однако насчёт локальной переменной ты тут лишка хватил, т.к. любой итератор по типу pairs/ipairs является не более чем функцией-обёрткой, хранящей этот самый счётчик в виде скрытой локальной переменной. Те же яйца, только в профиль:

    function myIPairs(t)
      local index, count = 0, #t
    
      return function()
        index = index + 1
        
        if index <= count then
          return t[index]
        end
      end
    end

    Я советовал использовать человеку конструкцию for i = 1, #t в первую очередь из-за потенциальной ошибки "хаотичного" порядка вывода игроков, т.к. у меня зачастую именно pairs был виной подобному поведению. А поскольку исходный код софта выложен не был, предположение могло оказаться не лишним. Это потом уже пошла дискуссия на тему "как быстрее"


  7. 1 час назад, Belzebub сказал:

    По поводу pairs и for i = 1, #tbl - всё и так ок.

    алсо я использую ipairs, не знаю как оно в обычном луа - но бэнчмарки в JIT показывают результат в 15-20% быстрее
    https://pastebin.com/vEH362LC

    Во-первых, твой тест заведомо некорректен, т.к. в первом случае при каждой итерации ты индексируешь таблицу (причём индексация - это довольно жирная операция), а во втором тело цикла попросту пустое. Уверен, что JIT-компилятор скипает цикл во втором случае, пытаясь оптимизировать код:

     

    s0QIzrd.png

     

    Во-вторых, тема твоего поста и моя рекомендация по ipairs относится к опенкомпам, где по дефолту не поддерживается JIT-компиляция. Зачем прилагать бенчмарк на GMod/LuaJIT вместо бенчмарка на опенкомпах - мне не ясно

     

    В-третьих, у тебя используется GMod'овский таймер вместо нативного os.clock, который, напомню, и следует использовать для бенчмарка алгоритмов согласно Lua wiki

     

    Поэтому если адаптировать твой код под чистый луа, то результат будет диаметрально противоположным:

    local function Benchmark(uid, func, count, onfinish)
      local time = os.clock()
    
      for i = 1, count do
        func()
      end
    
      print(uid, os.clock() - time)
          
      if onfinish then onfinish() end
    end
    
    .......................
    
    Bench()
    :Add("for i = 1, #tbl do", function()
        for i = 1, #tbl do
            local var = tbl[i]
        end
    end)
    :Add("for i, v in ipairs(tbl) do", function()
        for i, v in ipairs(tbl) do
            local var = v
        end
    end)
    :Start(10000000) -- 10 000 000

    Ой, что же это? Медленнее в 2.7 раза? Ой-ой-ой

     

    hIxhGtd.png

    • Одобряю 2

  8. Начнём с того, что изначальный метод сортировки невалиден для table.sort, т.к. не учитывал все возможные варианты напрямую. Да, нативный sort в этом плане слегка туповат:

     

    iDl8QO4.png

     

    Также рискну предположить, что вывод игроков на экран был хаотичным из-за использования for k, v in pairs вместо for i = 1, #array (который, к слову, еще и быстрее). Поэтому вот:

    local members = {
      {
        name = "Vasya",
        online = false,
        playtime = 10,
        offline_time = 2
      },
      {
        name = "Petya",
        online = true,
        playtime = 14,
        offline_time = 2
      },
      {
        name = "Sanya",
        online = true,
        playtime = 15,
        offline_time = 2
      },
      {
        name = "Igor",
        online = false,
        playtime = 1,
        offline_time = 3
      },
      {
        name = "Dima",
        online = false,
        playtime = 1,
        offline_time = 8
      },
    }
    
    table.sort(members, function(ply1, ply2)
      if ply1.online and ply2.online then
        return ply1.playtime > ply2.playtime
      elseif ply1.online and not ply2.online then
        return true
      elseif not ply1.online and ply2.online then
        return false
      else
        return ply1.offline_time < ply2.offline_time
      end
    end)
    
    for i = 1, #members do
      print(members[i].name)
    end

    Результат:

     

    XHbCXYS.png

    • Одобряю 1
    • Спасибо 1

  9. Ошибка "no such component" всегда возникает при попытке доступа к proxy компонента, записанному в переменную, если по какой-то причине сам компонент был физически отсоединён.

     

    А вот почему он отсоединился - фиг знает: либо сервак пролагал, либо с выгружающимися чанками проблема, либо возникает коллизия UUID'шников компонента (что маловероятно), либо вообще админ/сожитель своими кривыми ручонками пошарился. Исправить ситуацию можно путём периодического обновления proxy на актуальный через computer.uptime

     

    В любом случае ставлю последний счетверённый МОХ, что 108 строка ошибки просто "сдвинулась" в трейсе на единицу, и isAvailable тут ни при чём. Пруф:

     

    WNb4a5w.png

     

    5SXzkDx.png?1

     

    PtZY1Ob.png

    • Нравится 1
    • Одобряю 1
    • Спасибо 1

  10. 58 минут назад, Bs0Dd сказал:

    Просто стало интересно, метод вроде упоминается, а в самой библиотеке его нет

    Метод упоминается только на этом форуме в виде чейндж-лога, в документации на гите он отсутствует, и в процессе эволюционирования либы был выпилен по причине фиговой производительности. Если честно, то оставить его проблем не составило бы, однако либа менялась, принцип рендеринга тоже, принцип хранения кадров вообще расслоился на 6 таблиц вместо изначальных 2х, и долгосрочная поддержка неиспользуемой фичи мне показалась накладной. Да и браузер твой загнётся на фиг при отрисовке, т.к. formattedText имел тонну лишних условий и обрезок строк в каждой итерации отрисовки в буфер

     

    1 час назад, Bs0Dd сказал:

    ибо нужно просчитывать координаты смещения и вбивать их руками

    Что там просчитывать-то, один раз в цикле заюзать unicode.len()? И зачем хранить постоянно координаты смещений каждой цветной строки? Не эффективней ли будет организовать структуру таблицы в виде изначальной точки первого символа и перечислений вида "цвет, строка, цвет, строка."? Чет тип такого:

    local lines = {
      { 2, 5, 0xFFFFFF, "Hello world!", 0xFF0000, " It's a red symbols", ...}
    }
    
    local line, x, y, str
    for l = 1, #lines do
      line = lines[l]
      
      x, y = line[0], line[1]
      for i = 3, #line, 2 do
        str = line[i + 1]
        
        buffer.drawText(x, y, line[i], str)
        
        x = x + unicode.len(str)
      end
    end

     


  11. Для меня прям загадка, какая ж у тебя версия либы используется: метод был оч давно добавлен в старую, но удален при переходе на майноську ввиду низкой производительности и отсутствия практического применения. Обычно я юзаю несколько drawText со смещением по X и разными цветами друг за дружкой. А для каких целей метод пригодился бы, если не секрет?


  12. Мяу, ну явно ж какая-то кастомная отрисовка пикч идет у тебя в RenderEngine. Без сырцов фиг знает, что там происходит, и как это пофиксить. Вполне вероятно, кстати, что на скрине старая либа Image используется, где была иная RAM-структура картинок (с вложенными таблицами), а либа буферизации - новая. Я потому и прекратил поддержку всего этого балагана, т.к. по кускам собирать код никаких нервов не хватит

     

    Если критично - можешь просто выдрать обновленный и исправленный метод drawSemiPixelRectangle к себе в старую либу


  13. Надо же, до сих пор интересные баги всплывают! Ладно, фигня вопрос, сейчас пофиксим, тут проблема в смещении пикселей за пределами drawLimit ввиду одномерной структуры буфера экрана.

     

    Только учти, что эта либа - неподдерживаемое legacy, и основная версия находится в виде Screen API в майноське. Полупиксельный метод я обновлю, но никаких гарантий по работоспособности остальных методов нет, все дела


  14. 3 часа назад, ocelotman сказал:

    image.png.a1ed4317ad17d8f5d5fc4dcbb027d749.png

    Что делать?

     

    В случае невозможности открытия картинки image.load() выдаст false и причину, по которой это происходит. Возможно, файл был повреждён или же банально не хватает оперативки. Ну а GUI.image - это всего лишь обёртка над заранее загруженным изображением, и если пихать в неё boolean вместо самой картинки, то либа сдохнет.

     

    Почему же нет проверки на тип данных, чтобы предотвратить такие ситуации? Потому что тонны assert'ов и вызовов type() с последующим сравнением убивают и без того слишком малую производительность опенкомпов. Либа спроектирована по принципу перекладывания ответственности на программиста: такова цена спасения. Поэтому юзай следующий код и проверяй валидность пикч вручную:

    local result, reason = image.load("test.pic")
    
    if result then
      local image = GUI.image(1, 1, result)
      ...
    else
      GUI.alert("Хопа! Пiймав на сломанную пикчу: " .. reason)
    end

    Я было хотел ткнуть носом в документацию, мол, "читай сначала, блеан", но только сейчас заметил, что она сдохла как раз в разделе Image API. Пардоньте, щас исправим))0

     

    3Qe5fpH.png

    • Нравится 1

  15. 6 часов назад, vford сказал:

    А информацию о компе в MineOS можно (вроде) узнать в настройках или свойствах. Точно не знаю, @ECS может меня исправить

    Да, такая приложуха существовала, но она выдавала не столь подробную информацию, как твое творение. То есть без данных о "производителе" компонентов, без цветовых палитр и прочих вкусностей, лишь базовую инфу


  16. Проверил raw-ответ через сокет. API дискорда отдаёт сразу экранированные символы, либы опенкомпов тут ни при чём. Видимо, постман (как и ARC, кстати) сам их декодирует в русский эквивалент, из-за чего возникло подозрение на опенкомпы: 

     

    image.png.c182dedd7592f35b1f65197cdf8c4feb.png

     

    Значит, решение с регуляркой остаётся верным. Или нужно модифицировать JSON-либу соответственным образом, но всё равно используя ручной декодинг

     

×
×
  • Создать...