Implementieren Sie die Binäroperatoren von INTERCAL

29

Die Compiler-Sprache ohne aussprechbares Akronym, kurz INTERCAL , ist eine sehr einzigartige Programmiersprache. Zu seinen nicht reproduzierbaren Eigenschaften zählen die binären Operatoren.

Die beiden binären Operatoren von INTERCAL sind Interleave (auch als Mingle bezeichnet ) und Select . Interleave wird mit einer Änderung (¢) dargestellt, und Select wird mit einem Rechteck (~) dargestellt.

Interleave funktioniert, indem zwei Zahlen im Bereich von 0 bis 65535 abwechselnd verwendet werden. Zum Beispiel:

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

Wählen Sie Werke aus, indem Sie zwei Zahlen im Bereich 0-65535 nehmen, die Bits im ersten Operanden nehmen, die sich an der gleichen Position befinden wie 1s im zweiten Operanden, und diese Bits rechts packen.

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

In dieser Herausforderung erhalten Sie einen binären Ausdruck, der entweder die Interleave- oder die Select-Operation verwendet. Sie müssen das Ergebnis mit möglichst wenigen Bytes berechnen.

Der Ausdruck wird als durch Leerzeichen getrennte Zeichenfolge angegeben, die aus einer Ganzzahl in 0-65535, einem Leerzeichen ¢oder ~einem Leerzeichen und einer Ganzzahl in 0-65535 besteht.

Die Ein- und Ausgabe kann über ein beliebiges Standardsystem (STDIN, Funktion, Befehlszeile usw.) erfolgen. Standardlücken verboten.

Beispiele:

5 ¢ 6
54

5 ~ 6
2

51234 ¢ 60003
4106492941

51234 ~ 60003
422

Dies ist Code Golf - die wenigsten Bytes gewinnen. Viel Glück.

BEARBEITEN: Da einige Sprachen das INTERCAL-Änderungssymbol (¢) nicht unterstützen, können Sie stattdessen das Big-Money-Symbol ($) mit einer 5-Byte-Strafe verwenden.

isaacg
quelle
10
Es ist ein bisschen hart, Leute für die Verwendung des Dollarzeichens zu bestrafen. Dem kann nicht geholfen werden.
Beta-Zerfall
9
Ich habe gerade festgestellt, dass CLWNPA auf Walisisch perfekt ausgesprochen werden kann. Das W wird auf Spanisch als U oder auf Englisch als OO ausgesprochen.
Level River St
9
Ich bekomme keine 5-Byte-Strafe. C-INTERCAL verwendet die $.
kirbyfan64sos
13
Worüber streiten Sie alle? Ein $ ist deutlich teurer als ein ¢. Was willst du 99 ¢ für nichts?
Max
6
Ich hätte nicht gedacht, dass Sie mit INTERCAL Zahlen mit Dezimalzahlen eingeben können. Sie haben nicht zu schreiben FIVE ONE TWO THREE FOUR? Und sollte die Ausgabe nicht in römischen Ziffern erfolgen?
Nate Eldredge

Antworten:

9

Pyth, 32 31 29 Bytes

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

Probieren Sie es online aus: Regular Input / Test Suite

Vielen Dank an @isaacg für das Abschlagen eines Bytes.

Erläuterung:

                         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
quelle
Sie können , indem ein Byte speichern hMfeTzu machen smmFdund dann das Duplikat zu bewegen saußerhalb der ternären. Außerdem ist Ihr aktueller Code 32 Bytes, nicht 33.
isaacg
@isaacg Wow. Ich hätte nie gedacht, dass kluges Golf. Vielen Dank. Und ja, habe in letzter Minute Golf gespielt und dabei die Anzahl der Bytes nicht aktualisiert.
Jakube,
2
Es ist wirklich interessant zu sehen, wie Pyth und CJam antworten, fast immer die gleiche Byteanzahl, aber Pyth schlägt CJam oft um ein paar
Kametrixom
13

Python 2, 115 112 Bytes

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

Die Zeichenfolge in der zweiten Zeile enthält ein einzelnes nicht druckbares Zeichen \x7d, das nächste Zeichen danach ~.

Alle Hoffnungen auf ein schönes, einzelnes Lambda werden durch das Eingabeformat zunichte gemacht. Es gibt wahrscheinlich eine bessere Möglichkeit, Eingaben einzulesen. Eingabe wie "51234 ¢ 60003"über STDIN.

Die Funktion fkombiniert die folgenden zwei rekursiven Funktionen:

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 Bytes mit Hilfe von @xnor)

Sp3000
quelle
1
+1 für die erste wirklich konkurrenzfähige Python-Antwort. Ich habe mich gefragt, warum du dich mit dem Lambda beschäftigt hast und nicht nur einen Ausdruck benutzt hast, aber es sieht so aus, als ob es eine Rekursion gibt? Ich kenne Python nicht, freue mich auf eine Erklärung.
Level River St
Ein paar tolle Schläge! Ich möchte den konstanten Ausdruck komprimieren. Der Ausdruck (a%2*2+b%2)/3**dspeichert 3 Zeichen, verwendet jedoch das Komplement d=1-c. Haben Sie eine Möglichkeit, -~(3*c|b%2)mit der Ergänzung umzugehen? Im schlimmsten Fall verliert es 2 Zeichen mit 3-3*d. Das Format and-~x+ykann auch andy-~xso lang sein, wie es ymit einem Symbol oder einer Zahl beginnt.
Donnerstag,
@xnor Verstanden, (b%2+5&4-d). Vielen Dank!
Sp3000,
11

