Лидеры
Популярный контент
Показан контент с высокой репутацией 26.04.2020 в Сообщения
-
4 баллаМетодика ускоренного вычисления константы шума геосканера Предлагаю ознакомиться с методикой, позволяющий максимально быстро и абсолютно точно вычислить константу шума геосканера (geolyzerNoise в config/OpenComputers.cfg). Методика и скрипты тестировались в среде OpenComputers-MC1.7.10-1.7.5.1290-universal.jar. Сохранит ли эта методика свою актуальность в будущем, вселцело зависит от авторов мода. Зачем знать константу шума геосканера? Не на всех серверах параметр geolyzerNoise сохраняет значение по умолчанию. Алгоритмы же поиска руд, использующие для своей работы геосканер, в большинстве своём эффективны лишь при определённых параметрах шума. При увеличении или уменьшении зашумлённости будут эффективны другие алгоритмы. Поэтому знание точных параметров шума геосканера поможет использовать наиболее эффективные алгоритмы поиска руд на конкретном сервере в конкретных условиях шума. Традиционный алгоритм Традиционный алгоритм использует выполнение многократного сканирования плотности блока, поиск минимального и максимального значений и вычисление разницы между ними. Плюсом алгоритма является его простота. Минусом является низкая точность. Для повышения точности используется увеличение кратности сканирования, но даже очень большая кратность не даёт гарантии абсолютной точности. Всегда есть небольшой шанс, что шум окажется немного больше найденного алгоритмом. Дискретная структура шума Как было обнаружено в недавнем обсуждении про вычисление погрешности геосканера, шум имеет дискретную природу. Согласно коду OpenComputers для каждого из сканируемых расстояний существует 256 возможных значений шума. Знание этого факта позволяет нам считать результат достигнутым, как только сканер выдаст 256 уникальных значений плотности одного и того же блока. Плюсом такого подхода будет абсолютная точность. Главный же минус заключается в том, что получение всех 256 значений может занять даже больше времени, чем получение реальных минимума и максимума плотности. В моих экспериментах на получение всех 256 значений уходит примерно 10-20k попыток сканирования. Вот скрипт для наглядности: -- демонстрация: шум геосканера имеет 256 фиксированных значений -- установка: любой блок, сверху блок геосканера, на него спавним комп /oc_sc local scan = require'component'.geolyzer.scan local uniqTbl = {} local uniqCnt = 0 local v for i=1,1e4 do v = scan(0,0,-1, 1,1,1)[1] if not uniqTbl[v] then uniqTbl[v] = true uniqCnt = uniqCnt + 1 print(("try: %d, uniqCnt: %d"):format( i, uniqCnt )) end os.sleep(0) -- ^C для останова end Наблюдая за скриптом, легко заметить, как медленно добираются последние из оставшихся уникальных значений. Алгоритм абсолютно точен, но неоптимален. Оптимизация поиска Оптимизировать вычисления нам поможет знание о том, что все 256 значений шума расположены равномерно, расстояния между смежными значениями одинаковы, и они ровно в 256 раз меньше расстояния между максимальным и минимальным из значений. В пределах погрешности вычислений, разумеется. Это значит, что для вычисления константы шума достаточно найти любые два смежных значения и вычислить разницу между ними. Но смежными эти значения должны быть в своей полной таблице из 256 значений, в то время как в целях оптимизации рабочая таблица должна быть заполнена как можно меньшим количеством данных, и поэтому соседство значений в рабочей таблице не означает обязательности их соседства в полной. Уменьшать количество значений в рабочей таблице следует ровно до того момента, пока это не мешает обнаружению двух смежных значений. Можно сказать и наоборот: пополнять таблицу новыми значениями следует ровно до тех пор, пока смежные значения не удаётся обнаружить с абсолютной точностью. Самое очевидное, что приходит в голову, это набрать ровно 129 уникальных значений, и найти среди них ближайших соседей. Почему 129, а не 128? Потому что при 128 уникальных значениях возможна редкая ситуация, когда эти найденные значения находятся в полной таблице ровно через одно. Это маловероятно, но возможно. Зачем рисковать? Тем более, 129 элементов почти всегда находятся примерно за 200 попыток сканирований, что можно увидеть, наблюдая за работой демонстрационного скрипта. Но внимательный читатель наверняка заметит, что может быть достаточно использовать и 128 значений при условии, что они размещены неравномерно относительно друг друга. Почти всегда 129-ое значение оказывается необязательным. И если развить эту мысль, то выяснится, что и 127 значений почти всегда будет достаточно при введении дополнительных условий. Тем же путём можно перейти к 126 значениям и т.д. В итоге окажется, что роль играет не равномерность расположения значений относительно друг друга, а расстояние между крайними элементами и между двумя ближайшими. А для этой цели может быть достаточно даже трёх найденных значений. В лучшем случае. Но в худшем могут потребоваться и все 129 значений. Оптимальный алгоритм В общем виде алгоритм сводится к циклическому получению очередного значения от геосканера и поиску разницы между всеми найденными значениями. И если соотношение максимальной разницы к минимальной превысит 128, то результат достигнут: минимальная разница между найденными значениями обязана быть равной разнице между смежными значениями в полной таблице. Результатом умножения минимальной разницы на 128*33 будет искомая нами константа geolyzerNoise из файла конфигурации. Результирующий код может выглядеть, например, так: -- измеритель шума геосканера (константы geolyzerNoise в config/OpenComputers.cfg) -- установка: любой блок, сверху блок геосканера, на него спавним комп /oc_sc local abs = require'math'.abs local scan = require'component'.geolyzer.scan -- округление до сотых долей для сокрытия погрешностей local function round( v ) return (v*1e2+0.5)//1/1e2 end -- множитель для восстановления значения шума до справочного local mul = 128*33 local uniqTbl = {} local uniqCnt = 0 -- текущее значение, разница с другим значением, минимальная и максимальная разница local val, dif, min, max -- флаг обновления экстремумов local fUpd for i=1,99 do os.sleep(0) val = scan(0,0,-1, 1,1,1)[1] fUpd = false -- обрабатывать только новые уникальные значения if not uniqTbl[val] then -- обновить информацию о минимальной и максимальной разнице for v,_ in pairs(uniqTbl) do dif = abs( val-v ) if not min or min>dif then min=dif fUpd=true end if not max or max<dif then max=dif fUpd=true end end -- пополнить таблицу уникальных значений uniqTbl[val] = true uniqCnt = uniqCnt + 1 end -- при обновлении вывести информацию на экран if fUpd then print(("uniq:%2d/%2d | min:%7.3f | max:%7.3f | max/min:%7.3f"):format( uniqCnt,i, round(min*mul), round(max*mul), round(max/min) )) end -- закончить по достижении результата if fUpd and max/min > 128 then break end end -- сообщить результат if fUpd and max/min > 128 then print(("Congratulations! geolyzerNoise = %f"):format( round(min*mul) )) else print("Failure! Tray again please!") end Результат Знание об особенностях генерации шума геосканера, позволило достичь абсолютно точных результатов при очень малом времени сканирования при вычислении константы шума геосканера. В лучшем случае результат можно получить за три сканирования. В типичном случае требуется около 20 сканирований, что требует около одной секунды времени. Самый худший случай не ограничен ничем, но использованное в моём скрипте ограничение в 99 сканирвоаний ни разу не было достигнуто за несколько сотен попыток. И это ещё не всё, что может дать знание о шуме геосканера. Пошумим, брат!
-
2 баллаВстречный вопрос: зачем? Для руд плотности известны. Для других блоков, вряд-ли разрабы модов будут сильно фантазировать. Вот возможные плотности для последнего майна: 50 30 22.5 10 5 4 3 2.8 2.5 2 1.8 1.5 1.4 1.25 1 0.8 0.75 0.6 0.5 0.4 0.3 0.2 0.1 Нестандартные видел только в Galacticraft: 6 2.2 0.9
-
1 баллНе знаю относится ли это к инфраструктуре но у меня есть такая программка интересная, она для планшета с улучшением чат, вы можете писать в чат от любого пользователя ^_^ local chat = require("component").chat chat.setName("§6L§8") local name = 'Locher' require("term").clear() local tmp = tostring(...) if tmp ~= '' then name = tmp end while true do io.write("> ") local msg = io.read() if msg then chat.say("§7"..name..': §q' .. msg) end end Вы можете выбирать префикс поменяв цифру перед символом параграфа, цвета смотрите в гугле) чтобы сделать же префикс допишите к "§7" сам префикс например "§7[Iridium]" . Такая же ситуация и с сообщением) можно писать цветным текстом, запомните, вы можете писать только в "локальном" чате, в глобал писать не сможете, чтобы запустить программу, пишите (имя вашего файла) (ник который вы хотите) пример: chat Vasya (можно и с маленькой буквы без разницы)
-
1 баллВсе оказалось очень просто, впрочем, как и все гениальное. Надо было пойти дальше и разобрать на атомы весь алгоритм наложения шума. Вот как легко и без лишней памяти классифицировать блок: Берем результат работы геосканера R, известную твердость блока H, расстояние до блока D, множитель шума из конфига N, подставляем это в следующую формулу: (R - H) / D / N * 128 * 33 % 1 Если результат не равен нулю, то это искомый блок. Стоит помнить, что точность значений 32 бита, поэтому при вычислении с большей точностью, надо результат округлять. Остается сократить половину формулы, чтобы делать меньше вычислений и получаем функцию, которая отсекает шум примерно на 99.31% Ура, товарищи!
-
1 баллЭто распределение получается, если провести обратную операцию и проверить совпадение в списке из 256 возможных вариантов шума для руды. При условии, что нет совпадения с шумом для камня. Серая область - распределение шумов камня, бирюзовая - руда, зеленая - распределение верно распознанной руды. Если добавить точно известную руду по максимуму камня (math.max(3 - R * 0.606, 1.5 + R * 0.06013)), тогда получаем вот такое: Вероятность попадания по руде вырастает до 70.695% На следующей гистограмме отображено решение задачи, для всех расстояний (на самом деле не для всех, но это более удобный масштаб) исходя из этой подсказки: Красная область - распределение значений для камня, при условии, что мы пытаемся угадать руду. Зеленая - верно распознанная руда. Область пересечения занимает 7377 точек, при том, что реально пересекаются только 492. Итого, надо хранить 6845 точек. Точность получаем таким образом: имеем 444210 возможных значений для руды или камня, из них уникальных - 8224, следовательно 6845/8224 = 83.232%, если бы мы гадали по чему-то одному. Если же просто исключать камень по таблице, то точность будет 99.89% Пока поищу способ, разделить с такой же точностью, но без таблицы. Есть такая штука, называется уровень инструмента, но могут быть еще дополнительные условия в коде игры/мода. Есть статья на вики, там написано, что такое твердость и зачем она нужна. Слово "плотность" подошла бы для взрывоустойчивости, но опенкомповский георадар работает на магии, поэтому мы обзываем твердость плотностью скорее по привычке.
-
1 баллЕсть идея при условии, что мы пробуем отличать блоки, твердость которых кратна 0.1 (для кварцевых и других блоков со странной плотностью не работает). Из неправильно выведенной мною формулы: Которая на самом деле N = P0 - R*0.0606*[rand(-128; 127)]/128 Будем перебирать возможные плотности блоков в диапазоне максимальной погрешности. На максимальном расстоянии будет больше 70 вариантов, но надо учесть, что плотность не может быть отрицательной (если это не бедрок), этот диапазон скорее всего можно будет сузить. Тогда из формулы рассчитываем число, выдаваемое генератором: K = (P0 - N)*128/(0.0606*R). Если полученное число целое или крайне близко к таковому, есть вероятность, что это нужный результат, надо будет проверить. Upd: Можно создать массив плотностей возможных блоков, а не подбирать с шагом в 0.1.
-
1 баллА точно нужно вычислять само расстояние? Если требуется сравнить расстояние с другим значением, можно просто само значение возвести в квадрат, вместо того, чтобы извлекать корень, это менее ресурсоемко. Я просканировал кучу блоков, и думаю плотность зависит напрямую от времени ломания блока подходящим типом инструмента. Точнее, соотношение времени ломания для одного и того же подходящего для выбранных блоков инструмента будет равняться соотношению плотностей. В основном они кратны 0.1, есть исключения, например кварцевый блок, у него 0.80000001192093, но я во всех случаях пренебрегал подобными хвостами. У листвы плотность 0.2, песка, земли, плотного льда - 0.5, блока алмаза, железа - 5. У факелов, некоторых редстоун-компонентов плотность 0 (они мгновенно ломаются рукой в выживании). Исключение - обсидиан, имеет плотность 50, точно такая же у небесного камня из AE2 (можно легко находить метеориты). Есть два блока из IC2, которые имеют относительно уникальные плотности: 20 у базальта и 80 у укрепленного камня, я их хотел использовать для того, чтобы роботы могли точно определять свои координаты без улучшения навигации. У бедрока плотность -1, скорее всего так будет для всех неломающихся блоков. Для всех вышеперечисленных блоков соблюдалась закономерность с временем ломания. И да, "hardness" - это скорее твердость, чем плотность, что лучше объясняет прямую зависимость значения от времени разрушения блока и значение -1 для бедрока.
Эта таблица лидеров рассчитана в Москва/GMT+03:00
