Bir GUID değerini artırmak


30

Son bir Günlük WTF makalesinden esinlenildi ...

Bir GUID alan bir program veya işlev yazın ( XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXher X'in onaltılık bir basamağı temsil ettiği biçimdeki dize ) ve GUID değerini birer birer artırır.

Örnekler

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

notlar

  • Bağlantılı makalenin aksine, F ile biten bir GUID'in arttırılması önceki onaltılık basamağa “taşımak” zorundadır. Yukarıdaki örneklere bakınız.
  • Girişin olmayacağını varsayabilirsiniz ffffffff-ffff-ffff-ffff-ffffffffffff.
  • 9'un üzerindeki altıgen rakamlar için üst (AF) veya küçük (af) harf kullanabilirsiniz.
  • Evet, GUID'ler a ile başlayabilir 0.
  • Çıktınız , gerekli tüm yönlendirmeler de dahil olmak üzere beklenen biçimde tam olarak 32 onaltılık rakam ve 4 tire içermelidir 0.
  • GUID'in sürüm numarasını veya diğer sabit bitlerini saklamanız gerekmez. Bitlerin hiçbirinin özel bir anlamı olmayan, sadece 128 bit bir tam sayı olduğunu varsayalım. Benzer şekilde, GUID'lerin bir Windows GUIDyapısının ikili düzeninden ziyade basit bir sözlükbilimsel düzende sıralandığı varsayılmaktadır .
  • Bir işlevi yazma, giriş, her türlü dizi-of olabilir charveri türü: string, char[], List<char>vs.

1
UUIDv4'teki 6 sabit parçayı bozulmadan mı bırakmalıyız?
Filip Haglund

2
@FilipHaglund: Hayır, sadece GUID'i, bitlerin hiçbirinin özel bir anlamı olmayan 128-bit bir sayı olarak kullanın. Benzer şekilde, GUID'lerin bir Windows GUIDyapısının ikili düzeninden ziyade basit bir sözlükbilimsel düzende sıralandığı varsayılmaktadır .
dan04,

3
Önerilen test durumu: 89f25f2f-2f7b-4aa6-b9d7-46a98e3cb29fcevapların geçişi sağlayabilmesini sağlamak için 9 -> a.
Kamil Drakari

1
@dana: Dilinizin C # 'nın eşdeğeri için geçerli olduğu herhangi bir veri tipini kullanabilirsiniz foreach (char ch in theInput).
dan04,

Yanıtlar:


7

05AB1E , 17 15 18 bayt

Kevin Cruijssen sayesinde 2 bayt kaydedildi

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

Çevrimiçi deneyin! veya Test Paketi olarak

açıklama

'-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, beni yendin .. Çok benzer bir şey vardı ama žKÃbunun yerine '-K. Btw, sen değiştirerek 2 bayt kaydedebilirsiniz •É]•S3+için Ž¦˜S·.
Kevin Cruijssen

@KevinCruijssen: Teşekkürler! Bunu kaç kere unuttuğumu bilmiyorum Ž, şimdi bir şey ...
Emigna

Bu cevabı kabul etmedim, çünkü birisi liderlerden 0 'a düşeceğini belirtti. Lütfen düzelt.
dan04,

@ dan04: İyi arama! Bunu düşünmemiştim. Şimdi düzeltilmeli :)
Emigna


11

JavaScript (ES6), 85 bayt

Çıkış dizesi küçük harflerle yazılmıştır.

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

Çevrimiçi deneyin!

Yorumlananlar

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 bayt

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

Çevrimiçi deneyin!

İthalat veya onaltılık dönüşüm yok.

Bu döngü boyunca her karakteri hareketli, dize arkasından tarar 0123456789abcdefile -kendisi gidiyor. fVeya dışındaki bir sembole -çarptıktan sonra sola doğru taramayı durdurur ve kalanı değiştirmeden döndürür. Bu çözüm UUID biçimine özgü değildir - herhangi bir sayıda altıgen harften herhangi bir sayıdaki blok çalışacaktır.

