Mã màu xám tăng


36

Giới thiệu

Một Mã Grey là một thay thế cho biểu diễn nhị phân trong đó một số được tăng lên bằng cách chuyển đổi qua lại chỉ có một chút, chứ không phải là một số lượng biến của các bit. Dưới đây là một số mã màu xám cùng với số thập phân và tương đương nhị phân của chúng:

 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

Mô hình bit tuần hoàn của mã màu xám

Đôi khi được gọi là "nhị phân phản xạ", thuộc tính chỉ thay đổi một bit tại một thời điểm có thể dễ dàng đạt được với các mẫu bit tuần hoàn cho mỗi cột bắt đầu từ bit có trọng số thấp nhất:

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

... và cứ thế.

Mục tiêu

Đưa ra chuỗi đầu vào không đệm của mã màu xám, tăng mã màu xám bằng cách xen kẽ một ký tự trong chuỗi hoặc thêm vào một 1(khi tăng lên lũy thừa 2), sau đó xuất kết quả dưới dạng mã màu xám không đệm.

Hãy cẩn thận

  • Đừng lo lắng về việc lấy 0hoặc một chuỗi trống làm đầu vào.
  • Đầu vào thấp nhất sẽ là 1và không có giới hạn trên của độ dài chuỗi ngoài các giới hạn bộ nhớ được áp đặt bởi môi trường.
  • Theo chuỗi không đệm, ý tôi là sẽ không có khoảng trắng ở đầu hoặc cuối (ngoài dòng mới theo dõi tùy chọn) và không có 0s hàng đầu trong đầu vào hoặc đầu ra.

Định dạng I / O

Các định dạng sau đây là hình thức được chấp nhận cho đầu vào và đầu ra, nhưng các chuỗi được khuyến khích hơn các định dạng khác:

  • "bit" quan trọng nhất đầu tiên
  • mảng ký tự không đệm hoặc chuỗi của ASCII '1's và '0's
  • mảng số nguyên không đệm của 1s và 0s
  • mảng boolean không đệm

Những gì không được phép:

  • "bit" đáng kể đầu tiên
  • số nguyên thập phân, nhị phân hoặc đơn nguyên
  • cấu trúc dữ liệu có độ dài cố định
  • mảng ký tự hoặc chuỗi các chỉ mục ASCII không in được 10

Xét nghiệm

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

Nhiều bài kiểm tra có thể được thêm vào theo yêu cầu.

Tiêu chí

Đây là , vì vậy chương trình ngắn nhất tính bằng byte thắng! Tất cả các mối quan hệ sẽ bị phá vỡ bằng cách ủng hộ đệ trình trước đó; sơ hở tiêu chuẩn áp dụng. Câu trả lời được gửi tốt nhất sẽ được chấp nhận vào ngày 9 tháng 10 năm 2016 và được cập nhật bất cứ khi nào có câu trả lời tốt hơn.



Chúng ta có thể lấy đầu vào là một số?
xnor

1
Ít rõ ràng hơn, cũng liên quan .
Martin Ender

1
Tôi có thể đảo ngược cả đầu vào và đầu ra không, ví dụ như 0011trong 8
TonMedel

1
@TonHosp xin lỗi tôi không thấy câu hỏi của bạn về I / O đảo ngược. Như tôi đã nói 1000000000 câu trả lời của tôi là không.
Patrick Roberts

Câu trả lời:


13

Thạch , 10 8 byte

Cảm ơn Dennis vì đã tiết kiệm 2 byte.

^\Ḅ‘^H$B

Đầu vào và đầu ra là danh sách 0 và 1.

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

Giải trình

Nghịch đảo mã Gray được đưa ra bởi A006068 . Sử dụng điều này, chúng tôi không cần phải tạo ra một số lượng lớn mã Gray để tra cứu đầu vào. Một phân loại của chuỗi này được đưa ra trên OEIS là:

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

Trường hợp []là dấu ngoặc sàn. Hãy xem xét ví dụ về 44đại diện nhị phân của nó 101100. Chia cho 2 và sàn chỉ là một sự thay đổi đúng, cắt bỏ phần ít quan trọng nhất. Vì vậy, chúng tôi đang cố gắng XOR các số sau

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

