Збільшення GUID


30

Натхненний нещодавньою статтею Daily WTF ...

Напишіть програму або функцію, яка приймає GUID (рядок у форматі XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX, де кожен X являє собою шістнадцяткову цифру) та виводить GUID, збільшений на одиницю.

Приклади

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

Примітки

  • На відміну від пов'язаної статті, приріст GUID, який закінчується на F, повинен "переносити" на попередню шістнадцяткову цифру. Дивіться приклади вище.
  • Ви можете припустити, що введення не буде ffffffff-ffff-ffff-ffff-ffffffffffff.
  • Для шістнадцяткових цифр вище 9 ви можете використовувати верхній (AF) або нижній (af) регістр.
  • Так, GUID можуть починатися з 0.
  • Вихід повинен містити рівно 32 шістнадцяткових цифр та 4 дефісів у очікуваному форматі, включаючи будь-які необхідні провідні 0s.
  • Вам не потрібно зберігати номер версії чи інші фіксовані біти GUID. Припустимо, це просто 128-бітове ціле число, де жоден з бітів не має особливого значення. Аналогічно, GUID передбачається сортувати в прямому лексикографічному порядку, а не у бінарному порядку GUIDструктури Windows .
  • Якщо написання функції, вхід може бути будь-якою послідовністю-of charтипу даних: string, char[], List<char>і т.д.

1
Чи слід залишати 6 фіксованих бітів у UUIDv4 недоторканими?
Філіп Хаглунд

2
@FilipHaglund: Ні, просто розглядайте GUID як 128-бітове число, де жоден з бітів не має особливого значення. Аналогічно, GUID передбачається сортувати в прямому лексикографічному порядку, а не у бінарному порядку GUIDструктури Windows .
dan04

3
Пропонований тестовий випадок: 89f25f2f-2f7b-4aa6-b9d7-46a98e3cb29fщоб відповіді могли зробити перехід 9 -> a.
Каміль Дракарі

1
@dana: Ви можете використовувати будь-який тип даних, для якого вашою мовою є еквівалент C # foreach (char ch in theInput).
dan04

Відповіді:


7

05AB1E , 17 15 18 байт

Збережено 2 байти завдяки Kevin Cruijssen

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

Спробуйте в Інтернеті! або як тестовий набір

Пояснення

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

Данг, ти мене до цього побив .. Було щось дуже схоже, але žKÃзамість цього '-K. Btw, ви можете зберегти 2 байти, змінивши •É]•S3+на Ž¦˜S·.
Кевін Круїссен

@KevinCruijssen: Дякую! Я не знаю, скільки разів я забував, що Žце річ зараз ...
Емінья

Я не прийняв цю відповідь, тому що хтось зазначив, що вона знизить позиції 0. Виправте, будь ласка.
dan04

@ dan04: Добрий дзвінок! Я не думав про це. Слід виправити зараз :)
Емінья


11

JavaScript (ES6), 85 байт

Вихідний рядок знаходиться в малому регістрі.

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

Спробуйте в Інтернеті!

Прокоментував

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

Пітон 2 , 82 байти

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

Спробуйте в Інтернеті!

Немає імпорту чи шестинадцяти конверсій

Це сканує з задньої частини рядка, переміщуючи кожен символ по циклу 0123456789abcdef, за допомогою- переходячи до себе. Після потрапляння на символ, відмінний від fабо -, він зупиняє сканування ліворуч і просто повертає залишок незмінним. Це рішення не характерне для формату UUID - будь-яка кількість блоків будь-якої кількості шістнадцяткових літер буде працювати.

Основний випадок [str,f][s[-1]in'f-'](s[:-1])- це трюк, якого я раніше не бачив у гольфі. Він припиняє рекурсію без будь-яких if,and , orабо іншого явного потоку управління.

Виходячи з умови [s[-1]in'f-']останнього символу, код або повертається, f(s[:-1])або просто s[:-1]змінюється. Оскільки strідентичність на рядках, ми можемо вибрати одну з функцій [str,f]і застосувати її s[:-1]. Зауважте, що рекурсивний виклик з fне робиться, якщо його не вибрано, вирішуючи загальну проблему проблеми, що Python охоче оцінює невикористані параметри, що призводить до нескінченного регресу в рекурсіях.


ну, там іде мій мозок на ранок.
нехай яскравий

3

APL (Dyalog Unicode) , 46 байт SBCS

Функція анонімного мовчання.

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

Спробуйте в Інтернеті!

⎕CY'dfns'c op y бібліотека "dfns" (щоб отримати hexтаdec )

()
 Аргумент
 відрізняється від
'-' тире
()@ на підмножині, що складається з місць, у яких вказаний вище критерій є істинним, застосувати:
dec¨ перетворити кожен шістнадцятковий символ у десяткове число
 … @32у позиції 32 (остання цифра), застосувати:
  1+ приріст
16()⍣≡ кілька разів застосувати із лівий аргумент 16 до стабільного:
  = порівняйте (дає маску, де є шістнадцяткові цифри 16)
  1⌽ циклічно поверніть на один крок ліворуч (це біт переносу)
  |+ до цього, додайте залишок ділення при поділі (на шістнадцять, таким чином зробивши всі 16 на 0)  поверніть цифри в довжину-один шістнадцятковий подання символів ϵ nlist (сплющувати)
