Генерация случайного UUID


15

Мне нужен UUID. Ваша задача - создать его.

Канонический UUID (универсальный уникальный идентификатор) представляет собой шестнадцатеричное число из 32 цифр с дефисами, вставленными в определенные точки. Программа должна вывести 32 шестнадцатеричные цифры (128 бит) в виде xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx( 8-4-4-4-12цифр), где xслучайное шестнадцатеричное число. Предполагая, что PRNG вашего языка идеален, все действительные выходные данные должны иметь одинаковую вероятность генерации.

TL; DR

Генерация 32 случайных шестнадцатеричных цифр в форме 8-4-4-4-12цифр. Самый короткий код выигрывает.

РЕДАКТИРОВАТЬ: должен быть шестнадцатеричным. Всегда генерировать только десятичные числа недопустимо. РЕДАКТИРОВАТЬ 2: Нет встроенных модулей. Это не GUID, это просто шестнадцатеричные цифры.


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

ab13901d-5e93-1c7d-49c7-f1d67ef09198
7f7314ca-3504-3860-236b-cface7891277
dbf88932-70c7-9ae7-b9a4-f3df1740fc9c
c3f5e449-6d8c-afe3-acc9-47ef50e7e7ae
e9a77b51-6e20-79bd-3ee9-1566a95d9ef7
7b10e43c-3c57-48ed-a72a-f2b838d8374b

Вход и стандартные лазейки запрещены.


Это , поэтому выигрывает самый короткий код. Кроме того, не стесняйтесь просить разъяснений.


5
Похоже, менее строгая версия codegolf.stackexchange.com/q/32309/14215
Geobits

9
«Эти примеры не случайны. Попробуйте придать какое-то значение». Что это обозначает?
Алекс А.

3
На самом деле, не нужно шестнадцатеричные числа, 10-основание также может быть случайным. Например, 12345678-1234-1234-1234-123456789012должен быть действительный UUID (или необходима какая-либо шестнадцатеричная цифра?). Вы считаете это лазейкой?
Voitcus

3
Заголовок и первое предложение предполагают, что вам нужен канонический UUID, и приведенные примеры, похоже, соответствуют спецификации UUID, но на самом деле вы, кажется, просите что-то еще.
Питер Тейлор

3
Я чувствую себя обязанным указать, что версия 4 (случайная) UUID имеет обязательный формат xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx где yодин из [89AB]. На момент написания этого комментария ни один из ответов (кроме C #, использующего встроенную библиотеку) гарантированно не выдал действительный случайный UUID (и, скорее всего, вряд ли его выдаст).

Ответы:


11

Pyth, 20 байтов

j\-msm.HO16*4hdj83 3

Демонстрация.

Кодирует [1, 0, 0, 0, 2]как 83 в базе 3, затем добавляет единицу и умножает на четыре, чтобы получить длину каждого сегмента. Затем делает шестнадцатеричные цифры и присоединяется к дефисам.


8

Юлия, 80 байт

h=hex(rand(Uint128),32)
print(h[1:8]"-"h[9:12]"-"h[13:16]"-"h[17:20]"-"h[21:32])

Создайте случайное 128-разрядное целое число, получите его шестнадцатеричное представление в виде строки, дополненной до 32 цифр, и разделите ее на сегменты, соединенные штрихами.

Спасибо ConfusedMr_C и kvill за помощь!


8

CJam, 26 25 байтов

8 4__C]{{Gmr"%x"e%}*'-}/;

Попробуйте онлайн в интерпретаторе CJam .

Как это устроено

8 4__C]{              }/   For each I in [8 4 4 4 12]:
        {         }*         Do I times:
         Gmr                   Pseudo-randomly select an integer between 0 and 15.
            "%x"e%             Apply hexadecimal string formatting.
                    '-       Push a hyphen-minus.
                        ;  Discard the last hyphen-minus.

5

PowerShell, 77 69 67 байт

((8,4,4,4,12)|%{((1..$_)|%{'{0:X}'-f(random(16))})-Join""})-Join"-"

редактировать: посторонние парены:

((8,4,4,4,12)|%{((1..$_)|%{('{0:X}'-f(random(16)))})-Join""})-Join"-"

редактировать: удалось удалить конечный .Trim ("-") из оригинала:

(((8,4,4,4,12)|%{((1..$_)|%{('{0:X}'-f(random(16)))})+"-"})-Join"").Trim("-")

