Incrementa un GUID


30

Ispirato da un recente articolo del Daily WTF ...

Scrivi un programma o una funzione che accetta un GUID (stringa nel formato XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, in cui ogni X rappresenta una cifra esadecimale) e genera il GUID incrementato di uno.

Esempi

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

Gli appunti

  • Diversamente dall'articolo collegato, l'incremento di un GUID che termina con F deve "riportare" alla cifra esadecimale precedente. Vedi esempi sopra.
  • Si può presumere che l'input non lo sarà ffffffff-ffff-ffff-ffff-ffffffffffff.
  • Per cifre esadecimali superiori a 9, è possibile utilizzare maiuscole (AF) o minuscole (af).
  • Sì, i GUID possono iniziare con a 0.
  • L'output deve essere composto esattamente da 32 cifre esadecimali e 4 trattini nel formato previsto, inclusi tutti gli iniziali necessari 0.
  • Non è necessario conservare il numero di versione o altri bit fissi del GUID. Supponiamo che sia solo un intero a 128 bit in cui nessuno dei bit ha un significato speciale. Allo stesso modo, si presume che i GUID ordinino in ordine lessicografico semplice anziché nell'ordine binario di una GUIDstruttura di Windows .
  • Se crei una funzione, l'ingresso può essere di qualsiasi sequenza-di- chartipo di dati: string, char[], List<char>, etc.

1
Dovremmo lasciare intatti i 6 bit fissi in UUIDv4?
Filip Haglund,

2
@FilipHaglund: No, considera il GUID come un numero a 128 bit, dove nessuno dei bit ha un significato speciale. Allo stesso modo, si presume che i GUID ordinino in ordine lessicografico semplice anziché nell'ordine binario di una GUIDstruttura di Windows .
dan04

3
Caso di prova suggerito: 89f25f2f-2f7b-4aa6-b9d7-46a98e3cb29fassicurarsi che le risposte possano effettuare la transizione 9 -> a.
Kamil Drakari,

1
@dana: è possibile utilizzare qualsiasi tipo di dati per cui foreach (char ch in theInput)è valido l'equivalente della lingua di C # .
dan04,

Risposte:


7

05AB1E , 17 15 18 byte

Salvato 2 byte grazie a Kevin Cruijssen

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

Provalo online! o come una suite di test

Spiegazione

'-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, mi hai battuto ad esso .. Aveva qualcosa di molto simile, ma con žKÃinvece di '-K. A proposito, puoi salvare 2 byte cambiando •É]•S3+in ަ˜S·.
Kevin Cruijssen il

@KevinCruijssen: grazie! Non so quante volte ho continuato a dimenticare che Žè una cosa adesso ...
Emigna il

Non ho accettato questa risposta perché qualcuno ha sottolineato che lascerà cadere gli 0 iniziali. Per favore, aggiusta.
dan04,

@ dan04: buona chiamata! Non ci avevo pensato. Ora dovrebbe essere risolto :)
Emigna il


11

JavaScript (ES6), 85 byte

La stringa di output è in minuscolo.

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

Provalo online!

Commentate

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 byte

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

Provalo online!

Nessuna importazione o conversione esadecimale.

Questo esegue la scansione dalla parte posteriore della stringa, spostando ciascun personaggio lungo il ciclo 0123456789abcdef, -andando a se stesso. Dopo aver colpito un simbolo diverso da fo -, interrompe la scansione verso sinistra e restituisce il resto invariato. Questa soluzione non è specifica per il formato UUID: qualsiasi numero di blocchi di qualsiasi numero di lettere esadecimali funzionerebbe.

Il caso base di [str,f][s[-1]in'f-'](s[:-1])è un trucco che non avevo mai visto prima in un campo da golf. Termina la ricorsione senza if,and ,or , o altro flusso di controllo esplicito.

In base alla condizione [s[-1]in'f-']dell'ultimo carattere, il codice ritorna f(s[:-1])o è s[:-1]rimasto invariato. Poiché strè l'identità sulle stringhe, possiamo selezionare una delle funzioni [str,f]e applicarla s[:-1]. Si noti che la chiamata ricorsiva con fnon viene effettuata se non viene scelta, aggirando il problema del problema comune che Python valuta con entusiasmo le opzioni non utilizzate, portando a un regresso infinito nelle ricorsioni.


beh, mi va il cervello per la mattina.
don luminoso

3

APL (Dyalog Unicode) , 46 byte SBCS

Funzione prefisso tacito anonimo.

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

Provalo online!

⎕CY'dfns'c op y la libreria "dfns" (per ottenere hexedec )

(... )
 l'argomento
 differisce da
