다른 숫자, 같은 무게


22

배경

정수 의 해밍 가중치 는 이진 표현의 정수입니다. 이 문제의 경우 정수는 32 비트로 표시되며 부호가 없습니다.

도전

0에서 2 ^ 32-1 (비 포함) 사이의 정수가 주어지면 다른 출력 동일한 범위 내에서 동일한 해밍 가중치를 정수를 .

Input (Decimal) | Input (Binary) | Hamming weight | Possible output (Decimal)
       46       |   0b0010 1110  |       4        |      15
       12       |   0b0000 1100  |       2        |      3
        1       |   0b0000 0001  |       1        |      2
        3       |   0b0000 0011  |       2        |      6
      2^31      |   0b1000....0  |       1        |      1
      2^31+2    |   0b1000...10  |       2        |      3
      2^32-5    |   0b1111..011  |       31       |      2^31-1
      2^32-2    |   0b1111....0  |       31       |      2^31-1
        0       |   0b0000 0000  |       0        | None (This case need not be handled)
      2^32-1    |   0b1111....1  |       32       | None (This case need not be handled)

채점

이것은 이므로 각 언어에서 가장 적은 바이트 수의 솔루션이 승리합니다.


2
2 ^ 31 + 1과 2 ^ 32-3 사이에 홀수를 추가하는 것이 좋습니다. 일부 답변은 실패합니다.
Ørjan Johansen


방금 추가 했으므로 홀수2^31+2 라고 반복합니다 . 가장 높은 비트와 가장 낮은 비트가 모두 인 경우에만 문제의 대답이 실패했습니다 . 1
Ørjan Johansen 2016 년

나는 바보다. 고맙습니다. 그것을 해결할 것입니다
musicman523

1
@ musicman523 방금 활발한 질문을 탐색 하면서이 질문을 보았습니다. 요청한 테스트 사례를 아직 추가하지 않은 것으로 나타났습니다.
Draco18s

답변:


29

x86-64 어셈블리, 5 4 바이트

   0:   97                      xchg   %eax,%edi
   1:   d1 c0                   rol    %eax
   3:   c3                      retq   

C 호출 규칙을 사용하여 인수를 1 비트 씩 왼쪽으로 회전시키는 함수입니다.


젠장 - 내가 게시물에 대해 정확히 동일하게이 - 잘 :) 일
디지털 외상

12
어셈블리는 Jelly : o
Uriel

이 값에 2를 곱하지 않습니까? 만약 그렇다면, 제 2 바이트 Pyth의 대답은 아마도 승리
NoOneIsHere

@NoOneIsHere 아니, 이것은 이것은하지 곱셈 왼쪽의 오버 플로우 비트를 무시하면 외부 필요한 범위의 입력의 절반, 그리고 당신이 1만큼 해밍 무게를 감소했습니다 보냅니다 2 2. 곱셈입니다 비트 rotation . 오버플로 비트를 오른쪽에서 다시 가져옵니다.
Anders Kaseorg 2012 년

1
@DigitalTrauma GCC 4.9.0 및 이후 버전은 컴파일 할만큼 똑똑 n << 1 | n >> 31rol대신 ror(바이트 저장).
Anders Kaseorg 2012 년



6

젤리 , 10 8 바이트

‘&~^^N&$

최하위 설정 및 설정 해제 비트를 교환합니다.

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

작동 원리

‘&~^^N&$  Main link. Argument: n

‘         Increment; yield n+1, toggling all trailing set bits and the rightmost
          unset bit.
  ~       Bitwise NOT; yield ~n, toggling ALL bits of n.
 &        Bitwise AND; yield (n+1)&~n, keeping the only bit that differs in n+1 and
          ~n, i.e., the rightmost unset bit.
   ^      Perform bitwise XOR with n, toggling the rightmost unset bit.
       $  Combine the two links to the left into a monadic chain.
     N        Negate; yield -n. Since ~n = -(n+1) in 2's complement, -n = ~n+1.
      &       Take the bitwise AND of n and -n. Since -n = ~n + 1 and n = ~~n, the
              same reasoning that applied for (n+1)&~n applies to -n&n; it yields
              the rightmost unset bit of ~n, i.e., the rightmost set bit of n.
    ^      XOR the result to the left with the result to the right, toggling the
           rightmost set bit of the left one.

