Как да разберете дали две числа са последователни числа в сива кодова последователност

Опитвам се да намеря решение на проблема, че при дадени две числа да намеря дали те са последователните числа в поредицата от сиви кодове, т.е. дали са съседи на сиви кодове, като приемем, че поредицата от сиви кодове не е спомената.

Търсих в различни форуми, но не можах да намеря правилния отговор. Би било чудесно, ако можете да предоставите решение за това.

Моят опит за решаване на проблема - Преобразувайте две цели числа в двоични и добавете цифрите в двете числа поотделно и намерете разликата между сбора на цифрите в две числа. Ако разликата е една, тогава те са съседи със сив код.

Но смятам, че това няма да работи за всички случаи. Всяка помощ е високо оценена. Благодаря много предварително!!!


person user3923643    schedule 30.11.2014    source източник
comment
a и b са съседни кодове на сивото, ако се различават само в един бит, т.е. ако XOR b е степен на 2.   -  person Peter de Rivaz    schedule 01.12.2014
comment
Обърнете внимание, че тук има много кодови последователности на Грей. Имате ли предвид конкретна последователност или искате да знаете дали две числа могат да бъдат съседни в някаква последователност от кодове на Грей?   -  person ErikR    schedule 01.12.2014
comment
Благодаря много за вашите отговори. Възможно ли е да се знае дали дадените две числа са съседни със сив код в някаква последователност? Във въпроса не е посочена последователността. Попаднах в едно от интервютата. Всяка помощ се оценява!!!   -  person user3923643    schedule 01.12.2014


Отговори (9)


Трябваше да разрешавам и този въпрос на интервю. Едно от условията двете стойности да бъдат сива кодова последователност е стойностите им да се различават само с 1 бит. Ето решение на този проблем:

def isGrayCode(num1, num2):
    differences = 0
    while (num1 > 0 or num2 > 0):
        if ((num1 & 1) != (num2 & 1)):
            differences++
        num1 >>= 1
        num2 >>= 1
    return differences == 1
person David.Jones    schedule 30.11.2014
comment
Този отговор е грешен. Вижте Morwenn's отговор. - person Craig McQueen; 20.03.2015
comment
@DavidJones « [...] вярно е, че два съседни кода на Грей се различават само с един бит. Това обаче не означава, че два кода на Грей, които се различават с един бит, са съседни (a => b не означава, че b => a). » - person Morwenn; 20.03.2015

Всъщност няколко от другите отговори изглеждат грешни: вярно е, че два съседни двоично отразен код на Грей се различават само с един бит (предполагам, че под « » последователността от код на Грей имате предвид оригиналния двоично отразен код на Грей кодова последователност, както е описано от Франк Грей). Това обаче не означава, че два кода на Грей, които се различават с един бит, са съседни (a => b не означава, че b => a). Например кодовете на Грей 1000 и 1010 се различават само с един бит, но не са съседни (1000 и 1010 са съответно 15 и 12 в десетичен знак).

Ако искате да знаете дали два кода на Грей a и b са съседи, трябва да проверите дали previous(a) = b OR next(a) = b. За даден код на Грей получавате един съсед чрез обръщане на най-десния бит, а другият съседен бит чрез обръщане на бита отляво на най-десния зададен бит. За кода на Грей 1010 съседите са 1011 и 1110 (1000 не е един от тях).

Дали получавате предишния или следващия съсед чрез обръщане на един от тези битове всъщност зависи от паритета на кода на Грей. Въпреки това, тъй като искаме и двата съседа, не е нужно да проверяваме за паритет. Следният псевдокод трябва да ви каже дали два кода на Грей са съседни (използвайки C-подобни побитови операции):

function are_gray_neighbours(a: gray, b: gray) -> boolean
    return b = a ^ 1 OR
           b = a ^ ((a & -a) << 1)
end

Битов трик по-горе: a & -a изолира най-десния зададен бит в число. Преместваме този бит с една позиция наляво, за да получим бита, който трябва да обърнем.

person Morwenn    schedule 06.12.2014
comment
Страхотно решение. Това е най-добрият от всички и също правилният. Добра работа човече. - person Sameer Sawla; 15.12.2014
comment
Въз основа на приетия отговор на math.stackexchange.com/questions/965168/ , вашият псевдокод не може да премине през всички съседни възможности. Пример за две последователности на Грей код с еднаква дължина: [000,001,011,010,110,111,101,100], [000,001,011,111,101,100,110,010]. Кодът 000 може да има повече от два законни съседа. - person Di Wu; 22.10.2015
comment
@DiWu Разбира се, отговорът ми предполага двоично отразена кодова последователност на Грей, която обикновено е тази, за която хората се интересуват, когато нищо не е посочено. - person Morwenn; 22.10.2015

