ए एक्सोर एक्स = बी + एक्स के लिए एक समाधान खोजने के लिए एल्गोरिदम


46

पूर्णांक A और B को देखते हुए पूर्णांक X खोजें ताकि:

  • ए, बी <2 * 1 ई 18
  • एक एक्सोर एक्स = बी + एक्स

मुझे अत्यधिक संदेह है कि गणित का उपयोग करके इस समीकरण को हल करना संभव है। यह एक कोडिंग समस्या है जो मुझे 3 साल पहले आई थी और अब भी मैं इसे हल नहीं कर सकता।

मेरा अब तक का कोड: (यह जानवर बल समाधान है)

#include <iostream>

using namespace std;

int main()
{

    unsigned long long a, b;
    cin >> a >> b;
    for (unsigned long long x = 1; x < max(a, b); x++) {
        unsigned long long c = a ^ x;
        unsigned long long d = b + x;
        if (c == d) {
            cout << x << endl;
            break;
            return 0;
        }
    }

    cout << -1; //if no such integer exists

    return 0;
}

11
यदि आप विशेष के बारे में थोड़ा अधिक पढ़ते हैं या आपको बीजीय समतुल्यता का पता लगाना चाहिए a xor b = a + b mod 2। थोड़ी देर के लिए उस समानता के बारे में सोचने की कोशिश करें।
कुछ प्रोग्रामर ने

16
@Someprogrammerdude यह है कि यदि a और b बूलियन वैरिएबल हैं, तो या तो 0 या 1 है, और Xor बूलियन है। बिटवाइर एक्सर से क्या संबंध है?
जॉन कुगेलमैन

1
fwiw, मुझे लगता है कि जब तक आप कुछ ऐसा नहीं लिखना चाहते, जो सामान्य समीकरणों को साबित कर सकता है, तब तक यहां बल प्रयोग का तरीका है। इस बात पर विचार करें कि आपको अपने कोड का परीक्षण यह सुनिश्चित करने के लिए करना होगा कि यह सही है और सबसे आसान एक ब्रूट फोर्स एल्गोरिदम के खिलाफ परीक्षण करना होगा, लेकिन फिर आप पहले स्थान पर ब्रूट बल का उपयोग कर सकते हैं। दूसरी ओर, गणित को लागू करना अंततः किसी भी कोड को चलाने के लिए अनावश्यक बना देगा।
इडक्लेव 463035818

1
@molbdnilo ओह, टिप्पणियों में से एक ने सुझाव दिया कि एक xor b = a + b mod 2 और मुझे लगा कि यह पूर्णांकों को भी संदर्भित करता है। मैं अपने पोस्ट के उस हिस्से को हटा दूंगा।
AAAAA

1
@ जॉन्कगेलमैन उनका मतलब था mod 2गणितीय (मॉड 2), अर्थात 3 === 7 (मॉड 2)। मुद्दा यह है कि आप एक्स के पहले बिट के लिए एक समीकरण खोज सकते हैं, फिर अगले बिट पर जाएं जहां (कैरी का सम्मान करते हुए) आपको दूसरे बिट के लिए एक समीकरण मिलता है, आदि, जैसे डैनियल का जवाब।
मैक्स लैंगहॉफ़

जवाबों:


45

ध्यान दें A + X == (A xor X) + ((A and X)<<1)। इसलिए:

A xor X = A + X - ((A and X)<<1) = B + X
A - B = (A and X)<<1

और हमारे पास है:

(A - B) and not (A<<1) = 0    (All bits in (A - B) are also set in (A<<1))
(A - B)>>1 = A and X

यदि शर्त पूरी हो जाती है, तो किसी भी पूर्णांक Y के लिए जिनके पास A में सेट बिट्स नहीं हैं, (((A - B) >> 1) या Y) एक समाधान है। यदि आप सिर्फ एक समाधान चाहते हैं, तो आप ((ए - बी) >> 1) का उपयोग कर सकते हैं, जहां वाई = 0. अन्यथा कोई समाधान नहीं है।

int solve(int a, int b){
    int x = (a - b) >> 1;
    if ((a ^ x) == b + x)
        return x;
    else
        return ERROR;
}

15
+1। यह A xor X"कैरी के बिना जोड़" है, और ((A and X)<<1)"इसके अतिरिक्त ले" है। चूंकि A + X"कैरी के साथ जोड़" है, पहला समीकरण समझ में आता है।
जस्टफुल

3
(A and X)<<1मूल रूप से है 2*(A and X)और क्योंकि यह बराबर है क्योंकि A-Bयह कहता है कि समस्या का समाधान केवल तभी हो सकता है जब ए और बी दोनों विषम या दोनों घटना हो।
एक्सियाक

1
मुझे लगा कि इसमें घटाव के साथ कुछ करना होगा लेकिन मैं समय पर नहीं आया।
एसएस ऐनी

38

यह बहुत कठिन नहीं है, आपको बस छोटा सोचने की जरूरत है: मान लें कि हम लिख रहे हैं A, Bऔर Xबाइनरी में और Aᵢसबसे सही 2 most बिट के अनुरूप मूल्य है ।

हम जानते हैं कि Aₒ ⊕ Xₒ = Bₒ + Xₒ:।

