Mượn bit-bit


20

Bạn có biết rằng một số nhỏ có thể mượn bit từ một số lớn hơn không? Đây là một ví dụ. Giả sử hai số 5 và 14. Đầu tiên, viết chúng ra dưới dạng nhị phân:

5       14
000101  001110

Đầu tiên chúng ta hãy nhỏ nhất trên chút xa số lượng lớn hơn, và chúng tôi đưa nó cho nhỏ đi chút vào số khác. Vì thế

This bit turns off
            |
            v
000101  001110
    ^
    |
This bit turns on

Bây giờ chúng tôi có

000111  001100

và số của chúng tôi là 7 và 12. Số đầu tiên vẫn nhỏ hơn, vì vậy chúng tôi tiếp tục.

000111  001100
001111  001000

Bây giờ chúng tôi có 15 và 8, vì vậy chúng tôi có thể dừng lại. Chúng tôi sẽ gọi tập hợp hoạt động này là "vay mượn bit" hai số. Hãy làm một ví dụ khác. 20 và 61.

20        61
010100    111101
010101    111100
010111    111000
111111    100000
63        32

Vì vậy, kết quả cuối cùng của chúng tôi là 32, 63. Hãy làm thêm một lần nữa. 31 và 12. 31 đã lớn hơn 12, vì vậy không có gì để làm! Vay bit 31 và 12 cho 31 và 12, không thay đổi.

Các thách thức

Thử thách của bạn là viết một chương trình hoặc hàm lấy hai số và mượn chúng. Hai số sẽ luôn luôn là số nguyên dương. Đầu vào và đầu ra của bạn có thể ở bất kỳ định dạng hợp lý.

Kiểm tra IO:

Input: 2, 3
Output: 3, 2

Input: 3, 2
Output: 3, 2

Input: 8, 23
Output: 31, 0

Input: 42, 81
Output: 63, 0

Input: 38, 41
Output: 47, 32

Input: 16, 73
Output: 23, 0

Input: 17, 17
Output: 17, 17

Áp dụng sơ hở tiêu chuẩn và câu trả lời ngắn nhất tính bằng byte!

Câu trả lời:


12

Thạch , 11 byte

~1¦&N$^µ</¿

Hãy thử trực tuyến! hoặc xác minh tất cả các trường hợp thử nghiệm .

Lý lịch

Chúng ta có thể trích xuất bit thiết lập cuối cùng của một số nguyên n như sau.

n + 1 bật tắt tất cả các bit seting của n và bit unset liền kề. Ví dụ: 10011 2 + 1 = 10100 2 .

~ n = - (n + 1) = -n - 1 , -n = ~ n + 1 , vì vậy -n áp dụng cách trên cho bitwise KHÔNG của n (làm tắt tất cả các bit), do đó chuyển đổi tất cả các bit trước lần cuối 1 .

Ví dụ: -10100 2 = ~ 10100 2 + 1 = 01011 2 + 1 = 01100 2 .

Bằng cách lấy n & -n bitwise AND của n-n tất cả các bit trước bit set cuối cùng bị vô hiệu hóa (vì không bằng nhau trong n-n ), do đó thu được bit set cuối của n .

Ví dụ: 10100 2 & -10100 2 = 10100 2 & 01100 2 = 00100 2 .

Do đó, XORing n với n & -n bỏ cài đặt bit cuối cùng của n .

Ngược lại, để bỏ tập bit cuối cùng của n , nó đủ để áp dụng cách trên cho ~ n , từ đó chúng ta rút ra công thức n ^ (~ n & - ~ n) .

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

~1¦&N$^µ</¿  Main link. Argument: A (list of pairs)

          ¿  While loop:
        </     Condition: Reduce p by less-than. True iff x < y.
       µ       Body chain:
~1¦              Apply bitwise NOT to the x, first item of the pair.
     $           Convert the two links to the left into a monadic chain.
    N              Negate; multiply [~x, y] by -1, yielding [-~x, -y].
   &               Logical AND. Yields [-~x & ~x, -y & y].
      ^            Vectorized XOR with p. Yields [(-~x & ~x) ^ x, (-y & y) ^ y].

6

J, 31 26 byte

,`(($:~(OR>:))~(AND<:))@.<

Phương pháp tiếp cận thẳng bằng cách sử dụng đệ quy và thủ thuật bitwise. Để tắt (đặt thành 0 ), hầu hết phải ( bit 1 ) cho giá trị n , bạn có thể thực hiện theo chiều bit - và giữa nn -1, và bật (đặt thành 1 ) bên phải nhất tắt ( 0 ) bit cho một giá trị n , bạn có thể thực hiện bitwise - hoặc giữa nn +1.

Sử dụng

Đầu vào bao gồm hai số nguyên, một số nguyên được áp dụng trên LHS và số còn lại trên RHS và đầu ra là danh sách các giá trị được vay bit.

   f =: ,`(($:~(OR>:))~(AND<:))@.<
   2 f 3
