Wdrożenie operatorów binarnych INTERCAL

29

Język kompilatora bez wyraźnego akronimu, w skrócie INTERCAL , jest bardzo unikalnym językiem programowania. Wśród jego niepowtarzalnych cech znajdują się operatory binarne.

Dwa operatory binarne INTERCAL są przeplatane (znane również jako mingle ) i select . Przeplot jest reprezentowany przez zmianę (¢), a wybór jest reprezentowany przez sqiggle (~).

Przeplot działa poprzez pobranie dwóch liczb z zakresu 0-65535 i naprzemiennie ich bitów. Na przykład:

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

Wybierz prace, biorąc dwie liczby z zakresu 0-65535, biorąc bity w pierwszym operandzie, które są w tej samej pozycji co 1s w drugim operandzie, i odpowiednio upakuj te bity.

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

W tym wyzwaniu otrzymasz wyrażenie binarne za pomocą operacji przeplotu lub wyboru. Musisz obliczyć wynik, używając jak najmniejszej liczby bajtów.

Wyrażenie będą jako przestrzeń oddziela ciąg znaków, składający się z liczby całkowitej w 0-65535, przestrzeni albo ¢czy~ , przestrzeni i liczbę całkowitą 0-65535.

Wejście i wyjście może odbywać się za pośrednictwem dowolnego standardowego systemu (STDIN, funkcja, wiersz poleceń itp.). Standardowe luki zabronione.

Przykłady:

5 ¢ 6
54

5 ~ 6
2

51234 ¢ 60003
4106492941

51234 ~ 60003
422

To jest golf golfowy - wygrywa najmniej bajtów. Powodzenia.

EDYCJA: Ponieważ niektóre języki nie obsługują symbolu zmiany (¢) INTERCAL, możesz zamiast tego użyć symbolu dużych pieniędzy ($), z karą 5 bajtów.

isaacg
źródło
10
Trochę surowo karze się ludzi za używanie znaku dolara. To jest coś, na co nie można pomóc.
Rozpad beta w dniu
9
Właśnie zdałem sobie sprawę, że CLWNPA jest doskonale wymawiane w języku walijskim. W wymawia się jako U w języku hiszpańskim lub OO w języku angielskim.
Level River St
9
Nie dostaję kary 5 bajtów. C-INTERCAL korzysta z $.
kirbyfan64sos,
13
O co wszyscy się kłócicie? $ Jest wyraźnie droższy niż ¢. Czego chcesz 99 centów za nic?
Maks.
6
Nie sądziłem, że INTERCAL pozwoli ci na wprowadzanie liczb dziesiętnych. Nie musisz pisać FIVE ONE TWO THREE FOUR? I czy dane wyjściowe nie powinny być zapisane cyframi rzymskimi?
Nate Eldredge,

Odpowiedzi:

9

Pyth, 32 31 29 bajtów

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

Wypróbuj online: Regular Input / Test Suite

Dzięki @isaacg za grę w golfa na jednym bajcie.

Wyjaśnienie:

                         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
źródło
Można zapisać jeden bajt, zmieniając hMfeTsię smmFd, a następnie przesuwając powielać spoza trójskładnikowej. Ponadto twój bieżący kod to 32 bajty, a nie 33.
isaacg
@isaacg Wow. Nigdy nie pomyślałbym, że ten sprytny golf. Dzięki. I tak, grałem w golfa w ostatniej chwili podczas pisania wyjaśnień i nie aktualizowałem liczby bajtów.
Jakube,
2
Naprawdę interesujące jest zobaczyć odpowiedzi Pyth i CJam, prawie zawsze ta sama liczba bajtów, ale Pyth często pokonuje CJam o kilka
Kametrixom
13

Python 2, 115 112 bajtów

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

Łańcuch w drugim wierszu zawiera pojedynczy niedrukowalny znak \x7d, następny znak po ~.

Wszystkie nadzieje na ładną, pojedynczą lambdę zostają zmiażdżone przez format wejściowy. Prawdopodobnie jest lepszy sposób na odczyt danych wejściowych. Wprowadź jak "51234 ¢ 60003"przez STDIN.

Ta funkcja fłączy dwie następujące funkcje rekurencyjne:

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 bajty za pomocą @xnor)

Sp3000
źródło
1
+1 za pierwszą naprawdę konkurencyjną odpowiedź w języku Python. Zastanawiałem się, dlaczego zawracałeś sobie głowę lambda i nie użyłeś tylko wyrażenia, ale wygląda na to, że jest tam jakaś rekurencja? Nie znam Pythona, czekam na wyjaśnienie.
Level River St
Świetne bicie! Patrzę na kompresowanie wyrażenia stałego terminu. Wyrażenie (a%2*2+b%2)/3**dzapisuje 3 znaki, ale używa uzupełnienia d=1-c. Czy masz jakiś sposób -~(3*c|b%2)na uzupełnienie? W najgorszym wypadku traci 2 znaki 3-3*d. Format and-~x+ymoże być andy-~xtak długi, jak yzaczyna się od symbolu lub liczby.
xnor
@xnor Rozumiem (b%2+5&4-d). Dzięki!
Sp3000,
11

