Binary Path

After read Dr. D.E.Knuth's book, Mr. Bpt finds an interesting thing.

As we all known, a decimal number may be represented in binary form. For example, we are able to use (101)2 represent (5)10. And decimal number set {0, 1, 2, 3} can be changed to {00, 01, 10, 11} in binary. If we put them into a certain order, we can get a sequence like 00,01,11,10. And in this sequence, each two adjacent numbers have one and only one different digit (we can assume there are some zeros in the front of each number so that all of them have the same length) including the first number 00 and the last number 10.

Now Mr. Bpt has confirmed that to any non-negative integer N, there are such sequences formed by integer 0, 1, ... , 2N-1 as described above. Mr. Bpt wants you to help him to find the "smallest" sequence. "Smallest" means the first number in this sequence should not be bigger than the first number in other sequences. If there are some sequences having same first number, you should compare the second number and so on until you find the unique sequence.

Input

 

Input only contain one integer N as mentioned above (0<= N <= 18).
(Please use standard input, and don’t read or write files.)

Output

Output contains 2N line, every line contains one number, and put them in decimal, which represents the sequence Mr. Bpt wants.
(Please use standard output, and don’t read or write files.)

Sample Input

2

Sample Output

0

1

3

2

Source

'Crazy for Programming'Nankai University Programming Contest V

==================================================================

這個題目剛開始想了很久,後來想起了數字邏輯的卡諾圖。

雖然卡諾圖能夠很方便地找到相鄰兩個只變一位的二進制數,但是其多維的複雜度很可怕,而且經常會有走入死衚衕的危險。然而,現在我們遇到的這個問題可能並不適合用卡諾圖解決。

後來,隨便把楊老師的教材看了看,發現了格雷碼(Gray Code)。而這個問題,有點類似Gray Code,只是這個問題是有序。

趁這個機會,把可靠性編碼之一——Gray Code複習一下:

=====================================================

在數字系統中只能識別01,各種數據要轉換爲二進制代碼才能進行處理,格雷碼是一種無權碼,採用絕對編碼方式,典型格雷碼是一種具有反射特性和循環特性的單步自補碼,它的循環、單步特性消除了隨機取數時出現重大誤差的可能,它的反射、自補特性使得求反非常方便。格雷碼屬於可靠性編碼,是一種錯誤最小化的編碼方式,因爲,自然二進制碼可以直接由數/模轉換器轉換成模擬信號,但某些情況,例如從十進制的3轉換成4時二進制碼的每一位都要變,使數字電路產生很大的尖峯電流脈衝。而格雷碼則沒有這一缺點,它是一種數字排序系統,其中的所有相鄰整數在它們的數字表示中只有一個數字不同。它在任意兩個相鄰的數之間轉換時,只有一個數位發生變化。它大大地減少了由一個狀態到下一個狀態時邏輯的混淆。另外由於最大數與最小數之間也僅一個數不同,故通常又叫雷反射碼或循環碼。

From Gossip@caterpillar

Algorithm Gossip: 格雷碼(Gray Code

說明

Gray Code是一個數列集合,每個數使用二進位來表示,假設使用n位元來表示每個數好了,任兩個數之間只有一個位元值不同,例如以下為3位元的Gray Code

000 001 011 010 110 111 101 100


由定義可以知道,Gray Code的順序並不是唯一的,例如將上面的數列反過來寫,也是一組Gray Code

100 101 111 110 010 011 001 000


Gray Code
是由貝爾實驗室的Frank Gray1940年代提出的,用來在使用PCMPusle Code Modulation)方法傳送訊號時避免出錯,並於1953年三月十七日取得美國專利。

解法

由於Gray Code相鄰兩數之間只改變一個位元,所以可觀 Gray Code10或從01時的位置,假設有4位元的Gray Code如下:

0000 0001 0011 0010 0110 0111 0101 0100
1100 1101 1111 1110 1010 1011 1001 1000


觀察奇數項的變化時,我們發現無論它是第幾個Gray Code,永遠只改變最右邊的位元,如果是1就改為0,如果是0就改為1

觀察偶數項的變化時,我們發現所改變的位元,是由右邊算來第一個1的左邊位元。

以上兩個變化規則是固定的,無論位元數為何;所以只要判斷位元的位置是奇數還是偶數,就可以決定要改變哪一個位元的值,為了程式撰寫方便,將陣列索引 0當作最右邊的值,而在列印結果時,是由索引數字大的開始反向列印。

2位元的Gray Code當作平面座標來看,可以構成一個四邊形,您可以發現從任一頂點出發,繞四邊形周長繞一圈,所經過的頂點座標就是一組Gray Code,所以您可以得到四組Gray Code

同樣的將3位元的Gray Code當作平面座標來看的話,可以構成一個正立方體,如果您可以從任一頂點出發,將所有的邊長走過,並不重複經過頂點的話,所經過的頂點座標順序之組合也就是一組Gray Code

實作

·                C

 

 

 

·                Java

·                 

 

 

 

 

 

老古論壇:

1)格雷碼為無權值碼,不適合做運算。
(2)
是一種最小變化碼,其最主要特性是任意相鄰兩數,只有一個Bit改變,因此,適合做資
料傳輸、類比/數位轉換、輸出入裝置等。
(3)
具有上下反射性,所以又稱為反射數碼

 

(4)二進碼轉換成格雷碼:

        1.二進碼之MSB即為格雷碼之MSB

        2.二進碼之MSB起,兩兩Bit做互斥運算,即是相對應之格雷碼。

     27(D)之格雷碼

解:    27(D) = 1 1 0 1 1 B
          1  1  0  1  1  B
方法:先將低倆位進行異或,11異或得0,再01異或得1,再10異或得1,再11異或得0,然後
高位照寫,結果爲:10110GRAY)。

          

    (5)格雷碼轉換成二進碼:

        1.格雷碼之MSB,即為二進碼的MSB

        2.二進碼的MSB與格雷碼的次高Bit做互斥運算,其結果即是二進碼的次高Bit,以
此方式進行運算即可。

 2     1 1 0 1 0 1 (Gray)轉換成二進碼

解:       110101G=100110B

你的格雷碼:203G=1100000010G)轉換爲二進制爲:10 0000 0011B

我的將二進制轉化成Gray Code的代碼:

 

 

問題:

 

雖然Gray Code和這個題目看似相關,n=2時答案也正確,但是畢竟還是有些不同。有高手嗎,支招?

 

 

 

public class GrayCode {
private char[] digit;
private boolean first;
private boolean odd;
private int count;

public GrayCode(int length) {
digit = new char[length];
for(int i = 0; i < length; i++) {
digit[i] = '0';
}

first = true;
odd = true;
}

public boolean hasNext() {
// 計算第一個1的位置
for(count = 0;
(count < digit.length) && (digit[count] == '0');
count++) ;
return count != digit.length - 1;
}

public char[] next() {
if(first) {
first = false;
return digit;
}

if(odd)
chargeBit(digit, 0);
else {
// 最後一個Gray Code 嗎
if(hasNext())
chargeBit(digit, count+1);
}

odd = ((odd == true) ? false : true);

return digit;
}

private void chargeBit(char[] digit, int i) {
digit[i] = ((digit[i] == '0') ? '1' : '0');
}

public static void main(String[] args) {
GrayCode code = new GrayCode(4);

while(code.hasNext()) {
char[] digit = code.next();
for(int i = digit.length - 1; i >= 0; i--)
System.out.print(digit[i]);
System.out.println();
}
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章