3 2
   3 f 2
3 2
   8 f 23
31 0
   42 f 81
63 0
   38 f 41
47 32
   16 f 73
23 0
   17 f 17
17 17

Giải trình

,`(($:~(OR>:))~(AND<:))@.<  Input: x on LHS, y on RHS
                            If x < y,
,                             Form a 2-element array [x, y] and return
                            Else
                   <:         Decrement y
                AND           Perform bitwise-and on y and y-1, call it y'
          >:                  Increment x
        OR                    Perform bitwise-or on x and x+1, call it x'
    $:                        Call recursively on x' and y' and return

Câu trả lời tốt đẹp! Xin lỗi để thay đổi thử thách sau khi bạn đăng câu trả lời, nhưng tôi đã đơn giản hóa thử thách một chút. (bạn không cần phải lặp lại danh sách nữa). Điều đó sẽ cho phép bạn rút ngắn nó thêm một chút nữa.
DJMcMayhem

@DrGreenEggsandIronMan J thực sự đang áp dụng yếu tố chức năng khôn ngoan giữa hai mảng mà không có bất kỳ xếp hạng rõ ràng nào, điều này thật tuyệt. Trừ khi có một mẹo khác, nó có thể sẽ giữ nguyên.
dặm

4

Python, 42 byte

f=lambda x,y:x<y and f(x|x+1,y&y-1)or(x,y)

Cảm ơn @ jimmy23013 vì đã chơi golf 4 byte! Cảm ơn @LeakyNun vì đã chơi golf 2 byte!

Kiểm tra nó trên Ideone .


3

Toán học, 46 byte

If[#<#2,BitOr[#,#+1]~#0~BitAnd[#2,#2-1],{##}]&

Phương pháp tương tự như được sử dụng trong của tôi giải pháp trong J.

Nhờ vào @ Martin đã lưu 1 byte và nhắc nhở tôi về ứng dụng infix ~.

Sử dụng

Đầu vào bao gồm hai đối số nguyên và đầu ra là một danh sách với các giá trị được mượn bit.

Thí dụ


Nghĩ rằng tôi sẽ thử một cái gì đó buồn cười, nhưng tiếc là nó dài hơn một byte: #//.{x_,y_}/;x<y:>{BitOr[x,x+1],BitAnd[y,y-1]}&(có lẽ bạn có ý tưởng làm thế nào để rút ngắn nó)
Martin Ender

Đó là một quy tắc gọn gàng, nhưng tôi không rành lắm về các quy tắc chơi gôn. Tôi thường chỉ sử dụng thay thế /.và điều kiện /;. Wish Mathicala có thể chuyển đổi giữa boolean và bitwise bằng cách kiểm tra các loại đối số &&và như vậy.
dặm

3

Bình, 29 27 25 22 21 20 19 18 16 byte

MxG ^ 2x _ + \ 0.BG`HCm.W <FHgVZU2dC 
MxG ^ 2x_ + 0jG2HCm.W <FHgVZU2dC 
Cm.W <FH.bxN ^ 2x_ + 0jN2YZ2dC 
m.W <FH.bxN ^ 2x_ + 0jN2YZ2       <- thay đổi đầu vào / đầu ra định dạng
 mW <FH.exb ^ 2x_ + 0jb2kZ 
m.W <FH.U, | bhb. & ZtZZ 
.W <FH.U, | bhb. & ZtZZ          <- đã thay đổi định dạng đầu vào / đầu ra
 .W <FH.U, | bhb. & ZtZ
.W <FH.U, | bhb. & T

Bộ thử nghiệm.


Xin lỗi để thay đổi thử thách sau khi bạn đăng câu trả lời, nhưng tôi đã đơn giản hóa thử thách một chút. (bạn không cần phải lặp lại danh sách nữa). Mặc dù rất may điều đó sẽ cho phép bạn rút ngắn nó.
DJMcMayhem

@DrGreenEggsandIronMan Nó chỉ lưu một byte. Pyth hiệu quả.
Rò rỉ Nun


2

Mê cung , 37 34 byte

