Генератор случайных кодов билетов

18

Лотерейная компания хочет сгенерировать случайный лотерейный билет длиной 10 символов.

Напишите код на любом языке, чтобы создать такое число, в котором каждая цифра встречается только один раз, например, 9354716208в этом числе все целые числа от 0 до 9 встречаются только один раз. Это число должно быть случайным числом.

  • Сгенерированный номер должен отображаться на экране.
  • Он должен быть в состоянии генерировать все перестановки всех допустимых символов.
  • Код должен быть как можно меньше (в байтах).
Ankush
источник
3
Почему это должно быть в Java или PhP?
Fabinout
4
Как правило, рекомендуется использовать любой язык в соответствии с описанием кода-гольфа .
Конрад Боровски
10
Как получается, что один из самых длинных и наименее удачных ответов (ответ SQL), даже без подсчета символов, считается принятым ответом в code-golf, когда такие люди, как @Howard, имеют ответы из 5 или 8 символов?
Даррен Стоун
1
Да, у @marinus есть 4-байтовое решение (у меня 6 байт)
Timtech
4
-1 Выбор победителя неуместен, учитывая, что это было соревнованием по коду.
DavidC

Ответы:

41

J (4 байта)

Не смог устоять.

?~10

В J, если Fдвоично, F~ xто же самое, что и x F x.

Мэринус
источник
3
+1 Я думаю, что мне, возможно, придется попробовать что-то немного более лаконичное, чем Python, чтобы победить это.
Иоахим Исакссон
Это позволяет пароль, который начинается с нуля? Согласно правилам, программа «должна быть способна генерировать все перестановки всех допустимых символов»
DavidC
@DavidCarraher: да. Он выбирает 10 неповторяющихся случайных чисел из интервала [0..10), так что в основном это означает случайную перестановку «0123456789».
Маринус
1
Понимаю. Я поднял это, потому что в большинстве языков «число», 0123456789, будет автоматически отредактировано до формы 123456789. Строка, «0123456789», остается нетронутой. Так что мой вопрос на самом деле таков: вы выводите число или строку?
DavidC
@DavidCarraher Это массив.
swish
12

J, 5 символов и APL, 8 символов

J

10?10

У J есть встроенный оператор сделки ( ?). Таким образом, мы можем взять 10 из 10 ( 10?10).

APL

1-⍨10?10

APL имеет тот же оператор, который, к сожалению, начинается с единицы вместо нуля. Поэтому мы вычитаем по одному из каждого числа ( 1-⍨Xзначит, X-1из-за коммутирующего оператора).

Говард
источник
О, это мило.
Конрад Боровски
Если OP специально запросил бы число, а не массив, вы должны также преобразовать его в число base10, с10#.
swish
Вы можете предположить, что ⎕IO←0вам не нужно вычитать. Кроме того, как для J, так и для APL, вы можете использовать commute для сохранения байта с, ?~10и ?⍨10поскольку монадическое применение производной функции использует свой правый аргумент также в качестве левого аргумента. Отметим, однако, что это делает код J идентичным коду Marinus .
Адам
9

Python 2,7 ( 64 63 57)

Здесь нет шансов по сравнению с тяжелыми языками оператора и из-за отсутствия загруженного по умолчанию случайного числа :) Это самое короткое, что я мог придумать;

from random import*
print''.join(sample("0123456789",10))

Он создает диапазон и выбирает из него 10 номеров без замены.

(Спасибо @xfix за более короткое исправление формата импорта и @blkknght за указание на мой довольно сложный диапазон выборки)

Python 2,7 (40)

Если вы запускаете его из интерактивного приглашения и можете читать через запятую, вы можете сбрить его до 40, но это немного похоже на нарушение духа правил;

from random import*
sample(range(10),10)
Иоахим Исакссон
источник
1
Вы можете использовать, from random import*чтобы сохранить один символ. Это похоже на моё решение на Perl 6, но более многословно, но приятно видеть, что что-то подобное может работать в Python, даже если более многословно.
Конрад Боровски
@xfix Да, к сожалению, модули в Python немного многословны для сравнения :) Обновлен с исправлением импорта, совершенно новым для игры в гольф, так что не до "паритета" в моих идиомах.
Иоахим Исакссон
Вы можете сохранить еще несколько символов, используя выборку из строки, "0123456789"а не используя rangeих сопоставление str.
Blckknght
@Blckknght Спасибо, обновлено с вашим предложением :)
Йоахим Исакссон
8

PHP, 29 символов

<?=str_shuffle('0123456789');

