Gri Kodların Artırılması


36

Giriş

Bir gri kod sayısı sadece bir bit yerine bit değişken miktarda geçiş artırılır ki burada ikili gösterimi için bir alternatiftir. İşte ondalık ve ikili eşdeğerleriyle birlikte bazı gri kodlar:

 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

Gri Kodun Döngüsel Bit Deseni

Bazen "yansıyan ikili" olarak adlandırılır, bir seferde sadece bir bit değiştirme özelliği, en az anlamlı bitten başlayarak her sütun için döngüsel bit desenleriyle kolayca elde edilir:

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

...ve bunun gibi.

Amaç

Bir gri kodun yastıklı olmayan bir giriş dizgisine bakıldığında, sıradaki tek bir karakteri değiştirerek veya bir kod hazırlayarak gri kodu artırın 1( 2'nin bir sonraki gücünü artırırken ), ardından sonucu yastıklı olmayan bir gri kod olarak verin.

Uyarılar

  • 0Giriş olarak endişelenmeyin ya da boş bir dize.
  • En düşük giriş olacaktır 1ve ortamın dayattığı bellek sınırlamaları dışında dize uzunluğuna bir üst sınır yoktur.
  • Dolgulu olmayan dize ile demek istediğim, öndeki veya sondaki beyaz boşluk (isteğe bağlı sondaki yeni satır dışında) ve 0giriş veya çıkışta satır aralığı olmayacak .

G / Ç formatları

Aşağıdaki biçimler girdi ve çıktı için kabul edilir, ancak dizeler diğer biçimlere göre teşvik edilir:

  • ilk önce en anlamlı "bit"
  • dolgulu olmayan karakter dizisi veya ASCII '1's ve '0's dizeleri
  • 1s ve 0s doldurmasız tam sayı dizisi
  • dolgulu olmayan boolean dizisi

Nelere izin verilmiyor:

  • ilk önce en az anlamlı "bit"
  • ondalık, ikili veya tekli tam sayı
  • sabit uzunlukta veri yapısı
  • yazdırılamayan ASCII endekslerinin karakter dizisi veya dizesi 1ve0

Testler

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

İstek üzerine daha fazla test eklenebilir.

Kriterler

Bu , bayt cinsinden en kısa program kazanıyor! Tüm bağlar daha önceki başvuruları destekleyerek kopacak; standart boşluklar uygulanır. Gönderilen en iyi cevap 9 Ekim 2016'da kabul edilecek ve daha iyi cevaplar verildiğinde güncellenecektir.



Girdiyi sayı olarak alabilir miyiz?
xnor

1
Daha az açıkçası, aynı zamanda ilgili .
Martin Ender

1
Hem girişi hem de çıkışı tersine alabilir miyim, örneğin 00118
Ton Hospel için

1
@TonHospel üzgünüm tersine çevrilmiş G / Ç ile ilgili sorunuza bir şey görmedim. 1000000000’de dediğim gibi cevabım hayır.
Patrick Roberts

Yanıtlar:


13

Jöle , 10 8 bayt

2 bayt kaydettiğiniz için Dennis'e teşekkür ederiz.

^\Ḅ‘^H$B

Giriş ve çıkış 0 ve 1 lerin listesidir.

Çevrimiçi deneyin!

açıklama

Gri kodun tersi A006068 tarafından verilir . Bunu kullanarak girişi aramak için çok sayıda Gray kodu oluşturmamız gerekmez. OEIS'te verilen bu dizinin bir sınıflandırması şudur:

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

[]Zemin dirsekleri nerede . 44İkili gösterimi olan örneği düşünün 101100. İkiye bölme ve döşeme, en az önemli olan kısmı keserek sadece bir sağa kaymadır. Bu yüzden aşağıdaki numaraları XOR yapmaya çalışıyoruz

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

nTh sütununun ilk nbitleri içerdiğine dikkat edin . Bu nedenle, bu formül trivial olarak ikili girişte XOR'nin kümülatif indirgenmesi olarak hesaplanabilir (temel olarak listeyi her bir önek için XOR uygular ve sonuçların bir listesini verir).

Bu bize Gray kodunu ters çevirmenin basit bir yolunu verir. Daha sonra sonucu arttırır ve tekrar Gray koduna dönüştürürüz. İkinci adım için aşağıdaki tanımı kullanıyoruz:

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

Neyse ki, Jelly XOR'ları girmeye çalışırken girişleri otomatik olarak yapıyor gibi görünüyor. Neyse, işte kod:

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

İhtiyacınız yok Ḟ$; bitsel operatörler int olarak yayınlanır .
Dennis,

@Dennis Teşekkürler, yazarken keşfettim. :)
Martin Ender,

@MartinEnder Dahili olarak büyük bir tam sayıya dönüştürdüğü tam sayı mı?
Patrick Roberts,

@PatrickRoberts evet, gerekirse - bu başlık altında Python.
Jonathan Allan,

Güzel analiz ve açıklama.
Wayne Conrad

8

JavaScript (ES6), 58 bayt

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