Asıl mesele, [str,f][s[-1]in'f-'](s[:-1])daha önce golf oynamakta hiç görmediğim bir hiledir. Herhangi olmadan Özyinelemeyi sonlandırır if, and, orya da diğer açık kontrol akışı.

[s[-1]in'f-']Son karakterin durumuna göre, kod ya döner f(s[:-1])ya da sadece s[:-1]değişmez. Yana strdizeleri üzerinde kimlik, biz işlevlerden birini seçebilir [str,f]ve uygulamak s[:-1]. fSeçili olmayan özyinelemeli çağrı yapılmaz, Python'un kullanılmayan seçenekleri hevesle değerlendirir ve özyinelemelerde sonsuz gerilemeye yol açar.


Eh, işte beynim sabah gidiyor.
de aydınlık don

3

APL (Dyalog Unicode) , 46 bayt SBCS

Anonim zımni önek işlevi.

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

Çevrimiçi deneyin!

⎕CY'dfns'c op y "dfns" kütüphane elde etmek için ( hexvedec )

(... )
 argüman
 farklıdır
'-' bir çizgi
(... )@ yerle oluşan alt kümesini de yukarıdaki kriteri doğru olan geçerlidir:
dec¨ bir ondalık sayıya her onaltılık karakter dönüştürmek
 ... @32de 32 pozisyonundaki (son rakam), geçerlidir:
  1+ artışı
16(... )⍣≡ sürekli geçerlidir Kararlı olana kadar sol argüman 16:
  = karşılaştırmak (onaltılık basamakların 16 olduğu maskeyi sağlar)
  1⌽ döngüsel olarak bir adım sola (bu, taşıma bitidir) döndürün
  |+ , bölündüğünde bölünme kalanını ekleyin (on altıya kadar, böylece 16'yı 0'a  çevirerek) uzunluğu bir onaltılık karakter gösterimleri içine rakam ϵ
1hex
nlist (flatten)


3

Java 11, 152 149 111 108 bayt

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

-38 bayt @ OlivierGrégoire'a teşekkür eder . Sadece @ ASCII
sayesinde -3 bayt .

Çevrimiçi deneyin.

Açıklama:

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

Eski 149 baytlık cevap:

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

Çevrimiçi deneyin.

Açıklama:

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 Gerçek bir UUID kullanmayı düşünmemiştim! Güzel ve daha kısa bir alternatif. : D
Kevin Cruijssen


-1 yerine uzun var ile daha fazla
sadece ASCII




2

Retina 0.8.2 , 21 bayt

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

Çevrimiçi deneyin! Link, test durumlarını içerir. 9olur a. Açıklama: Regex tüm takip eden fs ve -s artı bir önceki karakter ile eşleşir . Harf çevirisi, bu karakteristikleri döngüsel olarak onaltılık basamaklar gibi artırır. Alternatif yaklaşım, ayrıca 21 bayt:

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

Çevrimiçi deneyin! Link, test durumlarını içerir. Harf çevirisini basitleştirmek için girişi küçük harflerle çalıştırarak çalışır. Bu nedenle, yalnızca küçük harfleri desteklemek zorunda olsaydı, 15 bayt olurdu. Çevrimiçi deneyin! Link, test durumlarını içerir.


2

MATLAB, 138 bayt

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

Bir öbekün tümünün sıfır olması durumunda bir hata düzeltildi. Ayrıca, dene / yakalamayı suistimal ederek çokça golf oynadı. Net sonuç: 0 bayt kaydedildi.

'Hile' girişimi java.util.UUIDbaşarısız oldu, çünkü longdöndürülen değer bir değere java.util.UUID.get[Most/Least]SignificantBitsdönüştü.double duyarlılık kaybı doğurur ki. Sizi bu tabloya bakmaya ve sessizce mutlak şekilde davet etmeye davet ediyorum "... ama neden? "

açıklama

