Incrementar um GUID


30

Inspirado em um artigo recente do Daily WTF ...

Escreva um programa ou função que use um GUID (sequência no formato XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, em que cada X representa um dígito hexadecimal) e produz o GUID incrementado por um.

Exemplos

>>> increment_guid('7f128bd4-b0ba-4597-8f35-3a2f2756dfbb')
'7f128bd4-b0ba-4597-8f35-3a2f2756dfbc'
>>> increment_guid('06b86883-f3e7-4f9d-87c5-a047e89a19fa')
'06b86883-f3e7-4f9d-87c5-a047e89a19fb'
>>> increment_guid('89f25f2f-2f7b-4aa6-b9d7-46a98e3cb2cf')
'89f25f2f-2f7b-4aa6-b9d7-46a98e3cb2d0'
>>> increment_guid('89f25f2f-2f7b-4aa6-b9d7-46a98e3cb29f')
'89f25f2f-2f7b-4aa6-b9d7-46a98e3cb2a0'
>>> increment_guid('8e0f9835-4086-406b-b7a4-532da46963ff')
'8e0f9835-4086-406b-b7a4-532da4696400'
>>> increment_guid('7f128bd4-b0ba-4597-ffff-ffffffffffff')
'7f128bd4-b0ba-4598-0000-000000000000'

Notas

  • Diferentemente do artigo vinculado, o incremento de um GUID que termina em F deve "transportar" para o dígito hexadecimal anterior. Veja exemplos acima.
  • Você pode assumir que a entrada não será ffffffff-ffff-ffff-ffff-ffffffffffff.
  • Para dígitos hexadecimais acima de 9, você pode usar maiúsculas (AF) ou letras minúsculas (af).
  • Sim, os GUIDs podem começar com a 0.
  • Sua saída deve consistir em exatamente 32 dígitos hexadecimais e 4 hífens no formato esperado, incluindo quaisquer 0s iniciais necessários .
  • Você não precisa preservar o número da versão ou outros bits fixos do GUID. Suponha que seja apenas um número inteiro de 128 bits em que nenhum dos bits tem algum significado especial. Da mesma forma, supõe-se que os GUIDs classifiquem em ordem lexicográfica direta e não na ordem binária de uma GUIDestrutura do Windows .
  • Se uma função de escrita, a entrada pode ser de qualquer sequcia-de- chartipo de dados: string, char[], List<char>, etc.

1
Devemos deixar intactos os 6 bits fixos no UUIDv4?
Filip Haglund

2
@FilipHaglund: Não, basta tratar o GUID como um número de 128 bits, em que nenhum dos bits tem algum significado especial. Da mesma forma, supõe-se que os GUIDs classifiquem em ordem lexicográfica direta e não na ordem binária de uma GUIDestrutura do Windows .
dan04 17/01

3
Caso de teste sugerido: 89f25f2f-2f7b-4aa6-b9d7-46a98e3cb29fpara garantir que as respostas possam fazer a transição 9 -> a.
Kamil Drakari 17/01

1
@ana: Você pode usar qualquer tipo de dado para o qual o equivalente em linguagem do C # foreach (char ch in theInput)seja válido.
dan04 17/01

Respostas:


7

05AB1E , 17 15 18 bytes

Guardado 2 bytes graças a Kevin Cruijssen

'-K1ìH>h¦Ž¦˜S·£'-ý

Experimente online! ou como um conjunto de testes

Explicação

'-K                  # remove "-" from input
   1ì                # prepend a 1 (to preserve leading 0s)
     H               # convert from hex to base 10
      >              # increment
       h             # convert to hex from base 10
        ¦            # remove the extra 1
         Ž¦˜S·       # push [8, 4, 4, 4, 12]
              £      # split into parts of these sizes
               '-ý   # join on "-"

Dang, você me venceu .. Tinha algo muito semelhante, mas com em žKÃvez de '-K. Aliás, você pode salvar 2 bytes mudando •É]•S3+para Ž¦˜S·.
Kevin Cruijssen 17/01

