グレーコードの増分


36

前書き

A グレイコード番号は1ビットだけではなく、ビットの可変量を切り替えるだけインクリメントされたバイナリ表現に対する代替です。以下に、10進数および2進数に対応するいくつかのグレーコードを示します。

 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

グレイコードのサイクリックビットパターン

「反射バイナリ」と呼ばれることもありますが、一度に1ビットのみを変更する特性は、最下位ビットから始まる各列の循環ビットパターンで簡単に実現できます。

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'sおよび'0'sの文字列
  • 1sおよび0sの非埋め込み整数配列
  • パディングされていないブール配列

許可されていないもの:

  • 最下位の「ビット」が最初
  • 10進、2進、または単項整数
  • 固定長データ構造
  • 非印字可能な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
あまり明らかでないが、関連する
マーティンエンダー

1
入力と出力の両方を逆にすることはできますか(例:00118
Ton Hospel

1
@TonHospel申し訳ありませんが、I / Oの逆についての質問はありませんでした。私が1000000000に言ったように、私の答えはノーです。
パトリックロバーツ

回答:


13

ゼリー10 8バイト

2バイトを節約してくれたDennisに感謝します。

^\Ḅ‘^H$B

入力と出力は、0と1のリストです。

オンラインでお試しください!

説明

グレイコードの逆数はA006068で与えられます。これを使用すると、入力を検索するために多数のグレーコードを生成する必要がありません。OEISで指定されたこのシーケンスの1つの分類は次のとおりです。

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

nth列には最初の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ありがとう、書いている間にそれを発見した。:)
マーティンエンダー

@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に切り替えるキャリーリップルを引き起こす数値をインクリメントする必要があります。再エンコードすると、その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物事はあなたのためにさらに簡単になります。
ニール

Haaaaa ...今、私\Gも実装を見たいです。
魔法のタコUr

2
あなたはをクリックして提出の古いバージョンを見ることができます@carusocomputing 編集したリンク
トンHospel

6

Haskell、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パディング付き)をf呼び出すglength(input)+1、まで、すべての要素を削除する0<inputstring>次の要素(おそらくは主要切り捨て見出され、リターン0)を。


1
良い最初の答え!より効率的なものをすぐに入手できることを願っています。
パトリックロバーツ

5

MATL、18バイト

ZBtE:t2/kZ~tb=fQ)B

オンラインでお試しください!または、すべてのテストケースを確認します

説明

ましょう(nは)グレイコード(に対応する整数のシーケンス示しOEIS A003188に)。プログラムは、キャラクタリゼーションan)= n XOR floor(n / 2)を使用します。XORはビット単位です。

基本的に、コードは入力を整数a 0に変換し、シーケンス内のその整数を見つけて、次の用語を選択します。これには、シーケンスan)の十分な数の項を生成する必要があります。2・a 0は十分に大きいことがわかります。これは、グレイコードan)がnより多くの2進数字を持たないという事実に起因します。

入力'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はい、正確に。許容範囲内だと思いましたか?
ルイスメンドー

そのまま受け入れます。I / O形式に関する要件は既に​​緩和されているため、再び厳密にする必要はありません。良くやった。
パトリックロバーツ

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バイト(非競合)

入力が見つかるまですべてのグレーコードを作成し、次の反復で停止する再帰関数。

入力可能な最大値は、ブラウザーの再帰制限(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


メソッドは無制限の文字列の長さでは機能しないため、この送信は資格がないと思います。ここでこの回答を維持したい場合は、非競合に変更してください。
パトリックロバーツ

@PatrickRoberts-もちろん。それは理にかなっている。
アーナルド

@PatrickRoberts本当に?再帰制限は、「環境によって課されるメモリ制限」に該当しないのはどうしてですか?
-Sanchises

@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:])

この関数は、指定されたバイナリ文字列を整数に変換し、元の文字列の設定ビット数が偶数の場合は最後のビットをx、または元の設定ビット数が右端の設定ビットの左にある場合文字列が奇数です。次に、結果をバイナリ文字列に変換し、0bブールプレフィックスを削除します。


1
の代わりにdef f(s):を使用して、次のスペース(Python 2を想定)を削除することで1バイト節約できます。printreturn
エルペドロ

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

説明:偶数には1の偶数があります。変数zは1をカウントします。場合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から入力をvariableに読み取りますs。0を削除し、1でパリティチェックを実行します。奇数がある場合、ループの右端の0を削除し、1を削除すると停止します。sしたがって、偶数のパリティプレフィックスとr残りの文字列が含まれます。s最後の桁を切り替えることができるように空白の場合はゼロに設定され、すべてが連結されます。


1

実際には、20 19 13バイト

に基づく Martin EnderのJellyの回答に、「入力に対するXORの累積的な削減」の独自バージョンを作成しました。ゴルフの提案を歓迎します。オンラインでお試しください!

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