이웃과 비트 교환


26

과업 설명

정수가 주어지면 모든 정수 k> 0에 대해 (2k–1) 번째와 2k 번째 최하위 비트를 교체하십시오 . OEIS의 시퀀스 A057300 입니다.

숫자는 "무한한"선행 0을 갖는 것으로 가정합니다. 실제로 이것은 단순히 단일 0 비트를 홀수 길이의 숫자 앞에 추가하는 것을 의미합니다.

여기에 이미지 설명을 입력하십시오

이것은 이므로 가장 짧은 코드 (바이트)가 이깁니다.

테스트 사례

0 -> 0
1 -> 2
9 -> 6
85 -> 170
220 -> 236
1827 -> 2835
47525 -> 30298

5
비트 시프트와 같은 숫자가 int로 적합하다고 가정 할 수 있습니까?
xnor

1
@ xnor : 이것이 기본 / 커뮤니티 합의라고 생각합니다 (그렇지 않으면 C 등의 대답은 항상 틀릴 것입니다)? 확신! :)
Lynn

@Lynn : C는 unsigned char array_of_bytes[1024]예상 한대로 작동 해야 합니다 (예 : 1024 * CHAR_BIT항목 이있는 비트 필드 ). CHAR_BIT바이트간에 비트를 이동하는 것이 번거롭기 때문에 임의 길이의 입력을 지원하는 대부분의 대답 은 짝수 라고 가정 합니다. 따라서 k256과 같은 일정한 크기 또는 AES에 적합한 것까지 일정한 크기 를 지원 해야한다는 요구 사항을 절대적으로 넣을 수 있으며 256 비트 정수 유형이없는 언어는 루프를 사용해야합니다. 그것은 x86 asm 답변을 고려할만한 SIMD 벡터를 만들 수 있습니다 : P
Peter Cordes

2
@Geobits를 Minibits로 바꾼다
Optimizer

답변:



20

파이썬 2, 26 바이트

lambda n:2*n-3*(4**n/3&n/2)

비트 트릭!

Say n...ghfedcba이진 형식 입니다. 그런 다음 우리는 그것을 다른 모든 비트로 나눌 수 있습니다.

n   = o + 2*e
n   = ...hgfedcba
o   = ...0g0e0c0a
2*e = ...h0f0d0b0

그런 다음 비트 전환 결과 s를로 표현할 수 있습니다 s=2*o+e.

s   = 2*o + e
s   = ...ghefcdab
2*o = ...g0e0c0a0
e   = ...0h0f0d0b

우리는 오히려 단 하나를 계산하는 것 e그리고 o우리가 표현할 수 있도록, o=n-2*e그리고 대체

s=2*(n-2*e)+e = 2*n-3*e

그래서, 지금은 표현하기 위해 유지 e의 관점에서 n. 숫자 M=4**n/3...10101010101이진수 형식 이며 홀수 자릿수의 마스크 역할을합니다. 지수 n는 그것이 M충분히 길도록 보장합니다 . 비트 단위 복용 and의를 n/2이 값은 범 e원하는.

n/2     = ...hgfedcb
M       = ...1010101
n/2 & M = ...h0f0d0b = e

우리는 대신 표현할 수있는 e측면에서 o e=(n-o)/2제공하는 s=(n+o*3)/2xsot에서 최적화에 바이트 감사를 절약 할 수.

lambda n:n+(n&4**n/3)*3>>1

에서 빼서 마스크를 한 번만 사용하는 좋은 설명과 멋진 트릭 n. 그러나 나는 반대의 "홀수"대 "짝수"비트 명명 규칙을 선호한다. LSB는 비트 0이며 짝수입니다 (첫 번째 비트 임에도 불구하고). 셔플이 종종 인덱스가있는 요소를 선택하는 SIMD 프로그래밍에서 인덱스는 0부터 계산되므로 낮은 요소를 짝수 요소로 간주하는 것이 일반적입니다. 예[ 3 2 1 0 ]
Peter Cordes 2016

식을 사용하여 C 답변을 추가했습니다. 바이트 절약 효과와 Digital Trauma의 C 답변에 대한 모든 크레딧은이 때문입니다.
Peter Cordes 2016

2
26 :lambda n:n+(n&4**n/3)*3>>1
xsot

@PeterCordes C 코드는 gcc 4.8.3 및 기본 설정으로 작동합니다. 입력 2에 대해 1f(x){return x+((x&~0U/3)*3)>>1;}반환합니다 .
Dennis

