Перетворіть ідентифікатор Salesforce 15 символів у 18 символів


20

У Salesforce CRM кожен об’єкт має 15-символьний буквено-цифровий ідентифікатор, який залежить від регістру. Якщо хтось цікавий, насправді це номер-62 . Однак інструменти, використовувані для міграції та інтеграції даних, можуть або не підтримують чутливість до регістру. Щоб подолати це, ідентифікатори можна безпечно перетворити на 18-символьні буквенечутливі буквено-цифрові ідентифікатори. У цьому процесі 3-символьна буквено-числова контрольна сума додається до ідентифікатора. Алгоритм перетворення:

Приклад :

a0RE000000IJmcN
  1. Розділіть ідентифікатор на три фрагменти з 5 символів.

    a0RE0  00000  IJmcN
    
  2. Переверніть кожен шматок.

    0ER0a  00000  NcmJI
    
  3. Замініть кожного символу в кожному фрагменті на 1великі літери або на 0інше.

    01100  00000  10011
    
  4. Для кожного 5-розрядного двійкового числа iзнайдіть символ у позиції iу поєднанні великого алфавіту та цифр 0-5 ( ABCDEFGHIJKLMNOPQRSTUVWXYZ012345).

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

    Вихід:

    M  A  T
    
  5. Додайте ці символи, контрольну суму, до оригінального ідентифікатора.

Вихід :

a0RE000000IJmcNMAT

Напишіть програму або функцію, яка бере 15-символьну буквено-цифрову (ASCII) рядок як вхід і повертає 18-символьний ідентифікатор.

Перевірка вхідних даних не виходить за рамки цього питання. Програми можуть повернути будь-яке значення або збій при неправильному введенні.

Будь ласка, не використовуйте функцію Salesforce propretiary Мови , які роблять цю задачу тривіальної (наприклад, формули CASESAFEID(), перетворюючи Idдо Stringв APEX & с).

Випробування

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

3
На жаль, перетворення рядка в Id в коді Apex все ще не буде коротшим, ніж деякі відповіді, подані тут, особливо якщо код повинен бути самостійним. Кодекс Apex не дуже підходить для гольфу.
фірфокс

2
@phyrfox як колишній розробник продажів. Apex не дуже підходить ...
Майк Макмахон

2
APEX, 56 байт: public class X{public X(Id i){System.debug((String)i);}}. Однак працює лише з дійсними ідентифікаторами Salesforce.
Транг Оул

Я прийшов сюди, шукаючи, щоб насправді це зробити для роботи ( success.jitterbit.com/display/DOC/… ) , а не для гольфу, але мене трохи бентежить опис алгоритму. Ви кажете, що кожен відмінений і очищений шматок на кроці 4 буде "двійковим числом", але ви ніколи не замінюєте цифри 2-8 на 0 і 1. Що саме я повинен зробити для кроку 4, коли кроки 1-3 на шматку типу "62mPg" призвели до числа типу "01026"?
к ..

Відповіді:


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

Виявляється, що waaay занадто довгий порівняно з простим регулярним виразом ( x.chars.each_slice(5)порівняно x.scan(/.{5}/)). Це здається очевидним заднім числом, але я ніколи над цим не замислювався ... можливо, я можу оптимізувати тут деякі мої старі відповіді Рубі.

Що я найбільше пишаюсь у цій відповіді, це такий код:

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

Добре, ось ось дещо для нерубінів. Ruby повністю відокремлює booleans ( TrueClass, FalseClass) від цілих чисел / чисел ( Numeric) - це означає, що автоматичного перетворення з true в 1 і false в 0 також немає. Це дратує при гольфі (але гарна річ ... для всіх інших цілей).

Наївний підхід до перевірки того, чи є один символ великим регістром (і повертає 1 або 0)

y.upcase==y?1:0

Ми можемо знизити це трохи далі (знову ж, за допомогою регулярного вираження):

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

Але потім я дійсно почав думати. Хм ... =~повертає індекс збігу (так, для нашого одиночного персонажа, завжди 0якщо є відповідність) або nilпри невідповідності, хибне значення (все інше, крім FalseClassрути в Ruby). ||Оператор бере свій перший операнд , якщо це truthy, а його другий операнд в іншому випадку. Таким чином, ми можемо це зробити в гольф

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

