Zwiększ identyfikator GUID

30

Inspirowany najnowszym artykułem Daily WTF ...

Napisz program lub funkcję, która pobiera GUID (ciąg znaków w formacie XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, w którym każdy X reprezentuje cyfrę szesnastkową), i wyświetla GUID z przyrostem o jeden.

Przykłady

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

Uwagi

  • W przeciwieństwie do artykułu z linkiem, zwiększenie identyfikatora GUID kończącego się na F musi „przenosić” do poprzedniej cyfry szesnastkowej. Zobacz przykłady powyżej.
  • Możesz założyć, że dane wejściowe nie będą ffffffff-ffff-ffff-ffff-ffffffffffff.
  • W przypadku cyfr szesnastkowych powyżej 9 możesz użyć dużej (AF) lub małej (af) wielkości liter.
  • Tak, identyfikatory GUID mogą zaczynać się od 0.
  • Dane wyjściowe muszą składać się z dokładnie 32 cyfr szesnastkowych i 4 łączników w oczekiwanym formacie, w tym wszelkich niezbędnych początkowych znaków 0.
  • Nie musisz zachowywać numeru wersji ani innych ustalonych bitów identyfikatora GUID. Załóżmy, że jest to tylko 128-bitowa liczba całkowita, w której żaden z bitów nie ma żadnego specjalnego znaczenia. Podobnie zakłada się, że identyfikatory GUID są sortowane w prostej kolejności leksykograficznej, a nie w kolejności binarnej GUIDstruktury systemu Windows .
  • Jeśli pisanie funkcji, wejście może być dowolnej sekwencji z eksploatacji chartypu danych: string, char[], List<char>, itd.
dan04
źródło
1
Czy mamy pozostawić 6 ustalonych bitów w UUIDv4 nienaruszonych?
Filip Haglund
2
@FilipHaglund: Nie, po prostu traktuj GUID jako liczbę 128-bitową, gdzie żaden z bitów nie ma żadnego specjalnego znaczenia. Podobnie zakłada się, że identyfikatory GUID są sortowane w prostej kolejności leksykograficznej, a nie w kolejności binarnej GUIDstruktury systemu Windows .
dan04
3
Sugerowany przypadek testowy: 89f25f2f-2f7b-4aa6-b9d7-46a98e3cb29faby upewnić się, że odpowiedzi mogą dokonać przejścia 9 -> a.
Kamil Drakari
1
@dana: Możesz użyć dowolnego typu danych, dla którego twój język odpowiada C # foreach (char ch in theInput).
dan04

Odpowiedzi:

7

05AB1E , 17 15 18 bajtów

Zaoszczędzono 2 bajty dzięki Kevinowi Cruijssenowi

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

Wypróbuj online! lub jako pakiet testowy

Wyjaśnienie

'-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
źródło
Dang, pobiłeś mnie do tego .. Miałem coś bardzo podobnego, ale z žKÃzamiast '-K. Przy okazji możesz zapisać 2 bajty, zmieniając •É]•S3+na Ž¦˜S·.
Kevin Cruijssen
@KevinCruijssen: Dzięki! Nie wiem, ile razy zapominałem, że Žto już coś takiego ...
Emigna
Nie zaakceptowałem tej odpowiedzi, ponieważ ktoś zauważył, że spadnie ona do wiodących zer. Proszę napraw.
dan04
@ dan04: Dobra rozmowa! Nie myślałem o tym. Należy naprawić teraz :)
Emigna,
20

Python 2 , 50

  • 3 bajty zapisane dzięki @Dennis.
lambda s:UUID(int=UUID(s).int+1)
from uuid import*

Wypróbuj online!

Cyfrowa trauma
źródło
11

JavaScript (ES6), 85 bajtów

Łańcuch wyjściowy jest pisany małymi literami.

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

Wypróbuj online!

Skomentował

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
źródło
5

Python 2 , 82 bajty

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

Wypróbuj online!

Brak importu lub konwersji heksadecymalnej.

To skanuje od tyłu sznurka, przesuwając każdą postać w całym cyklu 0123456789abcdef, -do samego siebie. Po trafieniu w symbol inny niż flub -przestaje skanować w lewo i po prostu zwraca pozostałą część bez zmian. To rozwiązanie nie jest specyficzne dla formatu UUID - działałaby dowolna liczba bloków o dowolnej liczbie liter szesnastkowych.