Lưu ý rằng ncột thứ chứa các nbit đầu tiên . Do đó, công thức này có thể được tính toán một cách tầm thường trên đầu vào nhị phân dưới dạng giảm tích lũy XOR trong danh sách (về cơ bản áp dụng XOR cho từng tiền tố của danh sách và cung cấp cho chúng tôi danh sách kết quả).

Điều này cho chúng ta một cách đơn giản để đảo ngược mã Gray. Sau đó, chúng tôi chỉ cần tăng kết quả và chuyển đổi lại thành mã Gray. Đối với bước sau, chúng tôi sử dụng định nghĩa sau:

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

Rất may, Jelly dường như tự động chuyển các đầu vào khi cố gắng XOR chúng. Dù sao, đây là mã:

^\          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.

Bạn không cần Ḟ$; toán tử bitwise đúc để int .
Dennis

@Dennis Cảm ơn, tôi phát hiện ra rằng trong khi viết lên. :)
Martin Ender

@MartinEnder Là số nguyên mà nó chuyển đổi thành bên trong một số nguyên lớn?
Patrick Roberts

@PatrickRoberts có, nếu cần - đó là Python dưới mui xe.
Jonathan Allan

Phân tích và giải thích tốt đẹp.
Wayne Conrad

8

JavaScript (ES6), 58 byte

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

Trực tiếp bật bit thích hợp. Giải thích: Như được hiển thị trong câu trả lời của MartinEnder ♦, mỗi bit trong mã Gray được giải mã là XOR tích lũy, hoặc tính chẵn lẻ của chính nó và các bit ở bên trái. Sau đó, chúng ta cần tăng số gây ra một gợn sóng mang tất cả các bit 1 bên phải thành 0 và sau đó 0 bit tiếp theo thành 1. Mã hóa lại kết quả trong một mã chỉ với một vị trí 0 bit được bật. Nếu tính chẵn lẻ của tất cả 1 bit là chẵn thì bit ngoài cùng bên phải là 0 và do đó chúng ta chỉ cần chuyển bit cuối cùng. Nếu tính chẵn lẻ của tất cả 1 bit là số lẻ, thì các bit ngoài cùng bên phải là 1 và chúng ta cần tìm 1 bit cuối cùng. Đây là bit cuối cùng được mang theo, vì vậy bit chúng ta cần chuyển đổi là bit tiếp theo từ bên phải.


Phương pháp rất hay. Là người đầu tiên ?trong /.?(?=10*$)/thực sự cần thiết? Ồ, đừng bận tâm. Đúng vậy :-)
Arnauld

8

Perl, 27 25 byte

Bao gồm +1 cho -p

Đưa ra chuỗi đầu vào trên STDIN, vd

gray.pl <<< 1010

gray.pl:

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

Perl không có số nguyên chính xác vô hạn giá rẻ. Vì vậy, trực tiếp chuyển bit bên phải là bit ngay trước nơi số 1 lẻ cuối cùng sẽ là.


1
Wow, \Gthực sự làm cho mọi thứ dễ dàng cho bạn!
Neil

1
Mặt khác, \Klàm cho mọi thứ thậm chí dễ dàng hơn cho bạn.
Neil

Haaaaa ... Bây giờ tôi cũng muốn xem việc \Gthực hiện.
Bạch tuộc ma thuật Urn

2
@carusocomputing Bạn có thể xem các phiên bản cũ hơn của bài gửi bằng cách nhấp vào liên kết đã chỉnh sửa
TonMedel

6

Haskell, 118 115 108 byte

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

Hãy thử nó trên Ideone.
Cách tiếp cận ngây thơ: gtạo tập hợp tất cả các mã màu xám có độ dài n(với 0 đệm), fgọi gvới length(input)+1, loại bỏ tất cả các phần tử cho đến khi 0<inputstring>được tìm thấy và trả về phần tử tiếp theo (cắt bớt phần dẫn có thể 0).


1
Câu trả lời đầu tiên tốt! Tôi hy vọng chúng ta có thể sớm nhận được một số hiệu quả hơn.
Patrick Roberts

5

MATL , 18 byte

ZBtE:t2/kZ~tb=fQ)B

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

Giải trình

