Виправити порушену випадкову функцію


18

Друг має на своєму комп’ютері додаткову карту, яка генерує ідеально випадкове число від 1 до 5 включно. На жаль, вони як-небудь пролили на нього кола, і тепер вона генерує лише 2-х для всіх чисел від 1 до 4. На щастя, випадковість збережена, але 2 мають вірогідність 80%, а 5 - ймовірність 20%, і немає Згенеровано 1, 3 або 4. Використовуючи це випадкове джерело (назвіть його BrokenRand()чи щось подібне), запишіть робочий генератор випадкових чисел, який створює числа від 1 до 5, кожне з рівними 20% -ною ймовірністю з такою ж ідеальною випадковістю, що і вихідне джерело.

Найкоротша програма виграє. Бонусні бали, що присуджуються за мінімальну кількість дзвінків BrokenRandнеупереджено шляхом демографічно підібраного консалтингу з обслуговування клієнтів, розбитий за віком і статтю - тобто мені.

Відповіді:


10

JavaScript - 69 символів

Для цього використовується витяжка фон Неймана для отримання об'єктивних шматочків; загальний алгоритм також описаний на веб-сайті HotBits . Три біти використовуються для формування числа від 0 до 7. Усі числа 5 і вище відкидаються, а 1 додається до кожного з решти перед їх надрукуванням. Я зробив імітацію, щоб показати, що це не дуже упереджено .

Вам потрібно надати власну функцію r()для доступу до RNG.

 for(;;v<5&&alert(v+1))for(v=i=0;i<3;a-b&&(v*=2,v+=a<b,i++))b=r(a=r())

Це дійсно добре зроблено! Мені подобається, як ви коротко замикаєте значення приросту.
snmcdonald

Ви можете генерувати 7 біт і витягувати 3 випадкових числа, щоб зменшити виклики до BrokenRand, але це, швидше за все, коштуватиме ще декількох ударів
gnibbler

5

Скала 79 символів:

// preparation: 
val r = util.Random 
def defektRNG = if (r.nextInt (5) == 0) 5 else 2 

(1 to 20).foreach (_ => print (" " + defektRNG))
// first impression:
// 2 2 2 2 2 2 2 5 2 2 5 2 2 2 5 2 2 2 2 2

def rnd : Int = { val k = (1 to 5).map (_ => defektRNG)
  if (k.sum == 13) k.findIndexOf (_ == 5) + 1 else rnd } 

// first impression:
(1 to 20).foreach (_ => print (" " + rnd))             
// 3 3 2 3 5 2 2 5 1 1 3 4 3 2 5 3 3 1 5 4
// control:
(1 to 50000).map (_ => rnd).groupBy (identity) .map (_._2.length) 
// scala.collection.immutable.Iterable[Int] = List(10151, 9997, 9971, 9955, 9926)

Тепер для справжнього гольфу, defektRNG псевдонім битийRand перейменований на b.

def r:Int={val k=(1 to 5).map(_=>b)
if(k.sum==13)k.findIndexOf(_==5)+1 else r} 

Як це працює: Найчастіше, b повертає послідовність 2s. Але якщо ви зробите 5 дзвінків на b, ви дуже часто закінчитеся результатом 4x2 та 1x5, це друга найбільш вірогідна подія, і це може бути 5-2-2-2-2, 2-5-2-2 -2, 2-2-5-2-2, 2-2-2-5-2 та 2-2-2-2-5.

Вони мають спільне, що сума дорівнює 4 * 2 + 5 = 13. Індекс першої п'ятірки може бути використаний для визначення дійсного випадкового числа. Якщо їх більше або менше, ніж 5, сума більша або менша 13, повторіть.

Лічильник в 'rnd' aka 'r' може показувати, скільки дзвінків потрібно в середньому для отримання номерів. Існує 121 200 дзвінків до r на 50 000 випадкових чисел, що не вражає. :)


3

> <> (Риба) - 55 байт

Оновлено, щоб використовувати той самий алгоритм, що і @user невідомий у своїй відповіді на шкалу

<v? = d + &: i & + &: i & + &: i & + &: i &: i
 0
 > 1 + $ 5 (? Vnao;
 ^ <

Він очікує підключення пошкодженого генератора до stdin; ось сценарій python, який я використав . Код відповідає поточній специфікації Fish, але я використав модифіковану версію старого перекладача.

bash:$ for i in $(seq 1000); do ./bad_rand.py | ./myfish.py rand.fish; done >res.txt
bash:$ for i in $(seq 5); do echo -n "$i : "; grep -c $i res.txt; done
1 : 193
2 : 204
3 : 198
4 : 206
5 : 199

Я б зробив більшу пробу, але це повільно.


2

GolfScript, 23 байти

Пізня відповідь, але оскільки це щойно трапилося, вискочив на першій сторінці ...

0{;[{r}5*].5?)\5-,4-}do

Використовується той же алгоритм, що і для Scala рішення невідомого користувача . Передбачає, що генератор упереджених випадкових чисел задається у вигляді підпрограми GolfScript з назвою r; ви можете самостійно визначити відповідний упереджений RNG, наприклад:

{5rand!3*2+}:r;

Ось швидкий тест, що демонструє відсутність упередженості. На жаль, онлайн-сервер GolfScript є дещо повільним, тому мені довелося скоротити демонстрацію до всього 100 зразків, щоб вчасно завершити роботу. Якщо ви запускаєте тест локально за допомогою інтерпретатора GolfScript , спробуйте збільшити 100*до 1000*або навіть 10000*.

(Сервер GolfScript також іноді випадковим чином зависає та вичерпується в будь-якому випадку. Якщо це трапляється у вас, повторне намагання зазвичай вирішує це. Це трапляється і з іншим кодом, і це відбувається лише на сервері, а не на моєму власному комп’ютері, тому я впевнений що це проблема із сервером, а не з моїм кодом.)


-1

javascript, 160 символів, не знижуючи читабельності, також оптимізації

function giveRandom(){
    var result = Math.floor(5 * Math.random()) + 1;
    while(BrockenRand() != 5){
        result = Math.floor(5 * Math.random()) + 1;
    }
    return result;
}

@ snmcdonald -деякі не є помилковими, це спосіб поліпшити js випадковим шляхом досконалим генератором випадкових випадків, що затверджує лише (абсолютно випадковий!) 20% результати
www0z0k

Хочете пояснити, що BrockenBand()тоді?
Mateen Ulhaq

6
Я думаю, ви пропустили пункт
cthom06

@muntoo - значитьBrockenRand
www0z0k

Збережіть кілька байтів таким чином:function giveRandom(){return Math.ceil(Math.random()*5)}
user300375
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.