Podstawowy przypadek [str,f][s[-1]in'f-'](s[:-1])to sztuczka, której wcześniej nie widziałem w golfie. To kończy rekurencję bez if, and, orlub innego jednoznacznego przepływu sterowania.

W zależności [s[-1]in'f-']od stanu ostatniego znaku kod albo zwraca, f(s[:-1])albo po prostu s[:-1]pozostaje niezmieniony. Ponieważ strjest to tożsamość na ciągach, możemy wybrać jedną z funkcji [str,f]i zastosować ją s[:-1]. Zauważ, że wywołanie rekurencyjne fnie jest wykonywane, jeśli nie zostanie wybrane, omijając typowy problem, który Python chętnie ocenia nieużywane opcje, co prowadzi do nieskończonego regresji w rekurencjach.

xnor
źródło
Cóż, rano idzie mi mózg.
don bright
3

APL (Dyalog Unicode) , 46 bajtów SBCS

Anonimowa ukryta funkcja prefiksu.

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

Wypróbuj online!

⎕CY'dfns'c op y bibliotekę „dfns” (aby uzyskać hexidec )

()
 Argument
 różni się od
'-' myślnika
()@ w podzbiorze składającym się z miejsc, w których spełnione jest powyższe kryterium, zastosuj:
dec¨ przekonwertuj każdy znak szesnastkowy na liczbę dziesiętną
 … @32w pozycji 32 (ostatnia cyfra), zastosuj:
  1+ przyrost
16()⍣≡ stosuj wielokrotnie lewy argument 16 do stabilnego:
  = porównaj (daje maskę, gdzie cyfry szesnastkowe wynoszą 16)
  1⌽ cyklicznie obracaj jeden krok w lewo (jest to bit przenoszący)
  |+ do tego, dodaj resztę podziału po podzieleniu (przez szesnaście, dzięki czemu wszystkie 16 na 0)  obróć cyfry w reprezentacji znaków szesnastkowych o długości jeden ϵ nlist (spłaszczony)
1hex

Adám
źródło
3

Java 11, 152 149 111 108 bajtów

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

-38 bajtów dzięki @ OlivierGrégoire .
-3 bajty dzięki tylko @ ASCII .

Wypróbuj online.

Wyjaśnienie:

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

Stara 149 bajtów odpowiedź:

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

Wypróbuj online.

Wyjaśnienie:

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
źródło
1
111 bajtów
Olivier Grégoire
@ OlivierGrégoire Nie myślałem o użyciu rzeczywistego UUID! Ładna i krótsza alternatywa. : D
Kevin Cruijssen
1
109
Tylko ASCII,
-1 więcej z var zamiast długiego
tylko ASCII
2

Python 2 , 113 112 bajtów

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

Wypróbuj online!

Bez importu

TFeld
źródło
2

Retina 0.8.2 , 21 bajtów

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

Wypróbuj online! Link zawiera przypadki testowe. 9staje się a. Objaśnienie: Wyrażenie regularne dopasowuje wszystkie końcowe fs oraz -s plus jeden poprzedni znak. Transliteracja następnie cyklicznie zwiększa te znaki, jakby były cyframi szesnastkowymi. Alternatywne podejście, również 21 bajtów:

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

Wypróbuj online! Link zawiera przypadki testowe. Działa poprzez obniżenie wejścia dla uproszczenia transliteracji. Byłby zatem 15 bajtów, gdyby miał obsługiwać tylko małe litery. Wypróbuj online! Link zawiera przypadki testowe.

Neil
źródło
2

MATLAB, 138 bajtów

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

Naprawiono błąd w przypadku, gdy fragment zawiera wszystkie zera. Grał też w golfa, nadużywając try / catch. Wynik netto: zapisano 0 bajtów.

Próba „oszukiwania” przy użyciu java.util.UUIDnie powiodła się, ponieważ longwartość zwrócona z java.util.UUID.get[Most/Least]SignificantBitsjest konwertowana na wartość, doublektóra powoduje utratę precyzji. Zapraszam do obejrzenia tego stołu i bezgłośnego powiedzenia „... ale dlaczego?

Wyjaśnienie

Do hex2decfunkcji wypluwa double, a więc nie może przetwarzać cały GUID jednocześnie w celu uniknięcia przekroczenia flintmax. Zamiast tego musimy przetworzyć fragment GUID metodą chunck, używając split. Zmienna asprawdza, czy musimy ją mieć, i oszukańczo jest to również początkowy przyrost, który dodajemy. Warunkiem przeniesienia jest to, czy długości oryginalnych i przyrostowych łańcuchów nie są już równe.

