Впроваджуйте двійкові оператори INTERCAL


29

Мова компілятора, яка не має вимовляння абревіатури, скорочено INTERCAL , є дуже унікальною мовою програмування. Серед невідтворюваних якостей - його бінарні оператори.

Два двійкові оператори INTERCAL переплітаються (також відомі як змішування ) і вибирають . Interleave представлений зміною (¢), а select представлений виворотом (~).

Interleave працює, беручи два числа в діапазоні 0-65535 і чергуючи їх біти. Наприклад:

234 ¢ 4321
234   = 0000011101010
4321  = 1000011100001
Result: 01000000001111110010001001
Output: 16841865

Виберіть твори, взявши два числа в діапазоні 0-65535, взявши біти в першому операнді, які знаходяться в тому ж положенні, що і 1s, у другому операнді, і право упаковуючи ці біти.

2345 ~ 7245
2345  = 0100100101001
7245  = 1110001001101
Taken : 010   0  10 1
Result: 0100101
Output: 37

У цьому виклику вам буде надано бінарний вираз за допомогою операції перемежування або вибору. Ви повинні обчислити результат, використовуючи найменші можливі байти.

Вираз буде подано у вигляді розділеного пробілом рядка, що складається з цілого числа в 0-65535, пробілу ¢або ~пробілу та цілого числа в 0-65535.

Введення та вихід можуть здійснюватися через будь-яку стандартну систему (STDIN, функція, командний рядок тощо). Стандартні лазівки заборонені.

Приклади:

5 ¢ 6
54

5 ~ 6
2

51234 ¢ 60003
4106492941

51234 ~ 60003
422

Це кодовий гольф - найменше виграш байтів. Удачі.

EDIT: Оскільки деякі мови не підтримують символ зміни (¢) INTERCAL, ви можете використовувати натомість символ великих грошей ($) у розмірі 5-байтного штрафу.


10
Це трохи жорстке покарання людей за використання знака долара. Це те, чого неможливо допомогти.
Бета-розпад

9
Я щойно зрозумів, що CLWNPA ідеально вимовляється у валлійській. W вимовляється як U по-іспанськи або OO в англійській мові.
Рівень річки Св.

9
Я не отримую 5-байтного штрафу. C-INTERCAL використовує $.
kirbyfan64sos

13
Про що ви все сперечаєтесь? A $ явно дорожче, ніж ¢. Що, ти хочеш 99 ¢ ні за що?
Макс

6
Я не думав, що INTERCAL дозволить вам вводити числа десятковими цифрами. Не треба писати FIVE ONE TWO THREE FOUR? І чи не слід виводити римськими цифрами?
Нейт Елдредж

Відповіді:


9

Pyth, 32 31 29 байт

isummFdG}\~zCm.[Z16jvd2%2cz)2

Спробуйте в Інтернеті: Регулярний пакет введення / тестування

Дякуємо @isaacg за те, що ти граєш на один байт.

Пояснення:

                         cz)   split input at spaces
                       %2      only take every second item (the numbers)
             m                 map each number d to:
                    vd           convert d to int
                   j  2          convert to base 2
              .[Z16              pad zeros at the left
            C                  zip
  u     }\~z                   apply the following function ("~" in input) times:
   m   G                         map each pair d to:
    mFd                          convert [x,0] to [] and [x,1] to [x]
 s                             take sum (unfold all lists)
i                           2  convert back from base 2 and print

Ви можете зберегти один байт шляхом зміни hMfeTв , smmFdа потім переміщення Дублікат sза межами троичной. Також ваш поточний код становить 32 байти, а не 33.
isaacg

@isaacg Нічого собі Я ніколи б не подумав, що той розумний гольф. Спасибі. І так, робив гольф в останню хвилину, коли писав пояснення, і не оновлював кількість байтів.
Якубе

2
Дійсно цікаво бачити відповіді Pyth та CJam, майже завжди однаковий підрахунок байтів, але Pyth часто б'є CJam кількома
Kametrixom

13

Python 2, 115 112 байт

x,y,z=input().split()
d=y<""
f=lambda a,b:a+b and(b%2+5&4-d)*f(a/2,b/2)+(a%2*2+b%2)/3**d
print f(int(x),int(z))