hex2decBir çıkış fonksiyonu şişler doubleaşılmasını önlemek için tek seferde, bu nedenle tüm GUID işleyemezflintmax . Bunun yerine, GUID öbeğini kullanarak, chunck ile işlemek zorundayız split. Değişkena taşımamız gerekip gerekmediğini kontrol eder ve aldatma da eklediğimiz ilk artıştır. Taşınmanın koşulu, orijinal ve artan tellerin uzunluğunun artık eşit olmamasıdır.

Orijinal sürüm 160 baytın hemen altındaydı, bu yüzden bunun başarılmasının kolay olmadığını düşünmek istiyorum.



2

C # (Visual C # Etkileşimli Derleyici) , 77 bayt

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

Çevrimiçi deneyin!

@ASCIIOnly sayesinde -1 bayt!

Bir argümanı değiştirerekchar[] girdi olarak alan ve çıktısını alan anonim işlev .

Giriş, sağdan sola taranır ve aşağıdaki kurallar kullanılarak değiştirilir.

  • -Karakter yok sayılır ve işleme devam edilir
  • FKarakter dönüştürülür0 ve işleme devam eder
  • 9Karakter dönüştürülür Ave işlem durur
  • Karakterleri A-Eve 0-81 ve işleme durur tarafından artırılır

2
==70->>69
ASCII-sadece

Mükemmel - Teşekkürler :)
dana

2

Powershell, 101 bayt

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

Çevrimiçi deneyin!

Harici kütüphane veya onaltılık dönüşüm yok. Herhangi bir dize uzunluğu. Küçük harf ve büyük harf izin verilir. İle eşleşen giriş dizesi^[f-]*$ de izin verilir.

Bu script dizgenin arkasından tarar ve her bir karakteri hashtable değerine göre arttırır:

  • -: artış = 1-1
  • 9: artış = 1 + 7, sonuç =A
  • F: artış = 1-23, sonuç =0
  • f: artış = 1-55, sonuç =0
  • diğer karakterler için artış = 1

Sonra, komut dosyası kullanır. $p , geçerli karakterin artırılıp artırılmayacağını belirlemek için .

Test komut dosyası:

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

Çıktı:

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 bayt

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

Çevrimiçi deneyin!

Oldukça önemsiz cevap. Sadece sevgili PowerShell'i listeye ekleyeceğimi düşündüm :)



0

Perl 5, 64 bayt

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

Burada gerekli parantez sayısı beni üzüyor ama -> çok sıkı sıkıya bağlı->as_hex onaltılık biçimli çıktı almak için bulabildiğim en hızlı yol olduğu bağlanıyor.

İle koş perl -Mbigint -p. Temel olarak, sayıyı sadece onaltılık bir bigint değerine dönüştürür, bir tane ekler ve ardından sonucun basamaklarını orijinal değerine geri döndürür ve kısa çizgilere dokunulmaz.


0

Pas, 258 bayt

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

evet uzun ... ama teknik olarak 1 ifadeli tek satır? ve fantezi kütüphaneleri yok mu? ve bir fuzz girişinde çökmeyecek? 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('-')));

pas oyun alanında deneyin



0

16/32/64-bit x86 derleme kodu, 28 bayt

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

ESI'yi GUID'e işaret ederek arayın. ESI'yi 16 bitlik SI veya 64 bitlik RSI (ve +2 bayt) ile değiştirin.


0

C (clang) , 62 bayt

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

Çevrimiçi deneyin!


Bekleyin. Küçük harf / büyük harf hiçbir şey mal olmuyor mu ???
ASCII-sadece

ben küçük harf hem işleyebilir, demek ve ByteCount hiçbir ücret ödemeden büyük harf ?!
ASCII-

Ah tamam .. ch-70% 32? : '0' a kadar ... 64 ve 96 32 'nin katlarıdır, yani 70-6 ve 102-6% 32.
AZTECCO

1
aslında her ikisini de halletmek zorunda değilsiniz, yani 64
ASCII-sadece

0

Ortak Lisp, 166 bayt

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

Çevrimiçi deneyin!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.