Виберіть випадкове число між 0 і n, використовуючи постійне джерело випадковості


26

Завдання

З огляду на додатне ціле число nменше 2^30вказаного як введення будь-яким обраним вами способом, ваш код повинен виводити випадкове ціле число між 0і n, включно. Кількість, яку ви генеруєте, слід вибирати рівномірно випадково . Це кожне значення від 0до nповинно відбуватися з однаковою ймовірністю (див. Правила та застереження).

Правила та застереження

Ваш код може припускати, що будь-який генератор випадкових чисел, вбудований у вашу мову або стандартну бібліотеку, який стверджує, що є рівномірно випадковим, насправді є рівномірним. Тобто вам не доведеться турбуватися про якість випадкового джерела, яке ви використовуєте. Однак,

  • Ви повинні встановити , що якщо випадковий джерело , який ви використовуєте рівномірний , то ваш код правильно виводить рівномірний випадкове число від 0до n.
  • Будь-які аргументи при виклику вбудованої або бібліотечної випадкової функції повинні бути постійними. Тобто вони повинні бути повністю незалежними від вхідного значення.
  • Ваш код може припинятися з ймовірністю 1, а не гарантовано припиняти його.

Примітки

  • randInt(0,n) недійсний, оскільки він приймає дані як аргумент вбудованої або бібліотечної функції.
  • rand()%nбуде НЕ дають рівномірне випадкове число в цілому. Як приклад, поданий betseg, якщо intmax == 15і n = 10, тоді ви будете набагато більше шансів отримати 0-5ніж 6-10.
  • floor(randomfloat()*(n+1)) також не даватиме рівномірного випадкового числа в цілому через кінцеве число різних можливих значень з плаваючою точкою між 0 і 1.

Як ви збираєтесь підтвердити, що вихід однаково випадковий? Можливо, така мова / бібліотека видаватиме рівномірно випадкові числа, але маніпуляція може призвести до нерівномірного виведення. (наприклад, rng()передбачає 0- 100, якщо n = 75і функція є rng()%75, то 0-25 буде більш поширеним ...)
Baldrickk

1
@Baldrickk Мудрістю натовпу :) Ми можемо лише читати код і думати про нього.

