그레이 코드 증가


36

소개

그레이 코드 번호는 한 비트 만이 아닌 비트의 가변 량을 전환하여 증가하는 바이너리 표현에 대한 대안이다. 다음은 십진수 및 이진수에 해당하는 회색 코드입니다.

 decimal | binary | gray
-------------------------
       0 |      0 |    0
-------------------------
       1 |      1 |    1
-------------------------
       2 |     10 |   11
-------------------------
       3 |     11 |   10
-------------------------
       4 |    100 |  110
-------------------------
       5 |    101 |  111
-------------------------
       6 |    110 |  101
-------------------------
       7 |    111 |  100
-------------------------
       8 |   1000 | 1100
-------------------------
       9 |   1001 | 1101
-------------------------
      10 |   1010 | 1111
-------------------------
      11 |   1011 | 1110
-------------------------
      12 |   1100 | 1010
-------------------------
      13 |   1101 | 1011
-------------------------
      14 |   1110 | 1001
-------------------------
      15 |   1111 | 1000

회색 코드의 주기적 비트 패턴

때때로 "반사 된 이진법"이라고도하며, 한 번에 하나의 비트 만 변경하는 속성은 가장 중요하지 않은 비트부터 시작하여 각 열에 대한 순환 비트 패턴으로 쉽게 얻을 수 있습니다.

bit 0: 0110011001100110011001100110011001100110011001100110011001100110
bit 1: 0011110000111100001111000011110000111100001111000011110000111100
bit 2: 0000111111110000000011111111000000001111111100000000111111110000
bit 3: 0000000011111111111111110000000000000000111111111111111100000000
bit 4: 0000000000000000111111111111111111111111111111110000000000000000
bit 5: 0000000000000000000000000000000011111111111111111111111111111111

...등등.

객관적인

회색 코드의 패딩되지 않은 입력 문자열이 주어지면 시퀀스에서 단일 문자를 번갈아 가거나 1(2의 다음 거듭 제곱으로 증가 할 때)를 앞에 추가하여 회색 코드를 증가시킨 다음 결과를 패딩되지 않은 회색 코드로 출력하십시오.

경고

  • 0빈 문자열을 입력으로 가져 가거나 걱정할 필요가 없습니다 .
  • 가장 낮은 입력은 1이며 환경에 의해 부과 된 메모리 제한 이외의 문자열 길이에 대한 상한은 없습니다.
  • 패딩되지 않은 문자열로 인해 선행 또는 후행 공백 (선택적 후행 줄 바꿈 제외)이 없으며 0입력 또는 출력에 선행 s가 없습니다 .

I / O 형식

다음 형식은 입력 및 출력에 허용되는 형식이지만 다른 형식보다 문자열을 사용하는 것이 좋습니다.

  • 가장 중요한 "비트"먼저
  • 패딩되지 않은 문자 배열 또는 ASCII '1''0's 문자열
  • 1s 및 0s 의 패딩되지 않은 정수 배열
  • 패딩되지 않은 부울 배열

허용되지 않는 것 :

  • 가장 중요하지 않은 "비트"
  • 십진, 이진 또는 단항 정수
  • 고정 길이 데이터 구조
  • 문자 배열 또는 비 인쇄 가능한 ASCII 인덱스의 문자열 10

테스트

input -> output
1 -> 11
11 -> 10
111 -> 101
1011 -> 1001
1111 -> 1110
10111 -> 10110
101100 -> 100100
100000 -> 1100000

요청에 따라 더 많은 테스트를 추가 할 수 있습니다.

기준

이것은 이므로 바이트 단위의 가장 짧은 프로그램이 승리합니다! 이전의 제출물을 선호함으로써 모든 유대 관계가 깨질 것입니다. 표준 허점이 적용됩니다. 최고의 답변은 2016 년 10 월 9 일에 수락되며 더 나은 답변이 제공 될 때마다 업데이트됩니다.



숫자로 입력 할 수 있습니까?
xnor

1
덜 명확하게, 또한 관련 .
Martin Ender

1
0011를 들어 8
Ton Hospel

1
@TonHospel 죄송합니다. I / O에 대한 귀하의 질문을 보지 못했습니다. 내가 1000000000에게 말했듯이 내 대답은 아니오입니다.
Patrick Roberts

답변:


13

젤리 , 10 8 바이트

2 바이트를 절약 해 준 Dennis에게 감사합니다.

^\Ḅ‘^H$B

입력과 출력은 0과 1의 목록입니다.

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

설명

