Incrémenter un GUID

30

Inspiré d' un récent article du Daily WTF ...

Écrivez un programme ou une fonction qui prend un GUID (chaîne au format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, où chaque X représente un chiffre hexadécimal) et génère le GUID incrémenté de un.

Exemples

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

Remarques

  • Contrairement à l'article lié, l'incrémentation d'un GUID qui se termine par F doit «porter» au chiffre hexadécimal précédent. Voir les exemples ci-dessus.
  • Vous pouvez supposer que l'entrée ne le sera pas ffffffff-ffff-ffff-ffff-ffffffffffff.
  • Pour les chiffres hexadécimaux supérieurs à 9, vous pouvez utiliser des majuscules (AF) ou des minuscules (af).
  • Oui, les GUID peuvent commencer par a 0.
  • Votre sortie doit être composée exactement de 32 chiffres hexadécimaux et de 4 traits d'union dans le format attendu, y compris les éventuels interlignes 0.
  • Vous n'avez pas à conserver le numéro de version ou d'autres bits fixes du GUID. Supposons que ce soit juste un entier de 128 bits où aucun des bits n'a de signification particulière. De même, les GUID sont supposés trier dans un ordre lexicographique simple plutôt que dans l'ordre binaire d'une GUIDstructure Windows .
  • Si vous écrivez une fonction, l'entrée peut être d'une séquence-of- chartype de données: string, char[], List<char>, etc.
dan04
la source
1
Sommes-nous censés laisser intacts les 6 bits fixes de l'UUIDv4?
Filip Haglund
2
@FilipHaglund: Non, il suffit de traiter le GUID comme un nombre de 128 bits, où aucun des bits n'a de signification particulière. De même, les GUID sont supposés trier dans un ordre lexicographique simple plutôt que dans l'ordre binaire d'une GUIDstructure Windows .
dan04
3
Cas de test suggéré: 89f25f2f-2f7b-4aa6-b9d7-46a98e3cb29fpour s'assurer que les réponses peuvent faire la transition 9 -> a.
Kamil Drakari
1
@dana: Vous pouvez utiliser n'importe quel type de données pour lequel l'équivalent de C # de votre langue foreach (char ch in theInput)est valide.
dan04

Réponses:

7

05AB1E , 17 15 18 octets

Enregistré 2 octets grâce à Kevin Cruijssen

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

Essayez-le en ligne! ou comme suite de tests

Explication

'-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
la source
Dang, tu m'as battu. Il y avait quelque chose de très similaire, mais avec žKÃau lieu de '-K. Btw, vous pouvez économiser 2 octets en passant •É]•S3+à Ž¦˜S·.
Kevin Cruijssen
@KevinCruijssen: Merci! Je ne sais pas combien de fois j'ai continué à oublier que Žc'est une chose maintenant ...
Emigna
J'ai refusé cette réponse parce que quelqu'un a souligné qu'elle chuterait en commençant par des 0. S'il-vous-plaît, réparez.
dan04
@ dan04: Bon appel! Je n'y avais pas pensé. Devrait être corrigé maintenant :)
Emigna
20

Python 2 , 50

  • 3 octets enregistrés grâce à @Dennis.
lambda s:UUID(int=UUID(s).int+1)
from uuid import*

Essayez-le en ligne!

Traumatisme numérique
la source
11

JavaScript (ES6), 85 octets

La chaîne de sortie est en minuscules.

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

Essayez-le en ligne!

Commenté

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
la source
5

Python 2 , 82 octets

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

Essayez-le en ligne!

Aucune importation ou conversion hexadécimale.

Cela balaye de l'arrière de la chaîne, en déplaçant chaque caractère le long du cycle 0123456789abcdef, avec -aller à lui-même. Après avoir touché un symbole autre que fou -, il arrête de balayer vers la gauche et renvoie simplement le reste inchangé. Cette solution n'est pas spécifique au format UUID - n'importe quel nombre de blocs de n'importe quel nombre de lettres hexadécimales fonctionnerait.

Le cas de base [str,f][s[-1]in'f-'](s[:-1])est un truc que je n'avais jamais vu utilisé dans un golf auparavant. Il met fin à la récursivité sans if, and,or ou un autre flux de contrôle explicite.