1hex


3

Java 11, 152 149 111 108 байт

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

-38 байт подякувати @ OlivierGrégoire .
-3 байти завдяки @ ASCII .

Спробуйте в Інтернеті.

Пояснення:

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

Старі 149 байт відповідають:

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

Спробуйте в Інтернеті.

Пояснення:

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 Не думав використовувати фактичний UUID! Приємна і коротша альтернатива. : D
Кевін Круїссен


-1 ще з var замість довгої
лише для ASCII




2

Сітківка 0,8,2 , 21 байт

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

Спробуйте в Інтернеті! Посилання включає тестові випадки. 9стає a. Пояснення: Режекс відповідає всім кінцевим fs і -s плюс одному попередньому символу. Потім транслітерація циклічно збільшує ці символи так, ніби вони були шістнадцятковими цифрами. Альтернативний підхід, також 21 байт:

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

Спробуйте в Інтернеті! Посилання включає тестові випадки. Працює, зменшуючи вхід, щоб спростити транслітерацію. Таким чином, було б 15 байт, якби він мав підтримувати лише малі регістри. Спробуйте в Інтернеті! Посилання включає тестові випадки.


2

MATLAB, 138 байт

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

Виправлена ​​помилка у випадку, якщо шматок - це нулі. Також багато гольфу, зловживаючи спробою / ловом. Чистий результат: 0 байтів збережено.

Спроба «обдурити» за допомогою використання java.util.UUIDне вдалася, оскільки longзначення, повернене з, java.util.UUID.get[Most/Least]SignificantBitsперетворюється на таке, doubleщо несе в собі втрату точності. Запрошую поглянути на цей стіл і мовчки вимовити "... але чому? "

Пояснення

У hex2decфункції випльовує double, тому він не може обробляти весь GUID відразу ж, щоб уникнути перевищення flintmax. Натомість ми маємо обробляти грудочку GUID, використовуючи split. Змінна aперевіряє, чи потрібно нам мати її, а обман також є початковим збільшенням, який ми додаємо. Умовою перенесення є те, чи довжини оригінальних та нарощених струн більше не рівні.

Оригінальна версія становила трохи менше 160 байт, тому я хотів би подумати, що це не повинно легко перемогти.



2

C # (Visual C # Interactive Compiler) , 77 байт

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

Спробуйте в Інтернеті!

-1 байт завдяки @ASCIIOnly!

Анонімна функція, яка приймає char[]як вхід і виводить, змінюючи аргумент .

Введення сканується справа наліво та замінюється за допомогою наступних правил.

  • The -Символ ігнорується , і обробка триває
  • FСимволів перетворюється в 0і обробка триває
  • 9Символів перетворюється в Aі обробка припиняється
  • Символи A-Eі 0-8збільшуються на 1 і обробка припиняється

2
==70->>69
Лише ASCII

Відмінно - Дякую :)
дата

2

Powershell, 101 байт

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-]*$ дозволено .

Цей скрипт сканує з задньої частини рядка та інкременту кожну таблицю за значенням з хештебля:

  • -: приріст = 1-1
  • 9: приріст = 1 + 7, результат =A
  • F: приріст = 1-23, результат =0
  • f: приріст = 1-55, результат =0
  • приріст = 1 для інших знаків

Далі використовується сценарій $p для визначення того, чи потрібно збільшувати поточну таблицю.

Тестовий сценарій:

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

Вихід:

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





0

Perl 5, 64 байти

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

Кількість дужок, необхідних тут, мене сумує, але ->пов'язує дуже щільно, як->as_hex це найшвидший спосіб, коли я можу знайти вихід у шістнадцятковий формат.

Бігайте з perl -Mbigint -p. В основному, він просто перетворює число в шістнадцятковий біг, додає одне, а потім підміняє цифри результату назад у вихідне значення, залишаючи тире не торкаючись.


0

Іржа, 258 байт

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

так, це довго .. але технічно це лише один рядок з 1 виразом? і немає фантазійних бібліотек? і не впаде на нечіткий вхід? 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('-')));

спробуйте на іржі ігровий майданчик



0

16/32/64-бітний x86 код складання, 28 байт

байти: 83C623FDAC3C2D74FB403C3A7502B0613C677502B03088460173E9C3

код:

     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 вказує на GUID. Замініть ESI на SI на 16-бітний або RSI на 64-розрядний (і +2 байти).


0

C (стук) , 62 байти

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

Спробуйте в Інтернеті!


чекати. чи велика / велика перевірка нічого не коштує ???
ASCII

я маю на увазі, він може обробляти як малі, так і великі регістри без будь-яких витрат, щоб не рахуватись ?!
ASCII

Ах добре .. ч-70% 32? : до '0' ... 64 і 96 кратні 32, тому 70-6 і 102-6% 32.
AZTECCO

1
вам насправді не доведеться поводитися з обома, тому 64
лише для ASCII

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.