В PHP закрывающий тег не требуется. Но если это противоречит правилам, вы можете заменить; с?> за 1 чистое увеличение.

Джеймс С
источник
Вы опередили меня с этим решением.
Шон Бебберс
8

Руби, 18

Запустите это в irb:

[*0..9].shuffle*''

Если вы хотите, чтобы это была отдельная программа с выводом в stdout(правила, кажется, этого не требуют ), добавьте эти 4 символа в начале:

$><<
Даррен Стоун
источник
Вы можете сократить (0..9).to_aдо [*0..9].
Говард
Сделано и сделано, сэр. Благодарность!
Даррен Стоун
Пожалуйста. Но почему вы не используете [*0..9].shuffleв первую очередь?
Говард
@ Говард, потому что уже поздно, а я тупой. :) Благодарность!
Даррен Стоун
этот возвращаемый массив с номером, а не числом
8

PHP - 37 символов

<?=join('',array_rand(range(0,9),10))

У меня было 18-символьное решение, которое теоретически должно работать, но PHP странный.

Или, если вы хотите получить ответ xkcd:

<?="5398421706" // Chosen by program above; guaranteed to be random ?>

РЕДАКТИРОВАТЬ: Спасибо xfix, теперь он на 5 символов короче и завершено. ИЗМЕНИТЬ СНОВА: живой пример .

cjfaure
источник
Напишите полную программу, а не только полные части. Кроме того, echoпаренсы не нужны, и если echoэто первое утверждение в программе, вы можете заменить <?php echoна <?=. Кроме того, joinэто псевдоним для implode.
Конрад Боровски
@xfix Спасибо, я исправлю. :)
cjfaure
Вам даже не нужны <?=и ?>. Это действительный код PHP без них.
Джереми
@ Джереми Гольф требует отображения номера; кроме того, echo это та же длина, что <?=и в ?>сочетании, и без них она не работает в Codepad. Спасибо хоть. : P
cjfaure
1
@ Джереми Ах, PHP, где не встроенные реализации, кроме терминала, немногочисленны. : P
cjfaure
8

Perl 6 (18 16 символов)

print pick *,^10

Это генерирует массив, содержащий все случайные элементы ( pick *) из 0to 9и выводит результат ( print).

Образец вывода:

$ perl6 -e 'print pick *,^10'
4801537269
$ perl6 -e 'print pick *,^10'
1970384265
$ perl6 -e 'print pick *,^10'
3571684902
Конрад Боровски
источник
+1 Я думаю, вам не нужны пробелы раньше pick.
Говард
1
@ Ховард: мне это действительно нужно. [~](который анализируется как листоп, согласно грамматике Perl 6) требует пробела (или paren) после него, если он содержит какие-либо аргументы. В противном случае компилятор Perl 6 жалуется на «два члена подряд». В старых версиях Perl 6 этого не было, но это уже прошлое. Perl 6 все еще работает над
Конрад Боровски
1
@xfix: используйте printвместо say [~]и сохраните 2 символа :)
Ayiko
@Ayiko: Спасибо за улучшение :).
Конрад Боровски,
7

GolfScript, 12 символов

10,{;9rand}$

Просто генерирует список цифр ( 10,) и сортирует его {...}$по некоторым случайным ключам - что дает случайный порядок цифр.

Примеры (попробуйте онлайн ):

4860972315

0137462985
Говард
источник
Я собирался опубликовать это: P
дверная ручка
Это вроде дерьмового шаффла, хотя: например, первая цифра примерно в три раза вероятнее будет 0, чем 1. Замена 9randна 99randэто (в основном) исправит это; 9.?randбыло бы практически идеально .
Ильмари Каронен
1
@IlmariKaronen Я знаю, но вопрос ничего не говорил о равномерном распределении.
Говард
6

R (23 символа)

cat(sample(0:9),sep="")

Образец вывода:

> cat(sample(0:9),sep="")
3570984216
> cat(sample(0:9),sep="")
3820791654
> cat(sample(0:9),sep="")
0548697132
djhurio
источник
6

TI-BASIC, 5 байтов