그레이 코드의 역수는 A006068에 의해 주어진다 . 이를 사용하여 입력을 찾기 위해 많은 수의 그레이 코드를 생성 할 필요가 없습니다. OEIS에 주어진이 순서의 분류는 다음과 같습니다.

a(n) = n XOR [n/2] XOR [n/4] XOR [n/8] ...

어디 []바닥 브래킷입니다. 44이진 표현 의 예를 고려하십시오 101100. 2로 나누고 바닥은 오른쪽으로 이동하여 가장 중요하지 않은 비트를 잘라냅니다. 그래서 우리는 다음 숫자를 XOR하려고합니다.

1 0 1 1 0 0
  1 0 1 1 0
    1 0 1 1
      1 0 1
        1 0
          1

n번째 열의 첫 번째 포함 된 n비트. 따라서이 공식은 목록에 대한 XOR의 누적 감소로 이진 입력에서 사소하게 계산 될 수 있습니다 (기본적으로 목록의 각 접두사에 XOR을 적용하고 결과 목록을 제공합니다).

이것은 우리에게 그레이 코드를 뒤집는 간단한 방법을 제공합니다. 그런 다음 결과를 늘리고 회색 코드로 다시 변환하면됩니다. 후자의 단계에서는 다음 정의를 사용합니다.

a(n) = n XOR floor(n/2)

고맙게도 Jelly는 입력을 XOR하려고 할 때 입력을 자동으로 플로어링하는 것으로 보입니다. 어쨌든, 여기 코드가 있습니다 :

^\          Cumulative reduce of XOR over the input.
  Ḅ         Convert binary list to integer.
   ‘        Increment.
    ^H$     XOR with half of itself.
       B    Convert integer to binary list.

당신은 필요하지 않습니다 Ḟ$; 비트 연산자는 int로 캐스트됩니다 .
Dennis

@ 데니스 감사합니다, 나는 쓰는 동안 그것을 발견했다. :)
Martin Ender

@MartinEnder 내부적으로 큰 정수로 변환되는 정수입니까?
Patrick Roberts

@PatrickRoberts 그렇습니다. 필요한 경우에는 파이썬입니다.
Jonathan Allan

좋은 분석과 설명.
Wayne Conrad

8

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

s=>s.replace(s.split`1`.length%2?/.$/:/.?(?=10*$)/,c=>1-c)

적절한 비트를 직접 토글합니다. 설명 : MartinEnder ♦의 답변에서 볼 수 있듯이 디코딩 된 회색 코드의 각 비트는 자체의 누적 XOR 또는 패리티이며 왼쪽의 비트입니다. 그리고 가장 오른쪽에있는 1 비트를 모두 0으로, 그 다음에 0 비트를 1로 토글하는 캐리 리플 (carry ripple)을 일으키는 숫자를 증가시켜야합니다. 모든 1 비트의 패리티가 짝수이면 가장 오른쪽 비트는 0이므로 마지막 비트를 토글합니다. 모든 1 비트의 패리티가 홀수이면 가장 오른쪽 비트는 1이며 마지막 1 비트를 찾아야합니다. 이것은 마지막으로 전달 된 비트이므로 토글해야 할 비트는 오른쪽에서 다음 비트입니다.


아주 좋은 방법입니다. 첫 번째 ?/.?(?=10*$)/정말로 필요한가요? 오, 신경 쓰지 마 네 그렇습니다. :-)
Arnauld

8

펄, 27 25 바이트

에 +1 포함 -p

STDIN에 입력 문자열을 제공하십시오. 예 :

gray.pl <<< 1010

gray.pl:

#!/usr/bin/perl -p
s%(10*\K1(\K0)*)*%1-$&%e

Perl에는 저렴한 무한정 수가 없습니다. 따라서 마지막 홀수 번호 1이있는 바로 앞에있는 비트를 직접 전환하십시오.


1
와우, \G정말 당신을 위해 일을 쉽게합니다!
Neil

1
반면에, \K당신을 위해 일을 더 쉽게 만듭니다.
Neil

Haaaaa ... 이제 \G구현도 보고 싶습니다 .
매직 문어 Urn

2
@carusocomputing 편집 된 링크 를 클릭하면 이전 버전의 제출물을 볼 수 있습니다
Ton Hospel

6

하스켈, 118115108 바이트

g 0=[""]
g n|a<-g$n-1=map('0':)a++map('1':)(reverse a)
d=dropWhile
f s=d(=='0')$(d(/='0':s)$g$1+length s)!!1