5

자바 스크립트 (ES6), 35 31 바이트

첫 번째 비트 전이 (0 → 1 또는 1 → 0)를 찾아 반전시킵니다.

f=(n,k=3)=>(n&k)%k?n^k:f(n,k*2)

데모

비트 회전, 14 바이트

훨씬 짧지 만 재미는 적습니다.

n=>n>>>31|n<<1

데모


JavaScript 비트 단위 연산자는 부호없는 것이 아니라 32 비트 부호있는 정수를 제공합니다. 예를 들어 f(2147483647)is -1073741825and (n=>n>>>31|n<<1)(2147483647)is -2입니다.
Anders Kaseorg 2016 년

2
32 비트를 넘지 않는 한 괜찮습니다.
musicman523 2016 년

첫 번째 설명을 추가 할 수 있습니까? Javascript를 배우려고하는데 k가 정의되지 않은 상태에서 f를 호출하고 합리적인 대답을 얻는 방법에 대해 약간의 손실이 있습니다!
musicman523

2
@ musicman523 다음 은 해당 팁입니다. 기본적 k으로는로 설정되어 있으며이 undefined사실을 이용합니다 . ~undefined-1
Arnauld

@ musicman523 (업데이트 된 버전에서는이 팁을 더 이상 사용하지 않습니다. 그러나 원래 답변에 대해 다른 질문이 있으면 언제든지 문의하십시오.)
Arnauld

4

Brain-Flak , 78 바이트

(([()()])[[]()]){((){}<({({})({}())}{})>)}{}([(({}(({}){})())<>)]){({}())<>}{}

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

n <2 ^ 31이면 2n을, 그렇지 않으면 2n + 1-2 ^ 32를 반환합니다. 불행히도, Brain-Flak은 숫자의 부호를 결정하는 빠른 방법이 없기 때문에 입력 값이 2 ^ 31과 약 500000 이상 차이가 나면 프로그램이 TIO에서 시간 초과됩니다.

설명

먼저 -2 ^ 32를 스택에 넣습니다.

(([()()])[[]()])                               push (initial value) -2 and (iterator) -5
                {((){}<                >)}     do 5 times:
                       ({({})({}())}{})        replace the current (negative) value with the negation of its square
                                            {}   pop the (now zero) iterator

그런 다음 원하는 출력을 계산하십시오.

      (({}){})                        replace n by 2n on left stack
   ({}        ())                     push 2n+1-2^32 on left stack
  (              <>)                  push again on right stack
([                  ])                push its negation on right stack
                      {({}())<>}      add 1 to the top value of each stack until one of them reaches zero
                                {}    pop this zero, and implicitly print the number below it on the stack

3

dc, 10

?2~z31^*+p

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

이것은 32 비트 오른쪽 회전의 산술 구현입니다.

?           # input
 2~         # divmod by 2 - quotient pushed first, then the remainder
   z        # z pushes the size of the stack which will be 2 (quotient and remainder) ...
    31^     #  ... and take that 2 to the 31st power
       *    # multiply the remainder by 2^31
        +   # add
         p  # output

3

자바 8, 117 17 29 바이트

n->n*2%~-(long)Math.pow(2,32)

의 최대 크기가 이므로 으로 변경 int하여 +12 바이트longint2³¹-1

100@AndersKaseorg 의 놀라운 파이썬 답변 포트를 생성하여 89 바이트 절약 .

여기에서 시도하십시오.

출력 :

