Implémenter les opérateurs binaires d'INTERCAL

29

Le langage du compilateur sans acronyme prononçable, abrégé INTERCAL , est un langage de programmation très unique. Parmi ses qualités non reproductibles figurent ses opérateurs binaires.

Les deux opérateurs binaires d'INTERCAL sont entrelacés (également appelés mingle ) et select . Interleave est représenté par un changement (¢), et select est représenté par un carré (~).

Interleave fonctionne en prenant deux nombres dans la plage 0-65535 et en alternant leurs bits. Par exemple:

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

Select fonctionne en prenant deux nombres dans la plage 0-65535, en prenant les bits du premier opérande qui sont dans la même position que 1s du deuxième opérande et en compressant à droite ces bits.

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

Dans ce défi, vous recevrez une expression binaire à l'aide de l'opération d'entrelacement ou de sélection. Vous devez calculer le résultat en utilisant le moins d'octets possible.

L'expression sera donnée sous la forme d'une chaîne séparée par des espaces, composée d'un entier en 0-65535, d'un espace, soit ¢ou ~, soit d'un espace, et d'un entier en 0-65535.

L'entrée et la sortie peuvent se faire via n'importe quel système standard (STDIN, fonction, ligne de commande, etc.). Échappatoires standard interdites.

Exemples:

5 ¢ 6
54

5 ~ 6
2

51234 ¢ 60003
4106492941

51234 ~ 60003
422

C'est le golf de code - le moins d'octets gagne. Bonne chance.

EDIT: Étant donné que certaines langues ne prennent pas en charge le symbole de changement (¢) d'INTERCAL, vous pouvez utiliser le symbole de gros prix ($) à la place, avec une pénalité de 5 octets.

isaacg
la source
10
C'est un peu dur de pénaliser les gens pour l'utilisation du signe dollar. C'est quelque chose qui ne peut être aidé.
Beta Decay
9
Je viens de réaliser que CLWNPA est parfaitement prononçable en gallois. Le W est prononcé comme U en espagnol ou OO en anglais.
Level River St
9
Je ne reçois pas la pénalité de 5 octets. C-INTERCAL utilise le $.
kirbyfan64sos
13
De quoi parlez-vous tous? Un $ est clairement plus cher qu'un ¢. Quoi, vous voulez 99 ¢ pour rien?
Max
6
Je ne pensais pas qu'INTERCAL vous permettrait de saisir des nombres avec des nombres décimaux. Tu n'as pas à écrire FIVE ONE TWO THREE FOUR? Et la sortie ne devrait-elle pas être en chiffres romains?
Nate Eldredge

Réponses:

9

Pyth, 32 31 29 octets

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

Essayez-le en ligne: Regular Input / Test Suite

Merci à @isaacg d'avoir joué au golf sur un octet.

Explication:

                         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
Jakube
la source
Vous pouvez enregistrer un octet en changeant hMfeTà smmFdet en déplaçant le double en sdehors du ternaire. De plus, votre code actuel est de 32 octets, pas 33.
isaacg
@isaacg Wow. Je n'aurais jamais pensé à ce golf intelligent. Merci. Et oui, a fait un golf de dernière minute en écrivant l'explication et n'a pas mis à jour le nombre d'octets.
Jakube
2
Il est vraiment intéressant de voir les réponses Pyth et CJam, presque toujours le même nombre d'octets, mais Pyth bat souvent CJam par quelques
Kametrixom
13

Python 2, 115 112 octets

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

La chaîne de la deuxième ligne contient un seul caractère non imprimable \x7d, le caractère suivant après ~.

Tous les espoirs d'une belle lambda unique sont écrasés par le format d'entrée. Il y a probablement une meilleure façon de lire l'entrée. Entrée comme "51234 ¢ 60003"via STDIN.

La fonction fcombine les deux fonctions récursives suivantes:

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 octets avec l'aide de @xnor)

Sp3000
la source
1
+1 pour la première réponse Python vraiment compétitive. Je me demandais pourquoi vous vous êtes soucié du lambda et n'avez pas simplement utilisé une expression, mais il semble qu'il y ait une récursion là-dedans? Je ne connais pas Python, j'ai hâte d'avoir une explication.
Level River St
Un peu de dénigrement! Je cherche à compresser l'expression du terme constant. L'expression (a%2*2+b%2)/3**denregistre 3 caractères mais utilise le complément d=1-c. Avez-vous un moyen de faire -~(3*c|b%2)avec le complément? Au pire, il perd 2 caractères avec 3-3*d. De plus, le format and-~x+ypeut être andy-~xaussi long qu'il ycommence par un symbole ou un nombre.
xnor
@xnor J'ai compris (b%2+5&4-d). Merci!
Sp3000
11

