"비트 빌린"두 숫자


20

작은 숫자 가 큰 숫자에서 비트를 빌릴 수 있다는 것을 알고 있습니까? 다음은 예입니다. 두 개의 숫자 5와 14를 가정 해 봅시다. 먼저 이진수로 쓰십시오.

5       14
000101  001110

먼저 우리는 가장 작은을 떨어져 많은 수의 비트, 우리는 가장 작은에게주고 떨어져 다른 수에 비트. 그래서

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

이제 우리는

000111  001100

우리의 숫자는 7과 12입니다. 첫 번째 숫자는 여전히 작기 때문에 계속 진행합니다.

000111  001100
001111  001000

이제 우리는 15와 8을 가지고 있으므로 멈출 수 있습니다. 이 작업 집합을 "비트 차용"두 숫자라고합니다. 다른 예를 봅시다. 20과 61.

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

최종 결과는 32, 63 입니다. 한 번 더 해봅시다 . 31, 12. 31은 이미 12보다 큽니다. 따라서 할 일이 없습니다! 비트 차입 31 및 12는 31 및 12를 변경하지 않습니다.

도전

당신의 도전은 두 개의 숫자를 취하여 비트 차용하는 프로그램이나 함수를 작성하는 것입니다. 두 숫자는 항상 양의 정수입니다. 입력 및 출력 형식은 합리적입니다.

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

표준 허점이 적용되고 바이트 단위의 최단 답변이 승리합니다!

답변:


12

젤리 , 11 바이트

~1¦&N$^µ</¿

온라인으로 사용해보십시오! 또는 모든 테스트 사례를 확인하십시오 .

배경

정수 n 의 마지막 세트 비트 를 다음과 같이 추출 할 수 있습니다 .

n + 1n의 모든 후행 설정 비트 와 인접 비 설정 비트를 토글합니다 . 예를 들어, 10011 2 + 1 = 10100 2 입니다.

이후 ~ N = - (N + 1) = -N - 1 , -n = ~ N + 1 , 그래서 -n NOT의 비트에 상기 적용되는 N (토글 모든 따라서 마지막 전에 모든 비트를 토글 링, 비트) 1 .

예를 들어, -10100 2 = ~ 10100 2 + 1 = 01011 2 + 1 = 01100 2 입니다.

취하여 -n n은 비트 단위 AND의 N-n (부등에 보낸 마지막 비트 전에 설정된 모든 비트는 무효화되어 N-n 따라서 마지막 비트 세트 수득) N을 .

예를 들어, 10100 2 & -10100 2 = 10100 2 & 01100 2 = 00100 2 입니다.

따라서, 배타적 논리합 N을 가진 N -n 및 설정 해제의 마지막 비트 세트 N을 .

반대로, n 의 마지막 세트 비트를 설정 해제하려면 위 의 수식 을 ~ n 에 적용 하면 수식 n ^ (~ n &-~ n)이 파생 됩니다.

작동 원리

~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 바이트

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

재귀와 비트 트릭을 사용하는 간단한 접근 방식. 값 n에 대해 가장 오른쪽에있는 1 비트를 끄고 ( 0으로 설정 ) nn -1 사이에서 비트 단위로 수행하고 가장 오른쪽 에 1을 설정하여 설정할 수 있습니다 값 n에 대해 off ( 0 ) 비트의 경우 비트 단위 또는 nn +1 사이에서 수행 할 수 있습니다 .

용법

입력은 두 개의 정수로 구성되며, 하나는 LHS에 적용되고 다른 하나는 RHS에 적용되며, 출력은 비트 차용 된 값의 목록입니다.

   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

설명

