Увеличить 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>и т.д.
dan04
источник
1
Мы должны оставить 6 фиксированных битов в UUIDv4 нетронутыми?
Филипп Хаглунд
2
@FilipHaglund: Нет, просто обрабатывайте GUID как 128-битное число, где ни один из битов не имеет какого-либо особого значения. Точно так же предполагается, что GUID сортируются в прямом лексикографическом порядке, а не в двоичном порядке GUIDструктуры Windows .
Ден04
3
Предлагаемый контрольный пример: 89f25f2f-2f7b-4aa6-b9d7-46a98e3cb29fчтобы убедиться, что ответы могут сделать переход 9 -> a.
Камил Дракари
1
@dana: Вы можете использовать любой тип данных, для которого foreach (char ch in theInput)допустим эквивалент C # на вашем языке .
Ден04

Ответы:

7

05AB1E , 17 15 18 байт

Сохранено 2 байта благодаря Кевину Круйссену

'-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 "-"
Emigna
источник
Черт, ты побил меня этим ... Было что-то очень похожее, но с žKÃвместо '-K. Кстати, вы можете сохранить 2 байта, изменив •É]•S3+на Ž¦˜S·.
Кевин Круйссен
@KevinCruijssen: Спасибо! Я не знаю, сколько раз я продолжал забывать, что Žэто вещь сейчас ...
Эминья
Я не принял этот ответ, потому что кто-то указал, что он опустит ведущие нули. Пожалуйста исправьте.
Ден04
@ Dan04: хороший звонок! Я не думал об этом. Должно быть исправлено сейчас :)
Emigna
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
Arnauld
источник
5

Python 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]. Обратите внимание, что рекурсивный вызов with fне выполняется, если он не выбран, что позволяет обойти общую проблему, заключающуюся в том, что Python с готовностью оценивает неиспользуемые опции, что приводит к бесконечному регрессу в рекурсиях.

XNOR
источник
что ж, мой мозг уходит на утро.
Дон
3

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

Функция анонимного молчаливого префикса.

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

Попробуйте онлайн!

⎕CY'dfns'с оп у «dfns» библиотека (для получения hexиdec )

()
 Аргумент
 отличается от
'-' тире
()@ в подмножестве, состоящем из мест, в которых приведенный выше критерий верен, применимо:
dec¨ преобразовать каждый шестнадцатеричный символ в десятичное число
 … @32в позиции 32 (последняя цифра), применить:
  1+ приращение
16()⍣≡ повторно применить с левый аргумент 16 до стабильного:
  = сравнить (дает маску , где шестнадцатеричные цифры 16)
  1⌽ циклический повороту на один шаг влево (это бито переноса)
  |+ к этому, добавить остаток деления при делении (на шестнадцать, таким образом , делая все 16 в 0)  поворот цифры в длину-один шестнадцатеричный символ представлений е NLIST (Flatten)
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-only .

Попробуйте онлайн.

Объяснение:

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
Кевин Круйссен
источник
1
111 байт
Оливье Грегуар
@ OlivierGrégoire Не думал об использовании фактического UUID! Хорошая и короткая альтернатива. : D
Кевин Круйссен
1
109
только ASCII
-1 больше с var вместо long
только 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))

Исправлена ​​ошибка, когда в чанке все нули. Также много играл в гольф, злоупотребляя try / catch. Чистый результат: 0 байтов сохранено.

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

объяснение

В hex2decфункции выплевывает double, поэтому он не может обрабатывать весь GUID сразу же, чтобы избежать превышения flintmax. Вместо этого мы должны обработать кусок GUID с помощью chunck, используя split. Переменная aпроверяет, нужно ли нам переносить единицу, и обманным путем также является начальным шагом, который мы добавляем. Условием переноса является то, что длины исходной и увеличенной строк больше не равны.

Оригинальная версия была чуть менее 160 байтов, поэтому я хотел бы думать, что это не должно быть легко переиграть.

Sanchises
источник
2

C # (интерактивный компилятор Visual C #) , 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[]качестве входных и выходных данных путем изменения аргумента .

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

  • -Символ игнорируется , и обработка продолжается
  • FСимволов преобразуется в 0и обработка продолжается
  • 9Символов преобразуется в Aи обработка прекращается
  • Символы A-Eи 0-8увеличиваются на 1 и обработка останавливается
Dana
источник
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
Mazzy
источник
1

Perl 6 , 65 байт

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

Попробуй это

Брэд Гилберт b2gills
источник
1
ОП пояснил, что ведущие нули должны быть сохранены.
Деннис
56 байтов с ведущими нулями
Джо Кинг
1
Или 53 байта , обрабатывая вещи более вручную
Джо Кинг,
1

PowerShell , 126 байт

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

Попробуйте онлайн!

Довольно тривиальный ответ. Просто думал, что я добавлю любимый PowerShell в список :)

KGlasier
источник
0

Perl 5, 64 байта

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

Необходимое здесь количество круглых скобок меня огорчает, но ->связывает очень тесно, так как ->as_hexэто самый быстрый способ найти вывод в шестнадцатеричном формате.

Беги с perl -Mbigint -p. По сути, он просто преобразует число в шестнадцатеричное значение bigint, добавляет его, а затем подставляет цифры результата обратно в исходное значение, оставляя штрихи нетронутыми.

Сильвио Майоло
источник
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 выражением? и никаких модных библиотек? и он не будет падать на вход 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('-')));

попробуйте на ржавчины площадка

не яркий
источник
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;);}

Попробуйте онлайн!

AZTECCO
источник
Подождите. проверка нижнего / верхнего регистра ничего не стоит ???
Только для ASCII
я имею в виду, что он может обрабатывать как строчные, так и прописные буквы бесплатно bytecount ?!
Только для ASCII
Ах, хорошо .. ch-70% 32? : до '0' ... 64 и 96 кратны 32, поэтому 70-6 и 102-6% 32.
AZTECCO
1
на самом деле вы не должны справляться с обоими, так что 64
только для ASCII
0

Common Lisp, 166 байт

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

Попробуйте онлайн!

Renzo
источник