@ 데니스 : 네, C에서 저를 위해 일합니다. calc실제로 실제로 C가 아닌 (일명 apcalc) 의 표현을 테스트하고 있었습니다 .32 비트 또는 2의 보수로 자르지 않아도되므로 괜찮을 것이라고 생각했습니다. 나는 그 표현이 옳다고 생각하지 않아서 내 잘못된 테스트를 기꺼이 믿었다. 그러나 어쨌든 비트 핵 개발을 위해 더 나은 REPL이 필요합니다. 어떤 제안? (이상적으로는 리눅스 명령 행, bc -l또는 calc실제로는 int32_t// uint32_t확장 된 것이 아니라 노출 된 것)
Peter Cordes

10

C 함수, 38

비트 트위들 링 :

f(x){return(x&~0U/3*2)/2+(x&~0U/3)*2;}

이데온


또는 그것의 재미를 위해 :

C 재귀 함수, 43

당으로서 OEIS 수식 ,a(4n+k) = 4a(n) + a(k), 0 <= k <= 3

f(x){return x>3?4*f(x/4)+f(x%4):x%3?3-x:x;}

또는

f(x){return x>3?4*f(x/4)+f(x%4):x%2*2+x/2;}

이데온


1
식의 xnor의 영리한 변환은 이것을 C에서 32 바이트로 줄였습니다. 나는 상당히 다른 접근법이기 때문에 별도의 답변으로 게시했습니다.
Peter Cordes 2016

8

CJam, 16 14 13 바이트

ri4b4e!2=f=4b

여기에서 테스트하십시오.

설명

ri  e# Read input and convert to integer.
4b  e# Get base-4 digits.
4e! e# Push all permutations of [0 1 2 3].
2=  e# Select the third one which happens to be [0 2 1 3].
f=  e# For each base-4 digit select the value at that position in the previous
    e# list, which swaps 1s and 2s.
4b  e# Convert back from base 4.

순열을 사용한 트릭은 매우 좋습니다!
Luis Mendo 2016 년

7

Pyth, 9 바이트

iXjQ4S2)4

Pyth Compiler 에서 사용해보십시오 .

작동 원리

  jQ4      Convert the input (Q) to base 4.
 X   S2)   Translate [1, 2] to [2, 1].
i       4  COnvert from base 4 to integer.

5

자바 스크립트 (ES6), 32 30 바이트

(n,m=0x55555555)=>n*2&~m|n/2&m

JavaScript 정수의 제한으로 인해 최대 1073741823까지만 작동합니다. 38 36 바이트는 최대 4294967295까지 작동합니다.

(n,m=0x55555555)=>(n*2&~m|n/2&m)>>>0

편집 : @ user81655 덕분에 2 바이트가 절약되었습니다.

51 바이트는 최대 4503599627370495에서 작동합니다.

n=>parseInt(n.toString(4).replace(/1|2/g,n=>3-n),4)

n<<1n*2있습니까?
user81655

@ user81655 그리고 나도 사용할 수 n/2있습니다! 왜 내가 이전에 그런 생각을하지 않았는지 모르겠습니다.
Neil

나는 본 적이 없다 >>>... 그게 뭐야?
Titus

@Titus 그것은 >>>같지만 서명되지 않은 시프트를 수행합니다. >>>0기본적으로 부호없는 32 비트 정수로 변환합니다.
Neil

5

x86 asm 기능 : 14 바이트의 기계 코드

uint64_t 버전 : 24 바이트

x86-64 SysV 호출 규칙 ( xin edi)이지만 동일한 기계 코드도 32 비트 모드에서 작동합니다. ((가) 어디 lea로서 디코딩한다 lea eax, [edi + eax*2], 동일한 결과를 제공한다 ).

0000000000000040 <onemask_even>:
  40:   89 f8                   mov    eax,edi
  42:   25 55 55 55 55          and    eax,0x55555555
  47:   29 c7                   sub    edi,eax
  49:   d1 ef                   shr    edi,1
  4b:   8d 04 47                lea    eax,[rdi+rax*2]
  4e:   c3                      ret    
4f: <end>

0x4f - 0x40 = 14 바이트

이것은 xnor의 뛰어난 마스크 원스 아이디어를 반대 방향으로 사용하여 얻은 컴파일러 출력 입니다. (그리고 반대 용어 : 낮은 비트는 비트 0이며, 홀수는 아닙니다.)

unsigned onemask_even(unsigned x) {
  unsigned emask = ~0U/3;
  unsigned e = (x & emask);
  return e*2 + ((x - e) >> 1);
}

컴파일러의 기능에 대한 개선 사항을 찾지 못했습니다. mov eax, 0x555.../ 로 작성했을 수도 and eax, edi있지만 길이는 같습니다.