Ideone에서 사용해보십시오.
순진한 접근 방식 : g길이 n가 0 인 패딩 이있는 모든 회색 코드 세트를 생성하고 with를 f호출 g하고 발견 length(input)+1될 때까지 모든 요소를 ​​제거 0<inputstring>하고 다음 요소를 반환합니다 (가능한 경우 앞을 자릅니다 0).


1
좋은 첫 대답! 좀 더 효율적인 것을 얻을 수 있기를 바랍니다.
Patrick Roberts

5

MATL , 18 바이트

ZBtE:t2/kZ~tb=fQ)B

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

설명

하자 ( n은 ) 그레이 코드 (에 대응하는 정수의 시퀀스를 나타내고 OEIS을 A003188 ). 프로그램은 특성화 a ( n ) = n XOR floor ( n / 2)를 사용합니다. 여기서 XOR은 비트 단위입니다.

기본적으로 코드는 입력을 정수 a 0으로 변환하고 시퀀스에서 해당 정수를 찾은 후 다음 항을 선택합니다. 이를 위해서는 충분히 많은 수의 시퀀스 a ( n ) 항을 생성해야합니다 . 그것은 2 · 밝혀 0이 충분히 크다. 이것은 그레이 코드 a ( n )이 n 보다 이진수를 더 이상 갖지 않기 때문 입니다.

입력 '101'을 예로 들어 봅시다 .

ZB      % Input string implicitly. Convert from binary string to integer
        %   STACK: 5
t       % Duplicate
        %   STACK: 5, 5
E       % Multiply by 2. This is the number of terms we'll generate from the sequence
        %   STACK: 5, 10
:       % Range
        %   STACK: 5, [1 2 3 4 5 6 7 8 9 10]
t       % Duplicate
        %   STACK: 5, [1 2 3 4 5 6 7 8 9 10], [1 2 3 4 5 6 7 8 9 10]
2/k     % Divide by 2 and round down, element-wise
        %   STACK: 5, [1 2 3 4 5 6 7 8 9 10], [0 1 1 2 2 3 3 4 4 5]
Z~      % Bit-wise XOR, element-wise
        %   STACK: 5, [1 3 2 6 7 5 4 12 13 15]
t       % Duplicate
        %   STACK: 5, [1 3 2 6 7 5 4 12 13 15], [1 3 2 6 7 5 4 12 13 15]
b       % Bubble up
        %   STACK: [1 3 2 6 7 5 4 12 13 15], [1 3 2 6 7 5 4 12 13 15], 5
=       % Equality test, element-wise
        %   STACK: [1 3 2 6 7 5 4 12 13 15], [0 0 0 0 0 1 0 0 0 0]
f       % Find: yield (1-based) index of nonzero values (here there's only one)
        %   STACK: [1 3 2 6 7 5 4 12 13 15], 6
Q       % Increase by 1
        %   STACK: [1 3 2 6 7 5 4 12 13 15], 7
)       % Apply as index
        %   STACK: 4
B       % Convert to binary array
        %   STACK: [1 0 0]
        % Implicitly display

출력이 공백으로 구분 된 문자입니다 ... 어떤 종류의 배열을 인쇄합니까?
Patrick Roberts

@PatrickRoberts 그렇습니다. 나는 그것을 받아 들일 수 있다고 생각합니까?
Luis Mendo

그대로 받아들입니다. 이미 I / O 형식에 대한 요구 사항을 풀었으므로 다시 엄격하게 만들 필요는 없습니다. 좋은 작업.
Patrick Roberts

5

CJam (19 바이트)

{_2b__(^@1b1&*)^2b}

온라인 데모 . 비트 배열에서 비트 배열까지의 익명 블록 (함수)이며 데모는 루프에서 실행됩니다.

그것은 세트 비트의 수가 짝수이면 최하위 비트를 토글해야하고 그렇지 않으면 비트를 최하위 세트 비트의 왼쪽으로 토글해야한다는 간단한 원리로 작동합니다. 실제로 비트를 식별하는 것이 비트 목록을 사용하는 것보다 정수에서 비트 핵을 사용하는 것이 훨씬 쉬운 것으로 판명되었습니다.

해부

{         e# Declare a block:
  _2b     e#   Convert the bit array to a binary number
  __(^    e#   x ^ (x-1) gives 1s from the least significant set bit down
  @1b1&   e#   Get the parity of the number of set bits from the original array
  *       e#   Multiply: if we have an even number of set bits, we get 0;
          e#   otherwise we have 2**(lssb + 1) - 1
  )^      e#   Increment and xor by 1 or 2**(lssb + 1)
  2b      e#   Base convert back to a bit array
}