Đặt a ( n ) biểu thị chuỗi số nguyên tương ứng với mã Gray ( OEIS A003188 ). Chương trình sử dụng đặc tính a ( n ) = n XOR floor ( n / 2), trong đó XOR là bit-khôn ngoan.

Về cơ bản, mã chuyển đổi đầu vào thành một số nguyên một 0 , phát hiện rằng số nguyên trong dãy, và sau đó chọn hạn tiếp theo. Điều này đòi hỏi phải tạo ra một số lượng lớn các điều khoản của chuỗi a ( n ). Nó chỉ ra rằng 2 · a 0 là đủ lớn. Điều này xuất phát từ thực tế là mã Gray a ( n ) không bao giờ có nhiều chữ số nhị phân hơn n .

Hãy lấy đầu vào '101'làm ví dụ.

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

Tôi nhận thấy đầu ra là các ký tự được phân tách bằng dấu cách ... nó có đang in một số mảng không?
Patrick Roberts

@PatrickRoberts Vâng, chính xác. Tôi cho rằng nó chấp nhận được, phải không?
Luis Mendo

Tôi sẽ chấp nhận nó như hiện tại. Tôi đã nới lỏng các yêu cầu của mình về định dạng I / O, vì vậy không có lý do gì để làm cho nó nghiêm ngặt hơn nữa. Công việc tốt.
Patrick Roberts

5

CJam (19 byte)

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

Bản demo trực tuyến . Đây là một khối ẩn danh (hàm) từ mảng bit đến mảng bit, mà bản demo thực hiện trong một vòng lặp.

Nó hoạt động theo nguyên tắc đơn giản là nếu số bit được đặt chẵn thì chúng ta nên chuyển bit có trọng số thấp nhất và nếu không, chúng ta nên chuyển bit sang bên trái của bit set ít quan trọng nhất. Trên thực tế, việc xác định bit đó hóa ra dễ dàng hơn nhiều khi sử dụng các bit hack trên một số nguyên so với sử dụng danh sách các bit.

Mổ xẻ

{         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
}

Chỉ làm việc với mảng bit, tôi nghĩ cần phải đảo ngược nó: làm việc với phần bên trái dễ nhất 1nhiều so với phần bên phải. Điều tốt nhất tôi tìm thấy cho đến nay là (24 byte):

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

Cách tiếp cận khác (19 byte)

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

Điều này chuyển đổi từ mã Gray sang chỉ mục, tăng và chuyển đổi lại thành mã Gray.


5

JavaScript (ES6), 53 byte (không cạnh tranh)

Hàm đệ quy xây dựng tất cả các mã màu xám cho đến khi tìm thấy đầu vào, sau đó dừng ở lần lặp tiếp theo.

Đầu vào cao nhất có thể phụ thuộc vào giới hạn đệ quy của trình duyệt (khoảng 13 bit trong Firefox và 15 bit trong Chrome).

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


Tôi e rằng bài nộp này không đủ điều kiện, vì phương thức này không hoạt động với độ dài chuỗi không giới hạn. Vui lòng thay đổi thành không cạnh tranh nếu bạn muốn giữ câu trả lời này ở đây.
Patrick Roberts

@PatrickRoberts - Chắc chắn rồi. Điều đó có ý nghĩa.
Arnauld

@PatrickRoberts Thật sao? Làm thế nào để giới hạn đệ quy không thuộc "giới hạn bộ nhớ do môi trường."?
Sanchises

@sanchises Tôi đã đề cập đến bộ nhớ heap, nhưng quan trọng hơn, chương trình này đệ quy cho mọi mã màu xám có thể cho đến mã được kiểm tra, cực kỳ kém hiệu quả. Về mặt kỹ thuật, điều này có thể được gửi dưới dạng "Node.js 6.5" và đã --harmonythêm các byte hình phạt để có quyền truy cập vào tối ưu hóa đệ quy cuộc gọi đuôi, điều này dường như có thể có ở đây.
Patrick Roberts

@sanchises Nhìn qua trả lời của tôi, đó là một lập luận kém. Vấn đề chính là giới hạn không bị áp đặt bởi môi trường, nó bị áp đặt bởi thuật toán. Có những câu trả lời khác lặp lại cho mỗi bit thay vì cho mỗi giá trị gia tăng và tôi thấy những câu trả lời đó dễ chấp nhận hơn vì nó hoạt động cho phạm vi giá trị rộng hơn nhiều.
Patrick Roberts

