2010-06-23 3 views
4

Я пытаюсь выяснить способ создания случайных чисел, которые «чувствуют» случайные короткие короткие последовательности. Это для викторины, где есть четыре возможных варианта, и программное обеспечение должно выбрать одно из четырех мест, где можно поставить правильный ответ, прежде чем заполнять остальные три с помощью дистракторов.Лучшее случайное «чувство» целочисленного генератора для коротких последовательностей

Очевидно, что arc4random % 4 создаст более чем случайные результаты в течение длинной последовательности, но в краткой последовательности его вполне возможное (и частое появление!), Чтобы иметь пять или шесть одинаковых чисел, возвращаются в ряд. Именно этого я и стараюсь избегать.

Я также не хочу просто сказать «никогда не выбирайте один и тот же квадрат дважды», потому что это приводит только к трем возможным ответам на каждый вопрос, кроме первого. В настоящее время я делаю что-то вроде этого:

bool acceptable = NO; 
do { 
    currentAnswer = arc4random() % 4; 
    if (currentAnswer == lastAnswer) { 
    if (arc4random() % 4 == 0) { 
     acceptable = YES; 
    } 
    } else { 
    acceptable = YES; 
    } 
} while (!acceptable); 

Есть ли лучшее решение для этого, что я пропускаю?

+0

Я думаю, что ответ на этот вопрос будет сильно зависеть от того, сколько 4-сторонних «монет» подряд, поскольку может быть не решение для достаточно короткой последовательности. Вы наделали проблему сокращения степеней свободы, но моя интуиция говорит мне, что * любой * послевыборный процесс выбора уменьшит DoF. В вашем примере пост-вероятность того, что A будет следовать за А, станет 1/16 вместо 1/4 для A, B. Я ожидаю, что игрок заметит это, даже если она не заметила, что заметила. Люди действительно хороши в этом (так же, как и голуби). – msw

+0

Я должен был указать, что последовательности открыты. Я думаю, что для большинства игроков они будут относительно короткими (до 100), но теоретически вы можете играть часами и проходить тысячи вопросов. Я не думаю, что это слишком важно, потому что игроки вряд ли помнят последовательность для более чем нескольких вопросов назад, хотя, как вы говорите, они могут заметить это, не заметив, что они замечают. :) –

ответ

3

Если ваш вопрос заключается в том, чтобы вычислить currentAnswer с использованием вероятности вашего примера в не-итеративно, Guffa имеет свой ответ.

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

from random import randrange 
# randrange(a, b) yields a <= N < b 

def decluster(): 
    for i in range(seq_len): 
     j = (i + 1) % seq_len 
     if seq[i] == seq[j]: 
      i_swap = randrange(i, seq_len) # is best lower bound 0, i, j? 
      if seq[j] != seq[i_swap]: 
       print 'swap', j, i_swap, (seq[j], seq[i_swap]) 
       seq[j], seq[i_swap] = seq[i_swap], seq[j] 

seq_len = 20 
seq = [randrange(1, 5) for _ in range(seq_len)]; print seq 
decluster(); print seq 
decluster(); print seq 

, где любое отношение к фактическому рабочему коду Python является чисто случайным. Я уверен, что предыдущие вероятности поддерживаются, и это похоже на разрыв кластеров (и иногда добавляет некоторые). Но я довольно сонный, поэтому это касается только развлечений.

+0

Awesome. Я закончил реализацию чего-то подобного. Игра открыта, поэтому я просто генерирую 100 значений в строке, а затем генерирую еще 100, когда они заканчиваются. Это, безусловно, «кажется» более случайным, чем мой подход. –

+0

Спасибо за интересную проблему. После долгих размышлений, я почти уверен, что комиссия по игре в Vegas одобрила бы этот алгоритм как «единообразный» (предполагая достойный PRNG, который является arc4). – msw

+0

msw: Я сомневаюсь, что они позволят использовать PRNG, криптографически безопасные или нет :-). Я мог бы попытаться создать декоратор для наших RNG и запустить это через наши тесты. Но я думаю, что если вы избегаете кластеризации, вы также выбрасываете целую кучу возможных результатов. Equiprobability не только для теста Monobit, но и для более крупных сегментов. Это, как говорится, для этого вопроса, конечно, правильно - обычно обычно плохая идея ;-) – Joey

0

Чтобы уменьшить вероятность повторного использования на 25%, вы можете выбрать случайное число от 0 до 3.75, а затем повернуть его так, чтобы 0,75 попадали в предыдущий ответ.

Чтобы избежать использования значений с плавающей точкой, вы можете умножить на четыре факторы:

псевдокод (где / представляет собой целое деление):

currentAnswer = ((random(0..14) + lastAnswer * 4) % 16)/4 
0

Настройка взвешенного массива. Допустим, последнее значение было равным 2. Сделайте такой массив:

array = [0,0,0,0,1,1,1,1,2,3,3,3,3]; 

Затем выберите число в массиве.

newValue = array[arc4random() % 13]; 

Теперь переключитесь на использование математики вместо массива.

newValue = (((arc4random() % 13)/4) + 1 + oldValue) % 4; 

Для получения возможности P и вес 0<W<=1 Использование:

newValue = (((arc4random() % (P/W-P(1-W))) * W) + 1 + oldValue) % P; 

При Р = 4 и W = 1/4, (P/WP (1-W)) = 13. Это говорит последнее значение будет на 1/4 больше, чем другие значения.

Если вы полностью устраните самый последний ответ, это будет так же заметно, как и самый последний ответ, который появляется слишком часто. Я не знаю, какой вес будет вам прав, но 1/4 является хорошей отправной точкой.

3

Вы заселить массив результатов, то shuffle его, а затем назначить их в таком порядке.

Так всего за 8 вопросов:

answer_slots = [0,0,1,1,2,2,3,3] 

shuffle(answer_slots) 

print answer_slots 
[1,3,2,1,0,2,3,0] 
+0

Это так же вероятно, как случайные кластеры. – msw

+0

@msw: Они будут только до тех пор, пока вы позволите им быть. Например, если вы перетасовываете '0..3 * 3', может быть до трех вхождений одного и того же номера. – Joey

+0

aye, если набор имеет длину 8, 87% возможных наборов имеют по крайней мере одну смежность. В этом случае вы не могли бы сделать лучше этого. – msw

Смежные вопросы