Сумний висновок, що задає найпростіший можливий питання теорії ймовірностей: випадковість та ймовірність дуже погано зрозуміли. :( (І правила читання важко, мабуть.)
Мартін Ендер

Це спадає на думку: Випадкове число
BgrWorker

Чому ви прийняли відповідь x86, коли є три коротші?
Денніс

Відповіді:


25

x86 машини з rdrandінструкцією, 10 байт

BITS 64

_try_again:

 rdrand eax
jnc _try_again

 cmp eax, edi
ja _try_again

 ret

машинний код

0FC7F0 73FB 39F8 77F7 C3

Вхід знаходиться в регістрі, rdiа вихід у rax.
Це поважає SYS V AMD64 ABI, тому код ефективно реалізує функцію C

unsigned int foo(unsigned int max); 

з 32-бітовими вкладками.

Інструкція rdrandописана Intel

RDRANDповертає випадкові числа, що поставляються криптографічно захищеним, детермінованим генератором випадкових бітів DRBG. DRBG розроблений відповідно до стандарту NIST SP 800-90A .

Що стосується CSRNG, то мається на увазі, що розподіл є рівномірним, цитуючи NIST SP 800-90A:

Випадкове число - це примірник неупередженої випадкової величини, тобто вихід, отриманий за допомогою рівномірно розподіленого випадкового процесу.


Процедура генерує випадкове число, і якщо воно не суворо перевищує вхід, воно повертається.
В іншому випадку процес повторюється.

Оскільки eaxє 32-бітним, rdrandповертає число між 0 і 2 32 -1, тому для кожного n у [0, 2 32 -1] кількість очікуваних ітерацій становить 2 32 / (n + 1), яке визначено для всіх n в [0, 2 30 ).


Блискуче низький рівень. Дякую.

Для чого jnc?
l4m2

@ l4m2 rdrandвстановлює, якщо CFповернені дані є дійсними. Дані можуть бути недійсними, оскільки надто багато запитів виснажили пул ентропії. Див. Ручний запис для rdrand та це .
Маргарет Блум

20

Желе , 7 6 байт

⁴!!X%‘

Дякуємо @JonathanAllan за те, що виграли 1 байт!

Неможливо запустити TIO, оскільки (16!)! це величезна кількість.

Як це працює

⁴!!X%‘  Main link. Argument: n

⁴       Set the return value to 16.
 !!     Compute (16!)!.
   X    Pseudo-randomly choose an integer between 1 and (16!)!.
        Since (16!)! is evenly divisible by any k ≤ 2**30, it is evenly divisible
        by n+1.
    %‘  Take the result modulo n+1.

Це виправлена ​​версія моєї видаленої відповіді, та сама ідея. Хоча в мене було зайве вираження.
orlp

Вибачте, я не оглядав його перед публікацією.
Денніс

О, це не має значення, я все одно не планував це виправляти. Мені занадто незручно з Jelly, щоб справді пограти з цим.
orlp

1
"Сер, я не знаю, чому ти злий. Алгоритм - це постійний час. Це гарна річ, правда? Чому безпека та кадрові послуги за дверима?"
corsiKa

1
Домовились. Трохи різниця між восьмизначним числом та 417 числом квінтільйонного числа: p
Джонатан Аллан

11

Математика, 29 байт

На основі відповіді Дженніса Желе .

RandomInteger[2*^9!-1]~Mod~#&

Я б не рекомендував насправді це виконувати. 2e9!це досить велика кількість ...

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

Вибірка відхилення, 34 байти

Мій старий підхід, який призвів до дещо цікавішого коду:

13!//.x_/;x>#:>RandomInteger[13!]&

Основний відбір проб відхилення. Ми ініціалізуємо вихід до 13! (що більше максимального вводу 2 30 ), а потім повторно замінити його випадковим цілим числом від 0 до 13! до тих пір, поки значення більше, ніж вхідне.


1
Ви маєте на увазі "менший або рівний входу"?

1
@Lembik Ні. Ми хочемо відновити значення до тих пір, поки воно не потрапить у потрібний діапазон.
Мартін Ендер

О Я бачу. Я чомусь подумав, що ми неодноразово проводили вибірку з потрібного діапазону. Спасибі.

1
Нагадайте, щоб наступний раз додати обмеження часу :)

9

Брахілог , 9 байт

≥.∧13ḟṙ|↰

Спробуйте в Інтернеті!

Це використовується 13!як у відповіді Мартіна Ендера ( 13ḟна один байт менше 2^₃₀).

реалізовано з використанням random_between/3, яке, викопуючи джерело, використовує те, random_float/0що пов'язане з цим, random/1використовує єдиний для наших цілей алгоритм Mersenne Twister.

Пояснення

≥.           Input ≥ Output
  ∧          And
   13ḟṙ      Output = rand(0, 13!)
       |     Else
        ↰    Call recursively with the same input

7

Пролог (SWI) , 38 байт

X*Y:-Z is 2^31,random(0,Z,Y),Y=<X;X*Y.

Працює шляхом відбору вибірки.

Створіть випадкове число між 0 і 2 ^ 31-1 = 2147483647, поки не буде знайдено один менший або рівний вхідному значенню.

Я відчуваю себе так, ніби я повинен мати можливість використовувати розріз замість іншого, але не можу зрозуміти, як.


1
Ви можете уникнути іншого використання repeat, але в кінцевому підсумку це 3 байти довше ... Я не впевнений, чи існує коротший спосіб мати нескінченний вибір пункту, ніж повторити.
Фаталізувати

@Fatalize: Так, я також спробував повторити. У мене була пам’ять про те, ,!.щоб використовувати щось на кшталт примушування назад, але я пам’ятаю його неправильно, або це не застосовується до цього рішення.
Емінья

7