2

Võng mạc, 25 byte

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

Tôi cảm thấy chắc chắn nên có cách tốt hơn để làm điều này ...


Bạn có thực sự cần ^ ?
TonMedel

@TonHosp Các regex đã cố gắng để phù hợp với mọi nơi mà không có nó. (Thay thế chế độ mặc định thành thay thế toàn cầu.)
Neil

2

05AB1E , 12 byte

Sử dụng mã hóa CP-1252 .

CÐ<^¹SOÉ*>^b

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

Giải trình

Ví dụ cho đầu vào 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

Python 2.7, 68 ký tự

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

Python 3, 68 ký tự

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

Hàm này chuyển đổi chuỗi nhị phân đã cho thành một số nguyên sau đó xor bit cuối cùng nếu số bit được đặt trong chuỗi gốc là chẵn hoặc bit của nó đổi bit sang trái của bit được đặt ngoài cùng bên phải nếu số bit được đặt trong gốc chuỗi là số lẻ. Sau đó, nó chuyển đổi kết quả thành một chuỗi nhị phân và loại bỏ 0btiền tố boolean.


1
Bạn có thể lưu 1 byte bằng cách xóa khoảng trắng sau def f(s):và (giả sử Python 2) khác bằng cách sử dụng printthay vì return.
ElPedro

@ElPedro Cảm ơn, tôi cũng đã áp dụng một mẹo điều kiện và tìm ra kích thước bên trái của một xor để lưu thêm một vài ký tự :)
Morwenn

Chỉ cần nhìn thấy điều đó. Câu trả lời hay :-)
ElPedro

Ừm .. kiểm tra tài liệu python, có vẻ như int()tạo ra một số nguyên 32 bit, mặc dù yêu cầu của tôi là bạn phải tăng bất kỳ chuỗi độ dài nào. Tôi không chắc chắn rằng điều này đủ điều kiện là một đệ trình hợp lệ
Patrick Roberts

1
@PatrickRoberts Tôi sẽ kiểm tra sau. longthay vì intcó thể giải quyết vấn đề.
Morwenn

2

C ++, 205 byte

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

Mô tả: Số chẵn có số chẵn. Biến zsố đếm; nếu zlà chẵn ( z mod 2 = z%2 = 0- nhánh khác), thay đổi bit cuối cùng; nếuz là số lẻ, hãy gọi lại hàm này mà không có ký tự cuối cùng và tính giá trị mới, sau đó nối thêm ký tự cuối cùng sau đó.

Nhấn vào đây để thử nó cho các trường hợp thử nghiệm.


Cảm ơn bạn đã gửi. Nếu bạn có thể cung cấp một mô tả ngắn về cách tiếp cận của bạn và một liên kết đến một bản tổng hợp trực tuyến này dưới dạng bản demo, tôi thực sự đánh giá cao điều đó.
Patrick Roberts

1
@PatrickRoberts Đã thêm liên kết và mô tả như bạn yêu cầu.
AlexRacer

2

Hàng loạt, 199 197 byte

@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%

Đọc đầu vào từ STDIN thành biến s. Loại bỏ các số 0 và thực hiện kiểm tra chẵn lẻ trên các số 1 và nếu có một số lẻ, nó sẽ loại bỏ các số 0 bên phải trong một vòng lặp, dừng lại khi nó tước một 1. sdo đó chứa tiền tố chẵn lẻ và rphần còn lại của chuỗi. sđược đặt thành 0 nếu nó trống để chữ số cuối cùng của nó có thể được bật, và sau đó mọi thứ được nối với nhau.


1

Trên thực tế, 20 19 13 byte

Dựa trên câu trả lời Jelly của Martin Ender với phiên bản "giảm XOR tích lũy so với đầu vào" của riêng tôi. Gợi ý chơi golf chào mừng. Hãy thử trực tuyến!

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

Ungolfing

      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 byte

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

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

Đây thực chất là thuật toán của Martin trong J.

Lưu ý đó 22 b.là 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

Làm tốt lắm, anh bạn!
Patrick Roberts
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.