비트 배열로만 작업하면 역 배열이 필요하다고 생각합니다. 가장 왼쪽으로 작업하는 것이 가장 1오른쪽보다 훨씬 쉽습니다. 지금까지 찾은 최고는 (24 바이트)입니다.

{W%_1b)1&1$+1#0a*1+.^W%}

대체 접근 방식 (19 바이트)

{[{1$^}*]2b)_2/^2b}

이것은 회색 코드에서 색인으로, 증분으로, 그리고 다시 회색 코드로 변환합니다.


5

자바 스크립트 (ES6), 53 바이트 (비경쟁)

입력이 발견 될 때까지 모든 회색 코드를 작성하고 다음 반복에서 중지하는 재귀 함수입니다.

가능한 최대 입력은 브라우저 재귀 한계 (Firefox의 경우 약 13 비트, Chrome의 경우 15 비트)에 따라 다릅니다.

f=(s,n=1)=>(b=(n^n/2).toString(2),s)?f(b!=s&&s,n+1):b

console.log(f("1"));      // -> 11
console.log(f("11"));     // -> 10
console.log(f("111"));    // -> 101
console.log(f("1011"));   // -> 1001
console.log(f("1111"));   // -> 1110
console.log(f("10111"));  // -> 10110
console.log(f("101100")); // -> 100100
console.log(f("100000")); // -> 1100000


이 방법이 제한되지 않은 문자열 길이에 대해 작동하지 않기 때문에이 제출이 적합하지 않을까 걱정됩니다. 이 답변을 여기에 유지하려면 비경쟁으로 변경하십시오.
Patrick Roberts

@ 패트릭 로버츠-물론. 말이 되네요
Arnauld

@PatrickRoberts 정말요? 재귀 제한이 "환경에 의해 부과 된 메모리 제한"에 어떻게 포함되지 않습니까?
Sanchises

@sanchises 힙 메모리를 언급하고 있었지만 요점은이 프로그램이 가능한 모든 회색 코드에 대해 테스트중인 코드까지 반복되므로 매우 비효율적입니다. 기술적으로 이것은 "Node.js 6.5"로 제출 될 수 있으며 --harmony테일 콜 재귀 최적화에 액세스하기 위해 페널티 바이트를 추가했으며 여기에서 가능해 보입니다.
Patrick Roberts

@sanchises 내 답변을 살펴보면, 그것은 잘못된 주장이었습니다. 주요 문제는 환경에 의해 제한이 적용되지 않고 알고리즘에 의해 제한된다는 것입니다. 모든 증분 값이 아닌 모든 비트에 대해 반복되는 다른 답변이 있으며 훨씬 넓은 범위의 값에서 작동하기 때문에 더 받아 들일 수 있습니다.
Patrick Roberts

2

망막, 25 바이트

^(10*10*)*
$1:
1:
0
.?:
1

더 좋은 방법이 있어야한다고 생각합니다 ...


실제로 필요 ^합니까?
Ton Hospel

@TonHospel 정규 표현식은 그것없이 모든 곳에서 일치하려고했습니다. (바꾸기 모드는 전역 대체로 기본 설정됩니다.)
Neil

2

05AB1E , 12 바이트

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

CÐ<^¹SOÉ*>^b

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

설명

입력 1011의 예 .

C              # convert to int (bigint if necessary)
               # STACK: 11
 Ð             # triplicate
               # STACK: 11, 11, 11
  <            # decrease by 1
               # STACK: 11, 11, 10
   ^           # XOR
               # STACK: 11, 1
    ¹          # push first input
               # STACK: 11, 1, 1011
     S         # split to list
               # STACK: 11, 1, [1,0,1,1]
      O        # sum
               # STACK: 11, 1, 3
       É       # mod 2
               # STACK: 11, 1, 1
        *      # multiply
               # STACK: 11, 1
         >     # increase by 1
               # STACK: 11, 2
          ^    # XOR
               # STACK: 9
           b   # convert to binary
               # STACK: 1001
               # implicitly print top of stack

2

파이썬 2.7, 68 자

def f(s):i=long(s,2);print bin(i^(1,(i&-i)<<1)[s.count('1')&1])[2:]

파이썬 3, 68 자

def f(s):i=int(s,2);print(bin(i^(1,(i&-i)<<1)[s.count('1')&1])[2:])

