Збільшення сірих кодів


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

...і так далі.

Об'єктивна

З огляду на непідставлений вхідний рядок сірого коду, збільшуйте сірий код шляхом чергування одного символу в послідовності або попередньо передбачуючи a 1(при збільшенні до наступної потужності 2), а потім виведіть результат у вигляді не забитого сірого коду.

Коваджі

  • Не турбуйтеся про те, як брати 0чи порожній рядок як вхід.
  • Найменшим входом буде 1, і немає верхньої межі довжини рядка, окрім обмежень пам'яті, накладених середовищем.
  • Під непорядним рядком я маю на увазі, що не буде провідної або кінцевої пробілів (крім необов'язкової кінцевої нової 0лінії ), а також немає провідних s у вході або виході.

Формати вводу / виводу

Наступні формати приймаються формою для введення та виводу, але рядки рекомендуються для інших форматів:

  • Перший найзначніший "біт"
  • масив символів або рядок ASCII '1's та '0's, що не містять символів
  • нерозкладений цілий масив 1s і 0s
  • непрокладений булівський масив

Що не дозволено:

  • найменш значущий "біт" спочатку
  • десятковий, двійковий чи одинарне ціле число
  • структура даних фіксованої довжини
  • масив символів або рядок недрукувальних індексів ASCII 1та0

Тести

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

Більше тестів можна додати за запитом.

Критерії

Це , тому найкоротша програма в байтах виграє! Усі зв'язки будуть порушені, якщо надавати перевагу більш раннім повідомленням застосовуються стандартні лазівки. Найкраща відповідь буде прийнята 9 жовтня 2016 року та оновлюється кожного разу, коли будуть надані кращі відповіді.



Чи можемо ми взяти введення як число?
xnor

1
Менш очевидно, також пов'язані .
Мартін Ендер

1
Чи можу я взяти зворотний і вхідний, і вихідний, наприклад, 0011для 8
тонного Євангелія

1
@TonHospel вибачте, що я не бачив вашого запитання щодо зворотного вводу / виводу. Як я сказав 1000000000, моя відповідь - ні.
Патрік Робертс

Відповіді:


13

Желе , 10 8 байт

Завдяки Деннісу за збереження 2-х байт.

^\Ḅ‘^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)

На щастя, Джелі, здається, автоматично подає входи при спробі їх 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 .
Денніс

@ Денніс Спасибі, я виявив це під час написання. :)
Мартін Ендер

@MartinEnder Чи є ціле число, яке воно перетворює у внутрішнє велике ціле число?
Патрік Робертс

@PatrickRoberts так, якщо потрібно - це Python під кришкою.
Джонатан Аллан

Приємний аналіз та пояснення.
Вейн Конрад

8

JavaScript (ES6), 58 байт

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

Безпосередньо перемикає відповідний біт. Пояснення: Як показано у відповіді MartinEnder ♦, кожен біт у розшифрованому коді Грея - це сукупний XOR або парність самого себе та бітів зліва. Потім нам потрібно збільшити число, яке спричиняє пульсацію перенесення, яка перемикає всі найправіші 1 біт на 0, а потім наступний 0 біт на 1. Повторне кодування призводить до коду з таким зміненим лише 0 бітовим положенням. Якщо парність усіх 1 біт є парною, то найправіший біт дорівнює 0, і тому ми просто перемикаємо останній біт. Якщо парність усіх 1 біт непарна, то найправіші біти дорівнюють 1, і нам потрібно знайти останній 1 біт. Зараз це останній з перенесених бітів, тому біт, який нам потрібно переключити, - це наступний біт справа.


Дуже приємний метод. Є першим ?в /.?(?=10*$)/дійсно необхідно? О, ніколи не пам'ятаю. Так. :-)
Арнольд

8

Perl, 27 25 байт

Включає +1 для -p

Наведіть рядок введення на STDIN, наприклад

gray.pl <<< 1010

gray.pl:

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

Perl не має дешевих цілих нескінченних цілих чисел. Тож безпосередньо перемикайте правий біт, який є самим раніше, де буде останній непарний номер 1.


1
Ух, \Gсправді полегшує вам справи!
Ніл

1
З іншого боку, \Kробить вас ще простішими.
Ніл

Хааааа ... Тепер я хочу бачити і \Gреалізацію.
Magic Octopus Urn

2
@carusocomputing Ви можете переглянути старіші версії подання, натиснувши відредаговане посилання
Тон Хоспел

6

Haskell, 118 115 108 байт

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-заповненням), fвикликів gз length(input)+1, видаляє всі елементи до тих пір , 0<inputstring>поки буде знайдений і повертає наступний елемент (усічення , можливо , призведе 0).


1
Гарна перша відповідь! Я сподіваюсь, що незабаром ми зможемо отримати ще ефективніші.
Патрік Робертс

5

MATL , 18 байт

ZBtE:t2/kZ~tb=fQ)B

Спробуйте в Інтернеті! Або перевірити всі тестові випадки .

Пояснення

