Triển khai các nhà khai thác nhị phân của INTERCAL


29

Ngôn ngữ trình biên dịch không có từ viết tắt có thể phát âm được, viết tắt INTERCAL , là một ngôn ngữ lập trình rất độc đáo. Trong số các phẩm chất không thể đạt được của nó là các toán tử nhị phân của nó.

Hai toán tử nhị phân của INTERCAL là xen kẽ (còn được gọi là mingle ) và chọn . Interleave được biểu diễn bằng một thay đổi (¢) và select được biểu diễn bằng một hình vuông (~).

Xen kẽ hoạt động bằng cách lấy hai số trong phạm vi 0-65535 và xen kẽ các bit của chúng. Ví dụ:

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

Chọn hoạt động bằng cách lấy hai số trong phạm vi 0-65535, lấy các bit trong toán hạng đầu tiên ở cùng vị trí với 1 số trong toán hạng thứ hai và đóng gói đúng các bit đó.

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

Trong thử thách này, bạn sẽ được cung cấp một biểu thức nhị phân bằng cách sử dụng thao tác xen kẽ hoặc chọn. Bạn phải tính toán kết quả, sử dụng ít byte nhất có thể.

Biểu thức sẽ được cung cấp dưới dạng một chuỗi phân tách không gian, bao gồm một số nguyên trong 0-65535, một khoảng trắng, ¢hoặc ~, một khoảng trắng và một số nguyên trong 0-65535.

Đầu vào và đầu ra có thể thông qua bất kỳ hệ thống tiêu chuẩn nào (STDIN, chức năng, dòng lệnh, v.v.). Sơ hở tiêu chuẩn bị cấm.

Ví dụ:

5 ¢ 6
54

5 ~ 6
2

51234 ¢ 60003
4106492941

51234 ~ 60003
422

Đây là mã golf - ít byte nhất thắng. Chúc may mắn.

EDIT: Vì một số ngôn ngữ không hỗ trợ biểu tượng thay đổi (¢) của INTERCAL, bạn có thể sử dụng biểu tượng số tiền lớn ($) thay vào đó, với hình phạt 5 byte.


10
Đó là một chút nghiêm khắc phạt người dân vì sử dụng đồng đô la. Đó là điều không thể giúp đỡ.
Beta Decay

9
Tôi mới nhận ra rằng CLWNPA hoàn toàn có thể phát âm được bằng tiếng Wales. Chữ W được phát âm là U trong tiếng Tây Ban Nha hoặc OO trong tiếng Anh.
Cấp sông St

9
Tôi không nhận được hình phạt 5 byte. C-INTERCAL sử dụng $.
kirbyfan64sos

13
Tất cả những gì bạn đang tranh luận về? Một đô la rõ ràng là đắt hơn một. Cái gì, bạn muốn 99 không có gì?
Tối đa

6
Tôi không nghĩ INTERCAL sẽ cho phép bạn nhập số với số thập phân. Bạn không phải viết FIVE ONE TWO THREE FOUR? Và không nên đầu ra bằng chữ số La Mã?
Nate Eldredge

Câu trả lời:


9

Bình thường, 32 31 29 byte

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

Dùng thử trực tuyến: Bộ kiểm tra đầu vào / kiểm tra thường xuyên

Cảm ơn @isaacg vì đã chơi golf một byte.

Giải trình:

                         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

Bạn có thể tiết kiệm một byte bằng cách thay đổi hMfeTđể smmFdvà sau đó di chuyển trùng lặp sngoài ternary. Ngoài ra, mã hiện tại của bạn là 32 byte, không phải 33.
isaacg

@isaacg Wow. Tôi sẽ không bao giờ nghĩ rằng golf thông minh. Cảm ơn. Và vâng, đã chơi golf vào phút cuối trong khi viết lời giải thích và không cập nhật số byte.
Jakube

2
Thật thú vị khi thấy câu trả lời của Pyth và CJam, hầu như luôn luôn có cùng số byte, nhưng Pyth thường đánh bại CJam một vài
Kametrixom

13

Python 2, 115 112 byte

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

Chuỗi trên dòng thứ hai chứa một ký tự không thể in được \x7d, ký tự tiếp theo sau ~.

Tất cả hy vọng về một lambda đơn, đẹp sẽ bị nghiền nát bởi định dạng đầu vào. Có lẽ có một cách tốt hơn để đọc đầu vào. Nhập như "51234 ¢ 60003"qua STDIN.

Hàm fkết hợp hai hàm đệ quy sau:

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 byte với sự trợ giúp của @xnor)


1
+1 cho câu trả lời Python thực sự cạnh tranh đầu tiên. Tôi đã tự hỏi tại sao bạn lại bận tâm với lambda và không chỉ sử dụng một biểu thức, nhưng có vẻ như có một số đệ quy trong đó? Tôi không biết Python, tôi mong được giải thích.
Cấp sông St

