Gere UUID aleatório


15

Eu preciso de um UUID. Seu trabalho é gerar um.

O UUID canônico (identificador universal único) é um número hexadecimal de 32 dígitos com hífens inseridos em determinados pontos. O programa deve gerar 32 dígitos hexadecimais (128 bits), na forma de xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx( 8-4-4-4-12dígitos), onde xé um número hexadecimal aleatório. Supondo que o PRNG do seu idioma seja perfeito, todas as saídas válidas devem ter a mesma probabilidade de serem geradas.

TL; DR

Gere 32 dígitos hexadecimais aleatórios nos dígitos do formulário 8-4-4-4-12. O menor código vence.

EDIT: deve ser hexadecimal. Sempre gerar apenas decimal é inválido. EDIT 2: Sem embutidos. Estes não são GUIDs, apenas dígitos hexadecimais genéricos.


Exemplo de saída:

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

As brechas de entrada e padrão não são permitidas.


Isso é , então o código mais curto vence. Além disso, fique à vontade para pedir esclarecimentos.


5
Parece uma versão menos rigorosa do codegolf.stackexchange.com/q/32309/14215
Geobits

9
"Esses exemplos não são aleatórios. Tente atribuir algum significado." O que isso significa?
Alex A.

3
Na verdade, não é necessário números hexadecimais, 10 bases também podem ser aleatórias. Por exemplo, 12345678-1234-1234-1234-123456789012deve ser um UUID válido (ou é necessário um dígito hexadecimal?). Você considera isso uma brecha?
Voitcus 22/09

3
O título e a primeira frase sugerem que você deseja um UUID canônico, e os exemplos dados parecem seguir as especificações dos UUIDs, mas você realmente parece estar pedindo outra coisa.
Peter Taylor