@KevinCruijssen: Obrigado! Não sei quantas vezes esqueci isso Žagora ...
Emigna 17/01

Eu não aceitei essa resposta porque alguém apontou que ela deixará os zeros à esquerda. Por favor conserte.
dan04 18/01

@ dan04: Boa chamada! Eu não tinha pensado nisso. Deve ser corrigido agora :)
Emigna 18/01


11

JavaScript (ES6), 85 bytes

A sequência de saída está em minúscula.

s=>(g=(c,x=+('0x'+s[--n])+!!c)=>1/x?g(x>>4)+(x&15).toString(16):~n?g(c)+'-':'')(n=36)

Experimente online!

Comentado

s => (                   // s = GUID
  g = (                  // g = recursive function taking:
    c,                   //   c = carry from the previous iteration
    x = +('0x' + s[--n]) //   x = decimal conversion of the current digit
        + !!c            //       add the carry
  ) =>                   //
    1 / x ?              // if x is numeric:
      g(x >> 4) +        //   do a recursive call, using the new carry
      (x & 15)           //   and append the next digit
      .toString(16)      //   converted back to hexadecimal 
    :                    // else:
      ~n ?               //   if n is not equal to -1:
        g(c)             //     do a recursive call, leaving the current carry unchanged
        + '-'            //     and append a hyphen
      :                  //   else:
        ''               //     stop recursion
)(n = 36)                // initial call to g with n = 36 and a truthy carry

5

Python 2 , 82 bytes

q='f0123456789abcdef--'
f=lambda s:[str,f][s[-1]in'f-'](s[:-1])+q[q.find(s[-1])+1]

Experimente online!

Nenhuma importação ou conversão hexadecimal.

Isso digitaliza a partir da parte de trás da corda, movendo cada caractere ao longo do ciclo 0123456789abcdef, -indo para si mesmo. Depois de atingir um símbolo diferente de fou -, ele para de digitalizar para a esquerda e retorna o restante inalterado. Esta solução não é específica para o formato UUID - qualquer número de blocos de qualquer número de letras hexadecimais funcionaria.

O caso base de [str,f][s[-1]in'f-'](s[:-1])é um truque que eu nunca vi usado em um golfe antes. Ele termina a recursão sem qualquer if, and, or, ou outro controle de fluxo explícito.

Com base na condição [s[-1]in'f-']do último caractere, o código retorna f(s[:-1])ou s[:-1]permanece inalterado. Como stré a identidade nas strings, podemos selecionar uma das funções [str,f]e aplicá-la s[:-1]. Observe que a chamada recursiva com fnão é feita se não for escolhida, contornando o problema comum que o Python avalia avidamente opções não utilizadas, levando a uma infinita regressão nas recursões.


bem, lá vai meu cérebro pela manhã.
don bright

3

APL (Dyalog Unicode) , SBCS de 46 bytes

Função de prefixo tácito anônimo.

CY'dfns'
(∊1hex 16(|+1⌽=)⍣≡1+@32dec¨)@('-'≠⊢)

Experimente online!

⎕CY'dfns'c op y a biblioteca "NDR" (para obter hexedec )

()
 O argumento
 difere de
'-' um traço
()@ no subconjunto que consiste nos locais nos quais o critério acima é verdadeiro, aplique:
dec¨ converta cada caractere hexadecimal em um número decimal
 … @32na posição 32 (o último dígito), aplique:
  1+ incremento
16()⍣≡ aplique repetidamente com argumento esquerda 16 até estável:
  = comparar (dá mascarar onde os dígitos hexadecimais são 16)
  1⌽ um passo ciclicamente rotação para a esquerda (este é o carry bit)
  |+ para que, adicione o resto da divisão quando dividido (por dezesseis anos, tornando assim todos os 16 para 0)  vez dígitos em comprimento e um de caracteres hexadecimal representações £ nlist (flatten)
1hex


3

Java 11, 152 149 111 108 bytes

s->{var b=s.getLeastSignificantBits()+1;return new java.util.UUID(s.getMostSignificantBits()+(b==0?1:0),b);}