Лабіринт , 63 байти

 ?
 #00}__""*_
 ;    #"  _
{-{=  } "><)
!{ : ;"({ +
@  }}:  >`#

(Дякуємо @MartinEnder за допомогу у важких полях для гольфу тут.)

Лабіринт - це двомісна мова, і єдине його джерело випадковості знаходиться в такій ситуації:

   x
  "<)
 " "
 " "

Припустимо, що вказівник інструкції знаходиться на xта рухається вниз. Далі він висаджується на <, що, якщо верхня частина стека дорівнює 0 (що завжди буває у фактичній програмі вище), зміщує поточний рядок, залишений на 1:

   "
 "<)
 " "
 " "

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

По суті, те, що робить програма вище, використовує функцію випадковості для генерування 100-бітових чисел (100 вказаних #00тут) і продовжувати циклічно, поки не генерує число <= n.

Для тестування, ймовірно, допоможе використовувати #0"замість цього 10-бітові числа, тому "що це шлях не входить Спробуйте в Інтернеті!

Грубе пояснення:

 ?            <--- ? is input and starting point
 #0"}__""*_   <--- * here: first run is *0, after that is *2 to double
 ;    #"  _
{-{=  } "><)  <--- Randomness section, +0 or +1 depending on path.
!{ : ;"({ +        After <, the >s reset the row for the next inner loop.
@  }}:  >`#

 ^    ^
 |    |
 |    The " junction in this column checks whether the
 |    100-bit number has been generated, and if not then
 |    continue by turning right into }.
 |
 Minus sign junction here checks whether the generated number <= n.
 If so, head into the output area (! is output as num, @ is terminate).
 Otherwise, head up and do the outer loop all over again.

7

Пітон, 61 байт

from random import*
lambda n,x=2.**30:int(randrange(x)*-~n/x)

Редагувати: оновлено, щоб уникнути забороненої форми

Edit2: збережено 2 байти, дякую @ JonathanAllan

Edit3: заплатив 2 байти за повністю функціональне рішення - ще раз дякую @JonathanAllan

Edit4: Видалено f=, збереження 2 байтів

Edit5: Збережено ще 1 байт завдяки @ JonathanAllan

Edit6: Збережено ще 2 байти завдяки @ JonathanAllan

На сьогоднішній день винна гіта вказувала б на мене за погані речі, а на Джонатана Аллана на речі, які допомагають.

Edit7: Коли йде дощ, він наливає - ще 2 байти

Edit8: І ще 2 байти


1
Ця річ ніколи не виводиться n, але ви можете зберегти два байти, коли ви виправите це за допомогою from random import*та випадання r..
Джонатан Аллан

1
Так, ви можете використовувати "оператора пуголовка", щоб уникнути необхідних дужок, ...*(-~n*1.0/2**30))а не...*((n+1)*1.0/2**30))
Джонатана Аллана,

1
Дійсно? Солодке! У вас є якась давня кривда проти числа 70? Велике спасибі за вашу допомогу
iwaseatenbyagrue

1
Насправді, randrangeздається, приймає поплавок, тому lambda n,x=2.**30:int(randrange(x)*-~n/x)зберігає ще два [редагувати ...] чотири!
Джонатан Аллан

1
^ ще двоє там із видаленням дужок. Просто іде, щоб показати ваше множення було шляхом!
Джонатан Аллан

6

Python 2 , 61 байт

from random import*
lambda n:map(randrange,range(1,2**31))[n]

Псевдовипадково вибирає цілі числа від 0 до k для всіх значень k між 0 і 2 31 - 2 , потім приймає ціле число, відповідне k = n .


5

Пакетна, 64 байти

@set/ar=%random%*32768+%random%
@if %r% gtr %1 %0 %1
@echo %r%

%random%дає лише 15 біт випадковості, тому мені доводиться поєднувати два випадкових числа. Цикли, поки випадкове значення не лежить у бажаному діапазоні, так повільно для низьких n; 98 байт для більш швидкої версії:

@set/a"n=%1+1,m=~(3<<30)/n*n,r=%random%*32768+%random%
@if %r% geq %m% %0 %1
@cmd/cset/a%r%%%%n%

Код може бути повільним, але ваша відповідь була швидкою!

3
@Lembik У мене було готове відповісти на ваше видалене запитання ...
Ніл

Чи не буде це спочатку відповідністю потрібне число, а потім усі інші числа, які виявились більшими за n?
Erik the Outgolfer

@EriktheOutgolfer Ні; якщо ви не використовуєте call, виклик пакетного сценарію припиняє поточний сценарій.
Ніл

5

MATL , 12 байт

Дякуємо @AdmBorkBork та @Suever за те, що вони сказали мені, як відключити кеш-пам'ять TIO.

