Hoạt động bit không khôn ngoan


16

Tôi thích chơi gôn dc, nhưng đôi khi tôi cảm thấy thất vọng vì dckhông có hoạt động bitwise.

Thử thách

Cung cấp bốn chức năng đặt tên đó thực hiện tương đương với các hoạt động c Bitwise &, |, ~^(bitwise AND, OR, NOT và XOR). Mỗi hàm sẽ lấy hai toán hạng ( ~chỉ mất một) là các số nguyên không dấu 32 bit. Mỗi hàm sẽ trả về một số nguyên không dấu có cùng độ rộng bit như các toán hạng.

Sự hạn chế

Bạn chỉ có thể sử dụng các hoạt động được hỗ trợ bởi dc. Đó là:

  • + - * / Cộng, trừ, nhân và chia số học
  • ~ modulo (hoặc divmod nếu ngôn ngữ của bạn hỗ trợ)
  • ^ lũy thừa
  • | mô đun lũy thừa
  • v căn bậc hai
  • > >= == != <= < toán tử đẳng thức / bất đẳng thức chuẩn
  • >> <<toán tử dịch chuyển bit. dckhông có những thứ này, nhưng vì chúng được thực hiện một cách tầm thường về mặt phân chia / nhân với quyền hạn của 2, nên tôi sẽ cho phép những thứ này.

Các cấu trúc điều khiển trong dctôi được xây dựng một cách vụng về bằng cách sử dụng các macro (đệ quy) và các phép toán bằng (trong). Bạn có thể sử dụng bất kỳ cấu trúc điều khiển tích hợp nào mà ngôn ngữ của bạn có.

Bạn cũng có thể sử dụng các toán tử logic && || ! , mặc dù chúng không có sẵn trực tiếp dc.

Bạn không được sử dụng các toán tử Bitwise & , |, ~^hay bất kỳ chức năng mà trivially thực hiện chúng.

Ngoài ra, bạn không được sử dụng các toán tử hoặc hàm chuyển đổi cơ sở tích hợp sẵn.


Ngoài ra, vui lòng xem xét việc cung cấp chương trình kiểm tra hoặc đoạn trình biên dịch trực tuyến (không bao gồm trong điểm đánh gôn) để giúp xác minh câu trả lời của bạn.


Chúng ta có thể thực hiện một chức năng lấy hoạt động mong muốn làm tham số không? Ngoài ra, chúng ta có thể chia số nguyên cho 2 dưới dạng thay thế cho bit-shift không?
xnor

@xnor Bạn phải cung cấp 4 chức năng công khai thực hiện từng trong số bốn toán tử. Bạn cũng có thể có các phương thức / hàm riêng chung / trợ giúp được gọi bởi cả bốn chức năng công cộng, nhưng tất cả chúng sẽ cần được đưa vào điểm golf.
Chấn thương kỹ thuật số

7
@xnor Bạn và bạn cũng chỉ phải triển khai toán tử xnor ;-)
Chấn thương kỹ thuật số

Tôi có thể tạo một danh sách bốn chức năng ẩn danh không?
xnor

@MariaTidalTug Sự khác biệt hiệu quả giữa việc trả về danh sách bốn hàm và chọn thủ công và áp dụng một (như xnor đề xuất) so với việc có một hàm chấp nhận tham số lựa chọn và tự thực hiện lựa chọn (như wolfhammer đã trả lời)? Cả hai dường như làm suy yếu tương tự điểm có bốn hàm được đặt tên, khi chúng giảm kích thước mã lên mã người dùng. Tôi thậm chí còn lập luận rằng cái trước làm suy yếu nó nhiều hơn, vì mã người dùng có thể phức tạp hơn trong trường hợp đó so với trường hợp sau.
Runer112

Câu trả lời:


4

C, 134

Bộ tiền xử lý C khá thú vị khi lạm dụng. Về cơ bản macro này xác định 3 chức năng, a, o, và x, cho and, orxortương ứng. Sự khác biệt duy nhất trong thuật toán cho các hoạt động này là các tiêu chí để thiết lập bit trong kết quả.

notlà chức năng n.

#define f(n,c)n(a,b){for(r=0,i=31;i+1;--i)if(((a>>i)%2+(b>>i)%2)c)r+=1<<i;return r;}
i,r;n(a){return 0xffffffff-a;}f(a,/2)f(o,)f(x,%2)

Chương trình thử nghiệm (mất nhiều thời gian, tôi không dành chút thời gian nào để tối ưu hóa nó, nhưng nó kiểm tra mọi trường hợp thử nghiệm có thể, bên cạnh các trường hợp liên quan đến MAX_INT):