randIntNoRep(1,10
Timtech
источник
Отображает список, а не число. Ты ищешь randIntNoRep(0,9:.1sum(Ans10^(cumSum(1 or Ans.
lirtosiast
2
Я не думаю, что этот вызов требует целочисленного типа, только то, что «сгенерированное число должно быть показано на экране», что это такое.
Timtech
Хм, я думал, что вопрос спрашивает номер (как и другие, но кажется, что цель автора
задания
Ну, я бы не стал это считать, если бы не был уверен, потому что этот метод короче.
Timtech
5

Октава (14)

randperm(10)-1

randperm к сожалению, создает выборку из 1..n, поэтому нужно вычесть 1 в конце, чтобы получить 0-9.

Иоахим Исакссон
источник
5

В sql server

DECLARE @RandomNo varchar(10)
SET @RandomNo = ''

;WITH num as (
SELECT 0 AS [number]
Union 
select 1
Union 
select 2
Union 
select 3
Union 
select 4
Union 
select 5
Union 
select 6
Union 
select 7
Union 
select 8
Union 
select 9
)
SELECT Top 9 @RandomNo = COALESCE(@RandomNo + '', '') + cast(n.number AS varchar(1))
FROM numbers n
ORDER BY NEWID()

SELECT cast(@RandomNo AS numeric(10,0))

Посмотреть демо

ИЛИ что-то похожее (любезно предоставлено @manatwork) с использованием рекурсии и xml.

with c as(select 0i union all select i+1from c where i<9)select i+0from c order by newid()for xml path('')
vhadalgi
источник
1
Чувак, ты любишь CTE ... Но так как это задача для игры в гольф , лучше сократить ее как можно больше. Мой лучший - это 186 символов select i+0from(select 0i union select 1union select 2union select 3union select 4union select 5union select 6union select 7union select 8union select 9)f order by newid()for xml path(''). (Кстати, отличный трюк newid().)
manatwork
1
Хорошо, ты прав. Короче с CTE. 106 символов: with c as(select 0i union all select i+1from c where i<9)select i+0from c order by newid()for xml path('').
manatwork
Вы можете упростить cte с помощью(VALUES (1),(2),...)
ypercubeᵀᴹ
5

Javascript ( 79 78 68 символов)

Вместо того, чтобы создавать массив с номерами 0-9 и сортировать его, я решил создать случайные числа. Когда он придумал число, которого еще не было в массиве, то добавил его. Это повторяется десять раз, а затем оповещает о выходе.

for(a="";!a[9];){~a.indexOf(b=~~(Math.random()*10))||(a+=b)}alert(a)

scribblemaniac
источник
Вы можете сохранить 1 байт, используя ||оценку короткого замыкания вместо if: for(a="";!a[9];){b=Math.floor(Math.random()*10);~a.indexOf(b)||(a+=b)}alert(a)
Стивен Палинкас
1
@ StevenPalinkas Спасибо, отличная идея! Я обновил пост соответственно.
scribblemaniac
Мы также могли бы сохранить 2 байта с небольшим перераспределением в коде: for(a="";!a[9];){~a.indexOf(b=Math.floor(Math.random()*10))||(a+=b)}alert(a)
Стивен Палинкас
Мы можем сохранить дополнительные 8 байтов, используя «сокращение» для Math.floor, например:for(a="";!a[9];){~a.indexOf(b=~~(Math.random()*10))||(a+=b)}alert(a)
Стивен Палинкас
4

Математика, 27

Row@RandomSample@Range[0,9]

введите описание изображения здесь

Аяся
источник
Хороший способ избежать строк!
DavidC
4

Shell / Coreutils, 23

shuf -i0-9|paste -sd ''
Хастуркун
источник
Если нам не нужен завершающий перевод строки, вы можете сбрить это до 20 с shuf -i0-9|tr -d \\n
Joeytwiddle
как насчет shuf -zi0-9
marcosm
@marcosm: Это дает вам строки, оканчивающиеся нулями, что немного странно.
Хастуркун
4

JavaScript, 82 символа

РЕДАКТИРОВАТЬ: Благодаря Робу W , длина кода уменьшена до 90 символов.

РЕДАКТИРОВАТЬ: Благодаря Джорджу Риту , длина кода сокращена до 82 символов (используется для цикла).

Довольно простой способ: выбрать случайный элемент [0,1,2,3,4,5,6,7,8,9]массива и добавить его к выводу, затем уменьшить массив и переиграть.

Старая версия (106 символов):

a=[0,1,2,3,4,5,6,7,8,9],l=11,t="";while(--l){r=Math.floor(Math.random()*l);t+=a[r];a.splice(r,1);}alert(t)

Читаемая версия:

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], l = 10,t = "";
while(l--) {
  r = Math.floor(Math.random() * l);
  t += a[r];
  a.splice(r, 1);
}
alert(t);

Лучшая версия (90 символов):

a="0123456789".split(t=""),l=11;while(--l)t+=a[r=0|Math.random()*l],a.splice(r,1);alert(t)

Последняя версия (82 символа):

a="0123456789".split(t='');for(l=11;--l;t+=a.splice(0|Math.random()*l,1));alert(t)

JSFiddle: http://jsfiddle.net/gthacoder/qH3t9/ .

gthacoder
источник
1
Я довел ваш метод до 90 символов a='0123456789'.split(t=''),l=10;while(l--)t+=a[r=0|Math.random()*l],a.splice(r,1);alert(t). Большие вкладчики: Math.random(x)=== 0|x. Замените фигурные скобки и точки с запятой запятыми. Непосредственно используйте результат присваивания в качестве значения вместо использования промежуточной переменной. Наконец, инициализируйте исходный массив, используя .split(r=''). Это короче, чем создание массива с использованием литералов массива и присвоение строкового значения в отдельном выражении.
Роб W
@RobW Спасибо за советы. Я обновил свой ответ. PS Я думаю, вы имели в виду Math.floor(x) === 0|x.
gthacoder
1
Это всегда имеет 9 в конце. Чтобы исправить, инициализировать l=11и переключить состояние цикла while наwhile(--l)
Greg
@ Грег Хороший вопрос. Спасибо. Я обновил ответ.
gthacoder
1
82 символа: a="0123456789".split(t='');for(l=11;--l;t+=a.splice(0|Math.random()*l,1));alert(t)- Ваш код идеально вписывается в инициализацию циклов for, условия и аргументы выражений. rПеременной является излишним.
Джордж Райт
4

C #, 145 байт

Ungolfed

using System;
using System.Linq;
class P
{
    static void Main()
    {
        Enumerable.Range(0,10).OrderBy(g => Guid.NewGuid()).ToList().ForEach(Console.Write);
    }
}

Golfed

using System;using System.Linq;class P{static void Main(){Enumerable.Range(0,10).OrderBy(g => Guid.NewGuid()).ToList().ForEach(Console.Write);}}
JMK
источник
1
Вы можете использовать Enumerable.Range(0,10), и вам не нужны фигурные скобки в foreachцикле.
Рик
3

JavaScript (80 символов)

alert("0123456789".split("").sort(function(){return .5-Math.random()}).join(""))

JS-Fiddle: http://jsfiddle.net/IQAndreas/3rmza/

IQAndreas
источник
3
Обратите внимание, что это может быть улучшено с помощью функции стрелки (которая в настоящее время работает только в FF, но скоро будет alert("0123456789".split("").sort(n=>.5-Math.random()).join(""))
доступна
1
Вам не нужно пространство между returnи.5
Тибос
1
@ Грег Тссс! Вы хоть представляете, сколько символов занимает настоящая функция тасования? ;)
IQAndreas
1
@Greg Это случайное распределение (при условии, что Math.random является достаточно случайным), оно просто не является равномерным.
SuperJedi224
1
Оригинальный пост в блоге пропал, добавлен интернет-архив для потомков: web.archive.org/web/20150212083701/http://sroucheray.org/blog/…
Грег
3

К / Кона (6)

-10?10

Как и в случае с J, ?является оператором сделки; что -силы значения , которые не повторяются.

Кайл Канос
источник
3

Mathematica 40

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

""<>RandomSample["0"~CharacterRange~"9"]

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

"0568497231"
"6813029574"

объяснение

"0"~CharacterRange~"9" является инфиксной нотацией для CharacterRange ["0", "9"] ". Любой из них возвращает список, {" 0 "," 1 "," 2 "," 3 "," 4 "," 5 "," 6" , "7", "8", "9"}.

RandomSample[list]по умолчанию возвращает перестановку списка. (Он также может быть использован для других видов выборки, когда включены параметры. Например RandomSample[list, 4], вернет случайную выборку из 4 символов без повторов.

DavidC
источник
Но зачем отображать 0 в качестве первого символа?
Ankush
Согласно ОП, программа «должна быть способна генерировать все перестановки всех допустимых символов».
DavidC
@Ankush Это инфиксная запись, поэтому «0» не всегда является первым символом.
Аяся
Аяся верна. Программа может генерировать любую перестановку. Я добавил несколько замечаний выше, чтобы прояснить это.
DavidC
3

Скала, 37

util.Random.shuffle(0 to 9).mkString
soldier.moth
источник
2

Далее 72

needs random.fs : r ': '0 do i loop 9 for i 1+ random roll emit next ; r

Возможно, еще есть место для игры в гольф, но Форт сделал это трудно. Я думаю.

Даррен Стоун
источник
2

Пролог, 177/302 персонажа

Я новичок в Прологе, так что, вероятно, это не самый сжатый код.

:- use_module(library(clpfd)).
sort(N) :-
    N = [N0,N1,N2,N3,N4,N5,N6,N7,N8,N9],
    domain([N0],1,9),
    domain([N1,N2,N3,N4,N5,N6,N7,N8,N9],0,9),
    all_different(N),
    labeling([],N).

Возвращает:

| ?- sort2(N).                                         
N = [1,0,2,3,4,5,6,7,8,9] ? ;
N = [1,0,2,3,4,5,6,7,9,8] ? ;
N = [1,0,2,3,4,5,6,8,7,9] ? ;
N = [1,0,2,3,4,5,6,8,9,7] ? ;
N = [1,0,2,3,4,5,6,9,7,8] ? 
yes

Если вы хотите, чтобы он возвращал целое число:

:- use_module(library(clpfd)).
sort(M) :-
    N = [N0,N1,N2,N3,N4,N5,N6,N7,N8,N9],
    domain([N0],1,9),
    domain([N1,N2,N3,N4,N5,N6,N7,N8,N9],0,9),
    all_different(N),
    labeling([],N),
    M is (N0*1000000000)+(N1*100000000)+(N2*10000000)+(N3*1000000)+
         (N4*100000)+(N5*10000)+(N6*1000)+(N7*100)+(N8*10)+N9.

Возвращает:

| ?- sort(N).
N = 1023456789 ? ;
N = 1023456798 ? ;
N = 1023456879 ? ;
N = 1023456897 ? ;
N = 1023456978 ? 
yes

Использование вместо:

labeling([down],N)

Дает числа в обратном порядке:

| ?- sort(N).                                        
N = 9876543210 ? n
N = 9876543201 ? n
N = 9876543120 ? n
N = 9876543102 ? n
N = 9876543021 ? 
yes

В отличие от некоторых других опубликованных кодов, это возвращает все возможности (без повторов).

образование
источник
2

q / kdb [6 символов]

-10?10

сгенерирует 10 уникальных случайных чисел.

Ньи
источник
2

√ å ı ¥ ® Ï Ø ¿ , 4 байта

XrśO

X    › Push 10 to the stack
 r   › Push the range from [1...10]
  ś  › Shuffle the stack
   O › Output the whole stack separated by spaces
Caird Coneheringaahing
источник
2

Clojure, 42

(println (apply str (shuffle (range 10))))

6209847315

claj
источник
Сгенерированный номер должен отображаться на экране, а не его части.
Сильвестр
2

Javascript, 83 символа

a=[];while(!a[9]){b=Math.floor(Math.random()*10);!a.includes(b)&&a.push(b)}alert(a)

Пока работает, пока массив не имеет 10 элементов.

Генерация случайного числа от 0 до 9, затем проверьте, включает ли массив! Это число, и добавьте его в массив.

Дэвид
источник
1
Добро пожаловать на сайт! :)
DJMcMayhem
1

Это не намного меньше, чем ответ JMK, но вот немного меньшее решение C # (135):

using System;
using System.Linq;
class P { 
    static void Main() 
    { 
        Console.Write(string.Join("", "0123456789".OrderBy(g => Guid.NewGuid()))); 
    } 
}

Уплотнено (134):

using System;using System.Linq;class P{static void Main(){Console.Write(string.Join("", "0123456789".OrderBy(g => Guid.NewGuid())));}}

Альтернативная версия (135):

using System;
using System.Linq;
class P { 
    static void Main() 
    { 
        "0123456789".OrderBy(g => Guid.NewGuid()).ToList().ForEach(Console.Write); 
    } 
}

Уплотненный:

using System;using System.Linq;class P{static void Main(){"0123456789".OrderBy(g => Guid.NewGuid()).ToList().ForEach(Console.Write);}}

Они равны по длине, но на самом деле это зависит только от того, хотите ли вы использовать функцию LinE ForEach или функцию String Join. Мне удалось удалить 10 символов длиной, указав в строке диапазон «0123456789» вместо использования Enumerable.Range (0, 10).

Кэмерон Тинкер
источник
1

ЛОГОТИП , 64 символа

make "d 1234567890
repeat 10 [
    make "n pick d
    show n
    make "d butmember n d
]

pick возвращает случайный элемент из предоставленного списка. butmember возвращает список, в котором все вхождения указанного элемента удалены. Примечание. Не все реализации логотипа поддерживают butmemberкоманду.

Sandman4
источник
1

Ракетка 45 43

(map print(shuffle'(0 1 2 3 4 5 6 7 8 9)))
Сильвестер
источник