Предположения: Входове a и b са последователности от код на сиво в двоичен отразен код на сиво. т.е. битовото кодиране на a и b е представяне на двоичен сив код.

#convert from greycode bits into regular binary bits
def gTob(num): #num is binary graycode 
    mask = num >> 1
    while mask!=0:
        num = num^mask
        mask >>= 1
    return num; #num is converted 

#check if a and b are consecutive gray code encodings
def areGrayNeighbors(a,b):
    return abs(gTob(a) - gTob(b)) == 1

Няколко тестови случая:

  • areGrayNeighbors(9,11) --> True (тъй като (1001, 1011) се различават само с един бит и са последователни числа в десетично представяне)
  • areGrayNeighbors(9,10) --> False
  • areGrayNeighbors(14,10) --> True

Препратки: методът gTob(), използван по-горе, е от rodrigo в тази публикация The съседи в кода на Грей

person codeKaichu    schedule 27.12.2014

Ако две числа са в сива кодова последователност, те се различават с една двоична цифра. т.е. изключителното ИЛИ за двете числа връща степен на 2. Така че, намерете XOR и проверете дали резултатът е степен на две.

Това решение работи добре за всички тестови случаи, написани от CodeKaichu по-горе. Бих искал да знам дали не успява в някои случаи.

public boolean grayCheck(int x, int y) {
       int z = x^y;
       return (z&z-1)==0;
}
person Ravikanth    schedule 16.04.2015

Очевиден отговор, но работи. Преобразувайте всеки сив код в съответната му двоична форма, извадете двете. Ако отговорът ви е двоичен еквивалент на +1 или -1, тогава двата сиви кода са съседни.

Това изглежда като прекалено убийство, но когато участвате в интервю и не знаете правилния метод, това работи. Освен това за оптимизиране може да се провери филтърът за единични битови разлики, така че да не губим време в преобразуване и изваждане на числа, за които със сигурност знаем, че не са съседни.

person leo    schedule 07.09.2015

Ако просто искате да проверите дали въведените числа се различават само с един бит:

public boolean checkIfDifferByOneBit(int a, int b){
    int diff = 0;
    while(a > 0 && b > 0){
        if(a & 1 != b & 1)
            diff++;
        a = a >> 1;
        b = b >> 1;
    }
    if (a > 0 || b > 0) // a correction in the solution provided by David Jones
        return diff == 0 // In the case when a or b become zero before the other
    return diff == 1;
}
person codeKaichu    schedule 27.12.2014

Можете да проверите дали две числа се различават с един бит или не, както следва. При този метод се вземат предвид разликите в дължината на двоичните числа. Например изходът за 11 (1011) и 3 (11) ще бъде върнат като true. Също така, това не разрешава втория критерий за съседство на кода на Грей. Но ако искате само да проверите дали числата се различават с един бит, кодът по-долу ще ви помогне.

class Graycode{
    public static boolean graycheck(int one, int two){
        int differences = 0;
        while (one > 0 || two > 0){
            // Checking if the rightmost bit is same
            if ((one & 1) != (two & 1)){
                differences++;
            }
            one >>= 1;
            two >>= 1;
        }
        return differences == 1;
    }
    public static void main(String[] args){
        int one = Integer.parseInt(args[0]);
        int two = Integer.parseInt(args[1]);
        System.out.println(graycheck(one,two));
    }
}
person Aswin    schedule 02.03.2015
comment
За какво е гласът против? Ясно споменах, че този метод проверява само първите критерии. По време на интервюта в технологични компании ме помолиха да напиша кода за тази конкретна задача и те не се интересуваха от точния тест за съседство на Gray Code. - person Aswin; 17.04.2015

Ако две числа са в сива кодова последователност, те се различават с една двоична цифра. т.е. изключителното ИЛИ за двете числа връща степен на 2. Така че, намерете XOR и проверете дали резултатът е степен на две.

питон 3.8

a=int(input())
b=int(input())
x=a^b 
if((x and (not(x & (x - 1))) )):
    print("True")
else:
    print("False")
person kabali    schedule 21.11.2020
comment
Това изглежда не се различава от грешния приет отговор на David.Jones. - person greybeard; 21.11.2020

person    schedule
comment
Моля, добавете малко обяснение защо смятате, че това отговаря на въпроса на OP. - person iRuth; 26.03.2015
comment
Опитахте ли се да прочетете и разберете приетия отговор и този на Morwenn и защо те са оценени по различен начин? - person greybeard; 26.03.2015