Рядок у другому рядку містить один недрукований символ \x7d, наступний знак після ~.

Всі сподівання на добру, єдину лямбда розбиваються форматом введення. Можливо, є кращий спосіб читати на вході. Введення як "51234 ¢ 60003"через STDIN.

Функція fпоєднує в собі наступні дві рекурсивні функції:

g=lambda a,b:a+b and 4*g(a/2,b/2)+a%2*2+b%2    # ¢
h=lambda a,b:a+b and(b%2+1)*h(a/2,b/2)+a*b%2   # ~

(-3 байти за допомогою @xnor)


1
+1 за першу дійсно конкурентоспроможну відповідь Python. Мені було цікаво, чому ти турбуєшся лямбда і не просто вживаєш вираз, але схоже, що там є якась рекурсія? Я не знаю Python, з нетерпінням чекаю пояснення.
Рівень Рівер Сент

Якийсь чудовий шматочок! Я дивлюсь на стиснення виразу постійного терміна. Вираз (a%2*2+b%2)/3**dзберігає 3 символи, але використовує доповнення d=1-c. У вас є спосіб поступити -~(3*c|b%2)з доповненням? У гіршому випадку він втрачає 2 символи 3-3*d. Також формат and-~x+yможе бути andy-~xтаким, який yпочинається символом або цифрою.
xnor

@xnor Зрозумів, (b%2+5&4-d). Спасибі!
Sp3000

11

CJam, 31 байт

rrc\r]{i2bF0e[}%(7=\zf{_)*?~}2b

Спробуйте його в Інтернеті в інтерпретаторі CJam .

Як це працює

rr                              e# Read two tokens from STDIN.
  c\                            e# Cast the second to char and swap with the first.
    r                           e# Read a third token from STDIN.
     ]                          e# Wrap everything in an array.
      {       }%                e# For all three elements:
       i2b                      e#   Cast to int and convert to base 2.
          F0e[                  e#   Left-pad with zeroes to complete 15 digits.
                (               e# Shift out the first base 2 array.
                 7=             e# Select its eighth MSB (1 for '¢', 0 for '~').
                   \            e# Swap with the array of base 2 arrays.
                    z           e# Zip to transpose rows with columns.
                     f{     }   e# For each pair of base 2 digits:
                                e#   Push the bit, then the pair.
                       _        e#   Copy the pair.
                        )       e#   Pop the second digit.
                         *      e#   Repeat the first digit that many times.
                          ?     e#   Ternary if. Select the pair if the bit is
                                e#    truthy, the repeated first bit if it's falsy.
                           ~    e#   Dump the selected array on the stack.
                             2b e# Convert from base 2 to integer.

8

JavaScript (ES6), 103 117 119 124

Відредагуйте зараз роботу з числами, а не рядками

(не рахуючи провідних пробілів, нових рядків та коментарів)

Тест запуску фрагмента в будь-якому веб-переглядачі, сумісному з EcmaScript 6 (особливо це не Chrome, а не MSIE. Я тестував на Firefox, Safari 9 може піти)

I=s=>
  (i=>{
    for(m=r=0,[a,o,b]=s.split` `;i>0;i<<=1) // loop until bit 31 of i is set
      o>'~'?r+=(b&i)*i+(a&i)*2*i:b&i?r+=(a&i)>>m:++m
  })(1)||r


// TEST
out=x=>O.innerHTML+=x+'\n\n';

[ ['234 ¢ 4321', 16841865], ['2345 ~ 7245', 37]
, ['5 ¢ 6', 54], ['5 ~ 6', 2]
, ['51234 ¢ 60003',4106492941], ['51234 ~ 60003', 422]]
.forEach(([i,o,r=I(i)])=>{
  out('Test '+ (o==r?'OK':'Fail')+'\nInput:    '+ i+'\nResult:   '+r+'\nExpected: '+o)})
<pre id=O></pre>


5

Матлаб, 119 113 байт

function f(s)
t=dec2bin(str2double(strsplit(s,{'¢' '~'}))');u=any(s>'~');[~u u]*bin2dec({t(1,t(2,:)==49) t(:)'})

Безголовки:

function f(s)                                     % input s is a string
t = dec2bin(str2double(strsplit(s,{'¢' '~'}))');  % get the two numbers and convert to
                                                  % two-row char array of zeros of ones
u = any(s>'~');                                   % 1 indicates '¢'; 0 indicates '~'
[~u u]*bin2dec({t(1,t(2,:)==49) t(:)'})           % compute both results and display
                                                  % that indicated by u

Приклади:

>> f('234 ¢ 4321')
ans =
    16841865

>> f('2345 ~ 7245')
ans =
    37

5

R, 145 байт

s=scan(,"");a=as.double(c(s[1],s[3]));i=intToBits;cat(packBits(if(s[2]=="~")c(i(a[1])[i(a[2])>0],i(0))[1:32] else c(rbind(i(a[2]),i(a[1]))),"i"))

Недоліковані + пояснення:

# Read a string from STDIN and split it on spaces
s <- scan(, "")

# Convert the operands to numeric
a <- as.double(c(s[1], s[3]))

o <- if (s[2] == "~") {
    # Get the bits of the first operand corresponding to ones in
    # the second, right pad with zeros, and truncate to 32 bits
    c(intToBits(a[1])[intToBits(a[2]) == 1], intToBits(0))[1:32]
} else {
    # Interleave the arrays of bits of the operands
    c(rbind(intToBits(a[2]), intToBits(a[1])))
}

# Make an integer from the raw bits and print  it to STDOUT
cat(packBits(o, "integer"))

5

Пітон 3, 174 166 148 126

Досить прості, строкові операції, а потім перехід назад до цілого числа.

Обмежено числами, які у двійковій формі мають 99 цифр (макс. 2 ^ 99-1 = 633825300114114700748351602687).

Спасибі, Sp3000 та Vioz!

a,o,b=input().split()
print(int(''.join([(i+j,i[:j>'0'])[o>'~']for i,j in zip(*[bin(int(j))[2:].zfill(99)for j in(a,b)])]),2))

Або 165 символів, без обмежень:

a,o,b=input().split()
a,b=[bin(int(j))[2:]for j in(a,b)]
print(int(''.join([(i if j=='1'else'')if o=='~'else i+j for i,j in zip(a.zfill(len(b)),b.zfill(len(a)))]),2))

Безголовки:

a, op, b = input().split()
a, b = [bin(int(j))[2:] for j in(a,b)] #convert to int (base 10), then to binary, remove leading '0b'
m = max(len(a), len(b))
a = a.zfill(m) #fill with leading zeroes
b = b.zfill(m)
if op == '~':
    ret = [i if j=='1' else'' for i, j in zip(a, b)]
else:
    ret = [i + j for i, j in zip(a, b)]
ret = ''.join(ret) #convert to string
ret = int(ret, 2) #convert to integer from base 2
print(ret)

2
Ви можете використовувати zfillзамість rjustпрокладки з нулями
Sp3000

Максимальна кількість входів - 16 біт, а вихідна - 32 біт. 99 біт більш ніж достатньо.
isaacg

Я знаю, але оскільки "99" займає стільки символів, скільки "16", обмеження в цьому немає.
Транг Оул

1
Ще кілька: 1) Вам не потрібно економити a,b, просто покладіть його в за zipдопомогою *шаблону, 2) (i if j=='1'else'') -> i[:j>'0']3) Ви можете скористатися цією порадою, щоб заощадити на іншомуif/else
Sp3000

1
Моє рішення виявилося занадто близьким до вашого, тож ось такий короткий, як я міг отримати ваше (126 байт).
Кейд

4

Pyth, 43 байти

Частина мене нервує публікувати таку довгу відповідь Піта на питання isaacg ...: oP

J.(Kczd1Am.BvdKiu?qJ\~u+G?qeH\1hHk+VGHk.iGH2

Пояснення:

                                               Implicit: z=input(), k='', d=' '
   Kczd                                        Split z on spaces, store in K
J.(    1                                       Remove centre element from K, store in J
         m    K                                For each d in K
          .Bvd                                 Evaluate as int, convert to binary string
        A                                      Store pair in G and H
                                               ~ processing:
                                 +VGH          Create vectorised pairs ([101, 110] -> [11, 01, 10])
                     u               k         Reduce this series, starting with empty string
                        ?qeH\1                 If 2nd digit == 1...
                              hHk              ... take the 1st digit, otherwise take ''
                      +G                       Concatenate
                                      .iGH     ¢ processing: interleave G with H
                ?qJ\~                          If J == ~, take ~ processing, otherwise take ¢
               i                          2    Convert from binary to decimal

4
Мені подобається ваша фотографія профілю! :)
kirbyfan64sos

2
@ Kirbyfan64sos Синій Кірбі краще Кірбі: о)
Sok