-38 bytes obrigado a @ OlivierGrégoire .
-3 bytes graças a @ ASCII-only .

Experimente online.

Explicação:

s->{         // Method with UUID as both parameter and return-type
  var b=s.getLeastSignificantBits()
             //  Get the 64 least significant bits of the input-UUID's 128 bits as long
        +1;  //  And increase it by 1
  return new java.util.UUID(
             //  Return a new UUID with:
    s.getMostSignificantBits()
             //   The 64 most significant bits of the input-UUID's 128 bits as long
    +(b==0?  //    And if the 64 least significant bits + 1 are exactly 0:
       1     //     Increase the 64 most significant bits by 1 as well
      :      //    Else:
       0,    //     Don't change the 64 most significant bits by adding 0
     b);}    //   And the 64 least significant bits + 1

Resposta antiga de 149 bytes:

s->{var t=new java.math.BigInteger(s.replace("-",""),16);return(t.add(t.ONE).toString(16)).replaceAll("(.{4})".repeat(5)+"(.*)","$1$2-$3-$4-$5-$6");}

Experimente online.

Explicação:

s->{                              // Method with String as both parameter and return-type
  var t=new java.math.BigInteger( //  Create a BigInteger
         s.replace("-",""),       //  Of the input-string with all "-" removed
         16);                     //  Converted from Hexadecimal
  return(t.add(t.ONE)             //  Add 1
         .toString(16))           //  And convert it back to a Hexadecimal String
         .replaceAll("(.{4})".repeat(5)+"(.*)",
                                  //  And split the string into parts of sizes 4,4,4,4,4,rest
           "$1$2-$3-$4-$5-$6");}  //  And insert "-" after parts of size 8,4,4,4,
                                  //  and return it as result


@ OlivierGrégoire Não tinha pensado em usar um UUID real! Alternativa agradável e mais curta. : D
Kevin Cruijssen 17/01


-1 mais com var em vez de longo
somente ASCII



2

Python 2 , 113 112 bytes

def f(s):a=hex(int(s.replace('-',''),16)+1+2**128);return'-'.join((a[3:11],a[11:15],a[15:19],a[19:23],a[23:-1]))

Experimente online!

Sem importações


2

Retina 0.8.2 , 21 bytes

T`FfdlL`0dlL`.[-Ff]*$

Experimente online! O link inclui casos de teste. 9torna-se a. Explicação: A expressão regular corresponde a todos arrasto fs e -s mais uma personagem anterior. A transliteração então incrementa ciclicamente esses caracteres como se fossem dígitos hexadecimais. Abordagem alternativa, também 21 bytes:

T`L`l
T`fo`dl`.[-f]*$

Experimente online! O link inclui casos de teste. Funciona com minúsculas na entrada para simplificar a transliteração. Seria, portanto, 15 bytes se tivesse apenas que suportar letras minúsculas. Experimente online! O link inclui casos de teste.


2

MATLAB, 138 bytes

a=1;Z=a;for r=flip(split(input(''),'-'))'
q=r{:};z=dec2hex(hex2dec(q)+a,nnz(q));try
z+q;a=0;catch
z=~q+48;end
Z=[z 45 Z];end;disp(Z(1:36))

Corrigido um bug no caso de um pedaço ser todos zeros. Também jogou muito, abusando do try / catch. Resultado líquido: 0 bytes salvos.

Uma tentativa de "trapacear" usando java.util.UUIDfalha porque o longvalor retornado java.util.UUID.get[Most/Least]SignificantBitsé convertido em um doubleque incorre em perda de precisão. Convido você a dar uma olhada nesta mesa e dizer silenciosamente "... mas por quê? "

Explicação

A hex2decfunção cospe a double, portanto, não pode processar o GUID inteiro de uma só vez para evitar exceder flintmax. Em vez disso, temos que processar o pedaço GUID por chunck, usando split. A variável averifica se precisamos carregar um e, também, enganosamente, é o incremento inicial que adicionamos. A condição para transportar é se os comprimentos das seqüências originais e incrementadas não são mais iguais.

A versão original tinha pouco menos de 160 bytes, então eu gostaria de pensar que isso não deve ser fácil de superar.



2

C # (compilador interativo do Visual C #) , 77 bytes

x=>{for(int i=35,c;(x[i]=(char)((c=x[i--])<48?c:c==57?65:c>69?48:c+1))<49;);}

Experimente online!

-1 byte graças a @ASCIIOnly!

Função anônima que recebe a char[]como entrada e sai modificando um argumento .

A entrada é digitalizada da direita para a esquerda e substituída usando as seguintes regras.

  • O -personagem é ignorado e o processamento continua
  • O Fcaractere é convertido 0e o processamento continua
  • O 9caractere é convertido Ae o processamento é interrompido
  • Os caracteres A-Ee 0-8são incrementados por 1 e pára o processamento

2
==70->>69
somente ASCII

Excelente - Obrigado :)
dana

