GUIDを増やす


30

最近のDaily WTFの記事に触発され ...

GUID(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX各Xが16進数を表すformatの文字列)を受け取り、1ずつ増加した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'

ノート

  • リンクされた記事とは異なり、Fで終わるGUIDをインクリメントすると、前の16進数に「移動」する必要があります。上記の例を参照してください。
  • 入力がにならないことを前提とするかもしれませんffffffff-ffff-ffff-ffff-ffffffffffff
  • 9を超える16進数の場合、大文字(AF)または小文字(af)を使用できます。
  • はい、GUIDはで始まる場合があり0ます。
  • 出力は、必要な先行s を含めて、正確に 32桁の16進数と期待される形式の4つのハイフンで構成する必要があります0
  • GUIDのバージョン番号またはその他の固定ビットを保持する必要はありません。ビットが特別な意味を持たない単なる128ビット整数であると仮定します。同様に、GUIDは、Windows GUID構造体のバイナリ順ではなく、簡単な辞書順でソートされると想定されます。
  • 関数を書く場合、入力は、任意の配列オブのものとすることができるcharデータの種類:stringchar[]List<char>、等

1
UUIDv4の6つの固定ビットはそのままにしておくことになっていますか?
フィリップハグランド

2
@FilipHaglund:いいえ、GUIDを128ビットの数値として扱います。どのビットにも特別な意味はありません。同様に、GUIDは、Windows GUID構造体のバイナリ順ではなく、簡単な辞書順でソートされると想定されます。
dan04

3
推奨テストケース:89f25f2f-2f7b-4aa6-b9d7-46a98e3cb29f回答が移行できることを確認します9 -> a
カミルドラカリ

1
@dana:C#と同等の言語foreach (char ch in theInput)が有効な任意のデータ型を使用できます。
dan04

回答:


7

05AB1E17 15 18バイト

Kevin Cruijssenのおかげで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 "-"

ダンは、あなたがたが..それに非常に類似した持っていたものを私を打つžKÃ代わりに'-K。ところで、に変更•É]•S3+することで2バイト節約できますŽ¦˜S·
ケビンクルーイッセン

@KevinCruijssen:ありがとう!私は忘却守ってきた何回か分からないŽ事が...今ある
Emigna

誰かが先行する0を落とすと指摘したので、私はこの答えを受け入れませんでした。修正してください。
dan04

@ 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

5

Python 2、82バイト

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

オンラインでお試しください!

インポートまたは16進変換はありません。

これは、文字列の後ろからスキャンし、サイクル0123456789abcdefに沿って各文字を移動-します。fまたは以外のシンボルにヒットすると、-左方向へのスキャンを停止し、残りを変更せずに返します。このソリューションは、UUID形式に固有のものではありません。任意の数の16進文字の任意の数のブロックが機能します。

の基本ケース[str,f][s[-1]in'f-'](s[:-1])は、これまでゴルフで使用したことがないトリックです。それはどんなことなく、再帰を終了しifandor、または他の明示的な制御フロー。

[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進数字が16であるマスクを与える)を
  1⌽ 1ステップ左(これはキャリービット)
  |+ に循環的に回転させ、分割時に除算剰余を加算(16で、すべて16を0にする) ターン長さ1の16進文字表現への数字ϵ 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に感謝します。@ ASCII-onlyの
おかげで-3バイト。

オンラインでお試しください。

説明:

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でlongの代わりに
ASCIIのみ




2

Retina 0.8.2、21バイト

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

オンラインでお試しください!リンクにはテストケースが含まれます。9になりaます。説明:正規表現は、すべての末尾fのsおよび-sに1つの先行文字を一致させます。音訳は、それらの文字を16進数であるかのように循環的に増分します。代替アプローチ、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がに変換され、double精度が失われるためです。この表を見て、静かに「...しかしなぜ?」と発言してください

説明

hex2decこの関数は吐き出しdouble、それは超えないように一度に全体のGUIDを処理することはできませんので、flintmax。代わりに、を使用してchunckでGUIDチャンクを処理する必要がありますsplit。変数aは、1つを保持する必要があるかどうかをチェックし、不正な方法で追加する最初の増分でもあります。持ち越しの条件は、元の文字列とインクリメントされた文字列の長さがもはや等しくないかどうかです。

元のバージョンは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;);}

オンラインでお試しください!

@ASCIIOnlyのおかげで-1バイト!

引数を変更しchar[]てを入力および出力として受け取る匿名関数。

入力は右から左にスキャンされ、次のルールを使用して置き換えられます。

  • -文字は無視され、処理が続行されます
  • F文字がに変換され0、処理が継続します
  • 9文字がに変換されAて処理を停止
  • 文字A-E0-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

オンラインでお試しください!

外部ライブラリまたは16進変換はありません。任意の文字列の長さ。小文字と大文字を使用できます。に一致する入力文字列^[f-]*$も許可されます。

このスクリプトは、文字列の後ろからスキャンし、ハッシュテーブルの値で各文字をインクリメントします。

  • -:インクリメント= 1-1
  • 9:インクリメント= 1 + 7、結果=A
  • F:increment = 1-23、result =0
  • f:増分= 1〜55、結果=0
  • 他の文字に対してincrement = 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

ここで必要な括弧の数は悲しくなりますが、16進形式の出力を取得するための最速の方法であるように->、非常に緊密に結びついてい->as_hexます。

で実行しperl -Mbigint -pます。基本的に、数値をbigint 16進数に変換し、1を加算してから、結果の数字を元の値に置き換え、ダッシュはそのままにします。


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つの式を持つ唯一の行ですか?豪華なライブラリはありませんか?ファズ入力でクラッシュしませんか?ウンゴルフ:

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

GUIDを指すESIで呼び出します。ESIを16ビットの場合はSI、64ビットの場合はRSI(および+2バイト)に置き換えます。


0

C(clang)、62バイト

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

オンラインでお試しください!


待つ。小文字/大文字のチェックに費用はかかりませんか?
ASCIIのみ

つまり、バイトカウントの費用なしで小文字大文字の両方を処理できますか?!
ASCIIのみ

ああ大丈夫.ch-70%32?: '0'に... 64と96は32の倍数なので、70-6と102-6は%32です。
アステカ

1
実際には両方を処理する必要はないので、64
ASCIIのみ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.