A xor X = B + X এর সমাধান অনুসন্ধানের জন্য অ্যালগরিদম


46

পূর্ণসংখ্যা A এবং B দেওয়া হয়েছে, পূর্ণসংখ্যার এক্সটি সন্ধান করুন যাতে:

  • এ, বি <2 * 1e18
  • একটি এক্সওর এক্স = বি + এক্স

আমি অত্যন্ত সন্দেহ করি গণিত ব্যবহার করে এই সমীকরণটি সমাধান করা সম্ভব। এটি একটি কোডিং সমস্যা যা আমি 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
@ সোমাগ্রোগ্রামারডুড এটাই যদি a এবং b হয় বুলিয়ান ভেরিয়েবল, অর্থাৎ 0 বা 1 হয়, এবং xor একটি বুলিয়ান জোর। বিটওয়াইস এক্সরে সংযোগ কী?
জন কুগেলম্যান

1
তদ্ব্যতীত, আমি মনে করি এখানে নিষ্ঠুর শক্তি ব্যবহার করা যদি আপনি এমন কিছু লিখতে চান না যা আরও সাধারণ সমীকরণ প্রমাণ করতে পারে। বিবেচনা করুন যে আপনার কোডটি সঠিক কিনা তা নিশ্চিত হওয়ার জন্য আপনাকে পরীক্ষা করতে হবে এবং একটি ব্রুট ফোর্স অ্যালগরিদমের বিরুদ্ধে পরীক্ষা করা সবচেয়ে সহজ হবে তবে তারপরে আপনি প্রথমে ব্রুট ফোর্সটি ব্যবহার করতে পারেন। অন্যদিকে গণিত প্রয়োগ করা শেষ পর্যন্ত কোনও কোড চালানো অপ্রয়োজনীয় করে তুলবে।
idclev 463035818

1
@ মোলবডনিলো ওহ, একটি মন্তব্যে পরামর্শ দেওয়া হয়েছিল যে একটি xor b = a + b mod 2 এবং আমি ভেবেছিলাম এটিও পূর্ণসংখ্যাকে বোঝায়। আমি আমার পোস্টের সেই অংশটি সরিয়ে দেব।
এএএএএ

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 এর জন্য বি তে বিট নেই যা এ, (((এ - বি) >> 1) বা ওয়াই) এর সমাধান। আপনি যদি কেবল একটি সমাধান চান তবে আপনি ((A - B) >> 1) ব্যবহার করতে পারেন, যেখানে Y = 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"বহন সহ সংযোজন" তাই প্রথম সমীকরণটি বোঝা যায়।
justhalf

3
(A and X)<<1এটি মূলত 2*(A and X)এবং কারণ এটি এর সমান A-Bবলে যে A এবং B উভয় অদ্ভুত বা উভয় ইভেন্ট হলেই সমস্যার সমাধান হতে পারে।
axiac

1
আমি ভেবেছিলাম এর বিয়োগের সাথে কিছু করার আছে তবে আমি সময় মতো এ আসিনি।
এসএস অ্যান

38

এটা খুবই কঠিন না, আপনি শুধু ছোট চিন্তা করতে হবে: অনুমান করা আমরা লিখছেন A, Bএবং Xবাইনারি এবং Aᵢমান ডানদিকের 2 সংশ্লিষ্ট বিট।

আমরা জানি যে: Aₒ ⊕ Xₒ = Bₒ + Xₒ

আসুন কীভাবে এটি মূল্যায়ন করতে হয় তা আবিষ্কার করতে একটি উদাহরণ ব্যবহার করুন: এ = 15 এবং বি = 6. বাইনারি রূপান্তর:

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

এখন আমাদের কিছু সম্ভাবনা আছে। আসুন এ এবং বি এর ডানদিকের বিটগুলি বিশ্লেষণ করুন:

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

সুতরাং সন্তুষ্ট হওয়া কোনও এক্স খুঁজে পাওয়া সর্বদা সম্ভব হবে না A ⊕ X = B + X , একটি মান কারণ নেই dসন্তুষ্ট যে 1 + d = 0 + d

যাইহোক, যদি এক্স উপস্থিত থাকে, আপনি ঠিক এইভাবে এটি ডান থেকে বামে খুঁজে পেতে পারেন bit


কাজ সম্পূর্ণ উদাহরণ

এ = 15, বি = 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 

এখানে, ডি = 0 এবং ডি = 1 উভয়ই প্রয়োগ করে, তবে কী? আমাদের পরবর্তী বিট পরীক্ষা করা উচিত। ধরুন ডি = 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)

সুতরাং এই ক্ষেত্রে, ডি 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

এখানে a 0 এবং 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;
}

আপনি এটি এখানে পরীক্ষা করতে পারেন ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.