Добре, давайте подивимось, що тут відбувається. Якщо yце велика літера, вона не збігається [^A-Z], тому частина регулярного вираження повернеться nil. nil || 1є 1, так стають великі літери 1. Якщо yнічого , крім великої літери, регулярний вираз частина буде повертатися 0(бо є збіг з індексом 0), а так як 0це truthy, 0 || 1є 0.

... і лише після написання всього цього я усвідомлюю, що це насправді така ж довжина y=~/[A-Z]/?1:0. Ха-ха, добре.


6

Pyth, 23 22 байти

1 байт, збережений FryAmTheEggman .

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

CJam, 27 байт

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

Запустити всі тестові справи.

Досить відверта реалізація специфікації. Найцікавіша частина - це перетворення символів у контрольній сумі. До кожного результату додаємо 17 результатів. Візьміть цей модуль 43 і додайте результат цього символу '0.



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``}`.
Mama Fun Roll

@ ՊՓԼՃՐՊՃՈԲՍԼ Право ти! Спасибі ще один байт поверх цього, дякую.
користувач81655

Збережіть 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
  • Порівняйте показники символів транспонованої матриці з її нижчим регістром та перетворять булеві рядки в рядки, які потім читаються як двійкові та перетворюються в десяткові.
  • Інтерпретуйте ці десяткові знаки (збільшені на 1) як індекси виділеного масиву.
  • Відобразить вхід із додатковими 3 символами

Тепер нижче 100 байт завдяки Луїсу Мендо!


1
Можна трохи заощадити, використовуючиe=['A':'Z',48:53]
Луїс Мендо

Я бачу, що мій підхід майже такий же, як і ваш :-)
Луїс Мендо

2

PHP, 186 181 байт

<?$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])

Гаразд, у цій справі багато акуратних речей. Почну з другого рядка.

Ми приймаємо введення як рядок через $args[0]і встановлюємо його $aдля подальшого використання. Це інкапсульовано ()таким чином, що він виконується, а результат повертається (тобто $a), тому ми можемо негайно об'єднати його в рядки з результатами трьох викликів функцій (f ...). Кожен виклик функції передається як аргумент, рядок введення, індексований у зворотному порядку, відрізками як масив char - значить, для прикладу введення, $a[4..0]буде рівним@('0','E','R','0','a') кожному запису як знаку, а не рядку.

Тепер до функції, де справжнє м'ясо програми. Ми приймаємо вклад як $f, але це лише використаний шлях до кінця, тому спочатку зосередимось там. Оскільки він переданий як масив char (завдяки нашому попередньому індексуванню), ми можемо негайно передати його в цикл $f|%{...}. Всередині циклу ми беремо кожен символ і проводимо відповідність регістру з урахуванням регістру -cmatch, в результаті чого він буде істинним / хибним, якщо це великі регістри / інакше. Ми вважаємо це цілим числом з інкапсуляцією +(), тоді цей масив 1-х та 0-х -joinредагується для формування рядка. Це потім передається в якості першого параметра в .NET[convert]::ToInt32() виклику , щоб змінити двійковий (базовий 2) в десяткової системі . Ми використовуємо це результативне десяткове число для індексації в рядку (-join(...)[...]). Спочатку рядок формулюється як діапазон, (65..90)який передається як масив char, потім об'єднується з діапазоном (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

Пітон 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()один раз, ви можете замінити її виклик і зберегти 25 байт. Також ваш код неправильно призначається [замість 0.
Транг Оул

Ну, це був бентежний нагляд з мого боку. Спасибі.
Стів Екерт

1
Ви можете зекономити ще більше, замінивши першу if elseна цю конструкцію, а другу - на потрійний оператор.
Транг Оул


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

Щоб зберегти кілька байтів, ви можете видалити n із загальної простори імен, якщо для підпису використовується main (n, v, s), оскільки ви не використовуєте argc.
cleblanc

Також замініть 26 * 17 звичайним старим 442 економить ще один байт
cleblanc

З кількома правками я зменшив вашу версію до 110 байт. Я не розумію, чому у вас був !! isupprer (), коли isupper (), здається, працює добре для мене. Також я відремонтував ваші петлі для видалення непотрібних{} 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ця функція не повертає 1 для істини в моїй системі, вона повертає 256. Це !!короткий спосіб перетворити її у значення повернення 0/1 незалежно від того. YMMV.
Коул Камерон

1

C #, 171 байт

Я не дуже добре практикуюсь у гольф на С #, але ось знімок.

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( &bool у C # - це в основному гольф-коротше &&без короткого замикання). 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;}

За запитом я поверну свій код назад до читабельного та опублікую його.


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