CJam, 31 octets

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

Essayez-le en ligne dans l' interpréteur CJam .

Comment ça marche

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.
Dennis
la source
8

JavaScript (ES6), 103 117 119 124

modifier maintenant travailler avec des nombres au lieu de chaînes

(sans compter les espaces principaux, les nouvelles lignes et les commentaires)

Testez l'exécution de l'extrait sur n'importe quel navigateur compatible EcmaScript 6 (notamment pas Chrome ni MSIE. J'ai testé sur Firefox, Safari 9 pourrait aller)

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>

edc65
la source
5

Matlab, 119 113 octets

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

Non golfé:

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

Exemples:

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

>> f('2345 ~ 7245')
ans =
    37
Luis Mendo
la source
5

R, 145 octets

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"))

Non golfé + explication:

# 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"))
Alex A.
la source
5

Python 3, 174 166 148 126

Opérations de chaîne assez simples, puis reconversion en entier.

Limité aux nombres qui en binaire ont 99 chiffres (max 2 ^ 99-1 = 633825300114114700748351602687).

Merci, Sp3000 et 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))

Ou 165 caractères, sans limite:

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

Non golfé:

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)
Trang Oul
la source
2
Vous pouvez utiliser zfillau lieu de rjustpour le remplissage avec des zéros
Sp3000
Entrées max à 16 bits et sorties à 32 bits. 99 bits est plus que suffisant.
isaacg
Je sais, mais comme '99' prend autant de caractères que '16', il n'y a aucun avantage à le limiter.
Trang Oul
1
Quelques autres: 1) Vous n'avez pas besoin de sauvegarder a,b, il suffit de le mettre zipavec un *splat, 2) (i if j=='1'else'') -> i[:j>'0']3) Vous pouvez utiliser cette astuce pour économiser sur l'autreif/else
Sp3000
1
Ma solution a fini par être trop proche de la vôtre, alors voici la plus courte possible (126 octets).
Kade
4

Pyth, 43 octets

Une partie de moi se sent nerveuse de poster une si longue réponse Pyth sur la question de isaacg ...: oP

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

Explication:

                                               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
Sok
la source
4
J'aime ta photo de profil! :)
kirbyfan64sos
2
@ kirbyfan64sos Blue Kirby est le meilleur Kirby: o)
Sok
3

C, 127 123 octets + 5 pénalités = 128

scanfcompte le symbole unicode comme plus d'un caractère, ce qui complique beaucoup les choses, donc j'applique la pénalité de 5 octets pour l'utilisation $.

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

Les changements par rapport à la version d'origine sont les suivants:

-Le test de $ ou ~ a été révisé de q&2à q%7. Cela inverse les valeurs vraies / fausses, permettant au code de l'opérateur $ d'aller avant le : qui signifie qu'un ensemble de parenthèses peut être éliminé.

-La iboucle compte désormais à rebours en puissance de 2 qui est plus longue, mais permet >>de la remplacer par/ et enregistre quelques parenthèses.

Version originale 127 octets

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

Je suis allé avec une seule boucle avec les conditions à l'intérieur pour éviter la surcharge de deux boucles. Dans les deux cas, je déplace les bits des opérandes vers le bit 1, et je crée le résultat du bit le plus significatif au moins significatif, en déplaçant le résultat à gauche (en multipliant par 2 ou 4) au fur et à mesure.