64 비트 정수의 동일한 함수에는 24 바이트가 필요합니다 (godbolt 링크 참조). movabs rax, 0x55...레지스터에서 마스크를 생성하는 데 10 바이트보다 짧은 방법은 없습니다 . (x86의 div지시는 어리석기 때문에 서명하지 않은 모든 사람을 3으로 나누는 것은 도움이되지 않습니다.)

마스크를 rax로 생성하는 루프를 만들었지 만 10 바이트입니다 (정확하게는 길이와 동일 mov imm64).

# since 0x55 has its low bit set, shifting it out the top of RAX will set CF
0000000000000000 <swap_bitpairs64>:
   0:   31 c0                   xor    eax,eax      ; old garbage in rax could end the loop early
0000000000000002 <swap_bitpairs64.loop>:
   2:   48 c1 e0 08             shl    rax,0x8
   6:   b0 55                   mov    al,0x55      ; set the low byte
   8:   73 f8                   jnc    2 <swap_bitpairs64.loop>  ; loop until CF is set
000000000000000a <swap_bitpairs64.rest_of_function_as_normal>:
 # 10 bytes, same as   mov  rax, 0x5555555555555555
 # rax = 0x5555...
   a:   48 21 f8                and    rax,rdi
   ...

기존의 바이트 중 rax하위 비트 세트 가 없다는 것을 알고 있다면을 건너 뛸 수 xor있으며 길이는 8 바이트입니다.

이 답변의 이전 버전에는 loopinsn을 사용하여 10 바이트 루프가 있었지만 0xFFFFFFFFFFFFFF08설정 만했기 때문에 최악의 반복 런타임이있었습니다 cl.


5

오아시스 , 17 바이트 (비경쟁)

n4÷axxn4÷xxe+3120

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

Oasis는 Adnan 이 디자인 한 언어 로 시퀀스에 특화되어 있습니다.

현재이 언어는 재귀 및 닫힌 양식을 수행 할 수 있습니다.

우리는이 공식을 사용합니다 : a(4n+k) = 4a(n) + a(k), 0 <= k <= 3

기본 사례를 지정하는 것은 간단 3120합니다 a(0)=0, a(1)=2, a(2)=1, a(3)=3. 끝에는 단순히 의미합니다 .

n4÷axxn4÷xxe+3120
                0  a(0) = 0
               2   a(1) = 2
              1    a(2) = 1
             3     a(3) = 3

n                  push n (input)
 4÷                integer-divide by 4
   a               a(n/4)
    xx             double twice; multiply by 4
                   now we have 4a(n/4)
      n            push n (input)
       4÷xx        integer-divide by 4 and then multiply by 4
                   since there is no modulo currently, n%4
                   is built as n-(n/4*4)
           e       we should have done a(n-(n/4*4)), but this
                   is a shortcut for a(n-x) where x is the top
                   of stack. Therefore, we now have a(n-n/4*4)
                   which is a(n%4).
            +      add.

4

MATL , 10 바이트

BP2eP1ePXB

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

시퀀스의 첫 번째 항을 생성하도록 수정 된 버전 ( OEIS A057300 ).

설명

B     % Take input implicitly. Convert to binary array
P     % Flip
2e    % Convert to two-row 2D array, padding with a trailing zero if needed. 
      % Because of the previous flip, this really corresponds to a leading zero
P     % Flip each column. This corresponds to swapping the bits
1e    % Reshape into a row
P     % Flip, to undo the initial flipping
XB    % Convert from binary array to number. Display implicitly

3

zsh, 28 바이트

<<<$[`tr 12 21<<<$[[#4]$1]`]

입력을 명령 행 인수로 사용하여 STDOUT에 출력합니다.