En fonction de la condition [s[-1]in'f-']du dernier caractère, le code retourne f(s[:-1])ou s[:-1]reste inchangé. Étant donné que strl'identité est sur les chaînes, nous pouvons sélectionner l'une des fonctions [str,f]et l'appliquer s[:-1]. Notez que l'appel récursif fn'est pas effectué s'il n'est pas choisi, contournant le problème courant que Python évalue avec impatience les options inutilisées, conduisant à une régression infinie dans les récursions.

xnor
la source
eh bien, voilà mon cerveau pour le matin.
Don Bright le
3

APL (Dyalog Unicode) , 46 octets SBCS

Fonction de préfixe tacite anonyme.

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

Essayez-le en ligne!

⎕CY'dfns'c op y la bibliothèque "dfns" (pour obtenir hexetdec )

(... )
 les arguments
 diffère de
'-' la planche de bord
(... )@ sur le sous - ensemble constitué par les emplacements à laquelle le critère ci - dessus est vrai, sont applicables:
dec¨ convertir chaque caractère hexadécimal à un nombre décimal
 ... @32à la position 32 (le dernier chiffre), sont applicables:
  1+ incrément
16(... )⍣≡ appliquer de façon répétée avec argument de gauche 16 jusqu'à ce qu'il soit stable:
  = comparer (donne un masque où les chiffres hexadécimaux sont 16)
  1⌽ faire pivoter cycliquement d'un pas vers la gauche (c'est le bit de retenue)
  |+ à cela, ajouter le reste de la division lorsqu'il est divisé (par seize, faisant ainsi tous les 16 en 0)  tourner chiffres en représentations de caractères hexadécimaux de longueur un ϵ nlist (aplatir)
1hex

Adam
la source
3

Java 11, 152 149 111 111 108 octets

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

-38 octets merci à @ OlivierGrégoire .
-3 octets grâce à @ ASCII uniquement .

Essayez-le en ligne.

Explication:

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

Ancienne réponse de 149 octets:

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

Essayez-le en ligne.

Explication:

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
la source
1
111 octets
Olivier Grégoire
@ OlivierGrégoire N'avait pas pensé à utiliser un véritable UUID! Alternative sympa et plus courte. : D
Kevin Cruijssen
1
109
ASCII uniquement le
-1 de plus avec var au lieu de long
ASCII uniquement le
2

Python 2 , 113 112 octets

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

Essayez-le en ligne!

Sans importations

TFeld
la source
2

Retina 0.8.2 , 21 octets

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

Essayez-le en ligne! Le lien inclut des cas de test. 9devient a. Explication: l'expression régulière correspond à tous les fs et -s de fin plus un caractère précédent. La translittération incrémente ensuite cycliquement ces caractères comme s'il s'agissait de chiffres hexadécimaux. Approche alternative, également 21 octets:

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

Essayez-le en ligne! Le lien inclut des cas de test. Fonctionne en minuscule l'entrée pour simplifier la translittération. Serait donc de 15 octets s'il ne devait prendre en charge que les minuscules. Essayez-le en ligne! Le lien inclut des cas de test.

Neil
la source
2

MATLAB, 138 octets

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

Correction d'un bug au cas où un morceau serait entièrement composé de zéros. Golfé aussi beaucoup en abusant de try / catch. Résultat net: 0 octet enregistré.

Une tentative de «triche» en utilisant a java.util.UUIDéchoué car la longvaleur renvoyée par java.util.UUID.get[Most/Least]SignificantBitsest convertie en un doublequi entraîne une perte de précision. Je vous invite à jeter un œil à ce tableau et à prononcer silencieusement "... mais pourquoi? "

Explication

La hex2decfonction crache un double, donc elle ne peut pas traiter tout le GUID à la fois pour éviter de dépasser flintmax. Au lieu de cela, nous devons traiter le bloc GUID par chunck, en utilisant split. La variablea vérifie si nous devons en porter un, et triche également est l'incrément initial que nous ajoutons. La condition de report est de savoir si les longueurs des chaînes originales et incrémentées ne sont plus égales.

La version originale était un peu moins de 160 octets, donc j'aimerais penser que cela ne devrait pas être facile à surpasser.