Một số bashing tuyệt vời! Tôi đang xem xét nén biểu thức thuật ngữ không đổi. Biểu thức (a%2*2+b%2)/3**dlưu 3 ký tự nhưng sử dụng phần bù d=1-c. Bạn có một cách để làm -~(3*c|b%2)với bổ sung? Tệ nhất là mất 2 ký tự với 3-3*d. Ngoài ra, định dạng and-~x+ycó thể andy-~xmiễn là ybắt đầu bằng ký hiệu hoặc số.
xnor

@xnor Đã hiểu rồi (b%2+5&4-d). Cảm ơn!
Sp3000

11

CJam, 31 byte

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

Hãy thử trực tuyến trong trình thông dịch CJam .

Làm thế nào nó hoạt động

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

Chỉnh sửa ngay bây giờ làm việc với số thay vì chuỗi

(không tính không gian hàng đầu, dòng mới và ý kiến)

Thử nghiệm chạy đoạn mã trên bất kỳ trình duyệt tuân thủ EcmaScript 6 nào (đáng chú ý không phải Chrome không phải MSIE. Tôi đã thử nghiệm trên Firefox, Safari 9 có thể đi)

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

Matlab, 119 113 byte

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

Ung dung:

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

Ví dụ:

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

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

5

R, 145 byte

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 + giải thích:

# 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

Trăn 3, 174 166 148 126

Khá đơn giản, hoạt động chuỗi, sau đó chuyển đổi trở lại số nguyên.

Giới hạn ở các số trong nhị phân có 99 chữ số (tối đa 2 ^ 99-1 = 633825300114114700748351602687).

Cảm ơn, Sp3000 và 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))

Hoặc 165 ký tự, không giới hạn:

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

Ung dung:

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
Bạn có thể sử dụng zfillthay vì rjustđể đệm bằng số không
Sp3000

Đầu vào tối đa ở mức 16 bit và đầu ra ở mức 32 bit. 99 bit là quá đủ.
isaacg

Tôi biết, nhưng vì '99' có nhiều ký tự như '16', nên không có lợi ích gì trong việc giới hạn nó.
Trang Oul

1
Một vài điều nữa: 1) Bạn không cần phải lưu a,b, chỉ cần đặt nó vào trong zipvới một *splat, 2) (i if j=='1'else'') -> i[:j>'0']3) Bạn có thể sử dụng mẹo này để lưu vào cái khácif/else
Sp3000

1
Giải pháp của tôi cuối cùng đã quá gần với bạn, vì vậy đây là ngắn nhất tôi có thể nhận được của bạn (126 byte).
Kade

4

Bình thường, 43 byte

Một phần trong tôi cảm thấy lo lắng khi đăng câu trả lời dài như vậy vào câu hỏi của isaacg ...: oP

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

Giải thích:

                                               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
Tôi thích hình Hồ sơ cá nhân của bạn! :)
kirbyfan64sos

2
@ kirbyfan64sos Kirby màu xanh là tốt nhất Kirby: o)
Sok

3

C, 127 123 byte + 5 hình phạt = 128

scanfđếm biểu tượng unicode có nhiều hơn một ký tự làm phức tạp mọi thứ, vì vậy tôi đang áp dụng hình phạt 5 byte khi sử dụng $.

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

Những thay đổi từ phiên bản gốc là:

-Kiểm tra $ hoặc ~ đã được sửa đổi từ q&2thành q%7. Điều này đảo ngược các giá trị đúng / sai, cho phép mã cho toán tử $ đi trước :điều đó có nghĩa là có thể loại bỏ một dấu ngoặc đơn.

-Bộ ivòng hiện đếm ngược với quyền hạn 2 dài hơn, nhưng cho phép >>được thay thế bằng /và lưu một số dấu ngoặc đơn.

Phiên bản gốc 127 byte

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

Tôi đã đi với một vòng lặp duy nhất với các điều kiện bên trong để tránh chi phí của hai vòng. Trong cả hai trường hợp, tôi chuyển các bit của toán hạng xuống bit 1 và xây dựng kết quả từ bit có ý nghĩa nhất đến ít quan trọng nhất, làm thay đổi kết quả (nhân với 2 hoặc 4) khi tôi đi.


Tôi đã đánh gôn cho bạn: 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);} Tôi đã thử chơi gôn >> i & 1 phần, nhưng không thể tìm ra cách hiệu quả về mặt chi phí. Tôi đã có thể lưu 1 ký tự tuy nhiên bằng cách đặt các định nghĩa biến trong chính. Lưu ý: chưa được kiểm tra.
LambdaBeta

@LamdaBeta cảm ơn, tôi không thể tìm thấy macro cho >> i & 1 nhưng tôi đã xoay sở để chơi nó theo cách khác. Đặt các biến làm đối số của mainnguyên nhânq bị hỏng trên máy của tôi, điều này thật lạ. Tôi hy vọng vấn đề thực sự là với scanf, nhưng vì điều đó tôi đã để chúng như những tuyên bố bình thường.
Cấp sông St