`30WYrqG>}2M

Спробуйте в Інтернеті! .

Для цього використовується метод відхилення : генерувати випадкове ціле число від 0до 2^30-1та повторювати, поки воно перевищує вхідний n. Це гарантовано припинити з ймовірністю 1, але середнє число ітерацій 2^30/n, і тому вона займає дуже багато часу , nзначно менше 2^30.

`         % Do...while
  30W     %   Push 2^30
  Yr      %   Random integer from 1 to 2^30
  q       %   Subtract 1
  G>      %   Does it exceed the input? If so: next iteration. Else: exit
}         % Finally (execute right before exiting the loop)
  2M      %   Push the last generated integer
          % End (implicit). Display (implicit)

4

JavaScript (ES6), 55 54 байти

f=(n,m=1)=>m>n?(x=Math.random()*m|0)>n?f(n):x:f(n,m*2)

Породжує цілі числа в діапазоні [0 ... 2 k - 1] , де k - найменше ціле число, таке, що 2 k більше, ніж n . Повторюється, поки результат не потрапить у [0 ... n] .

Чому?

Це ґрунтується на таких припущеннях:

  • Внутрішньо цілі значення псевдовипадкових цілих чисел, що генеруються двигуном JS для подачі, Math.random()є рівномірними за будь-який інтервал [0 ... 2 k -1]k <32 ).

  • Помноживши на точну потужність 2, величини IEEE 754 поплавця, повернуті Math.random(), залишаються рівномірними протягом таких інтервалів.

Якщо хтось може підтвердити або спростувати ці гіпотези, будь ласка, повідомте мене про це у коментарях.

Демо

Створює 1 мільйон значень у [0 ... 2] та відображає статистику результатів.


Math.floor (Math.random () * (n + 1)) дає не менш рівномірно розподілені результати для мене, тому було б непогано побачити, чи є реалістичні N <2 ^ 30, які дадуть будь-які аномалії розподілу зовсім.
зеппелін

1
@zeppelin вам знадобиться занадто багато пробних циклів, щоб точно визначити будь-які аномалії, оскільки випадковий поплавок у цьому діапазоні матиме одне з 2 ^ 53 значень, яке буде розподілено максимально рівномірно за 2 ^ 30 результатами. Тож навіть для великої кількості в діапазоні помилка буде чимось на зразок 1 на 2 ^ 23, а це означає, що вам знадобиться смішна кількість випробувань. Ви, мабуть, захочете на кілька порядків більше, ніж кількість початкових зразків (2 ^ 53). Тим не менш, він не може бути абсолютно рівномірним, якщо множник не розділить рівномірно кількість вибірок, через що Arnauld використовує потужність дві.
Мартін Ендер

4

Bash (+ coreutils), 44 байти

/ dev / рішення на основі випадкових обставин

od -w4 -vtu4</d*/ur*|awk '($0=$2)<='$1|sed q

Читає 32-бітові цілі без підпису /dev/urandomта відфільтровує їх до awkтих пір, поки не знайде одне в заданому діапазоні, а потім sed qперерве трубу.


Ура для bash :)

4

Haskell, 70 байт

import System.Random
g n=head.filter(<=n).randomRs(0,2^30)<$>getStdGen

Не дуже ефективний алгоритм, але він працює. Він генерує нескінченний список цілих чисел (або плаває, якщо це потрібно, через систему типу Хаскелла), обмежених [0,2 ^ 30], і приймає перше менше або рівне n. Для малих росіян це може зайняти тривалий час. Випадкові числа повинні бути розподілені рівномірно, як зазначено в документації до randomR, тому всі числа в інтервалі [0,2 ^ 30] повинні мати однакову ймовірність (1 / (2 ^ 30 + 1)), тому всі числа в [ 0, n] мають однакову ймовірність.

Альтернативна версія:

import System.Random
g n=head.filter(<=n).map abs.randoms<$>getStdGen

Ця версія жахлива, але вона економить цілий байт. randomsвикористовує довільний діапазон, визначений типом, для створення нескінченного списку чисел. Це може включати негативи, тому нам потрібно відобразити їх, absщоб примусити їх бути позитивними (або нульовими). Це надзвичайно повільно для будь-яких значень n, які не є абсурдно великими. EDIT : Пізніше я зрозумів, що ця версія не розподілена рівномірно, тому що ймовірність отримати 0 гірша, ніж інші числа через використання abs. Для того, щоб зробити кілька mгенератора може виробляти mабо , -mале в разі 0 0 тільки сам буде працювати, тому його ймовірність дорівнює половина інших чисел.