Sanchises
la source
2

Python 2 , 99 octets

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

Essayez-le en ligne!

Pas d' uuid.UUIDutilisation.

Erik le Outgolfer
la source
2

C # (Visual C # Interactive Compiler) , 77 octets

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

Essayez-le en ligne!

-1 octet grâce à @ASCIIOnly!

Fonction anonyme qui prend une char[]entrée et une sortie en modifiant un argument .

L'entrée est analysée de droite à gauche et remplacée à l'aide des règles suivantes.

  • le - caractère est ignoré et le traitement continue
  • Le Fpersonnage est converti en0 et le traitement se poursuit
  • Le 9personnage est converti enA et le traitement s'arrête
  • Les caractères A-Eet 0-8sont incrémentés de 1 et le traitement s'arrête
dana
la source
2
==70->>69
ASCII uniquement le
Excellent - Merci :)
dana
2

Powershell, 101 octets

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

Essayez-le en ligne!

Aucune bibliothèque externe ou conversion hexadécimale. N'importe quelle longueur de chaîne. Les minuscules et les majuscules sont autorisées. La chaîne d'entrée correspondant à ^[f-]*$est également autorisée.

Ce script analyse à l'arrière de la chaîne et incrémente chaque caractère par la valeur de la table de hachage:

  • -: incrément = 1-1
  • 9: incrément = 1 + 7, résultat =A
  • F: incrément = 1-23, résultat =0
  • f: incrément = 1-55, résultat =0
  • incrément = 1 pour les autres caractères

Ensuite, le script utilise $p pour déterminer s'il faut incrémenter le caractère actuel.

Script de test:

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

Sortie:

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
la source
1

Perl 6 , 65 octets

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

Essaye-le

Brad Gilbert b2gills
la source
1
Le PO a précisé que les zéros de tête doivent être préservés.
Dennis
56 octets avec des zéros non significatifs
Jo King
1
Ou 53 octets en traitant les choses plus manuellement
Jo King
1

Gelée , 20 octets

-2 (et correction d'un bug) grâce à Dennis!

ØhiⱮṣ0µẎḅ⁴‘ḃ⁴ịØhṁj”-

Essayez-le en ligne!

Jonathan Allan
la source
1

PowerShell , 126 octets

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

Essayez-le en ligne!

Réponse assez banale. Je pensais juste que le bien-aimé PowerShell serait ajouté à la liste :)

KGlasier
la source
0

Perl 5, 64 octets

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

Le nombre de parenthèses nécessaires ici me rend triste, mais -> se lie très étroitement, comme->as_hex c'est le moyen le plus rapide que je puisse trouver pour obtenir une sortie au format hexadécimal.

Courez avec perl -Mbigint -p. Fondamentalement, il convertit simplement le nombre en hexadécimal bigint, en ajoute un, puis sous-titre les chiffres du résultat dans la valeur d'origine, en laissant les tirets intacts.

Silvio Mayolo
la source
0

Rouille, 258 octets

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

oui c'est long .. mais techniquement c'est une seule ligne avec 1 expression? et pas de bibliothèques fantaisies? et il ne plantera pas sur une entrée 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('-')));

essayez-le sur le terrain de jeu de la rouille

Don Bright
la source
0

Code d'assemblage x86 16/32/64 bits, 28 octets

octets: 83C623FDAC3C2D74FB403C3A7502B0613C677502B03088460173E9C3

code:

     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

Appelez avec ESI pointant vers GUID. Remplacez ESI par SI pour 16 bits ou RSI pour 64 bits (et +2 octets).

peter ferrie
la source
0

C (clang) , 62 octets

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

Essayez-le en ligne!

AZTECCO
la source
attendez. le chèque minuscule / majuscule ne coûte rien ???
uniquement en ASCII
je veux dire, il peut gérer à la fois les minuscules et les majuscules sans frais pour bytecount?!
uniquement à ASCII
Ah ok .. ch-70% 32? : à '0' ... 64 et 96 sont multiples de 32 donc 70-6 et 102-6% 32.
AZTECCO
1
vous n'avez pas réellement à gérer les deux, donc 64
ASCII uniquement
0

Lisp commun, 166 octets

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

Essayez-le en ligne!

Renzo
la source