?"
}
|=:{:
)   }
: :;-{
=&( {!;\!@

Hãy thử trực tuyến!

Giải trình

Labyrinth mồi nhanh:

  • Labyrinth hoạt động trên hai ngăn xếp các số nguyên chính xác tùy ý, chínhphụ , ban đầu chứa đầy một số lượng vô hạn (ẩn).
  • Mã nguồn giống như một mê cung, trong đó con trỏ lệnh (IP) theo các hành lang. Tất cả các luồng điều khiển thú vị xảy ra tại các điểm nối: khi IP có nhiều hơn một ô để đi đến, đỉnh của ngăn xếp chính được kiểm tra. Nếu giá trị âm, IP sẽ rẽ trái, nếu nó dương, IP sẽ rẽ phải và nếu không, nó sẽ di chuyển thẳng về phía trước. Nếu hướng đã chọn bị chặn bởi tường (tức là khoảng trắng), IP sẽ di chuyển theo hướng ngược lại.

Chương trình sử dụng thuật toán tương tự như các câu trả lời khác: chúng tôi thay thế (a, b)bằng (a | a+1, b & b-1)miễn là a < b. Tôi sẽ thêm một lời giải thích đầy đủ sau khi tôi đã thử chơi golf thêm một số.

IP bắt đầu ở góc trên cùng bên trái, đi bên phải. ?đọc một số nguyên a. Sau đó "là không hoạt động, nhưng cần phải ngăn IP di chuyển xuống ngay lập tức. Đây cũng là một ngõ cụt, vì vậy IP quay lại và thực hiện ?lại để đọc b. }sau đó di chuyển btừ chính để AUX , vì vậy bây giờ chúng tôi đã có:

Main [ ... 0 a | b 0 ...] Aux

Sau |đó không làm gì cả, bởi vì nó mất bit OR của a0. Vì chúng tôi biết aluôn luôn tích cực, IP quay về hướng đông (vì nó không thể quay về hướng tây). Điều này bắt đầu vòng lặp chính của chương trình. Chúng tôi bắt đầu với một phần tuyến tính ngắn để so sánh ab:

=   Swap tops of stacks, i.e. swap a and b.
:   Duplicate b.
{   Pull a over to main.
:   Duplicate a.
}   Push one copy back to aux.
-   Compute b-a.

IP hiện đang ở một ngã ba khác. Đầu tiên, hãy xem xét trường hợp kết quả là dương tính. Điều đó có nghĩa b > avà chúng ta cần thực hiện thêm một lần lặp. Lặp đi lặp lại đó cũng hoàn toàn tuyến tính. Lưu ý rằng các ngăn xếp hiện đang:

Main [ ... 0 b (b-a) | a 0 ...] Aux

;   Discard b-a.
:   Duplicate b.
(   Decrement.
&   Bitwise AND with b, clearing the least-significant 1.
=   Swap new b with old a.
:   Duplicate a.
)   Increment.
|   Bitwise OR with a, setting the least-significant 0.

Và sau đó chúng tôi trở lại điểm bắt đầu của vòng lặp (vì amột lần nữa là dương, IP lại quay về hướng đông).

Nếu tại một thời điểm nào đó b-akhông còn tích cực, IP sẽ đi theo một trong hai đường dẫn khác. Lưu ý rằng trong cả hai trường hợp chúng tôi lấy avới {, sau đó nhấn một góc nơi IP sau uốn cong và sau đó in avới !. Bây giờ đỉnh của ngăn xếp lại là b-ađiều đó có nghĩa là trong cả hai trường hợp, IP sẽ kết thúc di chuyển về phía đông. Tất cả những gì còn lại là một bit tuyến tính ngắn bây giờ:

;   Discard b-a.
\   Print a linefeed.
!   Print b.
@   Terminate the program.

1

Java 7, 73 byte

void d(int x,int y){while(x<y){x|=x+1;y&=y-1;}System.out.print(x+","+y);}

Các trường hợp bất ngờ & thử nghiệm:

Hãy thử nó ở đây.

public class Main{
  static void d(int x, int y){
    while(x < y){
      x |= x + 1;
      y &= y - 1;
    }
    System.out.print(x + "," + y);
  }

  public static void main(String[] a){
    print(2, 3);
    print(3, 2);
    print(8, 23);
    print(42, 81);
    print(38, 41);
    print(16, 73);
    print(17, 17);
  }

  public static void print(int a, int b){
    d(a, b);
    System.out.println();
  }
}

Đầu ra:

3,2
3,2
31,0
63,0
47,32
23,0
17,17

Quy tắc thử thách cũ [ 126 125 123 byte]:

LƯU Ý: Các quy tắc thử thách cũ đã sử dụng hai mảng số nguyên làm đầu vào, thay vì hai số nguyên lỏng lẻo.

void d(int[]a,int[]b){int i=-1,x,y;while(++i<a.length){x=a[i];y=b[i];for(;x<y;x|=x+1,y&=y-1);System.out.println(x+","+y);}}

Xin lỗi để thay đổi thử thách sau khi bạn đăng câu trả lời, nhưng tôi đã đơn giản hóa thử thách một chút. (bạn không cần phải lặp lại danh sách nữa). Mặc dù rất may điều đó sẽ cho phép bạn rút ngắn nó.
DJMcMayhem

@DrGreenEggsandIronMan Đã chỉnh sửa. Btw, thông thường là không tốt để thay đổi các quy tắc sau khi mọi người đã đăng câu trả lời của họ .. Nhưng như bạn đã nói, nó sẽ làm giảm số lượng byte, vì vậy tôi ổn với nó. (PS: Bạn chưa đưa ra nhận xét trên về câu trả lời của mọi người.)
Kevin Cruijssen

1
Bạn có thể viết lại whilevòng lặp của bạn như thế nàyfor(;x<y;x|=x+1,y&=y-1);
cliffroot

Tôi biết nó là. -_-Tôi ước tôi đã viết nó tốt hơn từ đầu. Rất may đó không phải là một sự thay đổi vô lý hay quyết liệt. Ngoài ra, có, tôi không bình luận về mọi câu trả lời, nhưng tôi đã thông báo cho mọi người dùng. Tôi không cảm thấy muốn thông báo cho cùng một người dùng nhiều lần. Tôi không bình luận về bài đăng của Dennis, nhưng đó là vì anh ấy là một trong những người dùng khuyến khích tôi thay đổi nó ban đầu.
DJMcMayhem

1

JavaScript (ES6), 33 byte

f=(n,m)=>n<m?f(n|n+1,m&m-1):[n,m]

Cổng đơn giản của các câu trả lời bởi @miles.


Bạn đã quên vận f=động viên từ đầu: P
Mama Fun Roll

1
Bạn đã quên "một lần nữa" ;-)
Neil

1

Julia, 27 byte

x<|y=x<y?x|-~x<|y&~-y:[x,y]

Hãy thử trực tuyến!

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

Chúng tôi xác định toán tử nhị phân <|cho các mục đích của chúng tôi. Nó không được xác định trong các phiên bản gần đây của Julia, nhưng vẫn được trình phân tích cú pháp công nhận. Mặc dù \(không được xác định rõ ràng cho số nguyên) ngắn hơn một byte, nhưng mức độ ưu tiên cao của nó sẽ yêu cầu thay thế x|-~x<|y&~-ybằng (x|-~x)\(y&~-y), do đó làm tăng số lượng byte.

<|kiểm tra xem đối số thứ nhất của nó có đúng hơn so với đối số thứ hai không. Nếu vậy, nó gọi đệ quy chính nó bằng các đối số x | - ~ x = x | (x + 1)y & ~ -y = y & (y - 1) .

Kể từ khi thêm 1 vào x, bật tất cả các bit đặt cuối và bit không đặt thấp nhất, x | (x + 1) bật tắt bit unset thấp nhất (và không có bit nào khác). Tương tự như vậy, kể từ khi trừ 1 từ y sẽ tắt tất cả các bit unset trailing và bit set thấp nhất, y & (y + 1) bật tắt bit set thấp nhất.

Cuối cùng, khi bất bình đẳng x <y không còn giữ, <|trả về cặp [x, y] .


0

MATLAB, 67 66 byte

vòng lặp:

function[]=f(x,y)
while x<y
x=bitor(x,x+1);y=bitand(y,y-1);end
x,y

đệ quy (67 byte):

function[]=f(x,y)
if x<y
f(bitor(x,x+1),bitand(y,y-1))
else
x,y
end

Cách tiếp cận tương tự để thay đổi bit như nhiều anwers khác.


0

Clojure, 63 byte

#(if(< % %2)(recur(bit-or %(inc %))(bit-and %2(dec %2)))[% %2])

Phương pháp tương tự như được sử dụng trong của tôi giải pháp trong J.

Sử dụng

=> (def f #(if(< % %2)(recur(bit-or %(inc %))(bit-and %2(dec %2)))[% %2]))
=> (f 38 41)
[47 32]
=> (map (partial apply f) [[2 3] [3 2] [8 23] [42 81] [38 41] [16 73] [17 17]])
([3 2] [3 2] [31 0] [63 0] [47 32] [23 0] [17 17])
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.