CJam, 31 Bytes

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

Probieren Sie es online im CJam-Interpreter aus .

Wie es funktioniert

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
quelle
8

JavaScript (ES6), 103 117 119 124

Bearbeiten Sie jetzt, indem Sie mit Zahlen anstatt mit Zeichenfolgen arbeiten

(ohne führende Leerzeichen, Zeilenumbrüche und Kommentare)

Testlauf des Snippets in jedem EcmaScript 6-kompatiblen Browser (insbesondere nicht in Chrome und nicht in MSIE. Ich habe es in Firefox getestet, Safari 9 könnte funktionieren)

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
quelle
5

Matlab, 119 113 Bytes

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

Ungolfed:

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

Beispiele:

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

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

R, 145 Bytes

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

Ungolfed + Erklärung:

# 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.
quelle
5

Python 3, 174 166 148 126

Ziemlich unkomplizierte Zeichenfolgeoperationen, die dann wieder in eine Ganzzahl umgewandelt werden.

Beschränkt auf Zahlen mit 99 Ziffern (max. 2 ^ 99-1 = 633825300114114700748351602687).

Danke, Sp3000 und 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))

Oder 165 Zeichen, ohne Limit:

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

Ungolfed:

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
quelle
2
Sie können zfillanstelle von rjustzum Auffüllen mit Nullen verwenden
Sp3000 10.08.15
Eingaben maximal bei 16 Bit und Ausgaben bei 32 Bit. 99 Bits sind mehr als genug.
isaacg
Ich weiß, aber da '99' so viele Zeichen wie '16' enthält, ist es nicht vorteilhaft, sie einzuschränken.
Trang Oul
1
Ein paar mehr: 1) Sie müssen nicht speichern a,b, setzen Sie es einfach in die zipmit einem *Splat, 2) (i if j=='1'else'') -> i[:j>'0']3) Sie können diesen Tipp verwenden , um auf der anderen if/else
Seite
1
Meine Lösung war zu nahe an Ihrer, daher hier so kurz wie möglich (126 Byte).
Kade,
4

Pyth, 43 Bytes

Ein Teil von mir ist nervös, eine so lange Pyth-Antwort auf Isaacs Frage zu posten ...: oP

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

Erklärung:

                                               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
quelle
4
Ich mag dein Profilbild! :)
kirbyfan64sos
2
@ kirbyfan64sos Blau Kirby ist am besten Kirby: o)
Sok
3

C, 127123 Bytes + 5 Strafen = 128

scanfZählt das Unicode-Symbol als mehr als ein Zeichen, was die Dinge sehr kompliziert macht. Daher wende ich die 5-Byte-Strafe für die Verwendung an $.

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

Die Änderungen gegenüber der Originalversion sind:

-Der Test für $ oder ~ wurde von q&2bis überarbeitet q%7. Dies kehrt die Wahr / Falsch-Werte um, so dass der Code für den $ -Operator vor dem steht, :wodurch ein Satz von Klammern entfernt werden kann.

-Die iSchleife zählt jetzt in Potenzen von 2 herunter, was länger ist, aber erlaubt >>, durch /Klammern ersetzt zu werden und einige zu speichern.

Ursprüngliche Version 127 Bytes

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

Ich ging mit einer einzigen Schleife mit den Bedingungen im Inneren, um den Aufwand von zwei Schleifen zu vermeiden. In beiden Fällen verschiebe ich die Bits der Operanden mit der rechten Maustaste auf das Bit der 1 und baue das Ergebnis vom höchstwertigen zum niedrigstwertigen Bit auf, wobei ich das Ergebnis nach links verschiebe (multipliziere mit 2 oder 4).

