ECS
-
Публикации
533 -
Зарегистрирован
-
Посещение
-
Победитель дней
203
Сообщения, опубликованные пользователем ECS
-
-
Спасибо за статью, прямо в шараге себя ощутил: очень интересно, но ни хрена не понятно. И очень за это стыдно. А когда мне стыдно, то ладошки сами чешутся докопаться! Ну и заодно поинтересоваться, как же эта вундервафля работает.
В 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 сказал:Из-за дискретности случайных значений генератора, распределение вероятностей для блоков с разной плотностью не одинаковое.
Вах, красота какая... у меня бабушка похожие платочки шила, очень мягкие. А что это? "Распределение вероятностей"... вероятностей чего? Если это график, то зависимость какой величины от какой тут продемонстрирована? За что отвечают синие точки, а за что оранжевые? Напрягу последнюю неатрофированную извилину и предположу, что каждый цвет отвечает за блок с определённой плотностью. Но с какой именно? Если для статьи плотность несущественна, то насчёт того, что представляют собой координатные оси, я вообще могу лишь догадываться. Ладно, хрен с ним, пропускаю этот момент.
Далее идёт исходник. Ага, ну тут-то наверняка должна быть логика из предыдущего шага, по которой можно понять, "угадали мы плотность или нет":
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 является целым или почти целым числом, то плотность блока валидна".
Но почему именно так? Почему сравнение с "близостью к единице" менее точно, чем сравнение с "близостью к нулю"? Почему мы вообще анализируем дробную часть байта, который по определению является целым числом? Как она вообще отражает соответствие искомой плотности блока? Я понимаю, что у тебя были некие исходные данные, по которым это можно было легко понять, но в статье-то их нет. Сложна, оч сложна!
Пытаюсь читать дальше...
В 06.01.2021 в 14:58, Doob сказал:Результаты обратного вычисления для разных плотностей хорошо это демонстрируют.
Якорь мне в гузно, опять зависимость *магии* от *магии*! В порядке бреда можно предположить, что ось абсцисс олицетворяет расстояние до блока, но что за что тогда отвечает ось ординат? Стопудова не за плотность блока. Вероятно, за RANDOM_BYTE? Да вроде не, нижняя точка графика в -300 и диапазон signed byte в [-127, 127) как бы намекают... или по какой-то причине график построен в ином масштабе. Ой, всё, я сдаюсь
Аж вьетнамские флешбеки пошли с первого курса, где многие преподы имели милую манеру подавать материал в аналогичном "сокращённом" виде без разжёвывания. Надеюсь, каждый из них получит в аду личный котелок с антипригарным покрытием, хе-хе
Но если не трудно, то не мог бы ты прояснить момент хотя бы с логикой сравнения остатка от деления? Мне правда очень интересно
-
1 час назад, MrAbad сказал:для того, чтобы использовать библиотеку shell, ее надо подключить в программу:
local shell = require("shell")
Разве библиотека shell на ComputerCraft не глобальна? И существует ли там вообще require? Не os.loadAPI?
-
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
-
-
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)
Если же получить элемент таблицы и ничего с ним не делать, то компилятор оптимизирует тело второго цикла, банально удалив "лишнее" присвоение. При этом индексация в первом случае останется нетронутой, и создастся иллюзия ускорения:
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)
А вот в этом случае 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)
-
1
-
-
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)
-
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 был виной подобному поведению. А поскольку исходный код софта выложен не был, предположение могло оказаться не лишним. Это потом уже пошла дискуссия на тему "как быстрее"
-
1 час назад, Belzebub сказал:По поводу pairs и for i = 1, #tbl - всё и так ок.
алсо я использую ipairs, не знаю как оно в обычном луа - но бэнчмарки в JIT показывают результат в 15-20% быстрее
https://pastebin.com/vEH362LCВо-первых, твой тест заведомо некорректен, т.к. в первом случае при каждой итерации ты индексируешь таблицу (причём индексация - это довольно жирная операция), а во втором тело цикла попросту пустое. Уверен, что JIT-компилятор скипает цикл во втором случае, пытаясь оптимизировать код:
Во-вторых, тема твоего поста и моя рекомендация по 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 раза? Ой-ой-ой
-
2
-
-
Начнём с того, что изначальный метод сортировки невалиден для table.sort, т.к. не учитывал все возможные варианты напрямую. Да, нативный sort в этом плане слегка туповат:
Также рискну предположить, что вывод игроков на экран был хаотичным из-за использования 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
Результат:
-
1
-
1
-
-
Ошибка "no such component" всегда возникает при попытке доступа к proxy компонента, записанному в переменную, если по какой-то причине сам компонент был физически отсоединён.
А вот почему он отсоединился - фиг знает: либо сервак пролагал, либо с выгружающимися чанками проблема, либо возникает коллизия UUID'шников компонента (что маловероятно), либо вообще админ/сожитель своими кривыми ручонками пошарился. Исправить ситуацию можно путём периодического обновления proxy на актуальный через computer.uptime
В любом случае ставлю последний счетверённый МОХ, что 108 строка ошибки просто "сдвинулась" в трейсе на единицу, и isAvailable тут ни при чём. Пруф:
-
1
-
1
-
1
-
-
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
-
Для меня прям загадка, какая ж у тебя версия либы используется: метод был оч давно добавлен в старую, но удален при переходе на майноську ввиду низкой производительности и отсутствия практического применения. Обычно я юзаю несколько drawText со смещением по X и разными цветами друг за дружкой. А для каких целей метод пригодился бы, если не секрет?
-
2 часа назад, Bs0Dd сказал:выдергивать нужное и делать "подсистему" с требуемыми функциями (с учетом всяких упрощений их оказалось не так много, но возни это доставило)
Капец ты там потеешь
-
1
-
-
Мяу, ну явно ж какая-то кастомная отрисовка пикч идет у тебя в RenderEngine. Без сырцов фиг знает, что там происходит, и как это пофиксить. Вполне вероятно, кстати, что на скрине старая либа Image используется, где была иная RAM-структура картинок (с вложенными таблицами), а либа буферизации - новая. Я потому и прекратил поддержку всего этого балагана, т.к. по кускам собирать код никаких нервов не хватит
Если критично - можешь просто выдрать обновленный и исправленный метод drawSemiPixelRectangle к себе в старую либу
-
Надо же, до сих пор интересные баги всплывают! Ладно, фигня вопрос, сейчас пофиксим, тут проблема в смещении пикселей за пределами drawLimit ввиду одномерной структуры буфера экрана.
Только учти, что эта либа - неподдерживаемое legacy, и основная версия находится в виде Screen API в майноське. Полупиксельный метод я обновлю, но никаких гарантий по работоспособности остальных методов нет, все дела
-
Обновил доку по Image API, спасибо за наводку. Есть подозрение, что она уже года полтора как валялась пустующей
-
1
-
1
-
-
3 часа назад, ocelotman сказал:В случае невозможности открытия картинки 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
-
1
-
-
Заметил, что дефолтный EEPROM (который Lua BIOS) выставлен в режим ReadOnly. В игровых опенкомпах он доступен для перезаписи
-
1
-
1
-
1
-
-
6 часов назад, Totoro сказал:Как по мне - классный кошак.
Я когда лого для Оцелота придумывал, как раз его вспоминал. Типа вот, жаль что не мне идея пришла )Ой, как мило:3
Забирай себе, если хочется, не жалко ж
-
1
-
-
@Totoro Да, было такое, он в 3D-технодемке рендерился, т.к. движок назывался MeowEngine. А так логотипа нет, так же как и фантазии(
-
6 часов назад, vford сказал:А информацию о компе в MineOS можно (вроде) узнать в настройках или свойствах. Точно не знаю, @ECS может меня исправить
Да, такая приложуха существовала, но она выдавала не столь подробную информацию, как твое творение. То есть без данных о "производителе" компонентов, без цветовых палитр и прочих вкусностей, лишь базовую инфу
-
@Kolya Нет его уже давно. API обновились, инсталлеры сдохли. Если инфопанели нет в маркете - то её считай нет совсем
-
@Ivanuza В самой майноське из штатных средств существует только передача файлов по модемам. Да и что значит "зря делаю"? Если тебе это интересно и доставляет удовольствие, то ничто не зря
-
Пардон, мой косяк. Не указал, что в регулярке нужно юзать шестнадцатеричную систему:
str:gsub("\\u([a-fA-F%d]+)", function(code) return unicode.char(tonumber(code, 16)) end)
Проверил в кубаче, всё пашет:
-
Проверил raw-ответ через сокет. API дискорда отдаёт сразу экранированные символы, либы опенкомпов тут ни при чём. Видимо, постман (как и ARC, кстати) сам их декодирует в русский эквивалент, из-за чего возникло подозрение на опенкомпы:
Значит, решение с регуляркой остаётся верным. Или нужно модифицировать JSON-либу соответственным образом, но всё равно используя ручной декодинг


Оккультные практики при поиске руды
в Уроки
Опубликовано:
Спасибо, Алексейюрич, примерно в том же ключе вы меня отправили на пересдачу хд
Мне было совсем не ясно, т.к. в нити рассуждения отсутствует инфа о том, какое именно неизвестное значение мы желаем получить. Да, сделать предположение методом исключения - это не сложно. Однако не знаю, как у других, но у меня процесс додумывания смысла в готовом учебнике/уроке/гайде/статье вызывает припекание седалища
А почему мы не можем записать результат? Именованные переменные ушли на забастовку? И давно ли знак равенства для функций не указывается? Я пропустил всемирный апокалипсис? А если это так, то почему он присутствовал здесь?
Видимо, апокалипсис на данную запись не распространился? Какая стойкая, однако, запись, уважаю! Кроме того, в программировании (как и в физике, в отличие от математики), мы оперируем не абстрактными функциями, а фактическими формулами, т.к. всегда работаем с набором фактических данных или группой абстрактных, подчинённых фактическому правилу. Если бы твоя формула была человеком, то выглядела бы так:
Спасибо, прям как в кирпиче по матанализу от Виноградовой: ща пойду почитаю следующую главу, не дочитав текущую. Гениальная многоходовочка от автора, ставлю 5/5 на литресе!
Но... но... половина вопросов так и осталась без ответа. Какая часть графика указывает на плотность, а какая на расстояние? За что отвечают цвета точек? За состояние "угаданности" и "неугаданности"? Ты ж, блин, автор статьи в разделе "уроки", ты ж, блин, строил этот график, ты ж, блин, знаешь, что там за исходные данные были. Ну подпиши их, ну интересно же! А еще почему в реальной проекции и масштабе аналогичную зависимость не получится? "Скукожь" график, наплевав на масштаб - и все получится, разве нет?
Фух, хоть это я угадал. А каким образом читатель должен допереть, не имея графиков и исходных данных о геосканировании, что максимальная близость RANDOM_BYTE к целому числу означает "угаданность" плотности? Гипотетически это действительно будет так, и в идеальном случае, когда геосканер вернул результат без шума, RANDOM_BYTE будет целым, т.к. переменные из формулы оказали на результат минимальное влияние. Но чёрт возьми, это ж просто предположение, а вдруг нет! *кусаю ногти*
Ага, значит, догадка была близка к истине. Хотя это было вовсе не очевидно, т.к. диапазон signed byte в [-127; 127) противоречит этой очевидности. Да, глянув на код и условие по отсечению данных, у меня возникла мысль, что возвращаемое значение функции magic() может находиться в ином диапазоне, но, блин, даже в коде "ошибочный" диапазон просто игнорируется. А на графике - нет. Магия! Неужели рисовалка графиков не имеет фичи именования координатных осей для упрощения понимания?
О-о-о, на сократщину можно такую дискуссию развернуть, что счетчик PK БД форума выйдет за допустимые пределы. С методикой и подходом к самостоятельному обучению и личной интерпретации я полностью согласен, однако в данной ситуации мы имеем уже завершённый материал. Материал интересный, на актуальную тему, с хорошей науч. базой и даже наличием исследований с практическим опытом - это ж золотая жила знаний, пускай и в кубаче! Но... исходные данные только у автора. Упс.
Я, может быть, очень хочу "пощупать руками и понять своим языком", открыть консольку, подставить исходники в формулу, рассчитать, порадоваться, что результат изящно сходится. А не могу. Ну то есть да, конечно, я могу запустить кубач, воссоздать исследовательскую среду, понатыкать руд, поставить пайтон и матплотлиб, построить график - но чёрт побери, за меня это уже сделали! Зачем тратить столько времени на подтверждение рабочей теории? Лучше потрачу время на срач))0