Tôi đã không nghĩ về điều đó. Bạn nói đúng, q sẽ bị hỏng. Lý do là trong khi chúng ta biết rằng main có hai đối số, số lượng đối số dòng lệnh và một mảng các đối số, hầu hết các hệ thống thực sự cung cấp một đối số thứ ba (thường được gọi là char * envp []) mô tả môi trường mã được chạy trong (cấp quyền truy cập vào EG: biến môi trường). Do đó, giá trị thứ ba trong chính cũng có thể được hệ thống gán cho một giá trị, lần này scanf là vô tội.
LambdaBeta

@steveverill Tôi nghĩ bạn cũng có thể xóa hình phạt 5 byte. Tôi vừa kiểm tra mã của bạn (sử dụng ALT + 155 để tạo) và nó có vẻ hoạt động tốt. :)
LambdaBeta

@LambdaBeta thử nghiệm thực sự cho thấy nó là sự kết hợp của cả hai. Với khai báo bình thường qđược đảm bảo bằng 0, nhưng với khai báo là tham số qhàm chứa rác 32 bit. Điều đó sẽ không phải là một vấn đề nếu tôi giao một giá trị cho q, nhưng scanfvới "%c"chỉ ghi đè 8 bit thiểu đáng kể rác, để lại 24 khác không xác định. Tôi có thể gặp may mắn trên một trình biên dịch khác!
Cấp sông St

3

K5, 53 52 byte

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

Phiên bản 53 byte:

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

Vẫn cần thêm một chút chơi golf.



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

đầu vào được đưa ra bằng cách áp dụng đầu vào cho các hàm / toán tử ?¢được xác định trong mã (Haskell không thể xác định toán tử ~vì lý do kỹ thuật).

về cơ bản hoạt động cách tiếp cận đệ quy cũ.


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

mong đợi một dòng đầu vào

đầu vào dự kiến ​​sẽ chấm dứt sau dòng mới với EOF


2

Javascript ES6 (3 đối số) 141 138 136 121 119 byte

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

Kiểm tra:

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

Javascript ES6 (1 đối số) 135 133 byte

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

Kiểm tra:

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

PS: Dòng mới được tính là 1 byte vì nó có thể được thay thế bằng ;.


1
0x10000 == 65536 (lưu 2 ký tự)
edc65

@ edc65, tôi đã cập nhật câu trả lời.
Qwertiy

2
65536 | x để tránh ~ ~
edc65

Chỉ cho phép phiên bản thứ hai - đầu vào phải ở dạng chuỗi phân tách không gian.
isaacg

@isaacg, ok. Nhưng tôi không muốn xóa cái đầu tiên vì lý do lịch sử.
Qwertiy

2

Python 3, 157 byte

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

Phiên bản đầy đủ và giải thích có thể được tìm thấy trên pastebin của tôi .


Bạn có thể cùng một vài ký tự bằng cách xóa khoảng trắng xung quanh toán tử '==', trước 'if' và bằng cách chuyển 'cơ sở' làm đối số vị trí.
Trang Oul

Cảm ơn bạn, điều đó và một số người khác đã lưu 15 ký tự! nhưng cách nhân đôi định dạng thì lợi nhuận vẫn còn nhiều.
Oliver Friedrich

Ngoài ra, bạn có sử dụng 4 không gian cho mỗi lần thụt lề? Một (hoặc tab) là đủ.
Trang Oul

2
@BeowulfOF Trừ khi có quy định khác, bạn có thể gửi một chương trình đầy đủ hoặc một chức năng. Nói chung, ngắn hơn sẽ phụ thuộc vào cách ngôn ngữ của bạn phân tích cú pháp đầu vào cụ thể cho thử thách (ví dụ như ruby ​​vụng về với những con số từ stdin chẳng hạn). Bạn cũng có hai cách có thể để xuất: giá trị xuất chuẩn hoặc giá trị trả về, áp dụng cho cả hai (mặc dù giá trị trả về từ các chương trình rất hiếm.)
Level River St

1
Bạn chỉ xuất hiện để sử dụng emột lần, bạn có thể chỉ nội tuyến không?
Kevin Brown

0

Toán học, 155 byte

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

Đánh giá một hàm ẩn danh lấy chuỗi làm đầu vào. Ngắt dòng thêm cho rõ ràng.

fgchuyển đổi sang / từ cơ sở 2. Rifflethực hiện chính xác những gì được xen kẽ . Tôi muốn sử dụng Selectđể chọn nhưng Casestốt hơn là không may. Dòng cuối cùng là một chút mánh khóe; các không gian được thay đổi thành ~toán tử infix của Mathicala, sau đó chuỗi là eval'd.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.