CJam, 31 bajtów

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

Wypróbuj online w interpretatorze CJam .

Jak to działa

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
źródło
8

JavaScript (ES6), 103 117 119 124

Edytuj teraz pracując z liczbami zamiast ciągów

(nie licząc wiodących spacji, nowych linii i komentarzy)

Przetestuj uruchomienie tego fragmentu w dowolnej przeglądarce zgodnej z EcmaScript 6 (w szczególności nie Chrome, a nie MSIE. Testowałem na Firefox, Safari 9 mogłaby działać)

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
źródło
5

Matlab, 119 113 bajtów

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

Nie golfowany:

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

Przykłady:

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

>> f('2345 ~ 7245')
ans =
    37
Luis Mendo
źródło
5

R, 145 bajtów

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

Niegolfowane + wyjaśnienie:

# 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.
źródło
5

Python 3, 174 166 148 126

Całkiem proste operacje na łańcuchach, a następnie konwersja z powrotem na liczbę całkowitą.

Ograniczone do liczb, które w systemie binarnym mają 99 cyfr (maks. 2 ^ 99-1 = 633825300114114700748351602687).

Dzięki, Sp3000 i 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))

Lub 165 znaków bez ograniczeń:

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

Nie golfowany:

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
źródło
2
Możesz używać zfillzamiast rjustwypełniania zerami
Sp3000,
Wejścia maks. Przy 16 bitach, a wyjścia przy 32 bitach. 99 bitów to więcej niż wystarczająco.
isaacg,
Wiem, ale ponieważ „99” zajmuje tyle samo znaków, co „16”, nie ma korzyści z jego ograniczenia.
Trang Oul,
1
Jeszcze kilka: 1) Nie ma potrzeby, aby zapisać a,b, wystarczy umieścić go w zipz *ikoną, 2) (i if j=='1'else'') -> i[:j>'0']3) Można używać to wskazówka , aby zaoszczędzić na drugiejif/else
SP3000
1
Moje rozwiązanie okazało się być zbyt blisko twojego, więc tutaj jest tak krótko, jak mogę dostać twoje (126 bajtów).
Kade,
4

Pyth, 43 bajty

Część mnie czuje się zdenerwowana, publikując tak długą odpowiedź Pyth'a na pytanie Isaacga ...: oP

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

Wyjaśnienie:

                                               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
źródło
4
Uwielbiam twoje zdjęcie profilowe! :)
kirbyfan64sos
2
@ kirbyfan64sos Blue Kirby jest najlepsza Kirby: o)
Sok
3

C, 127 123 bajtów + 5 kar = 128

scanfliczy symbol Unicode jako więcej niż jedną postać, co bardzo komplikuje sytuację, więc stosuję karę 5-bajtową za używanie $.

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

Zmiany w stosunku do oryginalnej wersji to:

- Test na $ lub ~ został zmieniony z q&2na q%7. To odwraca wartości prawda / fałsz, umożliwiając operatorowi $ kod przejście przed znakiem : co oznacza, że ​​zbiór nawiasów można wyeliminować.

-Pętla iodlicza teraz moc 2, która jest dłuższa, ale pozwala >>na zastąpienie /i zapisuje niektóre nawiasy.

Oryginalna wersja 127 bajtów

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

Poszedłem z pojedynczą pętlą z warunkami w środku, aby uniknąć narzutu dwóch pętli. W obu przypadkach przesuwam bity operandów do bitu 1 i buduję wynik od najbardziej znaczącego do najmniej znaczącego bitu, przesuwając w lewo wynik (mnożenie przez 2 lub 4).