이 함수는 주어진 이진 문자열을 정수로 변환하고 원래 문자열의 세트 비트 수가 짝수 인 경우 x 또는 마지막 비트를 변환하거나 원래 비트 세트의 수가 비트 인 경우 맨 오른쪽 세트 비트의 왼쪽으로 비트를 교환합니다. 문자열이 홀수입니다. 그런 다음 결과를 이진 문자열로 변환하고 0b부울 접두사를 제거합니다 .


1
대신에 def f(s):(Python 2로 가정) 후 공백을 제거하여 1 바이트를 절약 할 수 있습니다 . printreturn
ElPedro

@ElPedro 감사합니다, 나는 또한 조건 트릭을 적용하고 몇 가지 추가 문자를 저장하기 위해 xor의 왼쪽 크기를 고려했습니다 :)
Morwenn

그냥 봤어 좋은 답변 :-)
ElPedro

음 .. 파이썬 문서를 확인 int()하면 32 비트 정수를 생성하는 것처럼 보이지만 길이 문자열을 늘리는 것이 필요합니다. 이것이 유효한 제출물인지 자격이 확실하지 않습니다
Patrick Roberts

1
@PatrickRoberts 나중에 확인하겠습니다. long대신 int문제를 해결할 수 있습니다.
Morwenn

2

C ++, 205 바이트

#include <string>
std::string g(std::string s){int i,z;if(s=="1")return"11";for(i=z=0;i<s.length();i++)if(s[i]=='1')z++;i--;if(z%2){char c=s[i];s.erase(i);s=g(s);s+=c;}else{s[i]=s[i]==49?48:49;}return s;}

설명 : 짝수는 짝수입니다. 변수 z는 1을 센다; z짝수 인 경우 ( z mod 2 = z%2 = 0-그렇지 않은 경우 ) 마지막 비트를 변경하십시오. z홀수 인 경우 마지막 문자없이이 함수를 다시 호출하고 새 값을 계산 한 다음 마지막 문자를 추가하십시오.

테스트 사례를 보려면 여기를 클릭하십시오.


제출해 주셔서 감사합니다. 접근 방식에 대한 간단한 설명과 데모로 온라인 편집에 대한 링크를 제공 할 수 있다면 정말 감사하겠습니다.
Patrick Roberts

1
@PatrickRoberts 요청한대로 링크와 설명을 추가했습니다.
AlexRacer

2

배치, 199 197 바이트

@echo off
set/ps=
set r=
set t=%s:0=%
if 1%t:11=%==1 goto g
:l
set b=%s:~-1%
set s=%s:~,-1%
set r=%b%%r%
if %b%==0 goto l
if 0%s%==0 set s=0
:g
set/ab=1-%s:~-1%
echo %s:~,-1%%b%%r%

STDIN의 입력을 variable로 읽습니다 s. 0을 제거하고 1에서 패리티 검사를 수행하고 홀수가있는 경우 루프에서 가장 오른쪽에있는 0을 제거하고 1을 제거 할 때 중지합니다. s따라서 짝수 패리티 접두어와 r나머지 문자열이 포함됩니다. s마지막 숫자를 토글 할 수 있도록 비어있는 경우 0으로 설정되고 모든 것이 연결됩니다.


1

실제로 20 19 13 바이트

"입력보다 XOR의 누적 감소"라는 내 자신의 버전 으로 Martin Ender의 Jelly 답변 을 기반으로 합니다. 골프 제안을 환영합니다. 온라인으로 사용해보십시오!

σ1♀&2@¿u;½≈^├

언 골핑

      Implicit input a as a list, such as [1,0,1,1,0,0].
σ     Get the cumulative sums of a.
1♀&   Map x&1 (equivalent to x%2) over every member of the cumulative sum.
2@¿   Convert from binary to decimal.
u     Increment x.
;½≈   Duplicate and integer divide by 2.
^     XOR x and x//2.
├     Convert to binary to obtain our incremented Gray code.
      Implicit return as a string, such as "100100".

1

J, 38 바이트

[:#:@(22 b.<.@-:)@>:@#.[:22 b./[:#:#.\

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

이것은 본질적으로 J의 Martin 알고리즘입니다.

참고 22 b.XOR입니다.

                                    [: #: #.\   Creates the prefixes of the input
                                                converts to a number, then converts
                                                back to binary.  Needed to get the
                                                padding on the left.

                          [: 22 b./             Reduce the rows of the resulting 
                                                matrix with XOR, giving us the 
                                                normal binary
                      @#.                       Convert to int and...
                   @>:                          Increment and...
      (22 b. <.@-:)                             XOR that with its own floored half
[: #:@                                          And turn the result back to binary

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