2

Powershell, 101 bytes

for($p=1;$d=+"$args"[--$i]){$d+=$p*(1-@{45=1;57=-7;70=23;102=55}.$d)
$p*=$d-in45,48
$r=[char]$d+$r}$r

Experimente online!

Nenhuma biblioteca externa ou conversão hexadecimal. Qualquer comprimento de string. Minúsculas e maiúsculas são permitidas. A string de entrada correspondente a também ^[f-]*$é permitida.

Esse script varre a parte de trás da string e aumenta cada caracter pelo valor da hashtable:

  • -: incremento = 1-1
  • 9: incremento = 1 + 7, resultado =A
  • F: incremento = 1-23, resultado =0
  • f: incremento = 1-55, resultado =0
  • incremento = 1 para outros caracteres

Em seguida, o script usa $ppara determinar se incrementa o caractere atual.

Script de teste:

$f = {

for($p=1;$d=+"$args"[--$i]){$d+=$p*(1-@{45=1;57=-7;70=23;102=55}.$d)
$p*=$d-in45,48
$r=[char]$d+$r}$r

}

@(
    ,('f','0')
    ,('F','0')
    ,('0','1')
    ,('9','A')
    ,('A','B')
    ,('a','b')
    ,('0-f','1-0')
    ,('0-F','1-0')
    ,("7f128bd4-b0ba-4597-8f35-3a2f2756dfbb","7f128bd4-b0ba-4597-8f35-3a2f2756dfbc")
    ,("06b86883-f3e7-4f9d-87c5-a047e89a19f9","06b86883-f3e7-4f9d-87c5-a047e89a19fa")
    ,("89f25f2f-2f7b-4aa6-b9d7-46a98e3cb2cf","89f25f2f-2f7b-4aa6-b9d7-46a98e3cb2d0")
    ,("8e0f9835-4086-406b-b7a4-532da46963ff","8e0f9835-4086-406b-b7a4-532da4696400")
    ,("7f128bd4-b0ba-4597-ffff-ffffffffffff","7f128bd4-b0ba-4598-0000-000000000000")
    ,("89f25f2f-2f7b-4aa6-b9d7-46a98e3cb29f","89f25f2f-2f7b-4aa6-b9d7-46a98e3cb2a0")
    ,("ffffffff-ffff-ffff-ffff-ffffffffffff","00000000-0000-0000-0000-000000000000")
) | % {
    $guid,$expected = $_
    $result = &$f $guid
    "$($result-eq$expected): $result"
}

Saída:

True: 0
True: 0
True: 1
True: A
True: B
True: b
True: 1-0
True: 1-0
True: 7f128bd4-b0ba-4597-8f35-3a2f2756dfbc
True: 06b86883-f3e7-4f9d-87c5-a047e89a19fA
True: 89f25f2f-2f7b-4aa6-b9d7-46a98e3cb2d0
True: 8e0f9835-4086-406b-b7a4-532da4696400
True: 7f128bd4-b0ba-4598-0000-000000000000
True: 89f25f2f-2f7b-4aa6-b9d7-46a98e3cb2A0
True: 00000000-0000-0000-0000-000000000000



1