Ура для Haskell (теж)!

4

Желе , 9 байт

⁴!Ẋ’>Ðḟ⁸Ṫ

Спробуйте в Інтернеті! - код вище не буде працювати на TIO, оскільки діапазон розмірів 16! спочатку треба будувати (не кажучи вже про те, що їх потім потрібно перемішати, а потім відфільтрувати!), так що це те саме в набагато менших масштабах, повторене 30 разів для введення 3 із обмеженням 10.

Як?

⁴!Ẋ’>Ðḟ⁸Ṫ - Main link: n
⁴         - 16
 !        - factorial: 20922789888000
  Ẋ       - shuffle random: builds a list of the integers 1 through to 16! inclusive and
          - returns a random permutation via Python's random.shuffle (pretty resource hungry)
   ’      - decrement (vectorises - a whole pass of this huge list!)
     Ðḟ   - filter out if: (yep, yet another pass of this huge list!)
    >     -     greater than
       ⁸  -     left argument, n
        Ṫ - tail: return the rightmost remaining entry.

Зауважте: було б більш ніж у тисячу разів ефективнішим для одного і того ж підрахунку байтів, якби ȷ⁵зробити те, що можна було б наївно очікувати, і повернути десять у десятку, але це не так, оскільки не оцінюється як буквальна десятка, яку слід використовувати за літеральним числом, ȷ...але досить двома окремими літералами розбираються, ȷпри цьому показник за замовчуванням три - це одна тисяча, а десять - 10.


Так, це 9 символів, але 22 байти
Крістофер Салл-Сторгард

@ KristofferSall-Storgaard Кожен символ є одним із 256 байтів на кодовій сторінці Jelly , я забув зробити байти слова посиланням, як я зазвичай роблю.
Джонатан Аллан

1
року, я подивився це і дізнався те саме
Kristoffer Sall-Storgaard

4

JDK 9 на jshell, 75 59 байт

n->(new Random()).ints(0,1<<30).dropWhile(x->x>n).findAny()

Використання

((IntFunction)(n->(new Random()).ints(0,1<<30).dropWhile(x->x>n).findAny())).apply(<n>)
  • -16 байт: Дякую Якобу!
  • Припускаємо, що ми вважаємо jshell дійсним середовищем виконання.
  • Сам jshell як середовище виконання не вимагає явного імпорту для основних бібліотек і не потребує крапки з комою.
  • Повертає OptionalInt. Правила не вказують, що тип повернення повинен бути примітивним, і я вважаю, OptionalIntщо це дійсне представлення результату.

1
Дякуємо @ kevin-cruijssen за натхнення. Мій перший гольф-код!
Піт Терлеп

Приймається чи ні в коробці вихід відрізняється від того, чи Optionalприймається ан . Я б підтвердив плакатом, якби ти був. Також не потрібно рахувати ціле завдання; просто вираз лямбда достатній.
Якоб

1
Ви можете зберегти 4 байти, видаливши дужки навколо параметра лямбда nта new Random().
Якоб

3

PHP, 30 байт

    while($argn<$n=rand());echo$n;

Бігайте з echo <N> | php -Rn '<code>'.

вибирає випадкове число між 0 і getrandmax()(2 ** 31-1 на моїй 64-бітовій машині);
Повторюється, поки це більше, ніж вхідний.

Це може зайняти деякий час ... моєму AMD C-50 (1 ГГц) потрібно від 0,3 до 130 секунд протягом N=15.

Більш швидкий спосіб середнього рівня N( 46 байт ):

for(;++$i<$x=1+$argn;)$n+=rand()%$x;echo$n%$x;

або

for(;++$i<$x=1+$argn;$n%=$x)$n+=rand();echo$n;

приймає N+1випадкові цілі числа, підсумовує їх і приймає модуль N+1.
С-50 потребує бл. 8 секунд за 1 мільйон пробіжок.

Недійсне рішення на 19 байт :

echo rand(0,$argn);

3

PowerShell , 35 байт

for(;($a=Random 1gb)-gt"$args"){}$a

Спробуйте в Інтернеті!

Ще один метод відбору проб відхилення. Це нескінченний forцикл, який встановлює значення $aдля Randomцілого числа між 0та 1gb( = 1073741824 = 2^30), і триває циклічно, поки це ціле число є -gреактором tна вході $args. Після завершення циклу ми просто ставимо $aна конвеєр і вихід неявний.