Это может быть яснее с некоторыми пробелами, учитывая природу флагов (-f и -Join). Я все еще хотел бы потерять окончательный Трим ("-"):

(((8,4,4,4,12)|%{((1..$_)|%{('{0:X}' -f (random(16)))}) + "-"}) -Join "").Trim("-")

Или, используя встроенную функциональность (аля ответ C # выше)

'{0}'-f[System.Guid]::NewGuid()

Тем не менее, он выглядит довольно коротко, даже если он занимает 31 байт.


61 байт:(8,4,4,4,12|%{-join(1..$_|%{'{0:X}'-f(random(16))})})-join'-'
Маззи

5

Python 2, 86 84 байта

from random import*;print'-'.join('%%0%ix'%i%randint(0,16**i-1)for i in[8,4,4,4,12])

Эта цепочка форматирует строки, чтобы заставить Python форматировать шестнадцатеричные числа уникально для каждого сегмента.

Ungolfed:

import random

final = []
for i in [8, 4, 4, 4, 12]:               # Iterate through every segment
    max = (16 ** i) - 1                  # This is the largest number that can be
                                         # represented in i hex digits
    number = random.randint(0, max)      # Choose our random segment
    format_string = '%0' + str(i) + 'x'  # Build a format string to pad it with zeroes
    final.append(format_string % number) # Add it to the list

print '-'.join(final)                    # Join every segment with a hyphen and print

Это может использовать некоторые улучшения, но я горжусь.



4

PHP, 69 72 75 байт

foreach([8,4,4,4,12]as$c)$r[]=rand(".1e$c","1e$c");echo join('-',$r);

Это не выводит шестнадцатеричные цифры (a , ... f). Они разрешены, но не обязательны для тела вопроса.

Группа цифр не начинается с 0(также не требуется).

редактировать: сохранено 3 байта благодаря @IsmaelMiguel


Это выглядит как би более 32 байтов.
Исаак

@isaacg да, извините - моя ошибка
Voitcus

Вы должны использовать join()вместо этого.
Исмаэль Мигель

3

C #, 65 байт

using System;class C{void Main(){Console.Write(Guid.NewGuid());}}

редактировать: да! C # короче другого языка (кроме Java) :)


1
Я думаю, что это считается стандартной лазейкой ... :( meta.codegolf.stackexchange.com/questions/1061/…
Дом Гастингс

1
Я думаю, что это не считается стандартной лазейкой: как вы можете видеть, запрос на отказ от этого материала только что получил 2 отзыва за 1 год. Наоборот, комментарий о том, что вы должны использовать встроенные функции, получил 58 голосов. Или, как сказал один из комментаторов -> Если бы мы все были ограничены одним и тем же набором встроенных функций, то в каждом соревновании победили бы APL или Golfscript, потому что их названия команд были самыми короткими. (Майкл Стерн)
Стефан Шинкель

1
или, проще говоря, по-другому: можем ли мы использовать printf? или мы должны использовать встроенный asm для запуска прерывания 21?
Стефан Шинкель

Хорошая мысль! Я не собирался расстраиваться, я только хотел быть полезным! Я думаю, тогда Mathematica может победить CreateUUID[]!
Дом Гастингс

1
@StephanSchinkel «Только 2 повышения в год» вводит в заблуждение. Сейчас у него 47 голосов против и 45 против, так что чистая +2. При этом общепринятый порог выше, чем этот, так что вы правы, что он "действительно" не считается стандартной лазейкой прямо сейчас.
Geobits

3

Гоук, 86

BEGIN{for(srand();j++<32;printf(j~"^9|13|17|21"?"-":E)"%c",x+(x>10?87:48))x=rand()*16}

Вы можете использовать это один раз в секунду, чтобы генерировать уникальный случайный «UUID». Это связано с тем, srand()что в качестве аргумента используется системное время в секундах с начала эпохи, если аргумент не указан.

for n in `seq 100` do awk 'BEGIN{for(srand();j++<32;printf(j~"^9|13|17|21"?"-":E)"%c",x+(x>10?87:48))x=rand()*16}'; sleep 1; done

Я думаю, что часть awk довольно элегантна.

BEGIN{
    srand()
    for(;j++<32;) {
        x=rand()*16
        x+=(x>10?87:48)
        printf "%c", x
        if(j~"^8|12|16|20")printf "-"
    }
}

Если вы хотите использовать его чаще, чем раз в секунду, вы можете назвать его в bash следующим образом. Обратите внимание, что часть awk также изменена.

echo `awk 'BEGIN{for(srand('$RANDOM');j++<32;printf(j~"^9|13|17|21"?"-":E)"%c",x+(x>10?87:48))x=rand()*16}'`

echoДобавляется там напечатать новую линию каждый раз.


3

К5, 35 байт

"-"/(0,8+4*!4)_32?`c$(48+!10),65+!6

Для создания шестнадцатеричного алфавита я генерирую символьную строку ( `c$) из списка цифр ( 48+!10) и первых 6 заглавных букв ( 65+!6). Альтернативный способ генерации цифр одинаковой длины ,/$!10.

С созданной строкой "0123456789ABCDEF" все остальное просто. Выберите 32 случайных значения из этого set ( 32?), slice ( _) результирующей строки при 0 8 12 16 20вычислении через (0,8+4*!4), а затем объедините полученные фрагменты строки с помощью dashes ( "-"/).

В бою:

  "-"/(0,8+4*!4)_32?`c$(48+!10),65+!6
"9550E114-A8DA-9533-1B67-5E1857F355E1"

3

R , 63 байта

x=sample(c(0:9,letters[1:6]),36,1);x[0:3*5+9]='-';cat(x,sep='')

Попробуйте онлайн!

Код сначала строит случайную строку из 36 символов, а затем помещает четыре дефиса. Он выводит UUID на стандартный вывод.


Заменить cвызов sprintf("%x",0:15)на -1.
J.Doe

3

JavaScript, ES6, 106 байт

"8-4-4-4-12".replace(/\d+/g, m => {t=0;for(i=0; i<m; i++) {t+=(Math.random()*16|0).toString(16)}return t})

Использует Regex заменить. Обрабатывает строку формата как счетчик для генерации шестнадцатеричного символа. Поднимать везде, где могу; пропуская точки с запятой, где это возможно.


89 байт,'8-4-4-4-12'.replace(/\d+/g,n=>Math.floor(16**n*Math.random()).toString(16).padStart(n,0))
kamoroso94

2

Perl 6 , 53 байта

Очевидный:

say join '-',(0..9,'a'..'f').flat.roll(32).rotor(8,4,4,4,12)».join # 67

Перевод примера Perl 5 с использованием printfприводит к тому, что код немного короче.

printf ($_='%04x')~"$_-"x 4~$_ x 3,(0..^4⁸).roll(8) # 53

(0..16⁴)?! Вы можете сделать это в Perl?
хлопнуть

1
@VoteToSpam Вы можете с 9 дней назад . (Perl 6 выйдет позже в этом месяце)
Брэд Гилберт b2gills

Cooooool. Может быть, я должен изучить это
хлопнуть

@VoteToSpam Это ничто по сравнению с тем, 1,2,4,8,16 ... *что генерирует ленивый бесконечный список степеней 2. ( {2**$++} ... *также работает)
Брэд Гилберт b2gills


2

APL (Dyalog Unicode) , 115 78 байт

a←⊣,'-',⊢
H←⊃∘(⎕D,819⌶⎕A16∘⊥⍣¯1
(H 8?16)a(H 4?16)a(H 4?16)a(H 4?16)a H 12?16

Попробуйте онлайн!

Это мое первое представление APL. Огромное спасибо @ Adám за поддержку в чате APL PPCG и за функцию шестнадцатеричного преобразования.

Спасибо @ Zacharý за 1 байт

Отредактировано, чтобы исправить количество байтов.


Вы можете принять ⎕IO←0на себя без стоимости байтов, Adám делает это много. Кроме того, большинство байтов (IIRC, все те, что у вас есть здесь) можно считать одним в APL.
Захари

@ Zacharý Я использовал TIO для подсчета байтов при отправке. Должен ли я использовать вместо этого количество символов? Я все еще новичок в PPCG и использую APL, поэтому у меня мало реальных знаний о том, как сделать подсчет байтов для него.
Ж. Салле

Кроме того , вы можете изменить , a(H 12?16)чтобы a H 12?16сохранить один байт.
Захари


2

Japt , 32 байта

[8,4,4,4,12]m@MqG**X sG ù0X} q"-

Попробуйте онлайн!


Добро пожаловать в PPCG и добро пожаловать в Japt :) Я пока пробежусь по вашим решениям, когда смогу уделить время (только из отпуска, так много, чтобы наверстать упущенное), но первый совет, который я предлагаю, - ознакомиться себя с ярлыками Unicode ( m@- £, например) и, чтобы помочь вам начать работу здесь наспех golfed версия 24 байт вашего решения: ethproductions.github.io/japt/... отброшенных в чат Japt , если у вас есть какие - либо вопросы.
Лохматый

1

MATLAB / Octave, 95 байт

a='-';b=strcat(dec2hex(randi(16,32,1)-1)');[b(1:8) a b(9:12) a b(13:16) a b(17:20) a b(21:32)]

1

Perl , 51 байт

say"xx-x-x-x-xxx"=~s/x/sprintf"%04x",rand 65536/reg

Требуется perl5> = 5.10 Я думаю. Для модификатора / r и для say ().


1
Ницца! Это намного лучше, чем у меня! Посмотрев на ваше решение, вы даже сможете сэкономить больше, основываясь на этом мета-посте, с s//xx-x-x-x-xxx/;s/x/sprintf"%04x",rand 65536/egиспользованием -pфлага, что также означает, что оно работает на более старых версиях без -E.
Дом Гастингс

Благодарю. Ваше предложение: echo | perl -pe's // xx-xxx-xxx /; s / x / sprintf "% 04x", rand 65536 / например, "И это всего лишь 48 символов между '". (Это обман? Возможно, нет)
Kjetil S.

Согласно этому мета-посту, это приемлемо, у меня еще не было возможности использовать этот механизм, но, надеюсь, скоро я это сделаю! Было бы 49 байт (+ -p), но все еще довольно хорошо, и я бы не стал рассматривать этот подход, не увидев ваш ответ!
Дом Гастингс


1

C ++, 194 193 221 210 201 байт

+7 байт благодаря Zacharý (обнаружил, -что не должно быть в конце)

#include<iostream>
#include<random>
#include<ctime>
#define L(a)for(int i=0;i<a;++i)std::cout<<"0123456789abcdef"[rand()%16];
#define P(a)printf("-");L(a)
void t(){srand(time(0));L(8)P(4)P(4)P(4)P(12)}

Если у кого-то есть способ получить разные значения при каждом выполнении без изменений srandи без учета <ctime>, это было бы здорово


Не может #define L(a) for... быть #define L(a)for...? (
Возможно


@ Zacharý Исправление применяется сейчас
HatsuPointerKun


1
Не могли бы вы сделать что-то подобное "0123456789abcdef"[rand()%16], а затем удалить f?
Захари



1

JavaScript REPL, 79 байт

'66-6-6-6-666'.replace(/6/g,_=>(Math.random().toString(16)+'00000').slice(2,6))

Попробуйте онлайн!

Math.randomможет вернуться 0. Добавив 5 нулей, получим нарезку 4 0с


1

Forth (gforth) , 91 89 байт

include random.fs
hex
: f 0 4 4 4 8 20 0 do dup i = if + ." -" then 10 random 1 .r loop ;

Попробуйте онлайн!

объяснение

Изменяет основание на шестнадцатеричное, затем выводит числа / сегменты соответствующей длины с тире через заданные интервалы

Код Объяснение

include random.fs          \ include the random module
hex                        \ set the base to hexadecimal
: f                        \ start a new word definition
  0 4 4 4 8                \ enter the intervals to place dashes
  20 0 do                  \ start a counted loop from 0 to 0x20 (32 in decimal)
    dup i =                \ check if we are on a character that needs a dash
    if                     \ if we are
      +                    \ calculate the next character that gets a dash
      ." -"                \ output a dash
    then                   \ end the if block
    f random               \ get a random number between 0x0 and 0xf
    1 .r                   \ output it right-aligned in 1-character space
  loop                     \ end the loop
;                          \ end the word definition

1

C (gcc) ,  94   91  86 байтов

main(i){srand(&i);i=803912;for(;i--%16||(i/=16)&&printf("-");printf("%x",rand()%16));}

Попробуйте онлайн!

Я хотел бы предложить эту версию в комментарии Максу Ехлакову ( его ответ ), но, к сожалению, у меня пока нет 50 необходимых очков репутации, так что вот мой ответ.

803912находится C4448в шестнадцатеричном формате, он описывает , как результат должен быть отформатирован ( 12-4-4-4-8), она восстанавливается , так как наименее значащие цифры будут считаны первым.
 

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

  • сэкономил 3 байта благодаря Джонатану Фреху
  • сэкономили более 5 байт, заменив srand(time(0))сsrand(&i)

1
main(){...;int i=может быть main(i){...;i=.
Джонатан Фрех

Я думал кое-что, очевидно srand()принимаю unsigned intкак его начальный параметр. На tio.run длина unsigned intсоставляет 4 байта, а UUID - 16 байтов. Это означает, что будет сгенерирована только малая часть действительных выходных данных (1/2 ^ 12), поэтому мое решение (как и предыдущее с time(0)) недействительно. Как вы думаете ?
Annyo

ОП утверждает Assuming that your language's PRNG is perfect, all valid outputs must have the same probability of being generated.. Начальная энтропия не обязательно определяет энтропию ГСЧ, хотя, скорее всего, она определяет (не проверяла srand()реализацию). Тем не менее, srand()насколько мне известно, это достаточно равномерно, поэтому, если бы ГСЧ было совершенным, оно все равно было бы однородным. Поэтому я думаю, что ваш ответ действителен.
Джонатан Фрех

Хорошо я понял. Я также мог бы представить свой ответ как функцию, предполагая, что srand()это уже сделано, и в этом случае не будет никаких сомнений. Но я не уверен, разрешено ли это, другие представления C / C ++, кажется, все включают srand()int ответ (если он не использует rand())
Annyo


1

C (gcc), 143 110 103 96 94 байта

Гольф до 94 байтов, благодаря потолочной кошке и Джонатану Фреху.

(*P)()="\xf\x31À";*z=L"\10\4\4\4\14";main(n){for(;*z;*++z&amp;&amp;putchar(45))for(n=*z;n--;printf("%x",P()&amp;15));}

Попробуйте онлайн!

Объяснение:

/*
  P is a pointer to a function.
  The string literal contains actual machine code of the function:

  0F 31     rdtsc
  C3        ret

  0xc3 is the first byte of the UTF-8 representation of the character À
*/
(*P)() = "\xf\61À";

// encode uuid chunk lengths as literal characters
// we use wide characters with 'L' prefix because
// sizeof(wchar_t)==sizeof(int) for 64-bit gcc C on TIO
// so z is actually a zero-terminated string of ints
*z = L"\8\4\4\4\14"

main (n)
{
    for (
        ; 

        // loop until we reach the trailing zero
        *z;

        // increase the pointer and dereference it
        *++z 
             // and output a hyphen, if the pointer does not point at zero
             && putchar(45) 
    )
        // output a random hex string with length pointed at by z
        for (n = *z; n--; printf ("%x", P()&15));
}

1
Привет и добро пожаловать в PPCG! 110 байтов .
Джонатан Фрех

@JonathanFrech Спасибо! Ваша версия очень впечатляет!
Макс Ехлаков

Предлагаю *z=L"\27\23\17\vz"вместо *z=L"\10\4\4\4\14"и for(n=32;n--;z+=printf("-%x"+(n!=*z),P()&15)-1)вместоfor(;*z;*++z&&putchar(45))for(n=*z;n--;printf("%x",P()&15))
потолок кошка



0

SmileBASIC, 65 62 байта

DEF G H?"-";:END
DEF H?HEX$(RND(65536),4);
END H G G G G H H H

Я создал функцию для печати 4 случайных шестнадцатеричных цифр: DEF H?HEX$(RND(65536),4);:ENDа также 4 цифры с А -после них DEF G:H?"-";:END. Тогда он просто должен вызывать эти функции несколько раз.


0

чип , 109 + 6 = 115 байт

Требуются флаги -wc36, вызывающие +6 байт

!ZZZZZZZZZZZZZZZZZZZZZZ
,-----.,+vv--^----^---z
?]]]--R\acd
?xx+-)\\b
?x+x-)\\c
?^xx\--\d
`-xx]v~\e
f*`)'`-\g

Попробуйте онлайн!

Создает 4 случайных бита (четыре ?) и преобразует их в шестнадцатеричные цифры:

  • 0x0- 0x9=> 0-9
  • 0xa- 0xe=> b-f
  • 0xf => a

... немного нетрадиционно, но это сэкономило мне несколько байтов без затрат на распределение результатов.

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