Level River St
la source
Je l'ai joué pour vous: principal (a, b, q, x, i) {scanf ("% d% c% d", & a, & q, & b); pour (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);} J'ai essayé de jouer au golf sur les pièces >> i & 1, mais je n'ai pas trouvé de moyen rentable de le faire. J'ai cependant pu enregistrer 1 caractère en mettant les définitions de variables en main. Remarque: non testé.
LambdaBeta
@LamdaBeta merci, je n'ai pas trouvé de macro pour >> i & 1 mais j'ai réussi à jouer au golf d'une autre manière. Mettre les variables comme arguments de maincauses qà corrompre sur ma machine, ce qui est étrange. Je m'attends à ce que le vrai problème soit avec scanf, mais à cause de cela je les ai laissés comme des déclarations normales.
Level River St
Je n'y avais pas pensé. Vous avez raison, q sera corrompu. La raison en est que tandis que nous apprenons que main prend deux arguments, le nombre d'arguments de ligne de commande et un tableau des arguments lui-même, la plupart des systèmes fournissent en fait un troisième argument (généralement appelé char * envp []) qui décrit l'environnement du code est exécuté (accordant l'accès à EG: variables d'environnement). Ainsi, la troisième valeur de main peut également se voir attribuer une valeur par le système, scanf est cette fois innocent.
LambdaBeta
@steveverill Je pense que vous pouvez également supprimer la pénalité de 5 octets. Je viens de tester votre code (en utilisant ALT + 155 pour faire ¢) et il semble bien fonctionner. :)
LambdaBeta
L'expérimentation de @LambdaBeta montre que c'est une combinaison des deux. Avec la déclaration normale q, la valeur zéro est garantie, mais avec la déclaration en tant que paramètre de fonction qcontient des ordures 32 bits. Ce ne serait pas un problème si j'attribuais une valeur à q, mais scanfavec "%c"uniquement les 8 bits les moins significatifs de la poubelle, laissant les 24 autres non définis. Je pourrais avoir de la chance avec un autre compilateur!
Level River St
3

K5, 53 52 octets

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

Version 53 octets:

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

Encore besoin d'un peu plus de golf.

kirbyfan64sos
la source
3

CJam, 61 50 46 41 34 octets

Merci @Dennis d'avoir signalé un golf de 4 octets.

rrc'~=:X;r]{i2bF0e[}/.{X{{;}|}&}2b

Essayez-le en ligne .

Andrea Biondo
la source
1
]{}/est un noop.
Dennis
1
@Dennis Merci. Je devrais probablement dormir un peu ...
Andrea Biondo
3

Haskell, 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

l'entrée est donnée en appliquant l'entrée aux fonctions / opérateurs ?et ¢définie dans le code (Haskell ne peut pas définir d'opérateur~ pour des raisons techniques).

fonctionne essentiellement l'ancienne approche récursive.

fier haskeller
la source
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)))

attend une ligne d'entrée

l'entrée devrait se terminer après une nouvelle ligne avec EOF

protiste
la source
2

Javascript ES6 (3 arguments) 141 138 136 121 119 octets

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

Tester:

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

Javascript ES6 (1 argument) 135 133 bytes

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')`)

Tester:

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

PS: la nouvelle ligne compte pour 1 octet car elle peut être remplacée par ;.

Qwertiy
la source
1
0x10000 == 65536 (enregistrer 2 caractères)
edc65
@ edc65, j'ai mis à jour la réponse.
Qwertiy
2
65536 | x à éviter ~~
edc65
Seule la deuxième version est autorisée - l'entrée doit être sous la forme d'une chaîne délimitée par des espaces.
isaacg
@isaacg, ok. Mais je ne veux pas supprimer le premier pour des raisons historiques.
Qwertiy
2

Python 3, 157 octets

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

La version complète et explicative peut être trouvée sur mon pastebin .

Oliver Friedrich
la source
Vous pouvez faire la même chose avec quelques caractères en supprimant les espaces autour de l'opérateur '==', avant 'if' et en passant 'base' comme argument positionnel.
Trang Oul
Merci, cela et quelques autres ont sauvé 15 caractères! mais la double façon de formater le retour est encore trop.
Oliver Friedrich
De plus, utilisez-vous 4 espaces par tiret? Un (ou un onglet) suffit.
Trang Oul
2
@BeowulfOF Sauf indication contraire, vous pouvez soumettre un programme complet ou une fonction. Généralement, ce qui est plus court dépendra de la façon dont votre langue analyse l'entrée spécifique pour le défi (ruby est étonnamment maladroit avec les chiffres de stdin par exemple). Vous avez également deux façons possibles de sortir: stdout ou valeur de retour, qui s'appliquent aux deux (bien que les valeurs de retour des programmes soient rares.)
Level River St
1
Vous ne semblez l'utiliser equ'une seule fois, ne pouvez-vous pas simplement l'intégrer?
Kevin Brown
0

Mathematica, 155 octets

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"}]&

Évalue à une fonction anonyme prenant la chaîne en entrée. Sauts de ligne ajoutés pour plus de clarté.

fet gconvertir en / depuis la base 2. Rifflefait exactement ce que l' entrelacement est censé faire. Je voulais utiliser Selectpour sélectionner mais Casesc'est mieux malheureusement. La dernière ligne est un peu de ruse; les espaces sont remplacés par ~l'opérateur infixe de Mathematica, puis la chaîne est évaluée.

jcai
la source