46 (101110):                                     92 (1011100)
12 (1100):                                       24 (11000)
1 (1):                                           2 (10)
3 (11):                                          6 (110)
10000 (10011100010000):                          20000 (100111000100000)
987654 (11110001001000000110):                   1975308 (111100010010000001100)
2147483648 (10000000000000000000000000000000):   1 (1)
4294967294 (11111111111111111111111111111110):   4294967293 (11111111111111111111111111111101)

기존 답변 ( 117 바이트) :

n->{long r=0;for(;!n.toBinaryString(++r).replace("0","").equals(n.toBinaryString(n).replace("0",""))|r==n;);return r;}

변경하여 +1 바이트 int의 최대 크기가 long이므로 하여int2³¹-1

여기에서 시도하십시오.

출력 :

46 (101110):                                     15 (1111)
12 (1100):                                       3 (11)
1 (1):                                           2 (10)
3 (11):                                          5 (101)
10000 (10011100010000):                          31 (11111)
987654 (11110001001000000110):                   255 (11111111)
2147483648 (10000000000000000000000000000000):   1 (1)

2

매스 매 티카, 29 바이트

Mod@##+Quotient@##&[2#,2^32]&

Wolfram 샌드 박스에서 사용해보십시오

산술적으로 왼쪽으로 회전 : 먼저 2를 곱하여 숫자를 범위 밖으로 이동 한 다음 범위를 벗어난 숫자를 잘라냅니다. Mod[...,2^32] 오른쪽으로 다시 추가합니다 +Quotient[...,2^32].

(Mathematica는 모듈러스와 몫을 한 번에 제공하는 단일 빌트인을 가지고 있지만 QuotientRemainder, 이것은 약간의 골프 핸디캡입니다 ...)


모드 2 ^ 32-1? (4 더 이동)
user202729

2

APL, 12 바이트

(2⊥32⍴1)|2×⊢

방법?

           ⊢  ⍝ monadic argument
         2×   ⍝ shift left (×2)
(2⊥32⍴1)|     ⍝ modulo 2^32 - 1


1

R, 42 63 바이트

function(x){s=x;while(s==x){sample(binaryLogic::as.binary(x))}}

비트를 무작위로 섞지 만 우연히 같은 숫자를 반환하지 않는지 확인합니다.


1

공백 , 81 80 바이트

(@ Ørjan Johansen 덕분에 1 바이트가 절약되어 dup이 푸시 0보다 짧다는 것을 상기시킵니다)

   
 
 	
					 
    	 
	 		
	 
   	        
 
 	  
 
 	  
	   
  
   	 
	 	 	
 	

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

기본적으로 정수 산술을 사용하여 순환 오른쪽 비트 시프트를 구현합니다. 공백에서 큰 상수를 푸는 것은 비싸므로 2 ^ 8을 누르고 두 번 제곱하여 일부 바이트를 절약합니다. (1 ^ 2 바이트 이상 (2 ^ 16) ^ 2 및 10 바이트 바이트를 2 ^ 32를 직접 누르면 저장합니다.)

설명

sssn  ; push 0
sns   ; dup
tntt  ; getnum from stdio
ttt   ; retrieve n from heap and put it on the stack
sns   ; dup
ssstsn ; push 2
tstt  ; mod - check if divisible by 2 (i.e. even)
ntsn  ; jez "even"
ssstssssssssn ; push 2^8
sns   ; dup
tssn  ; mul - square it to get 2^16
sns   ; dup
tssn  ; mul - square it to get 2^32
tsss  ; add 2^32 so MSB ends up set after the divide
nssn  ; even:
ssstsn ; push 2
tsts  ; divide by 2, aka shift right
tnst  ; putnum - display result

1
나는 당신이 두 번째 대체 할 수 있다고 생각 push 0A를 dup하나의 명령 이전을.
Ørjan Johansen 2016 년

당신의 말이 맞아요, 방금 트랜스포머에 바로 가기 구문을 추가해서 너무 많이 사용했습니다 ...
Ephphatha






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