,`(($:~(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

좋은 대답입니다! 답변을 게시 한 후 챌린지를 변경하여 죄송하지만 챌린지를 조금 단순화했습니다. (더 이상 목록을 반복 할 필요가 없습니다). 좀 더 짧게 만들어야합니다.
DJMcMayhem

@DrGreenEggsandIronMan J는 실제로 명시적인 순위없이 두 배열 사이에 요소 단위로 함수를 적용합니다. 또 다른 트릭이 없으면 아마 동일하게 유지 될 것입니다.
마일

4

파이썬, 42 바이트

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

4 바이트로 골프를 치는 @ jimmy23013에게 감사드립니다! 2 바이트를 골라 낸 @LeakyNun에게 감사드립니다!

Ideone에서 테스트하십시오 .


3

매스 매 티카, 46 바이트

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

J의 솔루션 에서 사용한 것과 동일한 방법 입니다.

1 바이트를 절약하고 infix 응용 프로그램을 상기시켜주는 @ Martin 에게 감사드립니다 ~.

용법

입력은 두 개의 정수 인수로 구성되며 출력은 비트 차용 된 값이있는 목록입니다.

예


내가 뭔가 재미있는 것을 시도했지만 불행히도 그것은 더 긴 바이트입니다 : #//.{x_,y_}/;x<y:>{BitOr[x,x+1],BitAnd[y,y-1]}&(어쩌면 그것을 줄이는 방법에 대한 아이디어가있을 수 있습니다)
Martin Ender

그것은 깔끔한 규칙이지만, 나는 골프 규칙에 익숙하지 않습니다. 나는 일반적으로 replacement /.와 condition 만 사용 합니다 /;. Wish Mathematica는 인수 유형을 검사하여 부울과 비트 단위로 전환 할 수 있습니다 &&.
마일

3

Pyth, 29 27 25 22 21 20 19 18 16 바이트

MxG ^ 2x _ + \ 0.BG`HCm.W <FHgVZU2dC 
MxG ^ 2x_ + 0jG2HCm.W <FHgVZU2dC 
Cm.W <FH.bxN ^ 2x_ + 0jN2YZ2dC 
m.W <FH.bxN ^ 2x_       출력 변경 형식
 mW <FH.exb ^ 2x_ + 0jb2kZ 
m.W <FH.U ,. | bhb. & ZtZZ 
.W <FH.U ,. | bhb. & ZtZZ          <-변경된 입력 / 출력 형식
 .W <FH.U ,. | bhb. & ZtZ
.W <FH.U ,. | bhb. & t

테스트 스위트.


답변을 게시 한 후 챌린지를 변경하여 죄송하지만 챌린지를 조금 단순화했습니다. (더 이상 목록을 반복 할 필요가 없습니다). 고맙게도 단축 할 수 있습니다.
DJMcMayhem

@DrGreenEggsandIronMan 1 바이트 만 저장했습니다. Pyth 그렇게 효율적입니다.
Leaky Nun


2

미로 , 37 34 바이트

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

온라인으로 사용해보십시오!

설명

빠른 미로 입문서 :

  • 미로는 임의 정밀도 정수 두 스택상에서 동작 메인보조 초기에 제로의 (내재) 무한대로 채워진다.
  • 소스 코드는 명령 포인터 (IP)가 복도를 따르는 미로와 유사합니다. 모든 흥미로운 제어 흐름은 정션에서 발생합니다. IP에 둘 이상의 셀이있는 경우 기본 스택의 맨 위가 검사됩니다. 값이 음수이면 IP가 왼쪽으로 돌아가고 양수이면 IP가 오른쪽으로 돌아가고 그렇지 않으면 직진합니다. 선택한 방향이 벽 (예 : 공간)으로 막히면 IP가 반대 방향으로 이동합니다.

이 프로그램은 다른 답변과 같은 알고리즘을 사용 : 우리는 대신 (a, b)(a | a+1, b & b-1)긴만큼 a < b. 골프를 좀 더 시도한 후에 전체 설명을 추가하겠습니다.

IP는 왼쪽 상단에서 시작하여 오른쪽으로 이동합니다. ?정수를 읽습니다 a. 그런 다음 "no-op이지만 IP가 즉시 아래로 이동하는 것을 방지해야합니다. 이것은 또한 막 다른 골목이므로 IP는 돌아 서서 ?다시 읽습니다 b. }다음 이동 b에서 주요 하기 AUX 그래서 지금 우리가 가지고 :

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

그런 |다음 a및 의 비트 단위 OR을 사용하므로 아무 것도 수행하지 않습니다 0. 우리 a는 항상 긍정적이라는 것을 알고 있기 때문에 IP는 동쪽으로 바뀝니다. 프로그램의 메인 루프가 시작됩니다. 우리는 비교하기 위해 짧은 직선 섹션 시작 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는 이제 다른 교차점에 있습니다. 먼저 결과가 긍정적 인 경우를 생각해 봅시다. 즉 b > a, 반복을 한 번 더 수행해야합니다. 반복도 완전히 선형입니다. 스택은 현재 다음과 같습니다.

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.