Level River St
źródło
Grałem w golfa dla Ciebie: 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);} Próbowałem grać w golfa w części >> i & 1, ale nie mogłem znaleźć opłacalnego sposobu na zrobienie tego. Udało mi się jednak zapisać 1 znak, umieszczając definicje zmiennych w main. Uwaga: niesprawdzone.
LambdaBeta,
@LamdaBeta dzięki, nie mogłem znaleźć makra dla >> i & 1, ale udało mi się zagrać w golfa w inny sposób. Umieszczanie zmiennych jako argumentów mainprzyczyn quszkodzenia na mojej maszynie, co jest dziwne. Oczekuję, że prawdziwy problem jest z tym scanf, ale z tego powodu zostawiłem je jako zwykłe deklaracje.
Level River St
Nie myślałem o tym. Masz rację, q zostanie uszkodzony. Powodem jest to, że podczas gdy dowiadujemy się, że main przyjmuje dwa argumenty, liczbę argumentów wiersza poleceń i tablicę samych argumentów, większość systemów faktycznie dostarcza trzeci argument (zwykle nazywany char * envp []), który opisuje środowisko kod jest uruchamiany (umożliwiając dostęp do zmiennych środowiskowych EG:). Tak więc trzecia wartość w main może być również przypisana do wartości przez system, tym razem scanf jest niewinny.
LambdaBeta,
@steveverill Myślę, że możesz również usunąć karę 5 bajtów. Właśnie przetestowałem twój kod (używając ALT + 155, aby zrobić ¢) i wydaje się, że działa dobrze. :)
LambdaBeta,
@LambdaBeta faktycznie eksperymenty pokazują, że jest to kombinacja obu. Przy normalnej deklaracji qgwarantowane jest zero, ale przy deklaracji jako parametrze funkcji qzawiera śmieci 32-bitowe. Nie stanowiłoby to problemu, gdybym przypisał wartość q, ale scanfz "%c"nadpisaniem tylko najmniej znaczących 8 bitów śmieci, pozostawiając pozostałe 24 niezdefiniowane. Mogę mieć szczęście na innym kompilatorze!
Level River St
3

K5, 53 52 bajty

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

Wersja 53-bajtowa:

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

Nadal potrzebuje trochę więcej gry w golfa.

kirbyfan64sos
źródło
3

CJam, 61 50 46 41 34 bajtów

Dzięki @Dennis za wskazanie 4-bajtowego golfa.

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

Wypróbuj online .

Andrea Biondo
źródło
1
]{}/jest noop.
Dennis,
1
@Dennis Thanks. Powinienem chyba trochę spać ...
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

dane wejściowe są podawane przez zastosowanie danych wejściowych do funkcji / operatorów ? i¢ zdefiniowane w kodzie (Haskell nie może zdefiniować operatora~ z przyczyn technicznych).

w zasadzie działa stare podejście rekurencyjne.

dumny haskeller
źródło
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)))

oczekuje jednego wiersza danych wejściowych

wejście ma się zakończyć po nowej linii z EOF

protist
źródło
2

JavaScript ES6 (3 argumenty) 141 138 136 121 119 bajtów

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

Test:

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

JavaScript ES6 (1 argument) 135 133 bajtów

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

Test:

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

PS: Nowa linia jest liczona jako 1 bajt, ponieważ można ją zastąpić ;.

Qwertiy
źródło
1
0x10000 == 65536 (zapisz 2 znaki)
edc65
@ edc65, zaktualizowałem odpowiedź.
Qwertiy,
2
65536 | x, aby uniknąć ~~
edc65
Dozwolona jest tylko druga wersja - dane wejściowe muszą mieć postać łańcucha rozdzielanego spacjami.
isaacg,
@isaacg, ok. Ale nie chcę usuwać pierwszego z powodów historycznych.
Qwertiy,
2

Python 3, 157 bajtów

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

Pełna i objaśniająca wersja znajduje się na moim pastebin .

Oliver Friedrich
źródło
Możesz zrobić kilka znaków, usuwając spacje wokół operatora „==”, przed „if” i przekazując „base” jako argument pozycyjny.
Trang Oul,
Dziękuję, że i inni zaoszczędzili 15 znaków! ale podwójny sposób formatowania zwrotu jest wciąż zbyt duży.
Oliver Friedrich,
Czy używasz 4 spacji na wcięcie? Wystarczy jedna (lub karta).
Trang Oul,
2
@ BeowulfOF O ile nie określono inaczej, możesz przesłać pełny program lub funkcję. Zasadniczo, która jest krótsza, będzie zależeć od sposobu, w jaki Twój język analizuje konkretne dane wejściowe dla wyzwania (ruby jest zaskakująco niezdarny, na przykład z liczbami ze standardowego wejścia). Istnieją również dwa możliwe sposoby generowania danych wyjściowych: wartość standardowa lub zwracana, które mają zastosowanie do obu (chociaż wartości zwracane z programów są rzadkie).
Level River St
1
Wydaje się, że używasz etylko raz, nie możesz tego po prostu wstawić?
Kevin Brown
0

Mathematica, 155 bajtów

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

Ocenia anonimową funkcję, biorąc ciąg znaków jako dane wejściowe. Dodano podział linii dla zachowania przejrzystości.

fi gkonwersja do / z bazy 2. Rifflerobi dokładnie to, co powinno się przeplatać . Chciałem użyć Selectdo wyboru, ale Casesniestety jest lepiej. Ostatnia linia to trochę oszustwo; spacje są zmieniane, na ~które jest operatorem matematycznym, a następnie ciąg znaków jest ewaluowany.

jcai
źródło