'-' un trattino
(... )@ sul sottoinsieme costituito dalle posizioni in cui il criterio sopra è vero, applica:
dec¨ converti ogni carattere esadecimale in un numero decimale
 ... @32alla posizione 32 (l'ultima cifra), applica:
  1+ incremento
16(... )⍣≡ applica ripetutamente con argomento di sinistra 16 fino stabile:
  = confronta (dà mascherare dove le cifre esadecimali sono 16)
  1⌽ passo uno ciclicamente rotazione sinistra (questo è il bit di riporto)
  |+ a ciò, aggiungere il resto della divisione quando diviso (da sedici, rendendo così tutti 16 nella 0)  turn cifre in rappresentazioni di caratteri esadecimali lunghezza uno ϵ nlist (appiattisci)
1hex


3

Java 11, 152 149 111 108 byte

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

-38 byte grazie a @ OlivierGrégoire .
-3 byte grazie solo a @ ASCII .

Provalo online.

Spiegazione:

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

Risposta a 149 byte vecchi:

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

Provalo online.

Spiegazione:

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 Non avevo pensato di usare un UUID reale! Alternativa piacevole e più breve. : D
Kevin Cruijssen il


-1 in più con var anziché long
ASCII il



2

Python 2 , 113 112 byte

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

Provalo online!

Senza importazioni


2

Retina 0.8.2 , 21 byte

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

Provalo online! Il link include casi di test. 9diventa a. Spiegazione: La regex corrisponde a tutte le fs e -s finali più un carattere precedente. La traslitterazione quindi incrementa ciclicamente quei caratteri come se fossero cifre esadecimali. Approccio alternativo, anche 21 byte:

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

Provalo online! Il link include casi di test. Funziona minuscola l'input per semplificare la traslitterazione. Sarebbe quindi di 15 byte se dovesse supportare solo lettere minuscole. Provalo online! Il link include casi di test.


2

MATLAB, 138 byte

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

Risolto un bug nel caso in cui un pezzo fosse tutto zeri. Ha anche giocato molto a golf abusando di try / catch. Risultato netto: 0 byte salvati.

Un tentativo di "imbrogliare" utilizzando java.util.UUIDnon è riuscito perché il longvalore restituito da java.util.UUID.get[Most/Least]SignificantBitsviene convertito in un valore doubleche comporta una perdita di precisione. Ti invito a dare un'occhiata a questo tavolo e pronunciare silenziosamente "... ma perché? "

Spiegazione

La hex2decfunzione sputa a double, quindi non può elaborare l'intero GUID in una sola volta per evitare il superamento flintmax. Invece, dobbiamo elaborare il pezzo GUID per chunck, usando split. La variabilea controlla se dobbiamo portarne una, e barare è anche l'incremento iniziale che aggiungiamo. La condizione per il riporto è se le lunghezze delle stringhe originali e incrementate non sono più uguali.

La versione originale era poco meno di 160 byte, quindi mi piacerebbe pensare che questo non dovrebbe essere facile da superare.



2

C # (compilatore interattivo Visual C #) , 77 byte

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

Provalo online!

-1 byte grazie a @ASCIIOnly!

Funzione anonima che accetta char[]input e output modificando un argomento .

L'input viene scansionato da destra a sinistra e sostituito con le seguenti regole.

  • Il - personaggio viene ignorato e l'elaborazione continua
  • Il Fpersonaggio viene convertito in0 e l'elaborazione continua
  • Il 9personaggio viene convertito inA e l'elaborazione si interrompe
  • I caratteri A-Ee 0-8vengono incrementati di 1 e l'elaborazione si interrompe

2
==70->>69
ASCII il

Eccellente - Grazie :)
Dana il

2

Powershell, 101 byte

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

Provalo online!

Nessuna libreria esterna o conversione esadecimale. Qualsiasi lunghezza di stringa. Sono consentite lettere minuscole e maiuscole. ^[f-]*$È consentita anche la corrispondenza della stringa di input con .

Questo script esegue la scansione dal retro della stringa e aumenta ogni carattere del valore di hashtable:

  • -: incremento = 1-1
  • 9: incremento = 1 + 7, risultato =A
  • F: incremento = 1-23, risultato =0
  • f: incremento = 1-55, risultato =0
  • incremento = 1 per altri caratteri

Successivamente, lo script utilizza $p per determinare se incrementare il carattere corrente.

Script di prova:

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

Produzione:

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 byte

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

Provalo online!

Risposta piuttosto banale. Pensavo solo di aggiungere l'amato PowerShell all'elenco :)



0

Perl 5, 64 byte

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

Il numero di parentesi necessarie qui mi rende triste, ma si ->lega molto strettamente, come ->as_hexè il modo più veloce che posso trovare per ottenere un output in formato esadecimale.

Corri con perl -Mbigint -p. Fondamentalmente, converte semplicemente il numero in esadecimale bigint, ne aggiunge uno e quindi sottotitola le cifre del risultato nel valore originale, lasciando i trattini intatti.


0

Ruggine, 258 byte

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ì, è lungo .. ma tecnicamente è solo una riga con 1 espressione? e niente librerie fantasiose? e non andrà in crash su un input 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('-')));

provalo nel parco giochi ruggine



0

Codice assembly x86 16/32/64 bit, 28 byte

byte: 83C623FDAC3C2D74FB403C3A7502B0613C677502B03088460173E9C3

codice:

     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

Chiamare con ESI che punta a GUID. Sostituire ESI con SI per 16 bit o RSI per 64 bit (e +2 byte).


0

C (clang) , 62 byte

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

Provalo online!


aspettare. il controllo minuscolo / maiuscolo non costa nulla ???
ASCII il

Voglio dire, può gestire sia minuscole che maiuscole senza costi aggiuntivi ?!
ASCII il

Ah ok .. ch-70% 32? : a '0' ... 64 e 96 sono multipli di 32, quindi 70-6 e 102-6% 32.
AZTECCO

1
in realtà non devi gestirli entrambi, quindi 64
ASCII, solo il

0

Lisp comune, 166 byte

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

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.