3
Sinto-me compelido a salientar que a UUID da versão 4 (aleatória) tem um formato exigido de xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx onde yestá um deles [89AB]. No momento deste comentário, nenhuma das respostas (exceto C # usando uma biblioteca interna) tem garantia de produzir um UUID aleatório válido (e, na verdade, provavelmente não produzirá um).

Respostas:


11

Pitão, 20 bytes

j\-msm.HO16*4hdj83 3

Demonstração.

Codifica [1, 0, 0, 0, 2]como 83 na base 3, depois adiciona um e multiplica por quatro para obter o comprimento de cada segmento. Em seguida, cria dígitos hexadecimais e se junta a hífens.


8

Julia, 80 bytes

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

Gere um número inteiro aleatório de 128 bits, obtenha sua representação hexidecimal como uma string preenchida com 32 dígitos e divida-a em segmentos unidos por traços.

Obrigado a ConfusedMr_C e kvill pela ajuda!


8

CJam, 26 25 bytes

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

Experimente on-line no intérprete CJam .

Como funciona

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 bytes

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

editar: parênteses estranhos:

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

edit: conseguiu remover o .Trim à direita ("-") do original:

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

Pode ser mais claro com algum espaço em branco, dada a natureza dos sinalizadores (-f e -Join). Eu ainda gostaria de perder o Trim final ("-"):

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

Ou, usando a funcionalidade interna (use a resposta C # acima)

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

No entanto, parece um pequeno atalho-y, mesmo que ele chegue aos 31 bytes.


61 bytes:(8,4,4,4,12|%{-join(1..$_|%{'{0:X}'-f(random(16))})})-join'-'
mazzy 08/08

5

Python 2, 86 84 bytes

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

Isso acopla os formatadores de string para fazer com que o Python formate os números hexadecimais exclusivamente para cada segmento.

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

Isso poderia melhorar, mas estou orgulhoso.



4

PHP, 69 72 75 bytes

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

Isso não gera dígitos hexadecimais (a , ...f ). Eles são permitidos, mas não exigidos pelo corpo da pergunta.

Nenhum grupo de dígitos começa com 0 (também não é necessário).

edit: salvou 3 bytes graças a @IsmaelMiguel


Parece um bi com mais de 32 bytes.
Isaacg 22/09

@isaacg sim, desculpe - meu erro
Voitcus

Você deve usar em seu join()lugar.
Ismael Miguel

3

C #, 65 bytes

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

editar: Sim! C # é mais curto que outra linguagem (além de Java) :)


1
Eu acho que isso é considerado uma brecha padrão ... :( meta.codegolf.stackexchange.com/questions/1061/…
Dom Hastings

1
Eu acho que isso não é considerado uma brecha padrão: como você pode ver, a solicitação para abandonar essas coisas acabou de receber 2 upvotes em mais de 1 ano. Ao contrário, o comentário que diz que você deve usar funções internas recebeu 58 votos positivos. Ou como um comentarista disse -> Se todos estivéssemos limitados ao mesmo conjunto de funções internas, todos os concursos seriam vencidos pela APL ou pela Golfscript porque seus nomes de comando são os mais curtos. (Michael Stern)
Stephan Schinkel

1
ou, em outras palavras: podemos usar printf? ou devemos usar asm inline para acionar a interrupção 21?
22415 Stephan Schinkel

Um bom ponto! Eu não pretendia me chatear, só queria ser útil! Acho que então, o Mathematica poderia ganhar CreateUUID[]!
Dom Hastings

1
@StephanSchinkel Os "apenas 2 votos positivos em um ano" são enganosos. No momento, há 47 upvotes e 45 downvotes, portanto, uma rede +2. Dito isto, o limite geralmente aceito é mais alto do que isso, então você está certo que ele não "realmente" conta como uma brecha padrão no momento.
Geobits

3

gawk, 86

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

Você pode usar isso uma vez a cada segundo para gerar um "UUID" aleatório exclusivo. Isso ocorre porque srand()usa o tempo do sistema em segundos desde a época como argumento, se não houver argumento.

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

Eu acho que a parte awk é bastante elegante.

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

Se você quiser usá-lo com mais frequência do que uma vez a cada segundo, pode chamá-lo no bash assim. Observe que a parte awk também foi alterada.

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

O echoé adicionado lá para imprimir uma nova linha de cada vez.


3

K5, 35 bytes

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

Para gerar um alfabeto hexadecimal, giro uma sequência de caracteres ( `c$) a partir de uma lista de dígitos ( 48+!10) e as 6 primeiras letras maiúsculas ( 65+!6). É uma maneira alternativa de gerar os dígitos com o mesmo comprimento ,/$!10.

Com a sequência "0123456789ABCDEF" gerada, o resto é simples. Selecione 32 valores aleatórios desse conjunto ( 32?), corte ( _) a sequência resultante em 0 8 12 16 20computada via (0,8+4*!4)e, em seguida, junte os fragmentos da sequência resultante com traços ("-"/ ).

Em ação:

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

3

R , 63 bytes

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

Experimente online!

O código primeiro cria uma seqüência aleatória de 36 caracteres e, em seguida, coloca os quatro hífens. Ele gera um UUID para stdout.


Substitua a cchamada sprintf("%x",0:15)por -1.
J.Doe

3

JavaScript, ES6, 106 bytes

"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})

Usa substituição de Regex. Trata a string de formato como uma contagem para gerar um caractere hexadecimal. Içando sempre que posso; omitindo ponto e vírgula sempre que possível.


89 bytes,'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 bytes

O óbvio:

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

A tradução do exemplo do Perl 5 usando printfresulta em código um pouco mais curto.

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

(0..16⁴)?! Você pode fazer isso no Perl?
clap

1
@VoteToSpam Você pode até 9 dias atrás . (Perl 6 será lançado no final deste mês)
Brad Gilbert b2gills

Cooooool. Talvez eu deva aprender isso
aplauso

@VoteToSpam isso não é nada comparado com 1,2,4,8,16 ... *o que gera uma lista infinita preguiçoso das potências de 2. ( {2**$++} ... *também funciona)
Brad Gilbert b2gills

2

Kotlin , 175 bytes

fun main(a:Array<String>){
fun f()="0123456789abcdef".get((Math.random()*16).toInt())
var s=""
for(i in listOf(8,4,4,4,12)){
for(j in 1..i)
s+=f()
if(i!=12)s+="-"}
println(s)}

Experimente online!

Meu primeiro programa Kotlin e envio de PPCG


152 bytes -> tio.run/...
jrtapsell

2

APL (Dyalog Unicode) , 115 78 bytes

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

Experimente online!

Este é o meu primeiro envio de APL. Um enorme obrigado a @ Adám por me acompanhar no chat do PPCG no APL e pela função de conversão hexadecimal.

Obrigado a @ Zacharý por 1 byte

Editado para corrigir a contagem de bytes.


Você pode assumir que ⎕IO←0, sem custo de bytes, Adám faz isso muito. Além disso, a maioria dos bytes (IIRC, todos os que você possui aqui) pode ser contada como um no APL.
Zachary

@ Zacharý Eu usei o TIO para contar os bytes para o envio, devo usar o número de caracteres? Ainda sou novo no PPCG e estou usando o APL, portanto não tenho muito conhecimento real de como fazer a contagem de bytes.
J. Sallé 20/10

Além disso, você pode mudar a(H 12?16)para a H 12?16salvar um byte.
Zachary


2

Japonês , 32 bytes

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

Experimente online!


Bem-vindo ao PPCG e bem-vindo ao Japt :) Vou dar uma olhada nas suas soluções até agora, quando tiver tempo (acabei de voltar de férias, tanto para recuperar o atraso), mas a primeira dica que vou oferecer é familiarizar-me você mesmo com os atalhos Unicode ( m@- £, por exemplo) e, para ajudar você a começar, aqui está uma versão de 24 bytes de sua solução às pressas : ethproductions.github.io/japt/… Entre na sala de chat do Japt se tiver alguma dúvida.
Shaggy

1

MATLAB / oitava, 95 bytes

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 bytes

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

Requer perl5> = 5,10, eu acho. Para o modificador / r e para say ().


1
Agradável! Isso é muito melhor que o meu! Tendo analisado sua solução, você pode economizar mais com base neste meta post com o s//xx-x-x-x-xxx/;s/x/sprintf"%04x",rand 65536/eguso de -psinalizador, também significa que ele funciona em versões mais antigas sem -E.
Dom Hastings

Obrigado. Sua sugestão é: echo | perl -pe's // xx-xxx-xxx /; s / x / sprintf "% 04x", rand 65536 / por exemplo 'E isso é apenas 48 caracteres entre' '. (É este tipo de batota talvez não?)
Kjetil S.

De acordo com este meta post , é aceitável, ainda não tive a oportunidade de utilizar esse mecanismo, mas espero que em breve! Seria 49 bytes (+ -p), mas ainda assim muito bom e eu não consideraria essa abordagem sem ver sua resposta!
Dom Hastings


1

C ++, 194 193 221 210 201 bytes

+7 bytes graças a Zacharý (detectou um -que não deveria estar no final)

#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)}

Se alguém tiver uma maneira de obter um valor diferente a cada execução, sem alterar srande sem incluir <ctime>, isso seria ótimo


Não pode #define L(a) forser #define L(a)for...? (Já poderia ter perguntado isso)
Zachary

Esta é inválido, há um "-" no final (que não deve haver)
Zachary

@ Zachary correção aplicada agora
HatsuPointerKun


1
Você poderia fazer algo assim "0123456789abcdef"[rand()%16]e depois remover f?
Zachary

1

Befunge-93 , 97 bytes

v>4448v,+<    <
0*    :  >59*0^
62v0-1_$:|>*6+^
>^>41v < @^99<
v<*2\_$:54+` |
?0>+\1-^ v*68<>
>1^

Experimente online!

Tenho certeza que isso pode ser reduzido, mas esta é minha primeira tentativa :)


1

Bash, 67 bytes

for l in 4 2 2 2 6;{ o+=`xxd -p -l$l</dev/random`-;}
echo ${o::-1}

Bem-vindo ao PPCG!
Dennis

1

JavaScript REPL, 79 bytes

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

Experimente online!

Math.randompode retornar 0. A adição de 5 zeros faz com que a fatia obtenha 4 0s


1

Quarto (gforth) , 91 89 bytes

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

Experimente online!

Explicação

Altera a base para hexadecimal e gera números / segmentos do comprimento apropriado com traços em intervalos especificados

Código Explicação

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 bytes

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

Experimente online!

Gostaria de sugerir esta versão em um comentário para Max Yekhlakov ( sua resposta ), mas infelizmente ainda não tenho os 50 pontos de reputação necessários, então aqui está a minha resposta.

803912está C4448em hexadecimal, descreve como a saída deve ser formatada ( 12-4-4-4-8), é revertida porque os dígitos menos significativos serão lidos primeiro.
 

Editar% s:

  • economizou 3 bytes graças a Jonathan Frech
  • economizou mais 5 bytes substituindo srand(time(0))porsrand(&i)

1
main(){...;int i=pode ser main(i){...;i=.
Jonathan Frech

Eu estive pensando em algo, aparentemente srand()aceite um unsigned intcomo seu parâmetro de semente. No tio.run, um unsigned inttem 4 bytes, mas o UUID tem 16 bytes. Isso significa que apenas uma pequena fração das saídas válidas (1/2 ^ 12) será gerada, portanto, minha solução (assim como a anterior com time(0)) não é válida. O que você acha ?
Annyo 27/08/19

O OP afirma Assuming that your language's PRNG is perfect, all valid outputs must have the same probability of being generated.. A entropia de sementes não determina necessariamente a entropia de RNG, embora provavelmente o faça (não verificou a srand()implementação). No entanto, srand()é do meu conhecimento razoavelmente uniforme, portanto, se o RNG fosse perfeito, ainda seria uniforme. Portanto, acho que sua resposta é válida.
Jonathan Frech

Ok, eu entendo. Eu também poderia enviar minha resposta como uma função, supondo srand()que já tenha sido feito e, neste caso, não haverá dúvida. Mas eu não tenho certeza se isso é permitido, outros C submissões / C ++ todos parecem incluem srand()int a resposta (a menos que ele não usa rand())
Annyo


1

C (gcc), 143 110 103 96 94 bytes

Jogou até 94 bytes graças a ceilingcat e Jonathan Frech.

(*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));}

Experimente online!

Explicação:

/*
  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
Olá e bem-vindo ao PPCG! 110 bytes .
Jonathan Frech

@JonathanFrech Thank you! Sua versão é muito impressionante!
Max Yekhlakov 8/08/18

Sugerir em *z=L"\27\23\17\vz"vez de *z=L"\10\4\4\4\14"e em for(n=32;n--;z+=printf("-%x"+(n!=*z),P()&15)-1)vez defor(;*z;*++z&&putchar(45))for(n=*z;n--;printf("%x",P()&15))
tetocat 9/1018

1

Java com pólo a laser de dez pés v. 1.06, 126 bytes

String u(){return sj224.tflp.util.StringUtil.replace("aa-a-a-a-aaa","a",s->String.format("%04x",(int)(Math.random()*65536)));}

Testado com a versão 1.06 da biblioteca, mas isso deve funcionar com qualquer versão 1.04 ou mais recente.



0

SmileBASIC, 65 62 bytes

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

Eu criei uma função para imprimir 4 dígitos hexadecimais aleatórios: DEF H?HEX$(RND(65536),4);:ENDassim como 4 dígitos com um -após elas DEF G:H?"-";:END. Depois, basta chamar essas funções várias vezes.


0

Chip , 109 + 6 = 115 bytes

Requer sinalizadores -wc36, causando +6 bytes

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

Experimente online!

Gera 4 bits aleatórios (os quatro ?) e converte em dígitos hexadecimais:

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

... um pouco não convencional, mas me salvou alguns bytes sem custos para a distribuição dos resultados.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.