3

C, 127 123 байт + 5 штрафних санкцій = 128

scanfзараховує символ unicode як більше одного символу, який значно ускладнює речі, тому я застосовую 5-байтовий штраф за використання $.

a,b,q,x,i;main(){scanf("%d %c %d",&a,&q,&b);for(i=65536;i/=2;)q%7?x=x*4|a/i*2&2|b/i&1:b/i&1&&(x=x*2|a/i&1);printf("%u",x);}

Зміни від початкової версії:

-Тест на $ або ~ було переглянуто з q&2до q%7. Це повертає значення true / false, що дозволяє коду оператора $ перейти до того, :що означає, що набір дужок може бути усунутий.

iданий час цикл відлічує потужність 2, яка довша, але дозволяє >>замінити /і зберегти деякі круглі дужки.

Оригінальна версія 127 байт

a,b,q,x,i;
main(){
  scanf("%d %c %d",&a,&q,&b);
  for(i=16;i--;)
    q&2?
      b>>i&1&&(x=x*2|a>>i&1):    // ~ operator. && used as conditional: code after it is executed only if code before returns truthy.
      (x=x*4|(a>>i&1)*2|b>>i&1); // $ operator
  printf("%u",x);
}

Я пішов однією петлею з умовними умовами всередині, щоб уникнути накладення двох петель. В обох випадках я зміщую біти операндів до біта 1 і збираю результат з найбільш значущого до найменш значущого біта, ліворуч переміщуючи результат (помножуючи на 2 або 4) у міру проходження.


Я гольфував це для вас: main (a, b, q, x, i) {scanf ("% d% c% d", & a, & q, & b); for (i = 16; i -;) q & 2? b >> i & 1 && (x = x * 2 | a >> i & 1) :( x = x * 4 | (a >> i & 1) * 2 | b >> i & 1); printf ("% u", x);} Я спробував займатися гольфом >> i & 1 частини, але не міг знайти рентабельний спосіб зробити це. Однак мені вдалося зберегти 1 символ, поставивши визначення змінної в основному. Примітка: неперевірений.
LambdaBeta

@LamdaBeta спасибі, я не зміг знайти макрос для >> i & 1, але мені вдалося переграти його іншим способом. Встановлення змінних як аргументів mainпричин qпошкодження на моїй машині, що дивно. Я очікую, що справжня проблема полягає в scanfтому, що я залишив їх як звичайні декларації.
Рівень річки Св.

Я не думав про це. Ви праві, q буде зіпсовано. Причина полягає в тому, що, коли ми дізнаємося, що main бере два аргументи, кількість аргументів командного рядка та масив самих аргументів, більшість систем фактично надають третій аргумент (як правило, називається char * envp []), який описує середовище кодом запускається (надання доступу до EG: змінні середовища). Таким чином, третє значення в основному може також призначати систему значенням, scanf цього разу невинний.
LambdaBeta

@steveverill Я думаю, ви також можете зняти 5 байт. Я щойно перевірив ваш код (використовуючи ALT + 155 для виготовлення ¢), і, здається, він працює добре. :)
LambdaBeta

@LambdaBeta насправді експерименти показують, що це поєднання обох. При нормальному оголошенні qгарантовано дорівнює нулю, але при оголошенні як функціональному параметрі qміститься 32-бітове сміття. Це не було б проблемою , якщо я призначений на значення q, але scanfз "%c"тільки переписує молодші 8 біт сміття, залишаючи інші 24 невизначені. Можливо, мені пощастить на іншому компіляторі!
Рівень річки Св.

3

К5, 53 52 байти