Примітка. Якщо вхід буде невеликим числом, це займе багато часу.


3

Python 2 , 72 69 байт

-3 байти завдяки xnor (замінює idвбудовану як змінну)

from random import*
n=input()
while id>n:id=randrange(2**30)
print id

Спробуйте в Інтернеті!

randrange(2**30)виробляє псевдо-рівномірно розподілене число (Mersenne Twister 2 19937-1 ) з діапазону [0,2 30 ) . Оскільки nгарантовано буде нижче 2 30, це можна просто викликати повторно, поки він не перевищить вхідний. Мине тривалий очікуваний час для дуже низьких значень n, але, як правило, працює протягом хвилини навіть для входів, рівних 50.


2
Ви можете ініціалізувати r=''як "нескінченність". Або ще краще, не ініціалізуйте, rа замість цього використовуйте idскрізь r.
xnor


2

05AB1E , 11 байт

žIÝ.rDI›_Ϥ

Спробуйте в Інтернеті!

Пояснення

žIÝ          # push the inclusive range [0 ... 2^31]
   .r        # get a random permutation (pythons random.shuffle)
     D       # duplicate this list
      I      # push input
       ›_Ï   # keep only elements from the list not greater than input
          ¤  # take the last one

Оскільки список [0 ... 2147483648]занадто великий для TIO, використовується посилання1.000.000 замість цього .

Чергуйте (в середньому) набагато швидше 11-байтне рішення