Uygun biti doğrudan değiştirir. Açıklama: MartinEnder'in cevabında gösterildiği gibi, kodu çözülmüş bir Gray kodundaki her bir bit, kendisinin kümülatif XOR'si veya paritesi ve solundaki bitlerdir. Daha sonra en sağdaki 1 bit'i 0'a ve ardından sonraki 0 ​​bit'i 1'e geçiren bir taşıma dalgalanmasına neden olan sayıyı arttırmamız gerekir. Yeniden kodlama, sadece bir tane 0 bit pozisyonlu bir kodla sonuçlanır. Tüm 1 bitlerin paritesi eşitse, o zaman en sağdaki bit 0 olur ve bu yüzden sonuncuyu değiştiririz. Tüm 1 bitlerin paritesi tuhafsa, en sağdaki bit 1'dir ve son 1 biti bulmamız gerekir. Bu şimdi taşınan bitlerin sonuncusu, bu yüzden değiştirmemiz gereken bit sağdan sonraki bit.


Çok güzel bir yöntem. İlk ?giren /.?(?=10*$)/gerçekten gerekli mi? Oh aldırma. Evet öyle. :-)
Arnauld

8

Perl, 27 25 bayt

İçin +1 içerir -p

STDIN'de giriş dizesi verin, örneğin

gray.pl <<< 1010

gray.pl:

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

Perl'de ucuz sonsuz tamsayı yoktur. Böylece doğrudan, son tek numaralı 1'in olacağı hemen önceki olan doğru ucu değiştirin.


1
Vay, \Ggerçekten işleri senin için kolaylaştırıyor!
Neil,

1
Öte yandan, \Kişleri sizin için daha da kolaylaştırıyor.
Neil

Haaaaa ... Şimdi de \Guygulamayı görmek istiyorum .
Magic Octopus Urn

2
@carusocomputing Bir gönderimin eski versiyonlarını, düzenlenen bağlantıya tıklayarak görebilirsiniz
Ton Hospel

6

Haskell, 118 115 108 bayt

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'da dene.
Naif yaklaşım: guzunluğa sahip tüm gri kodlar dizisini oluşturur n, (0-dolgu ile) fçağırır gile length(input)+1kadar tüm öğeleri kaldırır 0<inputstring>sonraki elemanını (muhtemelen öncü kesiliyor bulunan ve döner 0).


1
İyi ilk cevap! Umarım yakında daha verimli olanlar bulabiliriz.
Patrick Roberts,

5

MATL , 18 bayt

ZBtE:t2/kZ~tb=fQ)B

Çevrimiçi deneyin! Veya tüm test durumlarını doğrulayın .

açıklama

Let bir ( n ) Gri kodları (karşılık gelen tam sayı dizisini ifade OEIS A003188 ). Program, a ( n ) = n XOR katının ( n / 2) karakterizasyonunu kullanır , burada XOR bitidir.

Temel olarak, kod girişi bir 0 tamsayısına dönüştürür, dizideki tam sayıyı bulur ve ardından bir sonraki terimi seçer. Bu, a ( n ) dizisinin yeterince fazla sayıda terimini üretmesini gerektirir . Tesiste 2 · çıkıyor bir 0 yeterince büyüktür. Bu Grey kod olmasından kaynaklanıyor bir ( n ) asla daha ikili basamak n .

'101'Örnek olarak girdi alalım.

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

Çıktının boşlukla ayrılmış karakterler olduğunu farkettim ... bir tür dizi mi yazdırıyor?
Patrick Roberts

@PatrickRoberts Evet, kesinlikle. Kabul edilebilir olduğunu varsaydım, değil mi?
Luis Mendo,

Olduğu gibi kabul edeceğim. Gereksinimlerimi G / Ç formatında zaten gevşetmiştim, bu yüzden tekrar daha katı hale getirmenin bir anlamı yok. İyi iş.
Patrick Roberts

5

CJam (19 bayt)

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

Çevrimiçi demo . Bu anonim bir bloktur (fonksiyon), bit dizisinden bit dizisine, demonun bir döngü içinde çalıştırdığı.

Basit prensipte çalışır, eğer set bit sayısı bile en az anlamlı biti değiştirmeliyiz, aksi takdirde biti, en az anlamlı set biti'nin soluna değiştirmeliyiz. Aslında bu biti tanımlamak, bir tamsayıdaki bit kesmelerini kullanmak, bit listesini kullanmaktan çok daha kolay olur.

teşrih

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

Yalnızca bit dizisiyle çalışmak, onu tersine çevirmek gerektiğini düşünüyorum: en solda çalışmak, en sağdan 1daha kolaydır. Şimdiye kadar bulduğum en iyisi (24 byte):

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

Alternatif yaklaşım (19 bayt)

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

Bu Gray kodundan endekse, artışları ve Gray koduna geri dönüştürür.


5

JavaScript (ES6), 53 bayt (yarışmaz)

Giriş bulunana kadar tüm gri kodları oluşturan tekrarlayan bir işlev, ardından bir sonraki yinelemede durur.

Mümkün olan en yüksek giriş tarayıcı yineleme sınırına bağlıdır (Firefox'ta yaklaşık 13 bit ve Chrome'da 15 bit).

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


