Salesforceの15文字のIDを18文字に変換します


20

Salesforce CRM、すべてのオブジェクトは、大文字と小文字が区別される15文字の英数字のIDを持っています。好奇心urious盛な人は、実際にはbase-62番号です。ただし、データの移行と統合に使用されるツールは、大文字と小文字の区別をサポートする場合としない場合があります。これを克服するために、IDは大文字と小文字を区別しない18文字の英数字IDに安全に変換できます。そのプロセスでは、3文字の英数字のチェックサムがIDに追加されます。変換アルゴリズムは次のとおりです。

a0RE000000IJmcN
  1. IDを3つの5文字のチャンクに分割します。

    a0RE0  00000  IJmcN
    
  2. 各チャンクを逆にします。

    0ER0a  00000  NcmJI
    
  3. すべてのチャンクの各文字を1大文字の場合、または0そうでない場合は置き換えます。

    01100  00000  10011
    
  4. 5桁の2進数ごとにi、位置の文字を取得しますi、大文字のアルファベットと数字の0〜5(ABCDEFGHIJKLMNOPQRSTUVWXYZ012345)を連結ます。

    00000 -> A,
    00001 -> B,
    00010 -> C, ..., 
    11010 -> Z, 
    11011 -> 0, ...,
    11111 -> 5`
    

    降伏:

    M  A  T
    
  5. これらの文字、チェックサムを元のIDに追加します。

出力

a0RE000000IJmcNMAT

入力として15文字の英数字(ASCII)文字列を取り、18文字のIDを返すプログラムまたは関数を作成します。

入力の検証は、この質問の範囲外です。プログラムは、無効な入力で値を返すかクラッシュする場合があります。

このような式として(この課題些細な作りのSalesforce propretiary言語機能を使用しないでくださいCASESAFEID()変換、IdString APEX&Cで)。

テストケース

a01M00000062mPg    -> a01M00000062mPgIAI
001M000000qfPyS    -> 001M000000qfPySIAU
a0FE000000D6r3F    -> a0FE000000D6r3FMAR
0F9E000000092w2    -> 0F9E000000092w2KAA
aaaaaaaaaaaaaaa    -> aaaaaaaaaaaaaaaAAA
AbCdEfGhIjKlMnO    -> AbCdEfGhIjKlMnOVKV
aBcDEfgHIJKLMNO    -> aBcDEfgHIJKLMNO025

3
悲しいことに、Apexコードで文字列をIDに変換することは、特にコードが自己完結型でなければならない場合、ここで提供される回答のいくつかよりも短くなりません。Apex Codeはゴルフには適していません。
phyrfox

2
元セールスフォース開発者としての@phyrfox アペックスは...あまり適していません
マイク・マクマホン

2
APEX、56バイト:public class X{public X(Id i){System.debug((String)i);}}。ただし、有効なSalesforce IDでのみ機能します。
トランオウル

ゴルフではなく、実際に仕事success.jitterbit.com/display/DOC/…でこれを行うためにここに来ましたが、アルゴリズムの説明に少し混乱しています。手順4で反転してサニタイズされた各チャンクは「2進数」になると言いますが、数字2〜8を0と1に置き換えることはありません。「62mPg」のようなチャンクのステップ1から3が「01026」のような数になった場合、ステップ4で正確に何をするべきですか?
k ..

回答:


6

ルビー、97バイト

->s{s+s.scan(/.{5}/).map{|x|[*?A..?Z,*?0..?5][x.reverse.gsub(/./){|y|y=~/[^A-Z]/||1}.to_i 2]}*''}
->s{               # define an anonymous lambda
s+                 # the original string plus...
s.scan(/.{5}/)     # get every group of 5 chars
.map{|x|           # map over each group of 5 chars...
[*?A..?Z,*?0..?5]  # build the array of A-Z0-5
[                  # index over it with...
x.reverse          # the 5-char group, reversed...
.gsub(/./){|y|     # ... with each character replaced with...
y=~/[^A-Z]/||1     # ... whether it's uppercase (0/1)...
}.to_i 2           # ... converted to binary
]                  # (end index)
}*''               # end map, join into a string
}                  # end lambda

これには本当にすてきなトリックがあります。

文字列を5文字のグループに分割する私の本能はeach_slice次のとおりです。

irb(main):001:0> [*1..20].each_slice(5).to_a
=> [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20]]

単純な正規表現と比較して長すぎる(x.chars.each_slice(5)vs. x.scan(/.{5}/))ことがわかりました。これは後知恵で明白なように思えますが、私はそれについて本当に考えたことはありません...おそらく、ここで私の古いRubyの回答のいくつかを最適化することができます。

ただし、この回答で私が最も誇りに思っているのは、次のコードです。

y=~/[^A-Z]/||1

さて、ここで非ルビイストの背景を紹介します。Rubyはブール値(TrueClassFalseClass)を整数/数字()から完全に分離しますNumeric。つまり、trueから1、falseから0への自動変換は行われません。これはゴルフ中に迷惑です(しかし、良いこと...他のすべての目的のため)。

単一の文字が大文字かどうか(および1または0を返す)をチェックする単純なアプローチは

y.upcase==y?1:0

これをもう少し(正規表現を使用して)取得できます。

y=~/[A-Z]/?1:0

しかし、その後、私は本当に考え始めました。Hmm ... =~は、一致のインデックスを返します(したがって、単一の文字の0場合は常に一致する場合)、または一致nilしなかった場合は偽の値(FalseClassRuby 以外のすべては真実です)を返します。||それはtruthyだし、その第二オペランドそうでない場合は、オペレータは、その最初のオペランドを取ります。したがって、我々はこれを下にゴルフすることができます

y=~/[^A-Z]/||1

さて、ここで何が起こっているのか見てみましょう。yが大文字の場合、一致[^A-Z]に失敗するため、正規表現部分はを返しnilます。nil || 1です1ので、大文字はになり1ます。場合はy何もなく、大文字は、正規表現の部分が返されます0(インデックスの試合がありますので0)、そして以来0truthyがある、0 || 1です0

...そして、このすべてを書き出した後にのみ、これが実際にの長さと同じであることに気付きy=~/[A-Z]/?1:0ます。ハハ、まあ。


6

Pyth、23 22バイト

FryAmTheEggmanによって保存された1バイト。

sm@s+JrG1U6i}RJ_d2c3pz

オンラインでお試しください。 テストスイート。

pゴルフでリント命令を使用したのはこれが初めてかもしれません。

説明

     JrG1                   save uppercase alphabet in J
                     z      input string
                    p       print it without newline
                  c3        split into 3 parts
 m              d           for each part:
               _              reverse
            }R                map characters to being in
              J                 uppercase alphabet (saved in J)
           i     2            parse list of bools as binary
  @                           get correct item of
     J                          uppercase alphabet (saved in J)
   s+    U6                     add nums 0-5 to it
s                           concatenate and print

4

MATL、24バイト

j1Y24Y2hG5IePtk=~!XB1+)h

言語/コンパイラの現在のバージョン(9.1.0)を使用します。

>> matl
 > j1Y24Y2hG5IePtk=~!XB1+)h
 >
> a0RE000000IJmcN
a0RE000000IJmcNMAT

>> matl
 > j1Y24Y2hG5IePtk=~!XB1+)h
 >
> a01M00000062mPg
a01M00000062mPgIAI

説明

j            % input string
1Y2          % predefined literal: 'ABC...Z'
4Y2          % predefined literal; '012...9'
h            % concatenate into string 'ABC...Z012...9'
G            % push input string
5Ie          % reshape into 5x3 matrix, column-major order
P            % flip vertically
tk=~         % 1 if uppercase, 0 if lowercase
!XB1+        % convert each column to binary number and add 1
)            % index 'ABC...Z012...9' with resulting numbers
h            % concatenate result with original string

3

JavaScript(ES6)、108

x=>x.replace(/[A-Z]/g,(x,i)=>t|=1<<i,t=0)+[0,5,10].map(n=>x+='ABCDEFGHIJKLMNOPQRSTUVWXYZ012345'[t>>n&31])&&x

テスト

f=x=>x.replace(/[A-Z]/g,(x,i)=>t|=1<<i,t=0)+[0,5,10].map(n=>x+='ABCDEFGHIJKLMNOPQRSTUVWXYZ012345'[t>>n&31])&&x

// Less golfed

U=x=>{
  x.replace(/[A-Z]/g,(x,i)=>t|=1<<i,t=0); // build a 15 bit number (no need to explicit reverse)
  // convert 't' to 3 number of 5 bits each, then to the right char A..Z 0..5
  [0,5,10].forEach(n=> // 3 value for shifting
    x += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ012345' // to convert value to char
     [ t>>n&31 ] // shift and mask
  );
  return x
}

console.log=x=>O.innerHTML+=x+'\n';

;[
  ['a01M00000062mPg','a01M00000062mPgIAI']
, ['001M000000qfPyS','001M000000qfPySIAU']
, ['a0FE000000D6r3F','a0FE000000D6r3FMAR']
, ['0F9E000000092w2','0F9E000000092w2KAA']
, ['aaaaaaaaaaaaaaa','aaaaaaaaaaaaaaaAAA']
, ['AbCdEfGhIjKlMnO','AbCdEfGhIjKlMnOVKV']
, ['aBcDEfgHIJKLMNO','aBcDEfgHIJKLMNO025']
].forEach(t=>{
  var i=t[0],x=t[1],r=f(i);
  console.log(i+'->'+r+(r==x?' OK':' Fail (expected '+x+')'));
})
<pre id=O></pre>




2

JavaScriptの(ES6)、137の 132バイト

s=>s+s.replace(/./g,c=>c>"9"&c<"a").match(/.{5}/g).map(n=>"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"[0|"0b"+[...n].reverse().join``]).join``

@ՊՓԼՃՐՊՃՈԲՍԼのおかげで4バイト節約!

説明

この課題はJavaScriptにはまったく適していません。文字列を逆にする簡単な方法はありません。数字を文字に変換する最も短い方法は、可能な文字をそれぞれハードコードすることです。

s=>
  s+                                   // prepend the original ID
  s.replace(/./g,c=>c>"9"&c<"a")       // convert each upper-case character to 1
  .match(/.{5}/g).map(n=>              // for each group of 5 digits
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"
    [0|"0b"+                            // convert from binary
      [...n].reverse().join``]          // reverse the string
  ).join``

チェックサムの数字を小文字にすることが許可されている場合、次のように124バイトで実行できます。

s=>s+s.replace(/./g,c=>c>"9"&c<"a").match(/.{5}/g).map(n=>((parseInt([...n].reverse().join``,2)+10)%36).toString(36)).join``

テスト


間違っていなければ、parseInt([...n].reverse().join``,2)に変更できます+`0b${[...n].reverse().join``}`
ママファンロール

@ՊՓԼՃՐՊՃՈԲՍԼそうですね!その上に別のバイトも保存しました、ありがとう。
user81655

を使用して10バイト全体を保存します.replace(/.{5}/g,n=>/*stuff*/)
ニール

2

MATLAB、100 98バイト

s=input('');a=flip(reshape(s,5,3))';e=['A':'Z',48:53];disp([s,e(bin2dec(num2str(a~=lower(a)))+1)])

入力として文字列が要求され、出力が画面に表示されます。

説明

私はおそらくここで最も簡単なアプローチを使用しています:

  • 入力をリクエスト
  • 5(行)x 3(列)に変形します
  • 行の順序を反転する
  • 行列を転置して、バイナリとして読み取られるように準備します
  • ABC ... XYZ012345配列を割り当てる
  • 転置行列の文字インデックスを対応する小文字と比較し、ブール値を文字列に変換します。文字列はバイナリとして読み取られ、10進数に変換されます。
  • これらの10進数(1ずつ増加)を、割り当てられた配列のインデックスとして解釈します。
  • 追加の3文字で入力を表示します

ルイスメンドーのおかげで100バイト以下になりました!


1
少し節約できますe=['A':'Z',48:53]
ルイスメンドー

私のアプローチはあなたのアプローチとほとんど同じです:
ルイスメンドー

2

PHP、186181バイト

<?$z=$argv[1];$x=str_split($z,5);$l="ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";foreach($x as$y){foreach(str_split(strrev($y))as$a=>$w)$y[$a]=ctype_upper($w)?1:0;$z.=$l[bindec($y)];}echo $z;

グロフなし

<?php
$z = $argv[1];
$x = str_split($z,5);
$l = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
foreach($x as $y) {
    foreach( str_split( strrev($y) ) as $a => $w) {
        $y[$a] = ctype_upper($w) ? 1 : 0;
    }
    $z .= $l[bindec($y)];
}
echo $z;

私はこれよりずっと短くできると考え始めましたが、短くするためのアイデアを使い果たしました。


1

Python 2、97バイト

lambda i:i+''.join(chr(48+(17+sum((2**j)*i[x+j].isupper()for j in range(5)))%43)for x in[0,5,10])

1

PowerShell、162バイト

function f{param($f)-join([char[]](65..90)+(0..5))[[convert]::ToInt32(-join($f|%{+($_-cmatch'[A-Z]')}),2)]}
($a=$args[0])+(f $a[4..0])+(f $a[9..5])+(f $a[14..10])

OK、これでたくさんのきちんとしたことが起こっています。2行目から始めます。

入力を文字列として取得し、後で使用できるように$args[0]設定$aします。これはカプセル化され()て実行され、結果が返されます(つまり、$a)、すぐに3つの関数呼び出しの結果と文字列を連結できます(f ...)。各関数呼び出しは、文字配列として逆順のチャンクでインデックス化された入力文字列を引数として渡します。つまり、入力例では、文字列ではなく文字として各エントリ$a[4..0]と等しく@('0','E','R','0','a')なります。

ここで、プログラムの本当の要点である関数について説明します。入力はとして取得します$fが、最後の方にしか使用されないため、最初にそこに焦点を合わせましょう。(以前のインデックス作成のおかげで)char-arrayとして渡されるため、を使用してすぐにループにパイプできます$f|%{...}。ループ内で、各文字を取得し、大文字と小文字を区別する正規表現の一致を実行し-cmatchます。大文字と小文字が区別されない場合、true / falseになります。それをカプセル化された整数としてキャストし+()、1と0の配列が-join文字列を形成するためにedされます。そのその後の.NETの最初のパラメータとして渡され[convert]::ToInt32()、バイナリ(ベースを変更するコール2小数に)。結果の10進数を使用して、文字列にインデックスを付けます(-join(...)[...])。文字列は最初に範囲として定式化されます(つまり、文字列はです)。すべては、文字列から適切な文字を返すことです。(65..90)配列としてキャストされる、次に範囲と連結されます(0..5)"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"


1

Jolf、30バイト

最後に、おそらくまだ使い勝手がいいでしょう!ここで試してみてください!

+i mZci5d.p1CρA_Hpu1"[^1]'0"2
    Zci5                      split input into groups of 5
  _m                          map it
        d                      with this function
               _H              reverse H
              A  pu1            and replace in it all uppercase letters with 1
             ρ      "[^1]'0"    replace all non-ones with zeroes
            C               2   parse as binary integer
         .p1                    get the (^)th member of "A...Z0...9"

1

Python 3、201 174 138バイト

存在する必要がなくなった関数宣言を指摘してくれたTrang Oulに感謝します。そして、Pythonの三項演算子。そして、いくつかの誤った出力。ただ...彼に賛成票を与えてください。

i=input();n='';c=l=15;
while c:c-=1;n+=('0','1')[i[c].isupper()]
while l:v=int(n[l-5:l],2);l-=5;i+=(chr(v+65),str(v-26))[v>25]
print(i)

関数をz()1回使用すると、その呼び出しを置き換えて25バイトを節約できます。また、コードはの[代わりに誤って割り当てます0
トランオウル

まあ、それは私の側の恥ずかしい監視でした。ありがとう。
スティーブエッカート

1
最初if elseこの構造を使用し、2番目の構造を三項演算子に置き換えるとさらに節約できます。
トランオウル


1

C、 120 118バイト

n,j;main(c,v,s)char**v,*s;{for(printf(s=v[1]);*s;s+=5){for(n=0,j=5;j--;)n=n*2+!!isupper(s[j]);putchar(n+65-n/26*17);}}

長さが5の倍数であるすべての入力で機能します:)

非ゴルフ

n,j;

main(c,v,s) char **v, *s;
{
    for(printf(s = v[1]); *s; s+=5)
    {
        for(n=0, j=5; j--;)
            n=n*2+!!isupper(s[j]);

        putchar(n+65-n/26*17);
    }
}

数バイトを節約するには、argcを使用していないため、署名にmain(n、v、s)を使用している場合、グローバル名前空間からnを削除できます。
cleblanc

また、26 * 17を単純な古い442に置き換えて別のバイトを節約します
-cleblanc

さらに編集を加えると、バージョンが110バイトになりました。isupper()がうまく機能しているように思えるのに!! isupprer()があった理由がわかりません。また、forループをリファクタリングして不要なものを削除しました{} j;main(n,v,s)char**v,*s;{for(printf(s=v[1]);*s;s+=5,putchar(n+65-n/442))for(n=0,j=5;j--;n=n*2+isupper(s[j]));}
cleblanc

@cleblancすばらしい提案、ありがとう。n/26*17式では演算の順序が非常に重要であるため、442に置き換えることはオプションではありません。限り!!isupper、その関数はシステム上でtrueの場合1を返さず、256を返します。!!は、何であれ0/1の戻り値に変換する簡単な方法です。YMMV。
コールキャメロン

1

C#、171バイト

私はゴルフC#の練習はあまりしていませんが、ここにショットがあります。

s=>{for(var u=s;u.Length>0;u=u.Substring(5)){int p=0,n=u.Substring(0,5).Select(t=>char.IsUpper(t)?1:0).Sum(i=>(int)(i*Math.Pow(2,p++)));s+=(char)(n+65-n/26*17);}return s;}

提案:char.IsUpper(t)に置き換えることができますt>=65&t<=90&C#のboolは基本的に、&&短絡のないゴルフショートです)。447はより短い26*17。あなたは別にする必要はありませんSelect:あなたは直接に三成分を含めることができますSum。のすべての使用Substringを、Take代わりに基づくループに置き換えることを検討してくださいfor(int i=0;i<3;i++)s.Skip(i*5).Take(5)。将来の参考のために、u!=""より短くなりますu.Length>0(ただし、を使用している場合は不要ですTake)。
ボブ

この式n/26*17はと同等ではありませんn/442が、それ以外は提案のおかげです。述べたように、私はC#でのゴルフの経験があまりないので、これは今後検討するべき素晴らしいものです。
コールキャメロン

ああ、ごめんなさい-私はそれを誤解しています。
ボブ

1

C#334

string g(string c){string[]b=new string[]{c.Substring(0,5),c.Substring(5, 5),c.Substring(10)};string o="",w="";for(int i=0,j=0;i<3;i++){char[]t=b[i].ToCharArray();Array.Reverse(t);b[i]=new string(t);o="";for(j=0;j<5;j++){o+=Char.IsUpper(b[i][j])?1:0;}int R=Convert.ToInt32(o,2);char U=R>26?(char)(R+22):(char)(R+65);w+=U;}return c+w;}

要求があれば、コードを読み取り可能な状態に戻し、投稿します。


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