Salesforce 15 자 ID를 18 자로 변환


20

에서 세일즈 포스 CRM , 모든 객체는 대소 문자를 구분합니다 15 문자 숫자 ID를 가지고 있습니다. 호기심이 많은 사람이라면 실제로는 base-62 number 입니다. 그러나 데이터 마이그레이션 및 통합에 사용되는 도구는 대소 문자 구분을 지원하거나 지원하지 않을 수 있습니다. 이를 극복하기 위해 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 자리 이진수에 대해 대문자 알파벳과 숫자 0-5 ( ) 를 연결 i하여 위치 i에 문자를 가져옵니다 ABCDEFGHIJKLMNOPQRSTUVWXYZ012345.

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

    굽힐 수 있는:

    M  A  T
    
  5. 이러한 문자 (체크섬)를 원래 ID에 추가하십시오.

출력 :

a0RE000000IJmcNMAT

15 자 영숫자 (ASCII) 문자열을 입력으로 사용하고 18 자 ID를 리턴하는 프로그램 또는 함수를 작성하십시오.

입력 유효성 검사는이 질문의 범위를 벗어납니다. 잘못된 입력으로 인해 프로그램이 값을 반환하거나 충돌 할 수 있습니다.

이 문제를 사소하게 만드는 Salesforce 독점 언어 기능 (예 : 수식 CASESAFEID(), APEX & c에서 변환) Id을 사용하지 마십시오 String.

테스트 사례

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

3
안타깝게도 Apex Code에서 문자열을 Id로 변환하는 것은 여전히 ​​코드가 자체 포함되어야하는 경우 여기에 제공된 일부 답변보다 짧지 않습니다. 에이펙스 코드는 골프에 적합하지 않습니다.
phyrfox

2
@phyrfox는 전 salesforce 개발자입니다. 에이펙스는별로 적합하지 않습니다 ...
Mike McMahon

2
APEX, 56 바이트 : public class X{public X(Id i){System.debug((String)i);}}. 그러나 유효한 Salesforce ID에서만 작동합니다.
Trang Oul

나는 실제로 골프가 아닌 작업 ( success.jitterbit.com/display/DOC/… )을 위해이 작업을 수행 하려고 왔지만 알고리즘 설명에 약간 혼란 스럽습니다. 4 단계에서 리버스 앤 소독 된 각 청크는 "이진수"라고 말하지만 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

자, 여기에 비 루비 주의자들을위한 배경이 있습니다. 루비는 부울 ( TrueClass, FalseClass)을 정수 / 숫자 ()에서 완전히 분리합니다. Numeric즉, true에서 1로, false에서 0으로 자동 변환되지 않습니다. 이것은 골프를하는 동안 성가신 일입니다 (그러나 다른 모든 목적을 위해 좋은 것입니다).

단일 문자가 대문자인지 (그리고 1 또는 0을 반환하는지) 확인하는 순진한 접근 방식은

y.upcase==y?1:0

우리는 이것을 조금 더 내려받을 수 있습니다 (정규식으로).

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

그러나 나는 정말로 생각하기 시작했다. Hmm ... =~은 일치하는 색인 ​​(따라서 단일 문자의 경우 항상 0일치하는 경우) 또는 nil일치하지 않는 경우 잘못된 값 ( FalseClass루비에서는 진실이 아닌 다른 값)을 반환합니다 . ||이 truthy이고, 그 두 번째 오퍼랜드 그렇지 않은 경우, 작업자는 먼저 피연산자 걸린다. 따라서 우리는 이것을

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

자, 여기서 무슨 일이 일어나는지 봅시다. y대문자 이면 일치하지 [^A-Z]않으므로 정규식 부분이 반환 nil됩니다. nil || 11대문자가 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골프 에서 rint 명령을 사용한 것은 이번이 처음 일 것 입니다.

설명

     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