[žIÝ.RD¹›_#

Спробуйте в Інтернеті

Пояснення

[             # start loop
 žIÝ          # push the inclusive range [0 ... 2^31]
    .R        # pick a random integer (pythons random.chiose)
      D       # duplicate
       ¹      # push input
        ›_#   # break if random number is not greater than input
              # implicitly output top of stack (the random number)

žJL.R%для 6, якщо я не пропускаю чогось величезного. Натисніть 2 ^ 32, список від 0 до 2 ^ 32, випадковий вибір. Модульний вхід. Абсолютно викрутить ефективність у вас.
Чарівна восьминога Урна

@ carusocomputing. Вам знадобиться Iтуди на 7 байт, щоб отримати аргументи для модуля в потрібному порядку (а може, Ýзамість L), але в іншому випадку це, звичайно, коротше рішення. Я бачив, як це робив Денніс у своїй відповіді «Желе», але оскільки це було моєю першою ідеєю, я дотримувався цього. Оскільки такий підхід відрізняється від цього, ви можете опублікувати його як окрему відповідь.
Емінья

DI‹Ïуникне петлі.
Magic Octopus Urn

Крім того, це гарантовано не припиняється; якщо я не помиляюся, введення 0майже завжди призведе до майже нескінченного циклу, що ускладнить його завершення. Хоча рішення дійсно передбачає можливість припинення дії у всіх сценаріях, це не гарантується через випадковість.
Magic Octopus Urn

@carusocomputing: Для дуже малого введення, друга версія повинна в середньому зайняти дуже багато часу, щоб закінчити так, але з урахуванням достатньої кількості часу.
Емінья

2

Python 2, 89 байт

l=range(2**31)
import random
random.shuffle(l)
n=input()
print filter(lambda x:x<=n,l)[0]

Пояснення

L=range(2**31)      # Create a list from 0 to 2^31 exclusive. Call it <L>.
import random       # Import the module <random>.
random.shuffle(L)   # Use 'shuffle' function from <random> module,
                    # to shuffle the list <L>.
n=input()           # Take the input -> <n>.

print
    filter(         # Create a new sequence,
    lambda x:x<=n   # where each element is less than or equal to <n>.
    ,L)             # from the list <L>.
    [0]             # Take the first element.

Це дуже неефективно, оскільки створює 2 ^ 31 цілі числа, переміщує та фільтрує їх.

Я не бачу сенсу ділитися посиланням TIO, де він створює такі великі списки, тому тут є посилання TIO n = 100.

Спробуйте в Інтернеті!


2

Java 8, 84 83 80 71 62 байт

n->{int r;for(;(r=(int)(Math.random()*(1<<30)))>n;);return r;}

-1 байт завдяки @ OliverGrégoire .
-3 байти завдяки @Jakob .
-9 байт перетворення Java 7 в Java 8.
-9 байт шляхом зміни java.util.Random().nextInt(1<<30)на(int)(Math.random()*(1<<30)) .

Пояснення:

Спробуйте тут.

n->{        // Method with integer parameter and integer return-type
  int r;    //  Result-integer
  for(;(r=(int)(Math.random()*(1<<30)))>n;);
            //  Loop as long as the random integer is larger than the input
            //  (the random integer is in the range of 0 - 1,073,741,824 (2^30))
  return r; //  Return the random integer that is within specified range
}           // End method

ПРИМІТКА. Можливо, для невеликих входів може знадобитися дуже багато часу.

Приклад виводу:

407594936

2
@Aaron Я також поставив під сумнів це питання, але дивіться другий пункт кулі: "Будь-які аргументи при виклику вбудованої або бібліотечної випадкової функції повинні бути постійними. Тобто вони повинні бути повністю незалежними від вхідного значення". Це є причиною використання max int.
Поп

1
2^30= 1073741824. Ви вважали за краще використовувати -1>>>1(= 2147483647). Але це існує: 1<<30що точно дорівнює 2^30; і на 1 байт коротше.
Олів'є Грегоар

1
Як щодо int c(int n){int r;for(;(r=new java.util.Random().nextInt(1<<30))>n;);return r;}?
Якоб

@Jakob Дякую Я навіть скоротив його на ще 18 байт, використовуючи Java 8 замість 7 і використовуючи Math.random()замість java.util.Random().nextInt.
Kevin Cruijssen

2

Python 3, 51 байт

Ось рішення пітона з неортодоксальним випадковим джерелом.

print(list(set(map(str,range(int(input())+1))))[0])

Спробуйте в Інтернеті!

Отже, щоб зламати це.

int(input())+1

Отримує номер введення та додає 1його.

set(range(...))

Створює набір {0, 1, 2, 3, 4, ... n}для всіх можливих результатів.

print(list(...)[0])

Бере набір, перетворює його в список і хапає перший предмет.

Це працює, тому що в Python 3 порядок set()встановлюється PYTHONHASHSEED ( неможливо отримати, але встановлено при виконанні сценарію).

Звичайно, я здогадуюсь, що це рівномірний розподіл, оскільки hash()значення призначається випадковим чином, і я дивлюся на випадкове вибір значення з певним hash(), а не просто повернення самого hash(input())себе.

Якщо хтось знає, чи це рівномірний розподіл, чи як я можу це перевірити, будь ласка, прокоментуйте.


1

C #, 57 байт

n=>{int x=n+1;while(x>n)x=new Random().Next();return x;};

Анонімна функція, яка повертає ціле число від 0 до n включно.

Чим менше число введення, тим довше час повернення випадкового значення.

Повна програма:

using System;

class RandomNumber
{
    static void Main()
    {
        Func<int, int> f =
        n=>{int x=n+1;while(x>n)x=new Random().Next();return x;};

        // example
        Console.WriteLine(f(100000));
    }
}

2
"Будь-які аргументи при виклику вбудованої або бібліотечної випадкової функції повинні бути постійними. Тобто вони повинні бути повністю незалежними від вхідного значення." Аргумент до Nextне є статичним.
Yytsi

1

Bash + coreutils, 20 байт

Гольф

seq 0 $ 1 | shuf | sed 1q

shuf - генерувати випадкові перестановки

Shuf використовуватиме наступний код : для генерації перестановок:

permutation = randperm_new (randint_source, head_lines, n_lines);

який закінчується в randint_genmax

/* Consume random data from *S to generate a random number in the range
0 .. GENMAX.  */

randint
randint_genmax (struct randint_source *s, randint genmax) 
{
      ...

      randread (source, buf, i);

      /* Increase RANDMAX by appending random bytes to RANDNUM and
         UCHAR_MAX to RANDMAX until RANDMAX is no less than
         GENMAX.  This may lose up to CHAR_BIT bits of information
         if shift_right (RANDINT_MAX) < GENMAX, but it is not
         worth the programming hassle of saving these bits since
         GENMAX is rarely that large in practice.  */
      ...
}

який, у свою чергу, прочитає декілька байт випадкових даних із джерела випадковості низького рівня:

/* Consume random data from *S to generate a random buffer BUF of size
   SIZE.  */

void
randread (struct randread_source *s, void *buf, size_t size)
{
  if (s->source)
    readsource (s, buf, size);
  else
    readisaac (&s->buf.isaac, buf, size);
}

тобто на низькому рівні немає прямої залежності між shufвхідним значенням і даними, зчитаними від джерела випадковості (окрім обчислення необхідної байтової ємності буфера).


6
Хіба це не дає введення в якості аргументу вашому генератору випадкових чисел?
Мартін Ендер

Навіть якщо це не вірно, надішліть іншу грубій відповідь!

@MartinEnder добре, не безпосередньо, він просто використовує вхід, щоб визначити верхню межу для генерованого цілого діапазону і jot will arrange for all the values in the range to appear in the output with an equal probability(це, мабуть, межа, але все ж).
zeppelin

2
Якщо я копаюсь досить глибоко будь-якому генераторі випадкових чисел, я впевнений, що знайду виклик в RNG нижчого рівня, який не використовує безпосередньо вихідний аргумент. Суть завдання полягає в отриманні рівномірного розподілу довільного розміру з розподілу фіксованого розміру, чого ви досі не робите.
Мартін Ендер

1

SmileBASIC, 38 байт

INPUT N@L
R=RND(1<<30)ON N<=R GOTO@L?R

Генерує випадкові числа, поки не отримає одне, що менше вхідного.


1

Рубі, 23 15 23 32 29 байт

->n{1while n<q=rand(2**30);q}

Як це працює:

  • 1while [...];виконує заяву хоча б один раз: 1ранішеwhile як виступати як ноп
  • Отримайте випадкове число в діапазоні 0..2 ^ 30-1 ( нижче 2 ^ 30 , як зазначено)
  • Повторіть, якщо число перевищує вхідний параметр (може знадобитися певний час, коли n мале)

1

Ом, 26 байт

IΩ
D31º#╬D0[>?D-+∞;,

Пояснення:

IΩ                 ■Main wire
IΩ                 ■Call wire below

D31º#╬D0[>?D-+∞;,  ■"Real main" wire
D                  ■Duplicate input
 31º#╬D            ■Push random_int in [0..2^31] twice
       0[          ■Push input again
         >?    ;   ■If(random_int > input){
           D-+     ■  remove the random_int
              ∞    ■  recursion
               ;   ■}
                ,  ■Print random_int

Чи є перекладач цієї мови? А як щодо Code-page?
Атако

@ATaco: Перекладач , кодова сторінка: CP-437
Emigna

1

Іди, 63 61 байт

import."math/rand"
var n=0;func R(){q:=n;for;q<n+1;n=Int(){}}

Використовуйте його так:

func main() {
    n = 5000
    R()
    print(n)
}

Перевірте це на живому майданчику


Згідно з нашими типовими значеннями, забороняється приймати введення даних із заздалегідь заданих змінних та записувати вихідні дані до визначених змінних . Ви можете використовувати вказівники на глобальні змінні, хоча
Деніс

1

Голанг, 84 78 71 байт

import."math/rand"
func R(n int)int{q:=n+1;for;q>=n;q=Int(){};return q}

Простий відбір проб відхилення.

Примітка: оскільки насіння математики / ранду є постійною величиною 1, абонент повинен посіяти, якщо не бажано постійного результату.

Тест: https://play.golang.org/p/FBB4LKXo1r Більше практично не можна перевірити 64-бітну систему, оскільки вона повертає 64-бітну випадковість та використовує тестування відхилення.

package main

import "fmt"
import "time"

/* solution here *//* end solution */

func main() {
    Seed(time.Now().Unix())
    fmt.Println(R(1073741823))
}

1
якщо ви використовуєте, import."math/rand"то Int31це доступно в глобальному просторі імен, і ви можете зберегти 4 байти, також intгарантується, що принаймні 32 біти, заощаджуючи вам ще 6 байт
Kristoffer Sall-Storgaard

Використовуйте :=синтаксис ще для 3-х байт
Kristoffer Sall-Storgaard

Використання int замість int32 не зберігає жодних байт, оскільки нам потрібно передати результат Int31 () - 3 * int + () = 11 байт проти 2 * int32 = 10 байт.
Рікінг

1
Не потрібно робити передачу, є Int()функція в пакеті rand, також ви можете видалити пробіл післяimport
Kristoffer Sall-Storgaard
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.