Incrementar un GUID

30

Inspirado en un reciente artículo de Daily WTF ...

Escriba un programa o función que tome un GUID (cadena en el formato XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, donde cada X representa un dígito hexadecimal), y genera el GUID incrementado en uno.

Ejemplos

>>> 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

  • A diferencia del artículo vinculado, el incremento de un GUID que termina en F debe "llevar" al dígito hexadecimal anterior. Ver ejemplos arriba.
  • Puede suponer que la entrada no será ffffffff-ffff-ffff-ffff-ffffffffffff.
  • Para dígitos hexadecimales superiores a 9, puede usar mayúsculas (AF) o minúsculas (af).
  • Sí, los GUID pueden comenzar con a 0.
  • Su salida debe constar de exactamente 32 dígitos hexadecimales y 4 guiones en el formato esperado, incluidos los 0s iniciales necesarios .
  • No tiene que conservar el número de versión u otros bits fijos del GUID. Suponga que es solo un entero de 128 bits donde ninguno de los bits tiene un significado especial. Del mismo modo, se supone que los GUID se clasifican en un orden lexicográfico directo en lugar de en el orden binario de una GUIDestructura de Windows .
  • Si escribir una función, la entrada puede ser de cualquier secuencia-de- chartipo de datos: string, char[], List<char>, etc.
dan04
fuente
1
¿Se supone que debemos dejar intactos los 6 bits fijos en el UUIDv4?
Filip Haglund
2
@FilipHaglund: No, solo trata el GUID como un número de 128 bits, donde ninguno de los bits tiene un significado especial. Del mismo modo, se supone que los GUID se clasifican en un orden lexicográfico directo en lugar de en el orden binario de una GUIDestructura de Windows .
dan04
3
Caso de prueba sugerido: 89f25f2f-2f7b-4aa6-b9d7-46a98e3cb29fpara garantizar que las respuestas puedan hacer la transición 9 -> a.
Kamil Drakari
1
@dana: puede usar cualquier tipo de datos para los que foreach (char ch in theInput)sea ​​válido el equivalente de C # de su idioma .
dan04

Respuestas:

7

05AB1E , 17 15 18 bytes

Guardado 2 bytes gracias a Kevin Cruijssen

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

Pruébalo en línea! o como un conjunto de pruebas

Explicación

'-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 "-"
Emigna
fuente
Dang, me ganaste ... Tenía algo muy similar, pero con en žKÃlugar de '-K. Por cierto, puede guardar 2 bytes cambiando •É]•S3+a Ž¦˜S·.
Kevin Cruijssen
@KevinCruijssen: ¡Gracias! No sé cuántas veces he olvidado que eso Žes una cosa ahora ...
Emigna
No acepté esta respuesta porque alguien señaló que eliminará los ceros iniciales. Por favor, arregla.
dan04
@ dan04: ¡Buena llamada! No había pensado en eso. Debería arreglarse ahora :)
Emigna
11

JavaScript (ES6), 85 bytes

La cadena de salida está en minúsculas.

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

Pruébalo en línea!

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
Arnauld
fuente
5

Python 2 , 82 bytes

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

Pruébalo en línea!

Sin importaciones o conversión hexadecimal.

Esto escanea desde la parte posterior de la cadena, moviendo cada personaje a lo largo del ciclo 0123456789abcdef, -yendo a sí mismo. Después de tocar un símbolo que no sea fo -, deja de escanear hacia la izquierda y solo devuelve el resto sin cambios. Esta solución no es específica del formato UUID: funcionaría cualquier cantidad de bloques de cualquier cantidad de letras hexadecimales.

El caso base [str,f][s[-1]in'f-'](s[:-1])es un truco que nunca antes había visto en un golf. Se termina la recursión sin if, and, or, u otro flujo de control explícito.

Según la condición [s[-1]in'f-']del último carácter, el código vuelve f(s[:-1])o simplemente s[:-1]no cambia. Como stres la identidad en las cadenas, podemos seleccionar una de las funciones [str,f]y aplicarla s[:-1]. Tenga en cuenta que la llamada recursiva con fno se realiza si no se elige, evitando el problema de problema común que Python evalúa ansiosamente las opciones no utilizadas, lo que lleva a una regresión infinita en las recursiones.

xnor
fuente
bueno, ahí va mi cerebro por la mañana.
Don brillante
3

APL (Dyalog Unicode) , 46 bytes SBCS

Función de prefijo tácito anónimo.

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

Pruébalo en línea!

⎕CY'dfns'c op y la biblioteca "dfns" (para obtener hexydec )

(... )
 el argumento
 difiere de
'-' un guión
(... )@ en el subconjunto que consiste en las ubicaciones en las que el criterio anterior es verdadero, aplique:
dec¨ convierta cada carácter hexadecimal en un número decimal
 ... @32en la posición 32 (el último dígito), aplique:
  1+ incremente
16(... )⍣≡ aplique repetidamente con argumento izquierdo 16 hasta que sea estable:
  = compare (da la máscara donde los dígitos hexadecimales son 16)
  1⌽ gire cíclicamente un paso hacia la izquierda (este es el bit de acarreo)
  |+ a eso, agregue el resto de la división cuando se divide (por dieciséis, lo que convierte los 16 en 0)  gire dígitos en longitud-uno representaciones de caracteres hexadecimal varepsilon nlist (aplanar)
1hex

Adán
fuente
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 gracias a @ OlivierGrégoire .
-3 bytes gracias a @ ASCII-only .

Pruébalo en línea.

Explicación:

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

Antigua respuesta 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");}

Pruébalo en línea.