{b/({,/x,'y};{x@&y})[*"~"=y][b\.x;(b:20#2)\.z]}." "\

53-байтна версія:

{b/({,/x,'y};{x@&y})[*"¢~"?y][b\.x;(b:20#2)\.z]}." "\

Ще потрібно трохи більше гольфу.



3

Хаскелл, 77

g=(`mod`2)
h=(`div`2)
0¢0=0
a¢b=g a+2*b¢h a
a?0=0
a?b=g a*g b+(1+g b)*h a?h b

введення задається шляхом застосування вводу до функцій / операторів ?і ¢визначено в коді (Haskell не може визначити оператора~ з технічних причин).

в основному працює старий рекурсивний підхід.


2

J, 173

f=:|."1@(>@(|.&.>)@(#:@{:;#:@{.))
m=:2&#.@:,@:|:@:|.@:f
s=:2&#.@#/@:f
a=:{&a.@-.
(1!:2)&2(s@".@:a&126)^:(126 e.i)((m@".@:a&194 162)^:(1 e.194 162 E.i)i=._1}.(a.i.((1!:1)3)))

очікує один рядок введення

очікується, що вхід закінчиться після нового рядка з EOF


2

Javascript ES6 (3 аргументи) 141 138 136 121 119 байт

b=x=>(65536|x).toString`2`
f=(x,o,y)=>+eval(`'0b'+(b(y)+b(x)).replace(/^1|${o=='~'?1:'(.)'}(?=.{16}(.)())|./g,'$2$1')`)

Тест:

;[f(234,'¢',4321),f(2345,'~',7245)]=="16841865,37"

Javascript ES6 (1 аргумент) 135 133 байт

b=x=>(65536|x).toString`2`
f=s=>([x,o,y]=s.split` `)|eval(`'0b'+(b(y)+b(x)).replace(/^1|${o=='~'?1:'(.)'}(?=.{16}(.)())|./g,'$2$1')`)

Тест:

;[f('234 ¢ 4321'),f('2345 ~ 7245')]=="16841865,37"

PS: Новий рядок рахується як 1 байт, оскільки його можна замінити ;.


1
0x10000 == 65536 (збережіть 2 символи)
edc65

@ edc65, я оновив відповідь.
Qwertiy

2
65536 | x щоб уникнути ~~
edc65

Допускається лише друга версія - вхід повинен бути у вигляді рядка з обмеженим пробілом.
isaacg

@isaacg, добре. Але я не хочу видаляти першу з історичних причин.
Qwertiy

2

Пітон 3, 157 байт

a,x,y=input().split()
i=int
b=bin
print(i(''.join(([c for c,d in zip(b(i(a)),b(i(y)))if d=='1'],[c+d for c,d in zip(b(i(a))[2:],b(i(y))[2:])])['¢'==x]),2))

Повну та пояснювальну версію можна знайти на моєму пастебі .


Ви можете виконати кілька символів, видаливши пробіли навколо оператора '==', перед 'якщо' і передавши 'base' як позиційний аргумент.
Транг Оул

Дякую, що та деякі інші зберегли 15 символів! але подвоєний спосіб форматування повернення все ще багато.
Олівер Фрідріх

Також ви використовуєте 4 пробіли на відступ? Одного (або вкладки) достатньо.
Транг Оул

2
@BeowulfOF Якщо не вказано інше, ви можете надіслати повну програму або функцію. Як правило, що коротше, буде залежати від того, як ваша мова розбирає конкретний вклад для виклику (наприклад, рубін напрочуд незграбний з цифрами від stdin, наприклад). Також у вас є два можливі способи виведення: значення stdout або return, які застосовні для обох (хоча значення повернення в програмах рідкісні.)
Level River St

1
Здається, ви використовуєте лише eодин раз, чи не можете ви просто вбудувати його?
Кевін Браун

0

Математика, 155 байт

f=IntegerDigits[#,2,16]&;
g=#~FromDigits~2&;
¢=g[f@#~Riffle~f@#2]&;
s=g@Cases[Thread@{f@#,f@#2},{x_,1}->x]&;
ToExpression@StringReplace[#,{" "->"~","~"->"s"}]&

Оцінює анонімну функцію, приймаючи рядок як вхідний. Для чіткості додано розриви рядків.

fі gперетворити в / з бази 2. Riffleробить саме те, що має бути перемежоване . Я хотів використовувати Selectдля select, але Casesкраще, на жаль. Останній рядок - трохи хитрість; зміниться пробіл, ~який є інфіксним оператором Mathematica, тоді рядок є eval'd.

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