자바 스크립트 (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

CJam, 27 바이트

l_5/{W%{_el=!}%2bH+43%'0+}%

모든 테스트 사례를 실행하십시오.

사양을 매우 간단하게 구현합니다. 가장 흥미로운 부분은 체크섬에서 문자로 변환하는 것입니다. 각 청크의 결과에 17을 더합니다. 모듈로 43을 가지고 그 결과를 캐릭터에 추가하십시오 '0.



2

자바 스크립트 (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``}`.
Mama Fun Roll

@ ՊՓԼՃՐՊՃՈԲՍԼ 맞아! 나는 그 위에 또 다른 바이트를 저장했습니다. 감사합니다.
user81655

을 사용하여 10 바이트 전체를 저장하십시오 .replace(/.{5}/g,n=>/*stuff*/).
Neil

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 진수로 변환합니다.
  • 이 소수 (1 씩 증가)를 할당 된 배열의 인덱스로 해석하십시오.
  • 추가 3 자로 입력 표시

Luis Mendo 덕분에 이제 100 바이트 미만입니다!


1
당신은 조금만 절약 할 수 있습니다e=['A':'Z',48:53]
Luis Mendo

내 접근 방식이 당신과 거의 동일
하다는

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

파이썬 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])

자, 이것에서 많은 깔끔한 일들이 일어나고 있습니다. 두 번째 줄부터 시작하겠습니다.

우리는 입력을 문자열로 가져 와서 나중에 사용하도록 $args[0]설정합니다 $a. 이것은 캡슐화되어 ()실행되고 결과가 반환됩니다 (즉, $a) 그래서 우리는 즉시 세 개의 함수 호출의 결과로 문자열을 연결할 수 있습니다 (f ...). 각 함수 호출은 입력 문자열을 역순으로 색인하여 문자 배열로 인수로 전달합니다. 즉, 입력 예를 들어 문자열이 아닌 문자로 각 항목 $a[4..0]과 동일 @('0','E','R','0','a')합니다.

이제 프로그램의 실제 고기가있는 기능으로 이동하십시오. 우리는 입력을로 취하지 $f만 끝을 향한 방식으로 만 사용되므로 먼저 여기에 집중합시다. char-array로 전달되었으므로 (이전 색인 생성 덕분에)로 즉시 루프에 파이프 할 수 있습니다 $f|%{...}. 루프 내에서 각 문자를 가져와 대 / 소문자를 구분하는 정규 표현식 일치를 수행합니다 -cmatch. 대문자 / 그렇지 않으면 true / false가됩니다. 우리는 그것을 캡슐화하는 정수로 캐스팅 +()한 다음 1과 0의 배열을 -join문자열로 만듭니다. 그런 다음 [convert]::ToInt32()이진 (base 2)을 10 진수 로 변경하기 위해 .NET 호출 에서 첫 번째 매개 변수로 전달됩니다 . 결과 10 진수를 사용하여 문자열로 색인합니다 (-join(...)[...]). 문자열은 먼저 (65..90)문자 배열로 캐스트 된 범위로 공식화 된 다음 범위와 연결됩니다 (0..5)(예 : 문자열은 "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"). 이 모든 것은 문자열에서 적절한 문자를 반환하는 것입니다.


1

줄프, 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에게 큰 감사를드립니다. 그리고 파이썬 삼항 연산자. 그리고 일부 잘못된 출력. 그냥 ... 그에게 공감대를 주면됩니다.

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()한 번 사용 하면 해당 호출을 대체하고 25 바이트를 절약 할 수 있습니다. 또한 코드가 [대신에 잘못 할당 되었습니다 0.
Trang Oul

글쎄요, 그것은 저의 당황스러운 감독이었습니다. 감사.
Steve Eckert

1
먼저 대체하여 더욱 절약 할 수 있습니다 if else와 함께 이 건설 삼항 연산자와 두 번째.
Trang Oul


1

기음, 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

또한 평범한 구식 (442)와 26 * 17를 대체 할 다른 바이트 저장
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.
Cole Cameron

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. 예 SubstringTake들어을 대신 하여 루프 의 모든 사용법을 대체하는 것을 고려하십시오 for(int i=0;i<3;i++)s.Skip(i*5).Take(5). 나중에 참조 u!=""할 수있는 것보다 짧을 것입니다 u.Length>0(하지만 더 이상 사용할 필요는 없습니다 Take).
Bob

이 표현 n/26*17n/442에 대한 제안 이 아니라에 해당하는 것이 아니라 그 이외 의 표현 입니다 . 언급 한 바와 같이, C #에서 골프를 치는 경험이 많지 않으므로 앞으로 고려해야 할 사항이 모두 있습니다.
Cole Cameron

아 죄송합니다-잘못 읽었습니다.
Bob

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.