Генерировать любое случайное целое число


17

Ваша программа / функция должна

  • вывести ровно одно целое число
  • выведите любое целое число с положительной вероятностью
  • выведите целое число больше 1.000.000 или меньше -1.000.000 с вероятностью не менее 50%.

Пример выходов (все должно быть возможно):

59875669123
12
-42
-4640055890
0
2014
12
24
-7190464664658648640055894646646586486400558904644646646586486400558904646649001

Разъяснения:

  • Разрыв трейлинга разрешен.
  • Ведущие нули не допускаются.
  • -0 разрешено

Самый короткий код выигрывает.


2
@ Оптимизатор, почему вы предполагаете одинаковую вероятность? Вопрос не устанавливает это. На самом деле с этой точки зрения очевидно, что распределение не обязательно должно быть равномерным, если хотя бы 50% его распределения выходит за пределы [-1 миллиона, 1 миллиона].
Хоббс

10
Решение, которое дает « равномерное распределение по всем целым числам», невозможно. Существует бесконечно много целых чисел, поэтому каждое отдельное целое число будет отображаться с вероятностью 0. (Или: Вывод конечного числа будет означать, что вы пренебрегаете бесконечно многими другими!) Любое решение должно будет отклонять более высокие значения для достижения P (всего ) = 1.
Joeytwiddle

2
@Ypnypn ОЗУ компьютера тоже не предел. Вам не нужно нигде хранить частичный вывод.
jimmy23013

4
@GiantTree - way too long to fit in an integer- Это верно только в том случае, если вы предполагаете, что это integerозначает intтип данных в 32/64- битной арке, что не обязательно является допустимым предположением. «Integer» начинался как математический термин , который не имеет ограничений по размеру.
Фальшивое имя

5
Любой, кто использует генератор псевдослучайных чисел для принятия решений на выходе, исключает почти все целые числа и устанавливает верхний предел для размера целых чисел, которые могут быть получены (при условии, что PRNG имеет конечный период). Может ли это быть проигнорировано в ответах, или для правильного ответа требуется настоящий генератор случайных чисел?
Трихоплакс

Ответы:


12

CJam, 16 14 13 байт