आइए इसका मूल्यांकन करने के लिए एक उदाहरण का उपयोग करें: A = 15 और B = 6. बाइनरी में परिवर्तित करना:

A = 1 1 1 1           B = 0 1 1 0
X = a b c d           X = a b c d

अब हमारे पास कुछ संभावनाएं हैं। आइए A और B के सबसे सही बिट्स का विश्लेषण करें:

1  d = 0 + d

हम जानते हैं कि dकेवल 0 या 1 हो सकता है, इसलिए:

for d = 0
1  d = 0 + d    =>    1  0 = 0 + 0    =>    1 = 0 (not possible)

for d = 1
1  d = 0 + d    =>    1  1 = 0 + 1    =>    0 = 1 (not possible)

यह ध्यान देने योग्य है कि XOR द्विआधारी राशि की तरह व्यवहार करता है (इस अंतर के साथ कि XOR अगले बिट योग के लिए एक कैरीओवर नहीं बनाता है):

    XOR           SUM
0  0 = 0  |   0 + 0 = 0
0  1 = 1  |   0 + 1 = 1
1  0 = 1  |   1 + 0 = 1
1  1 = 0  |   1 + 1 = 0

इसलिए ऐसा X हमेशा खोजना संभव नहीं होगा जो संतुष्ट करता हो A ⊕ X = B + X, क्योंकि कोई ऐसा मूल्य नहीं है dजो संतुष्ट करता हो 1 + d = 0 + d

वैसे भी, यदि X मौजूद है, तो आप इसे केवल इस तरह से पता कर सकते हैं, दाएं से बाएं, थोड़ा-थोड़ा करके।


पूरा पूरा काम

A = 15, B = 7:

A = 1 1 1 1           B = 0 1 1 1
X = a b c d           X = a b c d

1  d = 1 + d 

यहाँ, दोनों d = 0 और d = 1 लागू होते हैं, फिर क्या? हमें अगले बिट की जांच करने की आवश्यकता है। मान लीजिए d = 1:

A = 1 1 1 1           B = 0 1 1 1
X = a b c d           X = a b c d

1  d = 1 + d    =>    1  1 = 1 + 1    =>    0 = 0 (possible)

BUT 1 + 1 = 0 generates a carryover for the next bit sum:

Instead of 1  c = 1 + c, we have 1  c = 1 + c (+1) =
                                   1  c = c  (not possible)

तो इस मामले में, d 0 होना चाहिए।

carryover                              0
         A = 1 1 1 1           B = 0 1 1 1
         X = a b 0 0           X = a b 0 0
        -----------------------------------
                   0                     0

we know that c must be 0:

carryover                            0 0
         A = 1 1 1 1           B = 0 1 1 1
         X = a b 0 0           X = a b 0 0
        -----------------------------------
                 1 1                   1 1

लेकिन बी के बारे में क्या? हमें हमेशा की तरह अगले बिट की जांच करने की आवश्यकता है:

if b = 0, there won't be a carryover, so we'll have:

1  a = 0 + a  (and this is not possible)

so we try b = 1:

1  b = 1 + b    =>    1  1 = 1 + 1    =>    0 = 0 (with carryover)

और अब, के लिए a:

carryover                          1 0 0
         A = 1 1 1 1           B = 0 1 1 1
         X = a 1 0 0           X = a 1 0 0
        -----------------------------------
               0 0 0                 0 0 0


1  a = 0 + a (+1)    =>    1  a = 1 + a

यहां a0 और 1 हो सकते हैं, लेकिन यह राशि में कैरीओवर से बचने के लिए 0 होना चाहिए B + X

फिर, X = 0 1 0 0इस प्रकार एक्स = 4।


कोड

#include <iostream>
using namespace std;

inline int bit(int a, int n) {
    if(n > 31) return 0; 
    return (a & ( 1 << n )) >> n; 
}

int main(){
    int A = 19;
    int B = 7;

    int X = 0;
    int carryover = 0;
    int aCurrent, aNext, bCurrent, bNext;

    for(int i = 0; i < 32; i++){
        aCurrent =  bit(A, i);      bCurrent =  bit(B, i);
        aNext =     bit(A, i + 1);  bNext =     bit(B, i + 1);

        if(aCurrent == 0 && bCurrent == 0){
            if(carryover) {X = -1; break;}
            if(aNext != bNext){
                X += 1 << i;
            }
            carryover = 0;
        }
        else if(aCurrent == 0 && bCurrent == 1){
            if(!carryover) {X = -1; break;}
            if(aNext == bNext){
                X += 1 << i;
            }
            carryover = 1;
        }
        else if(aCurrent == 1 && bCurrent == 0){
            if(!carryover) {X = -1; break;}
            if(aNext != bNext){
                X += 1 << i;
                carryover = 1;
            }
            else {
                carryover = 0;
            }
        }
        else if(aCurrent == 1 && bCurrent == 1){
            if(carryover) {X = -1; break;}
            if(aNext != bNext){
                X += 1 << i;
                carryover = 1;
            }
            else {
                carryover = 0;
            }
        }

    }

    if(X != -1) cout<<"X = "<<X<<endl;
    else cout<<"X doesnt exist"<<endl;

    return 0;
}

आप इसे यहाँ परीक्षण कर सकते हैं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.