О серии
Во-первых, вы можете относиться к этому, как к любому другому вызову для игры в гольф, и отвечать на него, не беспокоясь о серии вообще. Тем не менее, существует таблица лидеров по всем задачам. Вы можете найти таблицу лидеров вместе с дополнительной информацией о серии в первом посте .
Несмотря на то, что у меня есть ряд идей для этой серии, будущие проблемы еще не заложены. Если у вас есть какие-либо предложения, пожалуйста, сообщите мне об этом в соответствующей песочнице .
Отверстие 6: Roll d20
Очень распространенный кубик в настольных РПГ - это двадцатигранный кубик ( икосаэдр , широко известный как d20 ). Ваша задача бросить такой кубик. Однако, если вы просто возвращали случайное число от 1 до 20, это было бы немного тривиально. Итак, ваша задача - создать случайную сеть для данного кубика.
Мы будем использовать следующую сеть:
Это треугольная полоса, поэтому ее легко представить в виде списка целых чисел. Например, если вам дают вход:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
Это соответствовало бы следующему кубику (забавный факт: это сеть, используемая Магией: Собрание счетчиков жизни / игральные кости).
Тем не менее, это не единственная сеть, представляющая этот кубик. В зависимости от того, как мы разворачиваем лица, существует 60 различных сетей. Вот еще два:
[1, 8, 9, 10, 2, 3, 4, 5, 6, 7, 17, 18, 19, 11, 12, 13, 14, 15, 16, 20]
[10, 9, 18, 19, 11, 12, 3, 2, 1, 8, 7, 17, 16, 20, 13, 14, 4, 5, 6, 15]
Или графически (я не поворачивал метки лица для простоты):
Соревнование
Учитывая список целых чисел, представляющих матрицу (как описано выше) и целое число N
, выведите N
независимо, равномерно случайные сети d20, соответствующие данному кристаллу. (То есть каждая из 60 возможных сетей должна иметь одинаковую вероятность генерации.)
Конечно, из-за технических ограничений PRNG идеальная однородность будет невозможна. Для оценки единообразия вашего представления следующие операции будут рассматриваться как обеспечивающие абсолютно равномерное распределение:
- Получение номера из PRNG (в любом диапазоне), который задокументирован, чтобы быть (приблизительно) равномерным.
- Отображение равномерного распределения по большому набору чисел в меньший набор по модулю или умножению (или какой-либо другой операции, которая распределяет значения равномерно). Большой набор должен содержать как минимум в 1024 раза больше возможных значений, чем меньший набор.
Учитывая эти предположения, ваш алгоритм должен давать идеально равномерное распределение.
Ваша программа должна быть способна генерировать 100 сетей менее чем за секунду (поэтому не пытайтесь генерировать случайные сети, пока одна из них не соответствует матрице, указанной выше).
Вы можете написать программу или функцию, принимая ввод через STDIN (или ближайшую альтернативу), аргумент командной строки или аргумент функции и выводя результат через STDOUT (или ближайшую альтернативу), возвращаемое значение функции или параметр функции (out).
Ввод и вывод могут быть в любом удобном, однозначном, плоском формате списка. Вы можете предположить, что номинальные значения d20 - это разные положительные целые числа, которые соответствуют естественному целочисленному типу вашего языка.
Это код гольф, поэтому выигрывает самое короткое представление (в байтах). И, конечно же, самая короткая заявка на пользователя также войдет в общую таблицу лидеров серии.
Примеры выходов
Для ввода
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
60 возможных сетей (при условии, что я не ошибся) в произвольном порядке:
[11, 10, 9, 18, 19, 20, 13, 12, 3, 2, 1, 8, 7, 17, 16, 15, 14, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
[8, 7, 17, 18, 9, 10, 2, 1, 5, 6, 15, 16, 20, 19, 11, 12, 3, 4, 14, 13]
[3, 12, 13, 14, 4, 5, 1, 2, 10, 11, 19, 20, 16, 15, 6, 7, 8, 9, 18, 17]
[3, 4, 5, 1, 2, 10, 11, 12, 13, 14, 15, 6, 7, 8, 9, 18, 19, 20, 16, 17]
[11, 19, 20, 13, 12, 3, 2, 10, 9, 18, 17, 16, 15, 14, 4, 5, 1, 8, 7, 6]
[4, 14, 15, 6, 5, 1, 2, 3, 12, 13, 20, 16, 17, 7, 8, 9, 10, 11, 19, 18]
[2, 10, 11, 12, 3, 4, 5, 1, 8, 9, 18, 19, 20, 13, 14, 15, 6, 7, 17, 16]
[4, 5, 1, 2, 3, 12, 13, 14, 15, 6, 7, 8, 9, 10, 11, 19, 20, 16, 17, 18]
[10, 2, 1, 8, 9, 18, 19, 11, 12, 3, 4, 5, 6, 7, 17, 16, 20, 13, 14, 15]
[3, 2, 10, 11, 12, 13, 14, 4, 5, 1, 8, 9, 18, 19, 20, 16, 15, 6, 7, 17]
[7, 8, 1, 5, 6, 15, 16, 17, 18, 9, 10, 2, 3, 4, 14, 13, 20, 19, 11, 12]
[13, 12, 11, 19, 20, 16, 15, 14, 4, 3, 2, 10, 9, 18, 17, 7, 6, 5, 1, 8]
[16, 15, 14, 13, 20, 19, 18, 17, 7, 6, 5, 4, 3, 12, 11, 10, 9, 8, 1, 2]
[15, 16, 17, 7, 6, 5, 4, 14, 13, 20, 19, 18, 9, 8, 1, 2, 3, 12, 11, 10]
[20, 13, 12, 11, 19, 18, 17, 16, 15, 14, 4, 3, 2, 10, 9, 8, 7, 6, 5, 1]
[5, 4, 14, 15, 6, 7, 8, 1, 2, 3, 12, 13, 20, 16, 17, 18, 9, 10, 11, 19]
[10, 11, 12, 3, 2, 1, 8, 9, 18, 19, 20, 13, 14, 4, 5, 6, 7, 17, 16, 15]
[4, 3, 12, 13, 14, 15, 6, 5, 1, 2, 10, 11, 19, 20, 16, 17, 7, 8, 9, 18]
[19, 20, 13, 12, 11, 10, 9, 18, 17, 16, 15, 14, 4, 3, 2, 1, 8, 7, 6, 5]
[1, 8, 9, 10, 2, 3, 4, 5, 6, 7, 17, 18, 19, 11, 12, 13, 14, 15, 16, 20]
[8, 1, 5, 6, 7, 17, 18, 9, 10, 2, 3, 4, 14, 15, 16, 20, 19, 11, 12, 13]
[18, 9, 8, 7, 17, 16, 20, 19, 11, 10, 2, 1, 5, 6, 15, 14, 13, 12, 3, 4]
[12, 3, 2, 10, 11, 19, 20, 13, 14, 4, 5, 1, 8, 9, 18, 17, 16, 15, 6, 7]
[2, 3, 4, 5, 1, 8, 9, 10, 11, 12, 13, 14, 15, 6, 7, 17, 18, 19, 20, 16]
[10, 9, 18, 19, 11, 12, 3, 2, 1, 8, 7, 17, 16, 20, 13, 14, 4, 5, 6, 15]
[9, 8, 7, 17, 18, 19, 11, 10, 2, 1, 5, 6, 15, 16, 20, 13, 12, 3, 4, 14]
[16, 17, 7, 6, 15, 14, 13, 20, 19, 18, 9, 8, 1, 5, 4, 3, 12, 11, 10, 2]
[17, 7, 6, 15, 16, 20, 19, 18, 9, 8, 1, 5, 4, 14, 13, 12, 11, 10, 2, 3]
[1, 5, 6, 7, 8, 9, 10, 2, 3, 4, 14, 15, 16, 17, 18, 19, 11, 12, 13, 20]
[9, 18, 19, 11, 10, 2, 1, 8, 7, 17, 16, 20, 13, 12, 3, 4, 5, 6, 15, 14]
[16, 20, 19, 18, 17, 7, 6, 15, 14, 13, 12, 11, 10, 9, 8, 1, 5, 4, 3, 2]
[5, 1, 2, 3, 4, 14, 15, 6, 7, 8, 9, 10, 11, 12, 13, 20, 16, 17, 18, 19]
[8, 9, 10, 2, 1, 5, 6, 7, 17, 18, 19, 11, 12, 3, 4, 14, 15, 16, 20, 13]
[13, 20, 16, 15, 14, 4, 3, 12, 11, 19, 18, 17, 7, 6, 5, 1, 2, 10, 9, 8]
[6, 15, 16, 17, 7, 8, 1, 5, 4, 14, 13, 20, 19, 18, 9, 10, 2, 3, 12, 11]
[6, 5, 4, 14, 15, 16, 17, 7, 8, 1, 2, 3, 12, 13, 20, 19, 18, 9, 10, 11]
[7, 6, 15, 16, 17, 18, 9, 8, 1, 5, 4, 14, 13, 20, 19, 11, 10, 2, 3, 12]
[19, 18, 17, 16, 20, 13, 12, 11, 10, 9, 8, 7, 6, 15, 14, 4, 3, 2, 1, 5]
[14, 15, 6, 5, 4, 3, 12, 13, 20, 16, 17, 7, 8, 1, 2, 10, 11, 19, 18, 9]
[17, 18, 9, 8, 7, 6, 15, 16, 20, 19, 11, 10, 2, 1, 5, 4, 14, 13, 12, 3]
[6, 7, 8, 1, 5, 4, 14, 15, 16, 17, 18, 9, 10, 2, 3, 12, 13, 20, 19, 11]
[14, 13, 20, 16, 15, 6, 5, 4, 3, 12, 11, 19, 18, 17, 7, 8, 1, 2, 10, 9]
[20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
[7, 17, 18, 9, 8, 1, 5, 6, 15, 16, 20, 19, 11, 10, 2, 3, 4, 14, 13, 12]
[15, 6, 5, 4, 14, 13, 20, 16, 17, 7, 8, 1, 2, 3, 12, 11, 19, 18, 9, 10]
[9, 10, 2, 1, 8, 7, 17, 18, 19, 11, 12, 3, 4, 5, 6, 15, 16, 20, 13, 14]
[2, 1, 8, 9, 10, 11, 12, 3, 4, 5, 6, 7, 17, 18, 19, 20, 13, 14, 15, 16]
[12, 13, 14, 4, 3, 2, 10, 11, 19, 20, 16, 15, 6, 5, 1, 8, 9, 18, 17, 7]
[17, 16, 20, 19, 18, 9, 8, 7, 6, 15, 14, 13, 12, 11, 10, 2, 1, 5, 4, 3]
[18, 17, 16, 20, 19, 11, 10, 9, 8, 7, 6, 15, 14, 13, 12, 3, 2, 1, 5, 4]
[18, 19, 11, 10, 9, 8, 7, 17, 16, 20, 13, 12, 3, 2, 1, 5, 6, 15, 14, 4]
[11, 12, 3, 2, 10, 9, 18, 19, 20, 13, 14, 4, 5, 1, 8, 7, 17, 16, 15, 6]
[15, 14, 13, 20, 16, 17, 7, 6, 5, 4, 3, 12, 11, 19, 18, 9, 8, 1, 2, 10]
[19, 11, 10, 9, 18, 17, 16, 20, 13, 12, 3, 2, 1, 8, 7, 6, 15, 14, 4, 5]
[12, 11, 19, 20, 13, 14, 4, 3, 2, 10, 9, 18, 17, 16, 15, 6, 5, 1, 8, 7]
[20, 16, 15, 14, 13, 12, 11, 19, 18, 17, 7, 6, 5, 4, 3, 2, 10, 9, 8, 1]
[13, 14, 4, 3, 12, 11, 19, 20, 16, 15, 6, 5, 1, 2, 10, 9, 18, 17, 7, 8]
[5, 6, 7, 8, 1, 2, 3, 4, 14, 15, 16, 17, 18, 9, 10, 11, 12, 13, 20, 19]
[14, 4, 3, 12, 13, 20, 16, 15, 6, 5, 1, 2, 10, 11, 19, 18, 17, 7, 8, 9]
Для любой другой сети, просто заменить каждое вхождение i
с i
го числа на входе (где i
находится 1-основе).
Связанные проблемы
Leaderboard
Первый пост серии генерирует таблицу лидеров.
Чтобы убедиться, что ваши ответы отображаются, начните каждый ответ с заголовка, используя следующий шаблон уценки:
## Language Name, N bytes
где N
размер вашего представления. Если вы улучшите свой счет, вы можете сохранить старые результаты в заголовке, вычеркнув их. Например:
## Ruby, <s>104</s> <s>101</s> 96 bytes
(Язык в настоящее время не отображается, но фрагмент требует и анализирует его, и я могу добавить таблицу лидеров по языкам в будущем.)
источник
Ответы:
Рубин, 160 байтов (rev B)
17 байтов сэкономлено благодаря предложениям Мартина Бюттнера.
Рубин, 177 байт (версия A)
объяснение
Можно генерировать все возможные ориентации путем поворота вокруг одной грани (в 3 раза), одной вершины (в 5 раз) и двух ребер (в 2 раза). Но не просто лицо и края. Оси должны иметь правильное соотношение, и вращения должны выполняться в правильном порядке, иначе могут произойти странные вещи.
Я так и сделал (хотя я понимаю, что Мартин сделал это по-другому)
Все ориентации тетраэдра могут быть созданы комбинацией следующих трех операций симметрии:
а) Поворот вокруг двух 2-кратных осей прямо через середины ребер (они находятся под прямым углом друг к другу. Если мы умножим их вместе, мы обнаружим третью 2-кратную ось через оставшуюся пару ребер.)
б) Вращение вокруг 3-кратной оси, диагональной 2-кратным осям, проходящей через вершину и грань.
Симметрия икосаэдра является надмножеством симметрии тетраэдра. На изображении ниже от https://en.wikipedia.org/wiki/Icosahedron желтые и красные грани определяют два разных тетраэдра (или, альтернативно, один октаэдр), в то время как края, общие для двух синих граней, находятся в трех парах на прямые углы (и лежат на гранях куба.)
Все ориентации икосаэдра могут быть получены с помощью упомянутых выше операций симметрии плюс дополнительная 5-кратная операция.
Вращения вокруг трех из четырех упомянутых осей представлены волшебными струнами между
''
метками. Вращение вокруг второй 2-кратной оси отличается, и может быть сделано только путем обращения массиваa[]
.Разгружен в тестовой программе:
Альтернативное решение 131 байт (неверно из-за подхода двоичного случайного блуждания, дает только приблизительно правильное распределение.)
Это схватка (так же, как программы, используемые для шифрования кубика Рубика.)
Конкретные повороты, которые я использую, являются двумя из наиболее очевидных:
-Вращение на 120 градусов (около граней 1 и 20 на первой диаграмме)
-Вращение на 72 градуса (около вершин, общих для 1,2,3,4,5 и 16,17,18,19,20 на первой диаграмме.)
мы подбрасываем монету 99 раз, и каждый раз выполняем одно из этих двух вращений в зависимости от того, голова это или хвост.
Обратите внимание, что чередование этих данных приводит к довольно коротким последовательностям. Например, при правильных ощущениях вращения, поворот на 180 градусов может быть произведен с периодом всего 2.
источник
b.map
не работает напрямую, мне нужноb.chars.map
заставить его работать (кстати, это не работает на моей машине, так как у меня Ruby 1.9.3, но работает на Ideone). Это справедливая экономия. Я не думаю, что изменение магических строк для непечатаемых символов для сохранения-64
воли сработает:%w{}
интерпретирует\n
(а также пробел) как разделитель между строками в сгенерированном массиве. Я понятия не имею, что он будет делать с другими непечатными символами ASCII.Машинный код IA-32, 118 байт
HexDump:
Это немного долго, поэтому некоторые объяснения идут в первую очередь. Я использовал почти тот же алгоритм, что и существующий ответ по уровню реки Св . Чтобы сделать свой ответ другим, я взял другие базовые перестановки, которые не обязательно имеют интуитивное геометрическое значение, но как-то более удобны.
Код в основном должен генерировать перестановку, которая представляет собой последовательное применение следующего:
p3
, применялась 0 ... 2 разаq2
, применяется 0 или 1 разp5
, применялась 0 ... 4 разаp2
, применялась 0 или 1 разЕсть много возможных вариантов для этих перестановок. Один из них выглядит следующим образом:
Этот выбор лучше, чем другие, потому что перестановки здесь имеют длинные последовательности последовательных индексов, которые могут быть сжаты кодированием по длине прогона - всего 29 байтов для 4 перестановок.
Чтобы упростить генерацию случайных чисел, я выбрал степени (сколько раз применяется каждая перестановка) в диапазоне 1 ... 30 для всех из них. Это приводит к большой дополнительной работе в коде, потому что, например,
p3
становится перестановкой идентификаторов каждый раз, когда она умножается на себя в 3 раза. Тем не менее, в этом случае код меньше, и пока диапазон делится на 30, выходные данные будут иметь равномерное распределение.Кроме того, мощности должны быть положительными, чтобы операция декодирования по длине прогона выполнялась хотя бы один раз.
Код имеет 4 вложенных цикла; схема выглядит так:
Я надеюсь, что этот псевдокод понятнее, чем код встроенной сборки ниже.
Некоторые забавные детали реализации:
call
и последующиеpop
для доступа к данным (закодированные перестановки), хранящиеся в кодеjecxz
Инструкция удобно позволяет мне использовать нулевые байты в качестве окончания процесса декодирования длины прогонаК счастью, число 30 (2 * 3 * 5) почти равно степени 2. Это позволяет мне использовать короткий код для генерации числа в диапазоне 1 ... 30:
Я использую инструкцию «деления общего назначения» (
aam
) для разделения байта на битовые поля (3-битная длина и 5-битный индекс); к счастью, в этой позиции в кодеcl = 0
, так что я извлекаю выгоду из обеих "сторон"xchg
источник