Level River St
quelle
Ich habe es für Sie gespielt: main (a, b, q, x, i) {scanf ("% d% c% d", & a, & q, & b) für (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);} Ich habe versucht, die >> i & 1-Teile wegzuspielen, konnte aber keinen kostengünstigen Weg finden, dies zu tun. Ich konnte jedoch 1 Zeichen speichern, indem ich die Variablendefinitionen in main setzte. Anmerkung: ungetestet.
LambdaBeta
@LamdaBeta danke, ich konnte kein Makro für >> i & 1 finden, aber ich habe es geschafft, es auf eine andere Weise zu spielen. Es ist seltsam, die Variablen als Argumente für mainUrsachen qanzugeben, die auf meinem Computer beschädigt werden. Ich gehe davon aus, dass das eigentliche Problem darin besteht scanf, aber aus diesem Grund habe ich sie als normale Erklärungen zurückgelassen.
Level River St
Daran hatte ich nicht gedacht. Sie haben recht, q wird beschädigt. Der Grund dafür ist, dass, während wir lernen, dass main zwei Argumente benötigt, die Anzahl der Befehlszeilenargumente und ein Array der Argumente selbst, die meisten Systeme tatsächlich ein drittes Argument (in der Regel char * envp []) bereitstellen, das die Umgebung und den Code beschreibt wird ausgeführt in (Zugriff auf EG: Umgebungsvariablen gewähren). Damit dem dritten Wert in main auch ein Wert vom System zugewiesen werden kann, ist scanf diesmal unschuldig.
LambdaBeta
@steveverill Ich denke, Sie können auch die 5-Byte-Strafe entfernen. Ich habe gerade Ihren Code getestet (mit ALT + 155, um ¢ zu machen) und es scheint gut zu funktionieren. :)
LambdaBeta
@ LambdaBeta tatsächlich Experimentieren zeigt, es ist eine Kombination von beiden. Bei der normalen Deklaration qist garantiert Null, aber bei der Deklaration als Funktion qenthält der Parameter 32-Bit-Garbage. Das wäre kein Problem, wenn ich zugewiesen einen Wert q, aber scanfmit "%c"nur überschreibt die am wenigsten signifikanten 8 Bits des Mülls, undefiniert die anderen 24 zu verlassen. Ich könnte Glück auf einem anderen Compiler bekommen!
Level River St
3

K5, 53 52 Bytes

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

53-Byte-Version:

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

Benötigt noch ein bisschen mehr Golf.

kirbyfan64sos
quelle
3

CJam, 61 50 46 41 34 Bytes

Vielen Dank an @Dennis für den Hinweis auf ein 4-Byte-Golf.

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

Probieren Sie es online aus .

Andrea Biondo
quelle
1
]{}/ist ein Noop.
Dennis
1
@ Tennis Danke. Ich sollte wahrscheinlich etwas schlafen gehen ...
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

Die Eingabe erfolgt durch Anwenden der Eingabe auf die Funktionen / Operatoren ?und¢ definiert im Code (Haskell kann nicht definieren einen Operator ~aus technischen Gründen).

Grundsätzlich funktioniert der alte rekursive Ansatz.

stolzer haskeller
quelle
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)))

erwartet eine Eingabezeile

Eingabe wird voraussichtlich nach neuer Zeile mit EOF beendet

Protist
quelle
2

Javascript ES6 (3 Argumente) 141 138 136 121 119 Bytes

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

Prüfung:

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

Prüfung:

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

PS: Neue Zeile wird als 1 Byte gezählt, da sie durch ersetzt werden kann ;.

Qwertiy
quelle
1
0x10000 == 65536 (2 Zeichen sparen)
edc65
@ edc65, ich habe die Antwort aktualisiert.
Qwertiy
2
65536 | x zu vermeiden ~~
edc65
Es ist nur die zweite Version zulässig. Die Eingabe muss in Form einer durch Leerzeichen getrennten Zeichenfolge erfolgen.
isaacg
@isaacg, ok Aber ich möchte das erste aus historischen Gründen nicht löschen.
Qwertiy
2

Python 3, 157 Bytes

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

Die vollständige und erklärende Version finden Sie in meinem Pastebin .

Oliver Friedrich
quelle
Sie können auch ein paar Zeichen verwenden, indem Sie Leerzeichen um den Operator "==" vor "if" entfernen und "base" als Positionsargument übergeben.
Trang Oul
Vielen Dank, dass und einige andere 15 Zeichen gespart haben! Die doppelte Formatierung der Rückgabe ist jedoch immer noch zu viel.
Oliver Friedrich
Verwenden Sie außerdem 4 Leerzeichen pro Einzug? Eine (oder Registerkarte) ist genug.
Trang Oul
2
@BeowulfOF Sofern nicht anders angegeben, können Sie ein vollständiges Programm oder eine Funktion einreichen. Was kürzer ist, hängt im Allgemeinen davon ab, wie Ihre Sprache die spezifischen Eingaben für die Herausforderung analysiert (Ruby ist beispielsweise mit Zahlen von stdin überraschend ungeschickt). Sie haben auch zwei Möglichkeiten zur Ausgabe: stdout oder return value, die auf beide zutreffen (Rückgabewerte von Programmen sind jedoch selten).
Level River St
1
Sie scheinen nur eeinmal zu verwenden , können Sie es nicht einfach einbinden?
Kevin Brown
0

Mathematica, 155 Bytes

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

Wird zu einer anonymen Funktion ausgewertet, die die Zeichenfolge als Eingabe verwendet. Zeilenumbrüche zur Verdeutlichung hinzugefügt.

fund gkonvertiere zu / von Basis 2. Rifflemacht genau das, was Interleave soll. Ich wollte Selectfür select verwenden ist aber Casesleider besser. Die letzte Zeile ist etwas trickreich; Die Leerzeichen werden in ~den Infix-Operator von Mathematica geändert. Anschließend wird die Zeichenfolge ausgewertet.

jcai
quelle