Нехай a ( n ) позначає послідовність цілих чисел, що відповідають кодам Грея ( OEIS A003188 ). Програма використовує характеристику a ( n ) = n поверх XOR ( n / 2), де XOR є бітовим.

За суті, код перетворює вхідні дані в ціле число в 0 , знахідки , які ціле число в послідовності, а потім вибирає наступний член. Для цього потрібно генерувати достатньо велику кількість доданків послідовності a ( n ). Виявляється, 2 · a 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

Я помічаю, що вихід - це обмежені місцями символи ... це друк якогось масиву?
Патрік Робертс

@PatrickRoberts Так, саме так. Я припустив, що це прийнятно, чи не так?
Луїс Мендо

Я прийму це як є. Я вже послабив свої вимоги до формату вводу-виводу, тому немає сенсу робити його більш суворим. Хороша робота.
Патрік Робертс

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

JavaScript (ES6), 53 байти (не конкуруючий)

Рекурсивна функція, яка будує всі сірі коди до введення, а потім зупиняється на наступній ітерації.

Найвищий можливий вхід залежить від межі рекурсії браузера (близько 13 біт у Firefox та 15 біт у 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


Я боюся, що це подання не відповідає вимогам, оскільки метод не працює для необмеженої довжини рядків. Будь ласка, перейдіть на неконкурентоспроможні, якщо ви хочете залишати цю відповідь тут.
Патрік Робертс

@PatrickRoberts - Звичайно. Що має сенс.
Арнольд

@PatrickRoberts Дійсно? Як межа рекурсії не підпадає під "обмеження пам'яті, накладені навколишнім середовищем"?
Санчіз

@sanchises Я мав на увазі купу пам’яті, але, до речі, ця програма повторюється для кожного можливого сірого коду, аж до того, що тестується, що вкрай неефективно. Технічно це може бути подано як "Node.js 6.5" і --harmonyдодано до байтових штрафних санкцій, щоб мати доступ до оптимізації рекурсії виклику хвоста, яка, здається, можлива тут.
Патрік Робертс

@sanchises Переглядаючи мою відповідь, це був поганий аргумент. Основне питання полягає в тому, що обмеження не накладається середовищем, це накладається алгоритмом. Є й інші відповіді, які повторюються для кожного біта, а не для кожного додаткового значення, і я вважаю їх більш прийнятними, оскільки він працює для набагато більшого діапазону значень.
Патрік Робертс

2

Сітківка, 25 байт

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

Я впевнений, що має бути кращий спосіб зробити це ...


Вам справді потрібні ^?
Тон Євангелія

@TonHospel Регекс намагався відповідати всюди без нього. (Замініть за замовчуванням режим на глобальну заміну.)
Ніл

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

Python 2.7, 68 символів

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

Python 3, 68 символів

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

Ця функція перетворює задану двійкову рядок у ціле число, а потім xor останній біт, якщо число встановлених бітів у вихідній рядку є парним, або заміняє біт ліворуч від самого правого встановленого біта, якщо кількість встановлених бітів в оригіналі рядок непарний. Потім він перетворює результат у двійковий рядок і видаляє 0bбулевий префікс.


1
Ви можете зберегти 1 байт, видаливши пробіл після def f(s):та (припускаючи Python 2) інший, використовуючи printзамість return.
ElPedro

@ElPedro Спасибі, я також застосував умовний трюк і визначив лівий розмір xor, щоб зберегти кілька додаткових символів :)
Morwenn

Щойно це побачив. Приємна відповідь :-)
ElPedro

Гм .. перевіряючи документацію python, схоже, int()генерується 32-бітове ціле число, хоча моя вимога полягає в тому, щоб ви збільшували будь-яку довжину рядка. Я не впевнений, що це кваліфікується як дійсне подання
Патрік Робертс

1
@PatrickRoberts я перевірю пізніше. longзамість того, щоб intвирішити проблему.
Морвен

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підраховують одиниці; якщо zрівний ( z mod 2 = z%2 = 0- ще гілка), змініть останній біт; якщо zце не дивно, викличте цю функцію ще раз без останнього символу та обчисліть нове значення, а потім додайте останній символ.

Клацніть тут, щоб спробувати це для тестових випадків.


Дякуємо за ваше подання Якщо ви можете надати короткий опис свого підходу та посилання на онлайн-збірку цього як демонстраційного, я б дуже вдячний за це.
Патрік Робертс

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 в змінну s. Видаляє 0s і робить перевірку парності на 1s, і якщо є непарне число, воно знімає найправіший 0s у циклі, зупиняючись, коли він позбавляє a 1. sтому містить парний префікс парності та rрешту рядка. sвстановлюється на нуль, якщо він був порожнім, щоб його останню цифру можна було перемкнути, а потім все з’єднати.


1

Власне, 20 19 13 байт

На основі відповідь Jelly Мартина Ендера з моєю власною версією "накопичувального зменшення XOR над введеним". Пропозиції з гольфу вітаються. Спробуйте в Інтернеті!

σ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 байт

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

Спробуйте в Інтернеті!

Це по суті алгоритм Мартіна в Дж.

Зауважте, що 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

Гарна робота, чувак!
Патрік Робертс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.