0{Kmr(+esmr}g

Это будет выполняться очень долго, потому что он использует текущую временную метку (порядка 10 12 ), чтобы определить, должен ли цикл завершиться. Я использую это как представление, поскольку оно самое короткое, но есть две 14-байтовые альтернативы, которые имеют свои достоинства:

0{esmr(+esmr}g

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

Ниже приведена эквивалентная версия, которая использует 3e5вместо отметки времени. И 20для первого диапазона (как 13-байтовое представление). Это намного быстрее, а также соответствует всем правилам. Это своего рода ограничивающий случай - получить 50% вероятности для чисел, превышающих 1 000 000, при сохранении разумного времени выполнения и небольшого размера кода. Объяснение и математическое обоснование относятся к этой версии:

0{Kmr(+3e5mr}g

Обычно это занимает несколько секунд, чтобы бежать. Вы можете заменить 5с2 на, чтобы он работал еще быстрее. Но тогда требование о 50% вероятности будет выполнено только для 1000 вместо 1 000 000.

Я начинаю с 0. Затем у меня есть цикл, из которого я вырываюсь с вероятностью 1 / (3 * 10 5 ). В этом цикле я добавляю случайное целое число от -1 до 18 (включительно) к моему промежуточному итогу. Существует конечная (хотя и небольшая) вероятность того, что каждое целое число будет выведено, причем положительные целые числа гораздо более вероятны, чем отрицательные (я не думаю, что вы увидите отрицательное целое в своей жизни). Разрыв с такой малой вероятностью и увеличение в большинстве случаев (и добавление гораздо большего, чем вычитание) гарантирует, что мы, как правило, выйдем за пределы 1 000 000.

0              "Push a 0.";
 {          }g "Do while...";
  Kmr          "Get a random integer in 0..19.";
     (         "Decrement to give -1..18.";
      +        "Add.";
       3e5mr   "Get a random integer in 0..299,999. Aborts if this is 0.";

Некоторое математическое обоснование:

  • На каждом этапе мы добавляем в среднем 8,5.
  • Чтобы добраться до 1 000 000, нам нужно 117 647 из этих шагов.
  • Вероятность того, что мы сделаем меньше этого количества шагов,

    sum(n=0..117,646) (299,999/300,000)^n * 1/300,000
    

    который оценивает 0.324402. Следовательно, примерно в двух третях случаев мы предпримем более 117 647 шагов, и каждый из них легко будет составлять 1 000 000.

  • (Обратите внимание, что это не является точной вероятностью, потому что будут некоторые колебания относительно этих средних 8,5, но чтобы достичь 50%, нам нужно пройти значительно дальше 117 646 до примерно 210 000 шагов.)
  • Если вы сомневаетесь, мы можем легко взорвать знаменатель вероятности завершения, 9e9не добавляя байтов (кроме лет времени выполнения).

... или 11 байт?

Наконец, есть 11-байтовая версия, которая также не ограничена периодом PRNG, но у которой почти всегда будет не хватать памяти. Он генерирует только одно случайное число (на основе метки времени) каждой итерации и использует его как для увеличения, так и для завершения. Результаты каждой итерации остаются в стеке и суммируются только в конце. Спасибо Деннису за эту идею:

{esmr(}h]:+

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

(+1 независимо от простой элегантности)
trichoplax

Да, я думаю, все до сих пор. Мне любопытно посмотреть, если кто-то отправит ответ без этой проблемы, хотя ...
trichoplax

Я вижу, что ОП заявил, что вы можете предположить, что ваш генератор случайных чисел является истинным генератором случайных чисел, независимо от того, есть он или нет - так что теперь это избыточно ... :)
trichoplax

Сумма за Kmrпериод, скорее всего, всегда будет большим положительным числом, большим, чем период. И это не может произвести все возможные числа в этом случае.
jimmy23013

11

Ява, 133 149

void f(){String s=x(2)<1?"-":"";for(s+=x(9)+1;x(50)>0;s+=x(10));System.out.print(x(9)<1?0:s);}int x(int i){return new java.util.Random().nextInt(i);}

Пример выходов

-8288612864831065123773
0
660850844164689214
-92190983694570102879284616600593698307556468079819964903404819
3264

Ungolfed

void f() {
    String s = x(2)<1 ? "-" : "";       // start with optional negative sign
    s+=x(9)+1;                          // add a random non-zero digit
    for(; x(50)>0; )                    // with a 98% probability...
        s+=x(10)                        // append a random digit
    System.out.print(x(9)<1 ? 0 : s);   // 10% chance of printing 0 instead
}

int x(int i) {
    return new java.util.Random().nextInt(i);
}

Старый ответ (до изменения правила)

void f(){if(Math.random()<.5)System.out.print('-');do System.out.print(new java.util.Random().nextInt(10));while(Math.random()>.02);}

Вы оба правы, но вопрос гласит, что вероятность должна быть как минимум на 50% не в диапазоне +/- 1.000.000
GiantTree

@ Оптимизатор Redone.
Ypnypn

Если вы используете двоичные литералы, вам не нужно печатать -.
TheNumberOne

4

Mathematica - 47

Round@RandomVariate@NormalDistribution[0,15*^5]

В основном, просто сгенерируйте случайное число, используя нормальное распределение с дисперсией, равной 1500000. Это даст целое число от -10 ^ 6 до 10 ^ 6 с вероятностью 49,5015%.


«Это даст целое число от -10 ^ 6 до 10 ^ 6 с вероятностью 50,4985%». - этого не достаточно. Вы неправильно прочитали спецификацию? Возможно, вы хотели использовать 10 ^ 7 в качестве дисперсии?
Джон Дворжак

@JanDvorak Неправильная вероятность, извините. Теперь это правильный.
swish

Действительно ли реализация этого в Mathematica охватывает все целые числа? У меня нет доступа к источнику, но я думаю, что нет ...
trichoplax

@githubphagocyte Это будет зависеть от текущей точности.
swish

4
Я имею в виду, что указание любой конкретной точности исключит числа, превышающие это. Единственный способ, которым это могло бы работать, - это указывать неограниченную точность.
Трихоплакс

4

Python 2, 75 69 байт

from random import*;s=0;j=randrange
while j(12):s=s*9+j(-8,9)
print s

Тривиально проверить, что цикл while в середине может генерировать все целые числа (хотя и смещенные к нулю). «12» выбирается таким образом, чтобы примерно половина чисел превышала ± 10 6 .


Старое решение:

Python 2, 44 байта

Основано на решении Mathematica .

from random import*;print int(gauss(0,8**7))

На самом деле не работает, потому что Python floatимеет только конечную точность.


Это не сможет генерировать все целые числа, потому что генератор псевдослучайных чисел имеет конечное количество внутреннего состояния. Согласно документации Python использует Mersenne Twister, поэтому состояние довольно велико. Но оно не бесконечно, поэтому оно может производить только конечное подмножество всех целых чисел.
звездный синий

@starblue: из ОП: «Вы можете предположить, что генератор случайных чисел вашего языка - это настоящий генератор случайных чисел, даже если это не так».
kennytm

3

Руби, 70

f=->{m=10**6
r=rand -m..m
r<1?(r>-5e5??-:'')+r.to_s+f[][/\d+/]:r.to_s}

Чтобы сделать возможным генерирование очень больших чисел, я возвращаю число в Stringвиде лямбды. Если это не разрешено, считайте 8 дополнительных символов (для puts f[]), чтобы сделать его программой, а не функцией.

объяснение

Генерация числа между -1,000,000и 1,000,000. Если число больше 1или равно , номер возвращается как String.

Если число меньше чем 1, функция вызывается рекурсивно, чтобы вернуть число вне диапазона номеров. Чтобы убедиться, что отрицательные числа также могут быть сгенерированы, -перед результирующим Stringбудет добавлен префикс a, если начальное число больше, чем -500,000.

Надеюсь, я правильно понял задачу!


3

Р, 38

library(Rmpfr)
round(rnorm(1,2e6,1e6))

Тяги из распределения Гаусса со средним значением 2 000 000, выбранным случайным образом, и стандартным отклонением 1 000 000, так что около 2/3 тиражей будут находиться в пределах 1 000 000 и 3 000 000 Распределение не ограничено, поэтому в теории это может генерировать любое целое число. Пакет Rmpfr заменяет R встроенные двойные числа с произвольной точностью.


Да, я понял, что неправильно понял спецификацию. И я полагаю, что у Mathematica есть те же ограничения на точность станка
shadowtalker

Хм в таком случае я не уверен. Я должен изучить это; рассмотрите этот ответ "на удержании" пока
shadowtalker

@ MartinBüttner исправлено, я думаю
shadowtalker

Интересный. Я не думаю, что вам нужно все sample(c(1,-1),1)думать, хотя. Достаточно просто центрироваться на 1e6 ..
Мартин Эндер

@ MartinBüttner ой не должно быть 50% на обоих концах? Это было непонятно
теневик

2

Perl, 53 символа

print"-"if rand>.5;do{print int rand 10}while rand>.1

Я, конечно, не вижу смысла работать с целыми числами при печати одного :)

Имеет одинаковую вероятность печати числа с или без начального "-".

Печатает 1-значное число в 10% случаев, 2-значное число в 9% случаев, 3-значное число в 8,1% времени, 4-значное число в 7,29% времени, 5-значное число 6,56% времени, 6-значное число 5,9% времени и т. Д. Возможна любая длина с уменьшающейся вероятностью. Числа, состоящие из одной-пяти цифр, составляют около 41,5% выходных данных, а число 1 000 000 (или -1 000 000) - только 6 миллионов долей процента, поэтому выходное число будет выходить за пределы диапазона от 1 000 000 до 1 000 000, около 54,6. % времени.

И «0», и «-0» являются возможными выходами, что, я надеюсь, не является проблемой.


Разве это не печатает "числа" как -00000000167? Это не совсем целое число.
Исаак

1
@isaacg Я не понимаю, почему это не целое число.
Оптимизатор

2
@Optimizer Это так, но ОП явно запретил ведущий 0.
Мартин Эндер

Вы можете сгенерировать случайную ненулевую начальную цифру перед циклом, от -9 до +9. print int(rand(20)-10)||1, Мне нужен способ генерировать 0 в качестве вывода, хотя. Может быть || умрет 0, если разрешен завершающий мусор после нуля. Иначе нужен короткий способ напечатать ноль и выйти без дальнейшего вывода if int(rand(20)-10)==0.
Питер Кордес

@PeterCordes согласился, это достойный подход, но мне не хочется его писать, и я не думаю, что он будет конкурентоспособным по длине. Не стесняйтесь представить его самостоятельно :)
hobbs

2

Perl, 114 символов

use Math::BigInt;sub r{$x=Math::BigInt->new(0);while(rand(99)!=0){$x->badd(rand(2**99)-2**98);}print($x->bstr());}

Сломать:

use Math::BigInt;               -- include BigIntegers
  sub r{                        -- Define subroutine "r"
    $x=Math::BigInt->new(0);    -- Create BigInteger $x with initial value "0"
      while(rand(99)!=0){       -- Loop around until rand(99) equals "0" (may be a long time)
        $x->badd(               -- Add a value to that BigInt
          rand(2**99)-2**98);   -- Generate a random number between -2^98 and +2^98-1
        }print($x->bstr());}    -- print the value of the BigInt

Вероятность получения значения между -1.000.000 и 1.000.000 стремится к нулю, НО это возможно.

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

Perl, 25

sub r{rand(2**99)-2**98;}

Генерирует случайное целое число в диапазоне +/- 2 ^ 99.

Сломать

sub r{                    -- Define subroutine "r"
     rand(2**99)          -- Generate a random integer between 0 and 2^99
                -2**98;}  -- Subtract 2^98 to get negative values as well

Протестировано с 1 миллионом образцов:

~5 are inside the range of +/-1.000.000
~999.995 are outside that range
= a probability of ~99,99% of generating an integer outside that range.
Compare that number to the probability of 2.000.000 in 2^99: It is approx. the same.

Это соответствует всем правилам:

  • 1 целое число
  • возможно любое целое число
  • по крайней мере 50% (в моем случае 99,99%) всех сгенерированных целых чисел находятся вне диапазона +/- 1.000.000.

Это работает, потому что лежащий в основе генератор случайных чисел определяет равную вероятность для каждого сгенерированного бита, тем самым делая это и для сгенерированных целых чисел.
Каждое целое число имеет вероятность 1/2 ^ 99 для генерации.

Редактировать:

Мне пришлось увеличить показатель степени, чтобы генерировались большие целые числа. Я выбрал 99, потому что он делает код максимально коротким.


Разве мы не согласны с тем, что не должно быть никаких верхних / нижних границ? Например, целое число 2 ^ 31 + 1 имеет 0 вероятностей, нарушая правило 2
Оптимизатор

@Optimizer для меня целое число определяется как во многих языках программирования: число в пределах -2^31и +2^31-1(32 бита). Вы можете легко увеличить показатели, если вы хотите генерировать большие целые числа, но это может не сработать в зависимости от реализации Perl.
GiantTree

Я только что увидел, что это смехотворно большое целое число тоже должно быть сгенерировано. Я отредактирую свой код быстро.
GiantTree

@ MartinBüttner Я старался изо всех сил, чтобы соответствовать спецификации вопроса. Для меня просто невозможно (по крайней мере, без посторонней помощи) генерировать бесконечно большие целые числа. Наибольшее целое число в Perl составляет около 1.7e308, что является пределом, который я не могу контролировать.
GiantTree

@ MartinBüttner Возможно и то и другое, но, например, строка будет переполнена после 2 ГБ данных, что снова сделает ее конечной. Трудно сказать, что число должно быть бесконечно большим, если есть проблемы с памятью. Я скоро придумаю другой подход, используя BigInts. Также целое число не переполняется на 1.7e308, оно просто конвертируется в infite ( 1.#INFесли быть точным)
GiantTree

2

C #, 126 107 байт

string F(){var a=new System.Random();var b=a.Next(-1E6,1E6+1)+"";while(a.Next(1)>0)b+=a.Next(10);return b;}

Ungolfed:

string F()
{
    System.Random rand = new System.Random();
    string rtn = rand.Next(-1E6, 1E6 + 1) + "";
    while (rand.Next(1) > 0)
         rtn += a.Next(10);
    return rtn;
}

Шанс сгенерировать число n цифр составляет 1/2 ^ (n-10), что больше 0 для всех положительных n и 1/2 для n = 11.Также создает ведущие нули, которые, как представляется, не запрещены в исходном вопросе или в любом из его комментариев.


При использовании using System;вам не нужно System.Randomдважды, а просто Random, верно?
Чарли

@Charlie Это функция, поэтому я не могу использовать usingоператоры. В любом случае это сохранит только 1 символ.
LegionMammal978

1
Вы можете сохранить 1 символ, удалив пробел в -1E6, 1E6+1.
ProgramFOX

2

Perl, 62 байта

print $n=int rand(20)-10;while($n&&rand>.1){print int rand 10}

У меня была та же идея, что и у @Hobbs, - генерировать цифру за раз, но его код не удовлетворял добавленному требованию без ведущих нулей. Создание первой цифры вместо просто знака решило это. И если нет более короткого способа выхода, если мы напечатали ноль, или более короткого способа сгенерировать ведущие от -9 до 9, это должно сделать это для размера.

В цикле оболочки: while perl -e '...'; do echo;done |less

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

Я попытался использовать побитовое и сохранить символ в состоянии while, но я думаю, что это чаще всего оказывается истиной, поэтому цикл завершается раньше. Потребовалось бы больше символов для корректировки других вещей, чтобы противостоять этому, чтобы поддерживать вероятность генерации abs (выход)> 1M.


Хорошо, вы выдавили некоторые вещи, которые я бы не подумал :)
Хоббс

1

Javascript (73)

Это решение использует то, что вы можете построить число с основанием n , умножив предыдущее число на n и добавив цифру в основание n . У нас есть дополнительный, ..?..:..чтобы иметь возможность создавать все отрицательные целые числа. Следующий код должен быть протестирован в консоли браузера.

b=Math.round;c=Math.random;x=0;while(b(c()*99)){x*=b(c())?2:-2;x+=b(c())}

Вероятность получить целое число> = 2^1(или <= -(2^1)) равна вероятности того, что цикл будет выполнен 2 раза. Вероятность этого есть (98/99)^2. Следовательно, вероятность получить число, которое больше 2^20(или <= -(2^20)), составляет (98/99)^21 = 0.80881%. Это все теоретически, и при условии, что Math.random действительно случайный. Это явно не так.


Фрагмент, тестирующий этот код. Также более читабельным способом.


1
ОП теперь подтвердил, что вы можете предположить, что ваш PRNG действительно случайный, даже если это не так.
Трихоплакс

1

GolfScript, 20 байт

0{)8.?rand}do.2&(*4/

Да, этот тоже немного медленный.

По сравнению с такими языками, как CJam и Pyth, GolfScript страдает многословным ключевым словом генерации случайных чисел (rand ). Чтобы преодолеть этот недостаток, мне нужно было найти способ использовать его только один раз.

Этот код работает путем многократного выбора случайного числа в диапазоне от 0 до 8 8 -1 = 16 777 215 включительно и увеличения счетчика до тех пор, пока случайное число не окажется равным 0. Полученное значение счетчика имеет геометрическое распределение с медианой приблизительно -1 / log 2 (1 - 1/8 8 ) ≈ 11 629 080, что соответствует критерию «более 1 000 000, по крайней мере, 50% времени».

Увы, сгенерированное таким образом случайное число всегда строго положительно. Таким образом, дополнительная .2&(*4/часть необходима, чтобы позволить ей стать отрицательной или нулевой. Он работает, извлекая второй младший бит числа (который, таким образом, равен 0 или 2), уменьшая его до значения -1 или 1, умножая его на исходное число и деля результат на 4 (чтобы избавиться от младшие два бита, которые теперь соотносятся со знаком, а также позволяют результату стать нулевым). Даже после деления на 4 абсолютное значение случайного числа по-прежнему имеет медиану -1 / log 2 (1 - 1/8 8 ) / 4 ≈ 2 907 270, поэтому оно все равно проходит 50% тест.


1

JavaScript, 81 байт

Этот код выполняет все правила:

  • Выведите любое целое число с положительной вероятностью
  • Выведите целые числа вне диапазона +/- 1000000 с вероятностью не менее 50%
  • Нет лидирующих 0в выводе

В качестве бонуса алгоритм работает с временной сложностью O (log 10 n), поэтому он возвращает целое число почти мгновенно.

for(s="",r=Math.random;r()>.1;s+=10*r()|0);r(s=s.replace(/^0*/,"")||0)<.5?"-"+s:s

Это предполагает среду REPL. Попробуйте запустить приведенный выше код в консоли вашего браузера или используйте приведенный ниже фрагмент стека:

D.onclick = function() {
  for(s="", r=Math.random;r()>.1; s+=10*r()|0);
  P.innerHTML += (r(s=s.replace(/^0*/,"") || 0) <.5 ?"-" + s : s) + "<br>"
}
<button id=D>Generate a random number</button><pre id=P></pre>

Алгоритм :

  • Добавляйте случайные цифры в строку sдо тех пор, пока Math.random() > 0.1.
  • Исходя из Math.random() > 0.5, сделайте число отрицательным (добавив строку sс -).

Этот алгоритм не имеет равномерного распределения по всем целым числам. Целые числа с большим числом цифр менее вероятны, чем младшие. В каждой итерации цикла есть вероятность 10%, что я остановлюсь на текущей цифре. Я просто должен убедиться, что я останавливаюсь после 6 цифр более 50% времени.

Это уравнение от @nutki объясняет максимальное значение процента вероятности остановки на основе вышеуказанного условия:

1 - 50%^(1/6) ≈ 0.11

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


Есть несколько вещей, которые смущают меня об этом ответе. Предполагали ли вы, что Math.random () генерирует равномерное распределение случайных чисел, потому что спецификация утверждает, что это зависит от реализации. Предполагая, что это равномерное распределение, P (Math.random ()> 0.1) = 0,9, поэтому существует огромная вероятность, что оно будет завершаться между каждой итерацией. Реализация вашего алгоритма, работающего на Firefox 34.0 Ubuntu, дает мне вероятность ~ 0,47 (<0,5) каждый раз, когда я его тестирую: jsfiddle.net/WK_of_Angmar/dh8gq4pb
Wk_of_Angmar

Кроме того, как вам удалось рассчитать сложность времени для алгоритма без ввода?
Wk_of_Angmar

1

TI-BASIC, 14 байтов

1-2int(2rand:randNorm(AnsE6,9

Подобно R-ответу @ ssdecontrol, он основан на гауссовском распределении со средним значением -1 000 000 или 1 000 000, выбранным случайным образом, и стандартным отклонением 9. Распределение не ограничено, поэтому в теории это может генерировать любое целое число.

Пояснение :

1-2int(2rand     - get a random integer 0 or 1, then multiply by 2 and subtract 1
:                - this gives the number 1 or -1 (with equal probability) to Ans
randNorm(AnsE6,9 - displays Gaussian distribution with mean (Ans * 1,000,000) and std. dev. 9

Но может ли он генерировать «2» или «-2»?
Kennytm

Да, очевидно. tibasicdev.wikidot.com/randnorm
Timtech

1
ОК, неправильно прочитайте код (слово :«печатать» означает «объяснение»). Но может ли он генерировать числа более 20 цифр?
Kennytm

Любое произвольное длинное целое число возможно в качестве вывода? Разве это не ограничено диапазоном randNorm?
оптимизатор

«Распределение не ограничено, поэтому в теории это может генерировать любое целое число». Там нет диапазона.
Timtech

1

Баш, 66

LANG=C sed -r '/^-?(0|[1-9][0-9]*)$/q;s/.*/5000000/;q'</dev/random

Он почти всегда печатает 5000000. Но если он нашел правильное число в /dev/random , он вместо этого напечатает это число.

И этот быстрее:

LANG=C sed -r '/^-?(0|[1-9][0-9]*)$/q;s/.*/5000000/;q'</dev/urandom

1
@ Оптимизатор Это должно быть медленно. Это потому, что это настоящий случайный источник. Но вы можете проверить это с /dev/urandomменее случайным.
jimmy23013

@Optimizer Как это будет принимать ручной ввод? Он читает файл, но все это файл.
Нит,

@ Оптимизатор Я просто не понимаю, к чему ты клонишь.
Нит,

чтение из /dev/urandomсценария оболочки в основном аналогично вызову rand()в других языках. Хотя, если вы действительно используете bash, а не POSIX sh, вы можете получить случайные числа echo $RANDOM. wiki.ubuntu.com/DashAsBinSh дает hexdump /dev/urandomэквивалент для голого POSIX-минимума/bin/dash .
Питер Кордес

1

C ++, 95 байт

void f(){int d=-18,s=-1;while(s<9){d=(rand()%19+d+9)%10;cout<<d;s=9-rand()%10*min(d*d+s+1,1);}}

Expanded:

void f() {
    int d=-18,s=-1;
    while(s<9) {
        d=(rand()%19+d+9)%10;
        cout<<d;
        s=9-rand()%10*min(d*d+s+1,1);
    }
}

Объяснение:

Функция продолжает печатать последовательные случайные цифры, пока переключатель со случайным значением не примет необходимое значение для остановки функции. d - это переменная, в которой хранится значение следующей цифры для печати. s - переменная переключения, которая принимает случайные целочисленные значения в интервале [0, 9], если s == 9, то больше никаких цифр не печатается, и функция заканчивается.

Переменные d и s инициализируются, чтобы дать специальную обработку первой цифре (беря ее из интервала [-9, 9], и если первая цифра равна нулю, то функция должна заканчиваться, чтобы избежать начальных нулей). Значение d может быть назначено как d = rand ()% 10, но тогда первая цифра не может быть отрицательной. Вместо этого d присваивается как d = (rand ()% 19 + d + 9)% 10 и инициализируется в -18, поэтому первое значение d будет варьироваться от [-9, 9], а следующие значения всегда будут в диапазоне от [0 9].

Переменная s варьируется случайным образом от [0, 9], и если s равно 9, функция завершается, поэтому после печати первой цифры следующая будет напечатана с вероятностью 90% (при условии, что rand () действительно случайна, и чтобы удовлетворить третье условие). s можно легко назначить как s = rand ()% 10, однако, есть исключение: если первая цифра равна нулю, функция должна завершиться. Для обработки такого исключения s был назначен как s = 9-rand ()% 10 * min (d * d + s + 1,1) и инициализирован как -1. Если первая цифра равна нулю, min вернет 0, а s будет равно 9-0 = 9. Назначение переменной s всегда будет в диапазоне от [0, 9], поэтому исключение может произойти только в первой цифре.

Характеристики (при условии, что rand () действительно случайный)

  • Целое число печатается цифра за цифрой с фиксированной вероятностью 90% печати другой цифры после печати последней.

  • 0 - это целое число с наибольшей вероятностью печати, с вероятностью приблизительно 5,2%.

  • Вероятность печати целого числа на интервале [-10 ^ 6, 10 ^ 6] составляет примерно 44% (расчет здесь не написан).

  • Положительные и отрицательные целые числа печатаются с одинаковой вероятностью (~ 47,4%).

  • Не все цифры печатаются с одинаковой вероятностью. Например: в середине печати целого числа, если последняя цифра была 5, цифра 3 будет иметь немного меньшую вероятность быть напечатанной следующей. В общем, если последняя цифра была d, цифра (d + 18)% 10 будет иметь немного меньшую вероятность быть напечатанной следующей.

Пример выходов (10 исполнений)

-548856139437
7358950092214
507
912709491283845942316784
-68
-6
-87614261
0
-5139524
7

Process returned 0 (0x0)   execution time : 0.928 s
Press any key to continue.

1

Баш, 42 байта

printf "%d\n" 0x$(xxd -p -l5 /dev/random)
/ dev / random в OSX - это случайные байты, которые xxd -p -l5преобразуют 5 символов ascii в шестнадцатеричные и преобразуют printfих в десятичный формат.


0

Pyth , 11 байт

WOyG~ZtOT)Z

Примечание: эта программа, вероятно, завершится с ошибкой памяти на любом реальном компьютере. Чтобы проверить это, попробуйте заменить Gболее короткой строкой, такой как в этом коде, которая генерирует числа в среднем около 28000:

pyth -c 'WOy"abcdefghijklm"~ZtOUT)Z'

Этот код зацикливается, добавляя случайное число от -1 до 8 Zс вероятностью 2 ^ -26 выхода из цикла при каждом повторении. Вероятность 2 ^ -26 достигается выбором случайного элемента ( O) из набора всех подмножеств ( y) алфавита ( G).

Технические детали и обоснование:

Вероятность 2 ^ -26 определяется двумя фактами: yпри вызове последовательностей это функция набора мощности, которая строит список всех подмножеств входных данных. Поскольку Gдлина входного файла составляет 26 символов, в этом наборе мощности yGсодержится 2 ^ 26 записей. OyGвыбирает случайный элемент из этих 2 ^ 26 записей. Именно одна из этих записей, пустая строка, при передачеW в цикл while. Таким образом, существует вероятность 2 ^ -26 выхода из цикла каждый раз.

В любом фиксированном количестве циклов цикла K вероятность получения числа K * 3,5 + m и получения K * 3,5 - m равна, потому что каждая последовательность суммирований, которая достигает одного итога, может быть инвертирована, -1 -> 8, 0 -> 7 и т. Д., Чтобы добиться другого. Кроме того, числа ближе к K * 3.5 явно более вероятны, чем числа дальше. Таким образом, если K> 2000000 / 3.5 = 571428.5, вероятность получения числа свыше 1000000 превышает 75%, поскольку некоторые из результатов, превышающих это число, можно сопоставить один к одному со всеми результатами ниже этого число, а верхняя половина меньше, может быть приведено в соответствие один к одному с теми, кто меньше 1000000. Вероятность получения не менее 571429 циклов составляет (1-2 ^ -26) ^ 571429, что не менее чем (1-2 ^ -26 * 571429), ожидаемое количество выходов из цикла за первые 571429 попыток, что составляет 99,1%. Таким образом, в 99,1% или более испытаний существует 75% или более шансов получить как минимум 1000000, так что существует более 50% шансов получить более 1000000.

Этот код основан на поведении, Oкогда ошибка была случайно введена 3 дня назад и была исправлена ​​сегодня. Он должен работать на любой версии Pyth 3 до 22 декабря или после сегодняшнего дня. Следующий код эквивалентен и всегда работал:

WOyG~ZtOUT)Z

Что случилось с онлайн-компилятором?
Оптимизатор

@Optimizer Проблемы с сайтом, я над ним поработаю.
Исаак

Ах .. круто. Хотел вчера поработать над переводом Pyth моего ответа CJam и обнаружил, что он дает 404.
Оптимизатор

0

Java, 113 байт

void g(){String a=Math.random()>0?"10":"01";for(;Math.random()>0;)a+=(int)(Math.random()*2);System.out.print(a);}

Эта программа печатает двоичное число в стандартный поток вывода. Возможно, вам придется подождать некоторое время, потому что вероятность того, что число закончится (или оно будет положительным), равна приблизительно 0. Идея, что абсолютное значение сгенерированного числа составляет менее 1 миллиона, забавна, но возможна.

Ungolfed:

void g(){
    String a=Math.random()>0?"10":"01";             //Make sure there are no trailing zeroes.
    for(;Math.random()>0;)a+=(int)(Math.random()*2);//Add digits
    System.out.print(a);                            //Print
}

Образец вывода: будет публиковаться, когда число будет сделано, генерируется.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.