Oryginalna wersja miała niecałe 160 bajtów, więc chciałbym pomyśleć, że nie powinno to być łatwe do outgolfa.

Sanchises
źródło
2

Python 2 , 99 bajtów

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

Wypróbuj online!

Bez uuid.UUIDużycia.

Erik the Outgolfer
źródło
2

C # (interaktywny kompilator Visual C #) , 77 bajtów

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

Wypróbuj online!

-1 bajt dzięki @ASCIIOnly!

Anonimowa funkcja, która przyjmuje char[]dane wejściowe i wyjściowe poprzez modyfikację argumentu .

Dane wejściowe są skanowane od prawej do lewej i zastępowane przy użyciu następujących reguł.

  • The -Znak jest ignorowany, a proces jest kontynuowany
  • The FZnak jest przekształcany 0i przetwarzanie jest kontynuowane
  • The 9Postaci przekształca się Ai przetwarzanie zatrzymuje
  • Znaki A-Ei 0-8są zwiększane o 1, a przetwarzanie zostaje zatrzymane
dana
źródło
2
==70->>69
Tylko ASCII,
Doskonałe - Dzięki :)
dana
2

PowerShell, 101 bajtów

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

Wypróbuj online!

Brak zewnętrznej biblioteki lub konwersji szesnastkowej. Dowolna długość łańcucha. Małe i duże litery są dozwolone. Wpisz ciąg pasujący do^[f-]*$Dopuszczalny jest również .

Ten skrypt skanuje od tyłu łańcucha i inrementuje każdy znak o wartość z hashtable:

  • -: przyrost = 1-1
  • 9: przyrost = 1 + 7, wynik =A
  • F: przyrost = 1-23, wynik =0
  • f: przyrost = 1-55, wynik =0
  • przyrost = 1 dla innych znaków

Następnie skrypt używa $p do ustalenia, czy należy zwiększyć bieżący znak.

Skrypt testowy:

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

Wydajność:

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
źródło
1

Perl 6 , 65 bajtów

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

Sprawdź to

Brad Gilbert b2gills
źródło
1
OP wyjaśnił, że zera wiodące muszą zostać zachowane.
Dennis
56 bajtów z wiodącymi zerami
Jo King
1
Lub 53 bajty przez bardziej ręczne zarządzanie materiałami
Jo King
1

PowerShell , 126 bajtów

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

Wypróbuj online!

Dość trywialna odpowiedź. Pomyślałem, że dodam do listy ukochanego PowerShella :)

KGlasier
źródło
0

Perl 5, 64 bajtów

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

Niezbędna liczba nawiasów powoduje, że jestem smutny, ale ->wiąże się bardzo mocno, jak->as_hex najszybszy sposób na uzyskanie danych wyjściowych w formacie szesnastkowym.

Uruchom z perl -Mbigint -p. Zasadniczo po prostu konwertuje liczbę na duży szesnastkowy, dodaje jeden, a następnie podtytula cyfry wyniku z powrotem do pierwotnej wartości, nie zmieniając myślników.

Silvio Mayolo
źródło
0

Rdza, 258 bajtów

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

tak, jest długi .. ale technicznie jest to jedyna linia z 1 wyrażeniem? i żadnych fantazyjnych bibliotek? i nie zawiesi się na wejściu 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('-')));

spróbuj na rdzawym placu zabaw

Don Bright
źródło
0

16/32/64-bitowy kod zestawu x86, 28 bajtów

bajty: 83C623FDAC3C2D74FB403C3A7502B0613C677502B03088460173E9C3

kod:

     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

Zadzwoń z ESI wskazującym GUID. Zamień ESI na SI dla 16-bitów lub RSI dla 64-bitów (i +2 bajty).

Peter Ferrie
źródło
0

C (brzęk) , 62 bajty

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

Wypróbuj online!

AZTECCO
źródło
czekać. czy sprawdzanie małych / wielkich liter nic nie kosztuje ???
Tylko ASCII,
mam na myśli, że może obsługiwać zarówno małe, jak i wielkie litery bez żadnych kosztów bytount ?!
Tylko ASCII,
Ach ok .. ch-70% 32? : na „0” ... 64 i 96 są wielokrotnością 32, więc 70-6 i 102-6% 32.
AZTECCO
1
tak naprawdę nie musisz obsługiwać obu, więc 64
tylko ASCII
0

Common Lisp, 166 bajtów

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

Wypróbuj online!

Renzo
źródło