Explicación:

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
Kevin Cruijssen
fuente
1
111 bytes
Olivier Grégoire
@ OlivierGrégoire ¡No había pensado en usar un UUID real! Alternativa agradable y más corta. : D
Kevin Cruijssen
1
109
Solo ASCII
-1 más con var en lugar de largo
solo 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]))

Pruébalo en línea!

Sin importaciones

TFeld
fuente
2

Retina 0.8.2 , 21 bytes

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

Pruébalo en línea! El enlace incluye casos de prueba. 9se convierte a. Explicación: La expresión regular coincide con todos los fs y -s finales más un carácter anterior. La transliteración luego incrementa cíclicamente esos caracteres como si fueran dígitos hexadecimales. Enfoque alternativo, también 21 bytes:

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

Pruébalo en línea! El enlace incluye casos de prueba. Funciona al poner en minúscula la entrada para simplificar la transliteración. Por lo tanto, tendría 15 bytes si solo tuviera que admitir minúsculas. Pruébalo en línea! El enlace incluye casos de prueba.

Neil
fuente
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))

Se corrigió un error en caso de que un fragmento sea todo ceros. También jugaba mucho al abusar del try / catch. Resultado neto: 0 bytes guardados.

Un intento de 'engañar' usando java.util.UUIDfalló porque el longvalor devuelto por java.util.UUID.get[Most/Least]SignificantBitsse convierte en un doubleque incurre en una pérdida de precisión. Los invito a echar un vistazo a esta mesa y pronunciar en silencio "... pero ¿por qué? "

Explicación

La hex2decfunción escupe a double, por lo que no puede procesar todo el GUID a la vez para evitar excederlo flintmax. En cambio, tenemos que procesar el fragmento GUID por fragmento, usandosplit . La variable averifica si necesitamos llevar un uno, y con trampa también es el incremento inicial que agregamos. La condición para transferir es si las longitudes de las cadenas originales e incrementadas ya no son iguales.

La versión original tenía poco menos de 160 bytes, así que me gustaría pensar que esto no debería ser fácil de superar.

Sanchises
fuente
2

Python 2 , 99 bytes

s='%032x'%-~int(input().replace('-',''),16)
print'-'.join((s[:8],s[8:12],s[12:16],s[16:20],s[20:]))

Pruébalo en línea!

Sin uuid.UUIDuso

Erik el Outgolfer
fuente
2

C # (compilador interactivo de 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;);}

Pruébalo en línea!

-1 byte gracias a @ASCIIOnly!

Función anónima que toma char[]como entrada y salida modificando un argumento .

La entrada se escanea de derecha a izquierda y se reemplaza usando las siguientes reglas.

  • los - personaje se ignora y el procesamiento continúa
  • El Fpersonaje se convierte a0 y el procesamiento continúa
  • El 9personaje se convierte aA y el procesamiento se detiene
  • Los caracteres A-Ey 0-8se incrementan en 1 y el procesamiento se detiene
dana
fuente
2
==70->>69
Solo ASCII
Excelente - Gracias :)
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

Pruébalo en línea!

Sin biblioteca externa o conversión hexadecimal. Cualquier longitud de cuerda. Se permiten minúsculas y mayúsculas. La cadena de entrada que coincide también ^[f-]*$está permitida.

Este script escanea desde la parte posterior de la cadena y agrega a cada carácter el valor de la tabla hash:

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

A continuación, la secuencia de comandos se utiliza $ppara determinar si se incrementa el carácter actual.

Script de prueba:

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

Salida:

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
mazzy
fuente
1

Perl 6 , 65 bytes

{(:16(TR/-//)+1).base(16).comb.rotor(8,4,4,4,*)».join.join('-')}

Pruébalo

Brad Gilbert b2gills
fuente
1
El OP ha aclarado que los ceros iniciales deben conservarse.
Dennis
56 bytes con ceros a la izquierda
Jo King
1
O 53 bytes manejando cosas más manualmente
Jo King
1

PowerShell , 126 bytes

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

Pruébalo en línea!

Respuesta bastante trivial. Solo pensé que podría agregar el querido PowerShell a la lista :)

KGlasier
fuente
0

Perl 5, 64 bytes

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

La cantidad de paréntesis necesarios aquí me pone triste, pero -> une muy estrechamente, ya que ->as_hexes la forma más rápida que puedo encontrar para obtener una salida con formato hexadecimal.

Corre con perl -Mbigint -p. Básicamente, solo convierte el número en un bigint hexadecimal, agrega uno y luego sustituye los dígitos del resultado al valor original, dejando intactos los guiones.

Silvio Mayolo
fuente
0

Óxido, 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('-')));

sí, es largo ... pero técnicamente es solo una línea con 1 expresión? y no hay bibliotecas elegantes? y no se bloqueará en una entrada fuzz? 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('-')));

Pruébalo en el patio de óxido

don brillante
fuente
0

Código de ensamblado 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

Llame con ESI apuntando a GUID. Reemplace ESI con SI para 16 bits o RSI para 64 bits (y +2 bytes).

Peter Ferrie
fuente
0

C (clang) , 62 bytes

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

Pruébalo en línea!

AZTECCO
fuente
Espere. ¿el cheque en minúsculas / mayúsculas no cuesta nada?
Solo ASCII
Quiero decir, ¿puede manejar minúsculas y mayúsculas sin costo alguno?
Solo ASCII
Ah ok .. ch-70% 32? : a '0' ... 64 y 96 son múltiplos de 32, entonces 70-6 y 102-6% 32.
AZTECCO
1
en realidad no tienes que manejar ambos, así que 64
solo ASCII el
0

Lisp común, 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#))))

Pruébalo en línea!

Renzo
fuente