PowerShell , 126 bytes

$a=("{0:X32}" -f (1+[Numerics.BigInteger]::Parse($args[0]-replace"-", 'AllowHexSpecifier')));5..2|%{$a=$a.Insert(4*$_,"-")};$a

Experimente online!

Resposta bastante trivial. Apenas pensei em adicionar o amado PowerShell à lista :)



0

Perl 5, 64 bytes

$c=reverse((1+hex s/-//gr)->as_hex);$c=~s/..$//;s/[^-]/chop$c/ge

O número de parênteses necessários aqui me deixa triste, mas ->se liga muito bem, como ->as_hexé a maneira mais rápida que posso encontrar para obter uma saída no formato hexadecimal.

Corra com perl -Mbigint -p. Basicamente, ele apenas converte o número em um hexadecimal bigint, adiciona um e subtitula os dígitos do resultado novamente no valor original, deixando os traços intocados.


0

Ferrugem, 258 bytes

let x=|s:&str|s.chars().rev().scan(1,|a,c|{let d=c.to_digit(16).unwrap_or(99);match(d,*a){(15,1)=>{*a=1;Some(0)}(0..=14,1)=>{*a = 0;Some(d + 1)}_=> Some(d),}}).collect::<Vec<u32>>().iter().rev().for_each(|d| print!("{}", std::char::from_digit(*d, 16).unwrap_or('-')));

sim é longo .. mas tecnicamente é a única linha com 1 expressão? e sem bibliotecas chiques? e não falhará em uma entrada de penugem? ungolf:

let x=|s:&str|s.chars().rev().scan(1, |a, c| {
            let d = c.to_digit(16).unwrap_or(99);
            match (d, *a) {
                (15, 1) => {*a = 1;Some(0)}
                (0..=14, 1) => {*a = 0;Some(d + 1)}
                _ => Some(d),
            }
        }).collect::<Vec<u32>>().iter().rev()
        .for_each(|d| print!("{}", std::char::from_digit(*d, 16).unwrap_or('-')));

experimentá-lo no parque infantil ferrugem



0

Código de montagem x86 de 16/32/64 bits, 28 bytes

bytes: 83C623FDAC3C2D74FB403C3A7502B0613C677502B03088460173E9C3

código:

     add esi, 35       ;point to end of string - 1
     std               ;go backwards
l1:  lodsb             ;fetch a character
     cmp al, '-'
     je  l1            ;skip '-'
     inc eax           ;otherwise increment
     cmp al, '9' + 1
     jne l2            ;branch if not out of numbers
     mov al, 'a'       ;otherwise switch '9'+1 to 'a'
l2:  cmp al, 'f' + 1   ;sets carry if less
     jne l3            ;branch if not out of letters
     mov al, '0'       ;otherwise switch 'f'+1 to '0'
                       ;and carry is clear
l3:  mov [esi + 1], al ;replace character
     jnb l1            ;and loop while carry is clear
     ret

Ligue com o ESI apontando para GUID. Substitua ESI por SI por 16 bits ou RSI por 64 bits (e +2 bytes).


0

C (clang) , 62 bytes

g(char*i){for(i+=36;(*--i-45?*i+=*i-70?*i-57?1:8:-22:0)<49;);}

Experimente online!


esperar. a verificação em minúsculas / maiúsculas não custa nada ???
somente ASCII

Quero dizer, ele pode lidar com letras minúsculas e maiúsculas, sem nenhum custo para bytecount ?!
somente ASCII

Ah ok .. ch-70% 32? : para '0' ... 64 e 96 são múltiplos de 32, então 70-6 e 102-6% 32.
AZTECCO 22/01

1
você realmente não precisa lidar com ambos, então 64
somente ASCII

0

Lisp comum, 166 bytes

(lambda(s &aux(r(format()"~32,'0x"(1+(parse-integer(remove #\- s):radix 16)))))(format()"~{~a~^-~}"(mapcar(lambda(x y)(subseq r x y))#1='(0 8 12 16 20 32)(cdr #1#))))

Experimente online!

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.