그리고 우리는 루프의 시작으로 돌아갑니다 ( a다시 긍정적이기 때문에 IP는 다시 동쪽으로 바뀝니다).

어떤 시점 b-a에서 더 이상 긍정적이지 않으면 IP는 다른 두 경로 중 하나를 사용합니다. 두 경우 모두에서 우리가 가져 오는 것을 참고 a{다음의 IP는 굽힘을 다음 코너에 충돌 한 후 인쇄 a와 함께 !. 이제 스택의 상단이 다시 b-a나타납니다. 두 경우 모두 IP가 동쪽으로 이동합니다. 이제 남은 것은 짧은 선형 비트입니다.

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

1

자바 7, 73 바이트

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

산출:

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

오래 도전 규칙 [ 126 125 123 바이트]

참고 : 이전 챌린지 규칙은 두 개의 느슨한 정수 대신 두 개의 정수 배열을 입력으로 사용했습니다.

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

답변을 게시 한 후 챌린지를 변경하여 죄송하지만 챌린지를 조금 단순화했습니다. (더 이상 목록을 반복 할 필요가 없습니다). 고맙게도 단축 할 수 있습니다.
DJMcMayhem

@DrGreenEggsandIronMan 편집했습니다. Btw, 사람들이 답변을 게시 한 후에 규칙을 변경하는 것은 일반적으로 나쁜 습관입니다. 그러나 말했듯이 바이트 수를 줄여야하므로 괜찮습니다. (PS : 당신은 모든 사람의 대답에 위의 댓글을 추가하지 않았습니다.)
케빈 Cruijssen

1
다음 while과 같이 루프 를 다시 작성할 수 있습니다for(;x<y;x|=x+1,y&=y-1);
cliffroot

알고 있습니다. -_-처음부터 더 잘 작성했으면 좋겠다. 고맙게도 그것은 불합리하거나 과감한 변화가 아닙니다. 또한 예, 모든 답변에 대해서는 언급하지 않았지만 모든 사용자에게 알 렸습니다. 같은 사용자에게 여러 번 알리는 느낌이 들지 않았습니다. Dennis의 게시물에 대해서는 언급하지 않았지만, 처음에 변경하도록 권장 한 사용자 중 한 사람이기 때문입니다.
DJMcMayhem

1

자바 스크립트 (ES6), 33 바이트

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

@ 마일로 답변의 간단한 포트.


당신은 f=ath 시작을 잊었다 : P
Mama Fun Roll

1
당신은 "다시"를 잊었다 ;-)
Neil

1

줄리아, 27 바이트

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

온라인으로 사용해보십시오!

작동 원리

우리는 <|목적을 위해 이진 연산자 를 정의합니다 . 최근 버전의 Julia에서는 정의되지 않았지만 여전히 파서에서 연산자로 인식됩니다. 반면 \(명시 적으로 정의하지 정수)가 한 바이트 짧고, 높은 우선 순위는 교체 요구 x|-~x<|y&~-y(x|-~x)\(y&~-y)따라서, 바이트 카운트를 증가시킨다.

<|첫 번째 인수가 두 번째 인수보다 엄격하게 작은 지 확인합니다. 그렇다면, 인수 x | -~ x = x | (x + 1)y & ~ -y = y & (y-1) 입니다.

x에 1 을 추가하면 모든 후행 세트 비트와 가장 낮은 비 설정 비트가 토글 되므로 x | (x + 1) 은 가장 낮은 설정되지 않은 비트를 토글하며 다른 비트는 토글하지 않습니다. 마찬가지로 y 에서 1 을 빼면 모든 후행 설정되지 않은 비트와 최저 설정 비트가 토글되므로 y & (y + 1) 은 최저 설정 비트를 토글합니다.

마지막으로 부등식 x <y 가 더 이상 유지되지 않으면 [x, y]<| 쌍을 반환합니다 .


0

MATLAB, 67 66 바이트

고리:

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

재귀 적 (67 바이트) :

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

다른 많은 anwer와 같은 비트 변경에 대한 동일한 접근 방식.


0

클로저, 63 바이트

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

J의 솔루션 에서 사용한 것과 동일한 방법 입니다.

용법

=> (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])
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.