#define m_assert(expected, condition, actual)\
    if(!((expected) condition (actual)))\
        printf("assert fail @ line %i, expected: %x, actual %x, condition "#condition"\n", __LINE__, expected, actual);

int main()  {
    unsigned int j,k;
    for(j=0; j<0xffff; ++j)    {
        m_assert(~j, ==, n(j));
        for(k=0; k<0xffff; ++k)    {
            m_assert(j & k, ==, a(j,k));
            m_assert(j | k, ==, o(j,k));
            m_assert(j ^ k, ==, x(j,k));
        }
    }

1
Giáo sư. quên mất điều đó Đã sửa nó ngay.
bút danh 117

4

được 76 byte

ised cũng không có hoạt động bitwise - thường gây phiền nhiễu, nhưng bây giờ được chào đón, bởi vì chúng tôi thực sự cần phải thực hiện chúng.

Các chức năng sẽ được lưu trữ trong các khe nhớ được đánh số (không có tên dài dòng).

Chuyển đổi sang và từ nhị phân:

@5{:x/2^[32]%2:};
@6{:x@:2^[32]:};

KHÔNG có thể @1{:$6::{1-$5::x}:}nhưng rõ ràng là dễ dàng hơn để chỉ trừ:

@1{:2^32-x-1:};

HOẶC LÀ:

@2{:$6::{$5::{x_0}:+$5::{x_1}>0}:};

VÀ:

@3{:$6::{$5::{x_0}:*$5::{x_1}}:};

XOR:

@4{:$6::{$5::{x_0}:<>$5::{x_1}}:};

Điều này sẽ đưa chúng ta tới 156 byte (với dòng mới và dấu chấm phẩy). Mã kiểm tra sẽ chỉ là (KHÔNG, HOẶC, VÀ, XOR liên tiếp, được tìm thấy dưới các tên $ 1, $ 2, $ 3, $ 4):

> $1::{6}
4294967289
> $2::{12 11}
15
> $3::{12 11}
8
> $4::{12 11}
7

Nhưng tất nhiên HOẶC và KHÔNG là tất cả những gì chúng ta thực sự cần và mọi thứ có thể được đơn giản hóa:

@1{:2^32-x-1:};
@2{:@+{2^U{?{$5::x}%32}}:};
@3{:${1 2 1}::x:};
@4{:$3::{$2::x${1 2}::x}:};
@5{:x/2^[32]%2:};

Đó là 109 ký tự. Khi dòng mới và dấu chấm phẩy bị bỏ qua, và với việc chơi gôn nhiều hơn một chút, chúng ta có 76 ký tự:

@3{@1{:2^32-x-1:}@2{:@+{2^U{?{x/2^[32]%2}%32}}:}$1}@4{{:$2::x${1 2}::x:}$3};

1

Nim (537) (490)

Trình biên dịch Nim 0.10.2

Tôi đã tìm kiếm một lý do để học nim vì vậy chúng tôi đi đây.

Đối với mã golf, tôi đã tận dụng các tham số biến và trả về ẩn. Các tham số biến, theo tài liệu là ít hiệu quả ngăn xếp. Cá nhân, tôi thấy lợi nhuận ngầm khó đọc hơn và có lẽ sẽ chỉ sử dụng chúng trong các thủ tục tầm thường.

Đối với các thuật toán, chúng là đủ đơn giản. Đối với tất cả các hoạt động ngoại trừ KHÔNG, chúng tôi so sánh từng bit và so sánh chúng với bảng chân lý dự kiến ​​của chúng tôi. Đặt từng bit khi cần trên đường đi trong biến đầu ra của chúng tôi. Trong Nim, kết quả là giá trị trả về ngầm định.

Tôi không chắc chắn liệu chúng tôi có được phép sử dụng OR và AND tích hợp để xác nhận hai điều kiện boolean hay không để quy trình notZero được đặt vào vị trí của chúng.

proc s(x, y, b: var int)=
  x = x div 2
  y = y div 2
  b *= 2

proc n(x: var int): int =
  return -(x+1)

proc a(x, y: var int): int =
  var b = 1
  while x > 0 and y > 0:
    if (x mod 2  + y mod 2) == 2:
      result += b

    s(x,y,b)

proc o(x, y: var int): int =
  var b = 1
  while x + y > 0:
    if (x mod 2 + y mod 2) >= 1:
      result += b

    s(x,y,b)

proc r(x, y: var int): int =
  var b = 1
  while x + y > 0:
    if (x mod 2 + y mod 2) == 1:
      result += b

    s(x,y,b)

Vẫn đang tìm kiếm một phương pháp tốt hơn ...

Đây là phiên bản không squished cộng với khai thác thử nghiệm đầy đủ để chạy trên máy của riêng bạn.
Nếu bạn chỉ muốn chạy một vài đầu vào, đây là test case lite .


@MariaTidalTug cảm ơn đã làm rõ!
cory.todd

Tôi không thể tái tạo điều đó. Là máy tính của bạn ở chế độ cơ sở 16?
cory.todd

Tôi đã thêm một khai thác thử nghiệm tương tự như bút danh 117.
cory.todd

1

CJam, 71 byte

{:F;0{:R;2md@2md@+F~!2I#*R+}64fI\;\;}:B{"2-"B}:A{'!B}:O{0SB}:N{'(B}:X];

Giải trình

"B : UInt64 UInt64 String -> UInt64
 Computes a bitwise operation on the two given unsigned integers. The operation
 is defined by the logical inverse of the result of evaluating the given string
 given the sum of two input bits.";
{
  :F;             "Save the operation string.";
  0               "Initialize the result to 0.";
  {               "For I from 0 through 63:";
    :R;             "Save the result.";
    2md@2md@        "Divide each input by 2 and collect the remainders as the
                     next pair of bits to process.";
    +F~!            "Compute the logical inverse of the result of evaluating
                     the operation string given the sum of the two bits.";
    2I#*            "Adjust the resulting bit to be in the correct output
                     position by multiplying it by 2^I.";
    R+              "Add the location-adjusted bit to the result.";
  }64fI
  \;\;            "Clean up.";
}:B

"A : UInt64 UInt64 -> UInt64
 Computes the bitwise AND of the two given unsigned integers.
 This is done by passing the inputs along to B with an operation such that:
   bit_out = !((bit_in_1 + bit_in_2) - 2)";
{"2-"B}:A

"O : UInt64 UInt64 -> UInt64
 Computes the bitwise OR of the two given unsigned integers.
 This is done by passing the inputs along to B with an operation such that:
   bit_out = !(!(bit_in_1 + bit_in_2))";
{'!B}:O

"N : UInt64 -> UInt64
 Computes the bitwise NOT of the given unsigned integer.
 This is done by passing the input and 0 along to B with an operation such that:
   bit_out = !((bit_in + 0))";
{0SB}:N

"X : UInt64 UInt64 -> UInt64
 Computes the bitwise XOR of the two given unsigned integers.
 This is done by passing the inputs along to B with an operation such that:
   bit_out = !((bit_in_1 + bit_in_2) - 1)";
{'(B}:X

];              "Clean up.";

Bộ kiểm tra

Mã này kiểm tra chạy từng hàm của tôi và, hoặc, không, và xor 100 lần với các đầu vào không dấu 64 bit được phân phối đồng đều và so sánh kết quả với kết quả do toán tử tích hợp tạo ra. Do sử dụng miễn phí của nhà điều hành eval, nó khá chậm và có thể mất khoảng một phút với trình thông dịch trực tuyến. Nhưng nếu mọi việc suôn sẻ, việc thực thi sẽ kết thúc mà không có đầu ra, bởi vì bất kỳ sự khác biệt nào được tìm thấy đều được in.

N:L;
{:F;0{:R;2md@2md@+F~!2I#*R+}64fI\;\;}:B{"2-"B}:A{'!B}:O{0SB}:N{'(B}:X];
{;Y32#__mr*\mr+}2e2%2/{~:U;:V;"A&O|X^"2/{[{US@SV" = "UV5$~L}/9$2$={];}{]oLo}?}/"N~"[{U" = "U3$~Y64#(&L}/6$2$={];}{]oLo}?}/

0

JavaScript 294 267

Đã có thể tắt thêm một vài byte với các đề xuất của @ AlexA. và @ kennytm.

Chức năng:

B=(n,m,t)=>{for(var p=4294967296,y=0;p>=1;p/=2)y+=t=='x'&&(n>=p||m>=p)&& !(n>=p&&m>=p)?p:0,y+=t=='a'&&n>=p&&m>=p?p:0,y+=t=='o'&&(n>=p||m>=p)?p:0,n-=n>=p?p:0,m-=m>=p?p:0
return y}
N=(n)=>{return 4294967295-n}
A=(n,m)=>B(n,m,'a')
O=(n,m)=>B(n,m,'o')
X=(n,m)=>B(n,m,'x')

thí dụ:

var n = 300;
var m = 256;
console.log(X(n,m) + ", " + (n ^ m));
console.log(O(n,m) + ", " + (n | m));
console.log(A(n,m) + ", " + (n & m));
console.log(N(n) + ", " + (~n>>>0));
console.log(N(m) + ", " + (~m>>>0));

đầu ra:

44, 44
300, 300
256, 256
4294966995, 4294966995
4294967039, 4294967039

2
Bạn cần cung cấp bốn hàm công khai - mỗi hàm cho AND, OR. KHÔNG và XOR. (Bạn cũng có thể có các phương thức / hàm riêng chung / trợ giúp được gọi bởi cả bốn hàm công khai). Ngoài ra, bạn đang bỏ lỡ KHÔNG - có lẽ là dễ nhất trong số những việc phải làm
Chấn thương kỹ thuật số

Cảm ơn @AlexA. Tôi đã thêm các byte và đánh gôn thêm một số.
wolfhammer

Bạn có thể mất không gian sau forvà thay thế function B(n,m,t)bằng B=(n,m,t)=>. Tương tự như vậy cho các chức năng khác.
Alex A.

Bạn có thể sử dụng 4*(1<<30)cho 4294967296 và -1>>>0cho 4294967295. có varthực sự cần thiết ở đây không? Bạn có thể viết (n,m)=>B(n,m,'a')thay vì(n,m)=>{return B(n,m,'a')}
kennytm
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.