zsh 특정 기본 변환 구문을 사용하기 때문에 Bash와 호환되지 않습니다.

                       $1     input (first command line argument)
                 $[      ]    arithmetic expansion
                   [#4]       output in base 4
              <<<             pass the result of this to...
      tr                      the `tr' command
         12 21                and replace 1s with 2s, 2s with 1s
     `                    `   evaluate the result...
   $[                      ]  in another arithmetic expansion, to convert back
                                to base 10
<<<                           output the result on STDOUT

3

레티 나, 70 바이트

. +
$ *
+`(1 +) \ 1
$ 1x
x1
1
^
엑스
r` (.) (.)
$ 2 $ 1
1
엑스@
+`@ x
엑스@@
엑스*(@*)
$ .1
0 $

테스트 스위트. (약간 수정되었습니다.)

글쎄, 재미를 위해 : 7 바이트

T`12`21

base-4를 입력으로 취하고 base-4로 출력을 취합니다.

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


4
나는 충돌한다. 귀하의 답변의 하반부를 공감하고 싶지만 상반부를 공감하고 싶습니다.
Dennis

1
@Dennis 이제 그 비트가 바뀌 었습니다.
Leaky Nun

3

05AB1E, 8 바이트

4B12‡4ö

-5 바이트의 @Adnan에게 감사합니다!

CP-1252 인코딩을 사용합니다.

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

설명:

4B       - Take input and convert to base 4.
  12Â    - Push 12 bifurcated.
     ‡   - Transliterate [1, 2] to [2, 1].
      4ö - Convert to base 10.

2
니스,하지만 당신은 대체 할 수 1 2‚2 1‚12Â8 바이트.
Adnan

좋은 대답입니다! 8 바이트 대안 :4в2‰íJJC
Kevin Cruijssen

3

C, 32 30 29 바이트

f(x){return(x&~0U/3)*3+x>>1;}                // 30 bit version, see below

// less golfed:
f(x){return ((x & 0x55555555)*3 + x) >>1;}   //  >> is lower precedence than +

xnor의 Python answer에 대한 xsot의 의견에서 알고리즘이 복사되었습니다 . 두 가지 방법으로 마스킹하는 대신 한 가지 방법으로 마스킹하고 결합하십시오.

이것은 내가 테스트 한 마지막 버전과 동일한 asm으로 컴파일되며 작동합니다 (x ~ 최대 0x3FFFFFFF및 x 이상 비트 30이 설정되지 않은 경우 아래 참조). 기계 코드에서 기존 asm 답변과 길이가 같습니다.


위의 버전은 항상 결과의 높은 비트를 지 웁니다 . 가장 안전한 버전은 32 바이트입니다.

g(x){return 2*x-3*(x/2U&~0U/3);}   // safe 32bit version, works for all x

파이썬 버전에는이 문제가 없습니다. 파이썬은 고정 된 상한으로 잘리는 대신 필요할 때 임의의 정밀도 정수 유형을 사용 하기 때문 입니다.


@ 데니스 : 아, 그래, 고마워. 테스트 마지막으로 변경 했으며 asm 출력의 차이를 놓쳤습니다. 내가 잘못되었다고 생각한 것도 당연합니다. 나는 >>그렇게 낮은 우선 순위를 잊었다 . 위험한 경우에 스패너를 제안하는 컴파일러 경고가 실제 코드로 나를 저장하기 때문에 규칙이 무엇인지 정확하게 기억할 정도로 자주 골프를 치지 않습니다. : P
Peter Cordes 2016

2
표현식에서 용어를 재정렬하여 해당 공간을 제거 할 수 있습니다.
xsot

2

자바 스크립트 (ES6), (113) 109 바이트

Upgoat 덕분에 4 바이트 절약

n=>+('0b'+/(..)+$/.exec('0'+n.toString`2`)[0].split``.reduce((p,c)=>p.length-1?[p.join(c)]:[p[0],c],[''])[0],2)

작동 원리

n=>+('0b'+                              //parse as binary literal
    /(..)+$/.exec('0'+n.toString`2`)[0] //convert to binary string with an even number of digits
        .split``                        //convert to array
        .reduce((p,c)=>p.length-1?[p.join(c)]:[p[0],c],[''])
                                        //swap all numbers
)

+('0b"+binary_string_here)`parseInt (..., 2) 대신 사용
Downgoat

1

J, 20 바이트

4#.0 2 1 3{~4#.^:_1]

용법

>> f =: 4#.0 2 1 3{~4#.^:_1]
>> f 85
<< 170

>>STDIN은 어디에 있고 <<STDOUT입니다.

언 골프

to_base   =: 4 #.^:_1 ]
transpose =: 0 2 1 3 {~ to_base
from_base =: 4 #. transpose

세 포크.

사이드 노트

공식 인터프리터에서는 1 바이트를 절약 ^:_1하여로 대체 할 수 있습니다 inv.

그러나 온라인 통역사는이를 구현하지 않습니다.



1

INTERCAL , 60 바이트

DOWRITEIN.1PLEASE.1<-!1~#21845'$.1~#43690DOREADOUT.1DOGIVEUP

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

INTERCAL에 대해 가장 자연스러운 형식으로 I / O를 수행하는 16 비트 정수에 대해 작동합니다. 입력은 여러 자연어 또는 생성 된 언어 중 하나로 철자 된 일련의 10 진수이며 출력은 "도달 된 로마 숫자"입니다.

이것은 비트 재배치가 전부이기 때문에 INTERCAL의 이진 연산자를 실제로 직관적으로 사용할 수있는 드문 과제 중 하나입니다. Select ( ~)는 두 번째 인수의 1에 해당하는 첫 번째 인수에서 비트를 가져와 오른쪽으로 0으로 채 웁니다. mingle ( $)은 인수에서 비트를 인터리브하여 첫 번째 인수의 비트가 더 중요합니다. 따라서 간단한 해결책은 덜 중요한 대체 비트 ( .1~#21845)를 선택하고 더 중요한 대체 비트 (.1~#43690), 반대 순서로 다시 삽입합니다. 운 좋게도 바이트 수는 INTERCAL의 연산자가 정의 된 우선 순위를 갖지 않지만 (언어의 목표는 선례가 없기 때문에) TIO의 C-INTERCAL 은이 특정 표현식에 대해 많은 그룹화가 필요하지 않기 때문에 1 바이트 만 필요합니다 '.축약 될 수 있습니다 !.

32 비트 정수 지원 :

INTERCAL , 67 바이트

DOWRITEIN:1PLEASE:1<-':1~#0$#65535'$:1~#65535$#0DOREADOUT:1DOGIVEUP

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

INTERCAL은 32 비트 리터럴을 허용하지 않습니다. 실제로이 비트 를 읽기가 더 쉬워집니다. 교대로 비트를 선택하기위한 마술 상수는 두 개의 16 비트 리터럴을 함께 조합하여 구성해야합니다. 모든 것. (실제로 32 비트 리터럴이 있어도이 길이 #0$#65535는 더 짧을 것입니다. 2 바이트는 떨어져 #1431655765있고 다른 바이트도 마찬가지입니다.) 이것은 전체 프로세스를 부 자연스럽게 잘 전달합니다.

피연산자 오버로드 를 서투르게 사용하는 대체 접근법 :

INTERCAL , 71 바이트

DO:1<-:1/.2$.3PLEASEWRITEIN:2DO:1<-:2PLEASE:2<-.3$.2DOREADOUT:2DOGIVEUP

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

이것은 그 전체가 선언 선택 페지 :1되어 .2섞여 .3설정 :1을 출력 한 후, 상기 입력에 .3섞였다 .2. 이후 :1로 오버로드 .2$.3, DO :1 <- :2에 할당 한 값 .2.3같은 해당 :1값 취득하고 :2, 결과 .2에서 더 중요한 비트를 교대로 함유 :2하고 .3덜 중요한 교번 비트들을 포함한다. 이 경우 4 바이트로 두 개의 32 비트 솔루션의 짧은 것이다 PLEASE WRITE IN :1대체 할 수있는 PLEASE WRITE IN :2 DO :1 <- :2과부하로 :1하지만,CALCULATING과부하를 사용하는 데 필요한 것으로 밝혀졌습니다. 또한 프로그램을 시작하는 것보다 과부하 자체를 수행하는 더 짧은 방법이있을 것이라고 생각 DO:1<-:1/.2$.3하지만 이것이 INTERCAL이기 때문에 나는 또한 할 수없는 것처럼 느낍니다.


0

매스 매 티카, 44 바이트

Fold[3#+##&,#~IntegerDigits~4/.{1->2,2->1}]&

내 CJam 답변과 동일한 접근 방식 : 기본 4로 변환, 1과 2를 바꾸고 다시 변환하십시오. 또한 alephalpha의 트릭을 사용 하여 1 바이트를 저장 FromDigits하는 Fold작업으로 대체 합니다.



0

J, 22 바이트

([:,_2|.\,&0)&.(|.@#:)

기본 4 트릭 대신 배열 조작을 기반으로하는 대체 방법입니다.

용법

   f =: ([:,_2|.\,&0)&.(|.@#:)
   (,.f"0) 0 1 9 85 220 1827 47525
    0     0
    1     2
    9     6
   85   170
  220   236
 1827  2835
47525 30298

설명

([:,_2|.\,&0)&.(|.@#:)  Input: n
                   #:   Get the value as a list of base 2 digits
                |.@     Reverse it
(           )&.         Apply to the list of base 2 digits
         ,&0            Append a zero to the end of the list
    _2  \               Split the list into nonoverlapping sublists of size 2
      |.                Reverse each sublist
 [:,                    Flatten the list of sublists into a list
             &.(    )   Apply the inverse of (reversed base 2 digits)
                        to convert back to a number and return it

0

REXX, 88 바이트

n=x2b(d2x(arg(1)))
o=0
do while n>''
  parse var n a+1 b+1 n
  o=o||b||a
  end
say x2d(b2x(o))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.