Size: a a a

2021 March 30

DP

Defragmented Panda in pro.algorithms
Anatoly Tomilov
вызывая rand7 я генерирую a = log2(7) бит. Мне надо b = log2(10). Можно ли придумать какой-то "аккумулятор" acc, который бы комбинировал эти a бит с очередной порцией a бит, пока сумма не превысит b бит, а затем можно было бы извлечь  b бит и floating-point "счётчик количества бит в аккумуляторе" уменьшить на b? Т.е. вообще без rejection обойтись?
экстракторы энтропии

и более простой случай - домнажай акуммулятор на новое случайное число, (удаляй бит с начала и конца аккумулятора), бери модуль по 10. ответ по модулю - твой новый ответ. результат деления на 10 - твой новый аккумулятор
источник

DP

Defragmented Panda in pro.algorithms
это моя фантазия на тему https://en.wikipedia.org/wiki/Middle-square_method
источник

DP

Defragmented Panda in pro.algorithms
а это если делать по-хорошему https://en.wikipedia.org/wiki/Randomness_extractor
источник

DP

Defragmented Panda in pro.algorithms
Anatoly Tomilov
почему для этой задачи заходит такое решение?
class Solution {
public:
   int rand10() {
       for (int i = 0; i < 9; ++i) {
           acc += rand7() - 1;
       }
       int result = acc % 10;
       acc /= 10;
       return result + 1;
   }
private:
   int acc = rand7();
};

разве у меня остаток от деления суммы десяти U([0;6]) на 10 не будет распределён неравномерно?
тут будет 8 сложений 0...6

в среднем около 21, с очень острым пиком около 21
источник

DP

Defragmented Panda in pro.algorithms
источник

DP

Defragmented Panda in pro.algorithms
возможно они подобрали условия когда перекрытие правой и левой части дает почти равномерное распределение
т.е пик около области 19 20 21 22 23

остатки от %10 там
9 0 1 2 3

но края этой области покрывают те же числа второй раз
11 12 13 14 15 16 17 18 19 20 21
(слева от пика)
с перевесом около 9

справа от пика ситуация обратная. я не уверен что это все выравнивает. но возможно
источник

DP

Defragmented Panda in pro.algorithms
вертикаль - шанс этой суммы
горизонталь - значение в результате sum8(rand 0-6)
источник

DP

Defragmented Panda in pro.algorithms
источник

DP

Defragmented Panda in pro.algorithms
вот. это самое важное - форма распределения от сложения случайных независимых.

чем больше слагаемых - тем уже (относительно) пик. но шире в абсолютных единицах.

и только 2 слагаемых дают линейное распределение (треугольник) все остальные дают непонятную кривую, с которой я не уверен что будет если сложить ее со сдвигом с самой собой (как делают в твоем примере)
источник

AT

Anatoly Tomilov in pro.algorithms
Defragmented Panda
экстракторы энтропии

и более простой случай - домнажай акуммулятор на новое случайное число, (удаляй бит с начала и конца аккумулятора), бери модуль по 10. ответ по модулю - твой новый ответ. результат деления на 10 - твой новый аккумулятор
class Solution {
public:
   int rand10() {
       for (;;) {
           while (h < 10) {
               h *= 7;
               i *= rand7(); // in {1, 2, ..., 7}
           }
           int a = (h / 10) * 10;
           if (i <= a) {
               int result = (i - 1) % 10 + 1;
               i = (i - 1) / 10 + 1;
               h /= 10;
               return result;
           } else {
               i -= a;
               h -= a;
           }
       }
   }
private:
   int h = 1;
   int i = 1;
};
это тоже не заходит. Я здесь ту часть "случайности", которая не использована, сохраняю до следующего вызова. Сгенерированные 100000 rand10 действительно распределены неравномерно. Не могу понять в чём моя ошибка. Нельзя использовать неиспользованные разряды из предыдущей попытки? h здесь — объём гиперкуба, а i — индекс целой точки (распределённой равномерно (кмк)) в нём.
источник
2021 March 31

@N

@urandon Nikita Khom... in pro.algorithms
Kotomord_λapki
как-то предобсчитать, чтобы каждый запрос на логарифм потом
Сканлайн
источник

K

Kotomord_λapki in pro.algorithms
@urandon Nikita Khomutov
Сканлайн
О, это оффлайн посчитать можно?
источник

K

Kotomord_λapki in pro.algorithms
Сразу много таких запросов
источник

K

Kotomord_λapki in pro.algorithms
Круть
источник

@N

@urandon Nikita Khom... in pro.algorithms
Kotomord_λapki
О, это оффлайн посчитать можно?
Конечно, индекс оффлайн можно считать. Если ещё и на персистентных красно-черных деревьях, то можно гарантию на n log n иметь
источник

K

Kotomord_λapki in pro.algorithms
Так, можно будет потом в личку поспрашивать?
источник

@N

@urandon Nikita Khom... in pro.algorithms
Поспрашивай, правда не факт, что буду доступен
источник

АJ

Артём Jin in pro.algorithms
https://stepik.org/course/Быстрый-старт-в-спортивное-программирование-64454/ ребят, кто проходил, знает, что скажете по поводу курсов, стоит прорешивать?
источник

АJ

Артём Jin in pro.algorithms
Не бейте за рекламу).
источник

DP

Defragmented Panda in pro.algorithms
Anatoly Tomilov
class Solution {
public:
   int rand10() {
       for (;;) {
           while (h < 10) {
               h *= 7;
               i *= rand7(); // in {1, 2, ..., 7}
           }
           int a = (h / 10) * 10;
           if (i <= a) {
               int result = (i - 1) % 10 + 1;
               i = (i - 1) / 10 + 1;
               h /= 10;
               return result;
           } else {
               i -= a;
               h -= a;
           }
       }
   }
private:
   int h = 1;
   int i = 1;
};
это тоже не заходит. Я здесь ту часть "случайности", которая не использована, сохраняю до следующего вызова. Сгенерированные 100000 rand10 действительно распределены неравномерно. Не могу понять в чём моя ошибка. Нельзя использовать неиспользованные разряды из предыдущей попытки? h здесь — объём гиперкуба, а i — индекс целой точки (распределённой равномерно (кмк)) в нём.
сгенерируй 7 чисел d7

запиши подряд их

сгенерируй восьмое d7 и вставь b000 биты в позицию указанную в этом числе, получив 8 значений 0-7 с идеальным распределением и не теряя ни бита случайности

хочешь меньше предсказуемости о частоте встречаемости b000? используй группы 7*7 чисел d7 или еще больше, 7^n, добавив 2 или n b000
источник