Maalesef bu gönderim geçerli değil çünkü yöntem sınırsız dize uzunlukları için çalışmıyor. Lütfen bu cevabı burada tutmak istiyorsanız, rekabete aykırı olarak değiştirin.
Patrick Roberts,

@PatrickRoberts - Tabi. Bu mantıklı.
Arnauld,

@PatrickRoberts Gerçekten mi? Bir özyineleme sınırı “çevre tarafından uygulanan bellek sınırlamaları” altına nasıl girmez?
Sanchises

@ sanchises Yığın hafızasına değiniyordum, fakat daha önemlisi, bu program test edilene kadar her olası gri kod için, bu da son derece verimsizdir. Teknik olarak bu "Node.js 6.5" olarak sunulabilir ve --harmonyburada mümkün olduğu görünen kuyruk çağrısı özyineleme optimizasyonuna erişebilmek için ceza baytları için eklenmiş olabilir.
Patrick Roberts

@sanchises Cevabımı inceleyerek, bu zayıf bir tartışma oldu. Asıl sorun, sınırlamanın çevre tarafından getirilmemesi, algoritma tarafından getirilmesidir. Her artan değerden ziyade her bit için yinelenen başka cevaplar var ve çok daha geniş bir değer aralığında çalıştığından, bunları daha kabul edilebilir buluyorum.
Patrick Roberts,

2

Retina, 25 bayt

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

Bunu yapmanın daha iyi bir yolu olması gerektiğinden eminim ...


Gerçekten ihtiyacın var ^mı?
Ton Hospel

@TonHospel Regex onsuz her yerde eşleşmeye çalıştı. (Mod varsayılanını global bir değiştirme ile değiştirin.)
Neil

2

05AB1E , 12 bayt

CP-1252 kodlamasını kullanır .

CÐ<^¹SOÉ*>^b

Çevrimiçi deneyin!

açıklama

1011 girişi için örnek .

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 karakter

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

Python 3, 68 karakter

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

Bu işlev verilen ikilik dizgiyi bir tamsayıya dönüştürür, ardından orijinal dizgideki set bitlerinin sayısı eşitse son bit xor'a dönüştürür, ya da orijinal bit setindeki bitlerin sayısı bitse, bit en sağdaki bit bitinin soluna kaydırılır dize garip. Sonra sonucu bir ikili dizeye dönüştürür ve 0bboolean öneki kaldırır .


1
Boşluktan sonra def f(s):ve (Python 2 varsayarak) printyerine boşluk bırakarak 1 byte tasarruf edebilirsiniz return.
ElPedro,

@ElPedro Teşekkürler, aynı zamanda bir durum numarası yaptım ve bir kaç karakter daha kaydetmek için
xor'un

Sadece bunu gördüm. Güzel cevap :-)
ElPedro 4:16

Um .. python belgelerini kontrol ederken, int()32 bitlik bir tamsayı üretiyor gibi gözükmeme rağmen, benim isteğim herhangi bir uzunluktaki dizgeyi arttırmanızdır. Bunun geçerli bir gönderi olarak nitelendirildiğinden emin değilim
Patrick Roberts

1
@PatrickRoberts Sonra kontrol edeceğim. longyerine intsorunu çözebilir.
Morwenn

2

C ++, 205 bayt

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

Açıklama: Sayıların bile çift sayısı vardır. Değişken zolanları sayar; eğer zeşitse ( z mod 2 = z%2 = 0- başka dal), son biti değiştirin; zTek ise , bu işlevi son karakter olmadan tekrar çağırın ve yeni değeri hesaplayın, ardından son karakteri ekleyin.

Test durumları için denemek için buraya tıklayın.


Gönderdiğiniz için teşekkürler. Yaklaşımınızın kısa bir açıklamasını ve bunun bir demo olarak çevrimiçi derlenmesini içeren bir bağlantı sunabilirseniz, bunu gerçekten takdir ediyorum.
Patrick Roberts

1
@PatrickRoberts İstediğiniz gibi bağlantıyı ve açıklamayı ekledi.
AlexRacer

2

Toplu iş, 199 197 bayt

@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'den girişi değişkene okur s. 0'ları kaldırır ve 1'lerde bir eşlik kontrolü yapar ve tek bir sayı varsa, bir döngüde en sağdaki 0'ları çıkarır, bir sıyırdığında durur, bu snedenle eşit parite önekini ve rdizenin geri kalanını içerir. sboşsa sıfıra ayarlanır, böylece son basamağı değiştirilir ve sonra her şey birleştirilir.


1

Aslında, 20 19 13 bayt

Martin Ender'in Jelly'inden yola çıkarak, "girişte XOR birikimli azalması" kendi sürümümle cevap verdim. Golf önerileri kabul edilir. Çevrimiçi deneyin!

σ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 bayt

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

Çevrimiçi deneyin!

Bu aslında J'nin Martin'deki algoritması.

22 b.XOR olduğuna dikkat edin .

                                    [: #: #.\   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

Güzel iş dostum!
Patrick Roberts
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.