তৃতীয় ভেরিয়েবল ব্যবহার না করে দুটি ভেরিয়েবল মান অদলবদল করা


104

একটি সাক্ষাত্কারে জিজ্ঞাসা করা খুব জটিল প্রশ্নগুলির একটি।

মত দুটি ভেরিয়েবল মূল্যবোধের অদলবদল a=10এবং b=15

সাধারণত দুটি ভেরিয়েবলের মান অদলবদল করতে আমাদের তৃতীয় ভেরিয়েবলের দরকার:

temp=a;
a=b;
b=temp;

এখন প্রয়োজন, 3 য় ভেরিয়েবল ব্যবহার না করে দুটি ভেরিয়েবলের মান অদলবদল করুন।


76
কি দারুন. আইএমএইচওর পক্ষে খারাপভাবে নির্বাচিত একটি সাক্ষাত্কার প্রশ্ন। এটি এমন একটি কৌশল যা অনুশীলনে খুব কমই ব্যবহৃত হয় if এটির একটি খুব ভাল সম্ভাবনা রয়েছে যে এটি কেবল সংস্থার অপ্টিমাইজারকে বিভ্রান্ত করবে যার ফলস্বরূপ "অস্থায়ী অদলবদল" এর চেয়ে কম দক্ষ কোড তৈরি হবে। আপনি যেখানে এই জায়গাতে সাক্ষাত্কারটি দিচ্ছেন তা না থাকলে খুব গাণিতিক ভারী জিনিসগুলিতে জড়িত না হন (মনে করুন: এনক্রিপশন অ্যালগরিদম বিকাশ বা এর মতো) এই জাতীয় প্রশ্ন জিজ্ঞাসার কোনও ভাল কারণ আমি কল্পনা করতে পারি না।
ড্যান মোল্ডিং

10
প্রকৃতপক্ষে, এই প্রশ্নটি আপনাকে প্রার্থী এই নির্দিষ্ট কৌশলটি জানেন কিনা যা প্রোডাকশন কোডে বেশ বেহুদা। আমি মনে করি আপনি মাঝেমধ্যে উইজার্ড জুড়ে দৌড়াতে পারেন যিনি এটিকে ফ্লাইতে দেখিয়েছেন, তবে এর মতো লোকেরা যারা ইতিমধ্যে কৌশলটি জানেন না তারা সম্ভবত খুব বিরল বলে মনে করছেন।
ceo

2
হতে পারে তারা এমন লোকদের ঘায়েল করতে চায় যারা মনে করে যে এই জাতীয় কৌশলগুলি কী জেনে রাখা ভাল প্রোগ্রামারকে পরিণত করে? এছাড়াও, জোর ট্রিক সম্পর্কে পড়ার সময়, কখন এটি ব্যর্থ হবে (মনোযোগ দিন) যা সাধারণ-উদ্দেশ্য পূর্ণসংখ্যার অদলবদলের জন্য আইএমও এটিকে পুরোপুরি অকেজো করে তোলে)।
আঙ্কেলবেন্স 15

উত্তর:


155

এক্সওর অদলবদল অ্যালগরিদম ব্যবহার করে

void xorSwap (int* x, int* y) {
    if (x != y) { //ensure that memory locations are different
       *x ^= *y;
       *y ^= *x;
       *x ^= *y;
    }
}


পরীক্ষা কেন?

পরীক্ষাটি নিশ্চিত করা হয় যে এক্স এবং ওয়াইয়ের মেমরির আলাদা অবস্থান রয়েছে (ভিন্ন ভিন্ন মানের চেয়ে)। এটি কারণ (p xor p) = 0এবং x এবং y উভয়ই যদি একই মেমরি অবস্থান ভাগ করে নেয়, যখন একটিতে 0 সেট করা থাকে, উভয়কে 0 তে সেট করা হয় When 0 (যেমন তারা একই) তবে এর অর্থ হল যে ফাংশনটি * x এবং * y উভয়কে 0 তে সেট করবে।

যদি তাদের একই মান থাকে তবে একই মেমোরি অবস্থান না থাকে, সবকিছু প্রত্যাশার মতো কাজ করে

*x = 0011
*y = 0011
//Note, x and y do not share an address. x != y

*x = *x xor *y  //*x = 0011 xor 0011
//So *x is 0000

*y = *x xor *y  //*y = 0000 xor 0011
//So *y is 0011

*x = *x xor *y  //*x = 0000 xor 0011
//So *x is 0011


এটি ব্যবহার করা উচিত?

সাধারণ ক্ষেত্রে, না। সংকলকটি অস্থায়ী পরিবর্তনশীলটিকে অপ্টিমাইজ করবে এবং প্রদত্ত যে অদলবদল একটি সাধারণ পদ্ধতি যা এটি আপনার প্ল্যাটফর্মের জন্য সর্বোত্তম মেশিন কোড আউটপুট করে।

উদাহরণস্বরূপ সিটিতে লিখিত এই দ্রুত পরীক্ষা প্রোগ্রামটি ধরুন

#include <stdlib.h>
#include <math.h>

#define USE_XOR 

void xorSwap(int* x, int *y){
    if ( x != y ){
        *x ^= *y;
        *y ^= *x;
        *x ^= *y;
    }
}

void tempSwap(int* x, int* y){
    int t;
    t = *y;
    *y = *x;
    *x = t;
}


int main(int argc, char* argv[]){
    int x = 4;
    int y = 5;
    int z = pow(2,28); 
    while ( z-- ){
#       ifdef USE_XOR
            xorSwap(&x,&y);
#       else
            tempSwap(&x, &y);
#       endif
    }
    return x + y;    
}

ব্যবহার করে সংকলিত:

gcc -Os main.c -o swap

Xor সংস্করণ লাগে

real    0m2.068s
user    0m2.048s
sys  0m0.000s

অস্থায়ী ভেরিয়েবল সহ সংস্করণটি যেখানে লাগে:

real    0m0.543s
user    0m0.540s
sys  0m0.000s

1
পরীক্ষার কারণটি ব্যাখ্যা করার উপযুক্ত হতে পারে (x এবং y একই বস্তুর রেফারেন্স দিলে ট্রিপল এক্সর অ্যাপ্রোচ মারাত্মকভাবে ব্যর্থ হয়)।
dmckee --- প্রাক্তন-মডারেটর বিড়ালছানা

1
কোডটি এতটা ভেঙে গেলে কীভাবে এটি এতগুলি উপার্জন পেল তা আমি জানি না। পরীক্ষিত কোড বিভাগে উভয় অদলবদল সম্পূর্ণরূপে ভুল। কাছে দেখুন
সোপবক্স

@ সোপবক্স: খুব ভাল পয়েন্ট! এক্সওআর সোয়াপ জিরোস এক্স এবং অচিহ্নিত করে ছেড়ে দেয় এবং অস্থায়ী সোয়াপটি এক্স এর মান সহ উভয়কেই ছেড়ে দেয়। উপস!
ড্রু হল

4
@ সোপবক্স ভাল ক্যাচ স্থির এবং পুনরায় পরীক্ষিত এবং সময়গুলির মধ্যে আমি কোনও বড় পার্থক্য পাই না।
ইয়াকোবি

4
প্রশ্নকর্তা ইনট নয়, দুটি ভেরিয়েবল বলেছেন। : পি
প্লুম্যানেটর

93

সাধারণ ফর্মটি হ'ল:

A = A operation B
B = A inverse-operation B
A = A inverse-operation B 

তবে আপনাকে সম্ভাব্যভাবে অতিরিক্ত প্রবাহের জন্য নজর রাখতে হবে এবং সমস্ত ক্রিয়াকলাপের এমন কোনও বিপরীত নেই যা অপারেশনটি সংজ্ঞায়িত সমস্ত মানের জন্য ভালভাবে সংজ্ঞায়িত। যেমন * এবং / A বা B 0 না হওয়া অবধি কাজ করে

xor বিশেষত আনন্দদায়ক কারণ এটি সমস্ত ইনটগুলির জন্য সংজ্ঞায়িত এবং এটি নিজস্ব বিপরীত


এক্সওআর (এক্স, এক্স) == 0, সুতরাং এক্সওএসটি ইনসেটের জন্য কাজ করবে EXCEPT যখন দুটি মান অদলবদলের সমান হয়। আমি এটি প্রথম দেখায়নি এবং অনেকেই (এখানে এবং অন্য কোথাও) যেকোন ব্যক্তিকে singleণের জন্য একাকী করার জন্য বলেছিলেন।
অলঙ্ক

85
a = a + b
b = a - b // b = a
a = a - b

16
a+bওভারফ্লো যদি হয় ?
অলোক সিংহল

2
@Alok: তা বিবেচনার মধ্যে, এভাবেই অবাস্তব :) গ্রহণ না
দোর

4
যদি a এবং b একই, মৌলিক, আকারের পূর্ণসংখ্যার ধরণের (যেমন int,, unsigned short...) এর থেকে থাকে তবে এটি শেষের দিকে এমনকি ওভারফ্লো সহ কার্যকর হয়, কারণ যদি একটি + বি ওভারফ্লো হয় তবে a - b পাতাল হবে। এই মৌলিক পূর্ণসংখ্যার ধরণের সাথে মানগুলি কেবল রোলওভার হয়।
প্যাট্রিক জনমেয়ার

10
সি-তে, unsignedপূর্ণসংখ্যার ধরণের ক্ষেত্রে এটি ব্যবহার করা ঠিক আছে এবং সর্বদা কাজ করে। স্বাক্ষরিত ধরণেরগুলিতে, এটি ওভারফ্লোতে অনির্ধারিত আচরণ শুরু করবে।
jpalecek

1
@ শাহবাজ: স্বাক্ষরিত পূর্ণসংখ্যাগুলি 2 এর পরিপূরক হিসাবে সংরক্ষণ করা হলেও, ওভারফ্লোতে আচরণ এখনও অপরিজ্ঞাত।
কিথ থম্পসন

79

কেউই std::swapএখনও ব্যবহারের পরামর্শ দেয়নি।

std::swap(a, b);

আমি কোনো অস্থায়ী ভেরিয়েবল ব্যবহার করবেন না এবং ধরনের উপর নির্ভর করে aএবংb প্রয়োগের ক্ষেত্রে একটি অনুমানযোগ্যতা থাকতে পারে যা হয় না। কোনও 'কৌশল' উপযুক্ত কিনা তা জেনেও বাস্তবায়নটি লিখতে হবে। দ্বিতীয় অনুমান করার চেষ্টা করার কোনও মানে নেই।

আরও সাধারণভাবে, আমি সম্ভবত এটির মতো কিছু করতে চাই, কারণ এটি শ্রেণীর প্রকারের পক্ষে কাজ করা সম্ভব হবে যদি সম্ভব হয় তবে এটি আরও ভাল বোঝার সন্ধান করতে এডিএলকে সক্ষম করে।

using std::swap;
swap(a, b);

অবশ্যই, এই উত্তরের সাক্ষাত্কারকারীর প্রতিক্রিয়া শূন্যতা সম্পর্কে অনেক কিছু বলতে পারে।


অবশ্যই সি ++ 0 এক্সের মধ্যে অদলবদলগুলি রেভালিউ রেফারেন্স ব্যবহার করবে তাই আরও ভাল হবে!
জে কে।

16
এটি কীভাবে ব্যবহার করা যায় সে সম্পর্কে বিভিন্ন সতর্কতার সাথে প্রত্যেকে চকচকে জোর বা অন্য কৌশলগুলি শিখিয়ে দেখতে চায়, তবে এই indubitably সেরা উত্তর।

2
কেন স্টাড :: অদলবদল (ক, খ); ? মানে কেন ব্যবহার করছেন?
দিনাইজ

2
@ ডাইনাইজ ছাড়াই std::, ব্যবহারকারী-সংজ্ঞায়িত swapপ্রকারের জন্য ব্যবহারকারী-সংজ্ঞায়িত বাস্তবায়নগুলি কল করার জন্যও উপলব্ধ (এটি "এর দ্বারা বোঝানো হয় এটি যদি শ্রেণীর ধরণের পক্ষে সম্ভব হয় তবে আরও ভাল বোঝার সন্ধানের জন্য এটিএডিএল সক্ষম করে"))
কাইল স্ট্র্যান্ড

std::swapএর বাস্তবায়নে অতিরিক্ত অস্থায়ী মেমরি ব্যবহার করে? cplusplus.com/references/utility/swap
নিনজা

19

মনু দ্বারা ইতিমধ্যে উল্লিখিত হিসাবে, এক্সওআর এলগরিদম একটি জনপ্রিয় যা সমস্ত পূর্ণসংখ্যার মানগুলির জন্য কাজ করে (এতে পয়েন্টারগুলি অন্তর্ভুক্ত থাকে, কিছু ভাগ্য এবং কাস্টিং সহ)। সম্পূর্ণতার জন্য আমি সংযোজন / বিয়োগের সাথে আরও একটি কম শক্তিশালী অ্যালগরিদম উল্লেখ করতে চাই:

A = A + B
B = A - B
A = A - B

এখানে আপনাকে ওভারফ্লো / আন্ডারফ্লোগুলি সম্পর্কে সতর্ক থাকতে হবে, তবে অন্যথায় এটি ঠিক কাজ করে। এমনকি আপনি যদি এটির ক্ষেত্রে এক্সওর অনুমোদিত না হয় তবে আপনি ভাসা / ডাবল এ চেষ্টা করে দেখতে পারেন।


" সমস্ত পূর্ণসংখ্যা মান (এতে পয়েন্টার অন্তর্ভুক্ত থাকে) " - কী? না, পয়েন্টারগুলি পূর্ণসংখ্যা নয় এবং আপনি পয়েন্টার মানগুলিকে জোর করতে পারবেন না। আপনি ভাসমান-পয়েন্টের মানগুলিও জোর করতে পারবেন না। তবে সংযোজন / বিয়োগের পদ্ধতিটি ওভারফ্লো বা আন্ডারফ্লোতে (স্বাক্ষরিত বা ভাসমান-বিন্দুর ধরণের জন্য) সংজ্ঞায়িত আচরণ করে, ভাসমান-পয়েন্টের জন্য নির্ভুলতা হারাতে পারে এবং পয়েন্টার বা অন্যান্য অ-সংখ্যাযুক্ত প্রকারে প্রয়োগ করা যায় না।
কিথ থম্পসন

@ কিথথম্পসন - ঠিক আছে, ভাসমান পয়েন্টগুলির যথার্থতা হ্রাস সত্য, তবে পরিস্থিতির উপর নির্ভর করে এটি গ্রহণযোগ্য হতে পারে। পয়েন্টারগুলি হিসাবে - ভাল, আমি কোনও সংকলক / প্ল্যাটফর্মের কথা কখনও শুনিনি যেখানে পয়েন্টারগুলি নির্দ্বিধায় পূর্ণসংখ্যায় এবং আবার ফিরে যেতে পারে না (অবশ্যই সঠিক আকারের একটি পূর্ণসংখ্যা চয়ন করার জন্য যত্ন নেওয়া)। তবে, আমি কোনও সি / সি ++ বিশেষজ্ঞ নই। আমি জানি যে এটি স্ট্যান্ডার্ডের বিপরীতে চলেছে, তবে আমি এই ধারণার মধ্যে ছিলাম যে এই আচরণটি ... সব কিছুতেই বেশ সামঞ্জস্যপূর্ণ।
ভিলাক্স-

1
@ ভিলাক্স: অস্থায়ী পরিবর্তনশীল - বা ব্যবহার করে এটি এড়ানো সহজ কেন যখন যথার্থতা হারাতে হবে std::swap()? অবশ্যই, আপনি পয়েন্টারগুলিকে পূর্ণসংখ্যায় রূপান্তর করতে পারেন এবং আবার ফিরে যেতে পারেন (ধরে নেওয়া যায় যে যথেষ্ট পরিমাণে পূর্ণসংখ্যার ধরণ রয়েছে যা গ্যারান্টিযুক্ত নয়), তবে এটি আপনার পরামর্শ মতো নয়; আপনি ইঙ্গিত দিয়েছিল যে, পয়েন্টার হয় পূর্ণসংখ্যার না যে, তারা পূর্ণসংখ্যার রূপান্তরিত করা যেতে পারে। হ্যাঁ, গৃহীত উত্তর পয়েন্টারগুলির জন্য কাজ করবে না। চার্লস বেলির উত্তর ব্যবহার std::swapকরা সত্যই একমাত্র সঠিক।
কিথ থম্পসন

1
প্রথমত, প্রশ্নটি ছিল "তৃতীয় ভেরিয়েবলটি ব্যবহার না করে কীভাবে অদলবদল করা যায়" এবং এর জন্য দেওয়া কারণটি ছিল "একটি সাক্ষাত্কারের প্রশ্ন"। আমি সবেমাত্র অন্য একটি সম্ভাব্য উত্তর দিয়েছি। দ্বিতীয়, ঠিক আছে, পয়েন্টারগুলি পূর্ণসংখ্যা বলে বোঝানোর জন্য আমার ক্ষমা চাই। আমি উত্তরটি আশাবাদী আরও সুস্পষ্ট এবং সঠিক হতে আপডেট করেছি। আমি এখনও ভুল থাকলে দয়া করে আমাকে সংশোধন করুন (অথবা উত্তরটি নিজেই আপডেট করুন)। তৃতীয়ত, আমি গৃহীত উত্তর সম্পর্কে অংশটি মুছলাম। এটি কোথাও পয়েন্টার-থেকে-পূর্ণসংখ্যা কাস্ট ব্যবহার করছে না এবং এটি সঠিকভাবে কাজ করে (যতদূর আমি বুঝতে পারি)।
ভিলেক্স-

@ কিথথম্পসন: std::swapতৃতীয় ভেরিয়েবল ব্যবহার না করে কীভাবে প্রয়োগ করা যায় সে সম্পর্কে প্রশ্নটি সংশোধন করা যেতে পারে।
jxh

10

বোকা প্রশ্নগুলি যথাযথ উত্তরের প্রাপ্য:

void sw2ap(int& a, int& b) {
  register int temp = a; // !
  a = b;
  b = temp;
}

মূলশব্দটির একমাত্র ভাল ব্যবহার register


1
স্টোরেজ-শ্রেণীর নিবন্ধের সাথে ঘোষিত কোনও বস্তু কি "পরিবর্তনশীল" নয়? এছাড়াও আমি নিশ্চিত নই যে এটি নিবন্ধের একটি ভাল ব্যবহার, যেহেতু আপনার সংকলক যদি ইতিমধ্যে এটি অপ্টিমাইজ করতে না পারে তবে এমনকি চেষ্টা করার কী দরকার, আপনি হয় যা-কিছু জঞ্জাল পান তা গ্রহণ করতে পারেন বা সমাবেশ নিজেই লিখতে হবে ;-) তবে হিসাবে আপনি বলছেন, একটি অদ্ভুত প্রশ্ন একটি জঘন্য উত্তর প্রাপ্য।
স্টিভ জেসোপ

1
খুব সুন্দর সমস্ত আধুনিক সংকলকগণ রেজিস্ট্রার স্টোরেজ ক্লাসটিকে উপেক্ষা করে, কারণ আপনার চেয়ে বার বার অ্যাক্সেস করা হয় সে সম্পর্কে তাদের আরও ভাল ধারণা রয়েছে।
সিইও

6
মনে রাখবেন যে এই উত্তরটি সংকলক নয়, সাক্ষাত্কারের জন্য (এর) এর উদ্দেশ্যে। এটি বিশেষত এই সুযোগটি গ্রহণ করে যে এই ধরণের প্রশ্ন জিজ্ঞাসাকারী সাক্ষাত্কারকারীরা সত্যই সি ++ বুঝতে পারে না। সুতরাং, তারা এই উত্তরটি প্রত্যাখ্যান করতে পারে না। (এবং কোনও স্ট্যান্ডার্ড উত্তর নেই; আইএসও সি ++ ভেরিয়েবল নয়, এমন বিষয়ে আলোচনা করে)।
এমসাল্টাররা 15

আহ, আমি তোমাকে পেয়েছি আমি একটি বিশেষ্য হিসাবে পরিবর্তনশীল উল্লেখ করার জন্য সি স্ট্যান্ডার্ডের দিকে তাকিয়ে ছিলাম, এবং কেবল নন-কনস্টের অর্থ নয়। ইনিশিয়ালিসায়ারে ঘোষিত "ভেরিয়েবল" এর স্কোপ সংজ্ঞা দেওয়ার লুপের জন্য বিভাগে আমি n1124-তে একটি পেয়েছি। তখন আমি বুঝতে পেরেছিলাম যে প্রশ্নটি সি ++, এবং অনুসন্ধানের জন্য বিরক্ত করেনি যে সি ++ কোথাও একই টাইপ করেছে কিনা।
স্টিভ জেসোপ

3

তৃতীয় ভেরিয়েবল ব্যবহার করে দুটি সংখ্যা অদলবদল করা এই জাতীয় হতে হবে,

int temp;
int a=10;
int b=20;
temp = a;
a = b;
b = temp;
printf ("Value of a", %a);
printf ("Value of b", %b);

তৃতীয় ভেরিয়েবল ব্যবহার না করে দুটি সংখ্যা অদলবদল করা

int a = 10;
int b = 20;
a = a+b;
b = a-b;
a = a-b;
printf ("value of a=", %a);
printf ("value of b=", %b);

2
#include<iostream.h>
#include<conio.h>
void main()
{
int a,b;
clrscr();
cout<<"\n==========Vikas==========";
cout<<"\n\nEnter the two no=:";
cin>>a>>b;
cout<<"\na"<<a<<"\nb"<<b;
a=a+b;
b=a-b;
a=a-b;

cout<<"\n\na="<<a<<"\nb="<<b;
getch();
}

1
cout << "Enter the two no=:"আমি পড়ার প্রত্যাশার পরেcout << "Now enter the two no in reverse order:"
ব্যবহারকারী 253751

অন্যান্য বেশ কয়েকটি উত্তরের মতো এটির ওপরে প্রবাহিত হলে a+bবা তার সাথে a-bপ্রবাহিত আচরণের সংজ্ঞা রয়েছে । এছাড়াও, void main()অবৈধ এবং <conio.h>মানহীন।
কিথ থমসন 21

2

যেহেতু মূল সমাধানটি হ'ল:

temp = x; y = x; x = temp;

আপনি এটি ব্যবহার করে একটি দুটি লাইনার তৈরি করতে পারেন:

temp = x; y = y + temp -(x=y);

তারপরে এটি ব্যবহার করে এটি একটি লাইনার করুন:

x = x + y -(y=x);

1
অপরিবর্তিত আচরণ। yকোনও ইন্টারভেনিং সিকোয়েন্স পয়েন্ট ছাড়াই একই অভিব্যক্তিটিতে পড়া এবং লেখা হয়।
কিথ থমসন 21

1

আপনি যদি ভেরিয়েবলের পরিবর্তে প্রায় 2 টি অ্যাসেম্বলি রেজিস্টার জিজ্ঞাসা করার জন্য প্রশ্নটি একটু পরিবর্তন করেন তবে আপনি xchgঅপারেশনটিকে একটি বিকল্প হিসাবে এবং স্ট্যাক অপারেশনটিকে অন্য হিসাবে ব্যবহার করতে পারেন ।


1
আপনি কোন xchgঅপারেশনের কথা উল্লেখ করছেন? প্রশ্নটি কোনও সিপিইউ আর্কিটেকচার নির্দিষ্ট করে নি।
কিথ থম্পসন

1

বিবেচনা করুন a=10, b=15:

সংযোজন এবং বিয়োগফল ব্যবহার করে

a = a + b //a=25
b = a - b //b=10
a = a - b //a=15

বিভাগ এবং গুন ব্যবহার করে

a = a * b //a=150
b = a / b //b=10
a = a / b //a=15

1
ওভারফ্লোতে অপরিজ্ঞাত আচরণ রয়েছে।
কিথ থমসন 21

1
এছাড়াও, সি ++ এ, মানগুলি একই ধরণের না হলে এটির অনাকাঙ্ক্ষিত আচরণ থাকতে পারে। উদাহরণস্বরূপ, a=10এবং b=1.5
ম্যাথু কোল

1
#include <iostream>
using namespace std;
int main(void)
{   
 int a,b;
 cout<<"Enter a integer" <<endl;
 cin>>a;
 cout<<"\n Enter b integer"<<endl;
 cin>>b;

  a = a^b;
  b = a^b;
  a = a^b;

  cout<<" a= "<<a <<"   b="<<b<<endl;
  return 0;
}

আপডেট: এতে আমরা ব্যবহারকারীর কাছ থেকে দুটি পূর্ণসংখ্যার ইনপুট নিচ্ছি। তারপরে আমরা সেগুলি বদলানোর জন্য বিটওয়াইস এক্সওআর অপারেশনটি ব্যবহার করছি ।

আমরা দুটি পূর্ণসংখ্যার আছে বলুন a=4এবং b=9তারপর:

a=a^b --> 13=4^9 
b=a^b --> 4=13^9 
a=a^b --> 9=13^9

ভবিষ্যতের দর্শকদের জন্য দয়া করে আপনার উত্তরের সংক্ষিপ্ত ব্যাখ্যা যুক্ত করুন।
নিকলে মিহাইলোভ

1
এটিতে আমরা ব্যবহারকারীর কাছ থেকে দুটি পূর্ণসংখ্যার ইনপুট নিচ্ছি। তারপরে আমরা বিটওয়াইজ এক্সওর অপারেশন দুটি এটিকে স্ব্যাপ করব। বলুন আমাদের দুটি ইন্টারজার রয়েছে a = 4 এবং b = 9 এর পরে এখন a = a ^ b -> 13 = 4 ^ 9 b = a ^ b -> 4 = 13 ^ 9 a = a ^ b -> 9 = 13 ^ 9
উল হাসান

1

এখানে আরও একটি সমাধান তবে একক ঝুঁকি।

কোড:

#include <iostream>
#include <conio.h>
void main()
{

int a =10 , b =45;
*(&a+1 ) = a;
a =b;
b =*(&a +1);
}

অবস্থানের যে কোনও মান 1 + 1 ওভাররাইড করা হবে।


2
এটি একটি দরকারী উত্তর ছিল, সম্ভবত মান অদৃশ্য।
বিবি তাহিরা

1
বিভিন্ন ধরণের অপরিজ্ঞাত আচরণ। *(&a+1)ভাল হতে পারে bvoid main()অবৈধ. <conio.h>মানহীন (এবং আপনি এটি ব্যবহার করেন না)।
কিথ থমসন 21

কোডটি অন্য আউটপুট পরামিতিগুলির সাথে পরীক্ষা করা হয়েছিল, যা বাদ ছিল, কারণ আমি একটি ঝুঁকি উল্লেখ করেছি। মেমরির ঝুঁকি ওভাররাইড হয়ে গেছে .. এটি আছে .. তবে এটি তৃতীয়টির জড়িত না হয়ে দুটি পরিবর্তনশীল অদলবদল করা একটি দরকারী।
ডেরেডভিল

সবচেয়ে খারাপ দিকটি হ'ল এটি সম্ভবত কিছু সময় কাজ করতে পারে, তাই আপনি অবিলম্বে বুঝতে পারবেন না যে এটি সম্পূর্ণরূপে ভেঙে গেছে এবং অপ্টিমাইজেশনের অধীনে ব্যর্থ হবে, অন্যান্য সংকলক ইত্যাদি
avl_swenen

1

অবশ্যই, সি ++ উত্তর হওয়া উচিত std::swap

তবে নিম্নলিখিত প্রয়োগে তৃতীয় কোন পরিবর্তনশীল নেই swap:

template <typename T>
void swap (T &a, T &b) {
    std::pair<T &, T &>(a, b) = std::make_pair(b, a);
}

বা, ওয়ান-লাইনার হিসাবে:

std::make_pair(std::ref(a), std::ref(b)) = std::make_pair(b, a);

0
#include <stdio.h>

int main()
{
    int a, b;
    printf("Enter A :");
    scanf("%d",&a);
    printf("Enter B :");
    scanf("%d",&b);
    a ^= b;
    b ^= a;
    a ^= b;
    printf("\nValue of A=%d B=%d ",a,b);
    return 1;
}

0

এটি সঠিক এক্সওআর সোয়াপ অ্যালগরিদম

void xorSwap (int* x, int* y) {
   if (x != y) { //ensure that memory locations are different
      if (*x != *y) { //ensure that values are different
         *x ^= *y;
         *y ^= *x;
         *x ^= *y;
      }
   }
}

আপনাকে নিশ্চিত করতে হবে যে মেমরির অবস্থানগুলি পৃথক এবং এটিও যে আসল মানগুলি আলাদা কারণ একটি এক্সওর এ = 0


মানগুলি আলাদা কিনা তা আপনাকে নিশ্চিত করতে হবে না।
ব্যবহারকারী 253751

0

আপনি করতে পারেন .... সহজ উপায়ে ... এক লাইনের মধ্যে লজিক

#include <stdio.h>

int main()
{
    int a, b;
    printf("Enter A :");
    scanf("%d",&a);
    printf("Enter B :");
    scanf("%d",&b);
    int a = 1,b = 2;
    a=a^b^(b=a);
    printf("\nValue of A=%d B=%d ",a,b);

    return 1;
}

অথবা

#include <stdio.h>

int main()
{
    int a, b;
    printf("Enter A :");
    scanf("%d",&a);
    printf("Enter B :");
    scanf("%d",&b);
    int a = 1,b = 2;
    a=a+b-(b=a);
    printf("\nValue of A=%d B=%d ",a,b);

    return 1;
}

1
অপরিবর্তিত আচরণ। উভয় সংস্করণে, bউভয়ই একই অভিব্যক্তির মধ্যে পড়া এবং সংশোধন করা হয়, কোনও অন্তর্বর্তী ক্রম বিন্দু ছাড়াই।
কিথ থমসন 21


0

এক্সওআর ব্যবহার করা এবং এটি এক লাইনে ব্যবহার করা ভাল উত্তর হবে।

    (x ^= y), (y ^= x), (x ^= y);

x, y হল ভেরিয়েবল এবং তাদের মধ্যে কমাটি ক্রম পয়েন্টগুলি প্রবর্তন করে যাতে এটি সংকলক নির্ভরশীল হয় না। চিয়ার্স!


0

তৃতীয় ভেরিয়েবলটি ব্যবহার না করে দুটি সংখ্যার অদলবদল করার জন্য একটি সি সি উদাহরণ দেখুন।

প্রোগ্রাম 1:

#include<stdio.h>
#include<conio.h>
main()
{
int a=10, b=20;
clrscr();
printf("Before swap a=%d b=%d",a,b);
a=a+b;//a=30 (10+20)
b=a-b;//b=10 (30-20)
a=a-b;//a=20 (30-10)
printf("\nAfter swap a=%d b=%d",a,b);
getch();
}

আউটপুট:

অদলবদলের আগে a = 10 b = 20 এর পরে a = 20 b = 10 After

প্রোগ্রাম 2: * এবং / ব্যবহার করে

আসুন আরেকটি উদাহরণ দেখুন * এবং / ব্যবহার করে দুটি সংখ্যা অদলবদল করতে।

#include<stdio.h>
#include<conio.h>
main()
{
int a=10, b=20;
clrscr();
printf("Before swap a=%d b=%d",a,b);
a=a*b;//a=200 (10*20)
b=a/b;//b=10 (200/20)
a=a/b;//a=20 (200/10)
printf("\nAfter swap a=%d b=%d",a,b);
getch();
}

আউটপুট:

অদলবদলের আগে a = 10 b = 20 এর পরে a = 20 b = 10 After

প্রোগ্রাম 3: বিটওয়াইজ এক্সওআর অপারেটরটি ব্যবহার করা:

বিটওয়াইজ এক্সওআর অপারেটরটি দুটি ভেরিয়েবল অদলবদল করতে ব্যবহৃত হতে পারে। X এবং y দুটি সংখ্যার XOR একটি সংখ্যার রিটার্ন দেয় যেখানে যেখানে x এবং y এর বিট পৃথক হয় সেখানে 1 হিসাবে সমস্ত বিট থাকে। উদাহরণস্বরূপ, 10 এর XOR (বাইনারি 1010 ইন) এবং 5 (বাইনারি 0101 তে) 1111 এবং 7 (0111) এবং 5 (0101) এর XOR (0010)।

#include <stdio.h>
int main()
{
 int x = 10, y = 5;
 // Code to swap 'x' (1010) and 'y' (0101)
 x = x ^ y;  // x now becomes 15 (1111)
 y = x ^ y;  // y becomes 10 (1010)
 x = x ^ y;  // x becomes 5 (0101)
 printf("After Swapping: x = %d, y = %d", x, y);
 return 0;

আউটপুট:

অদলবদলের পরে: x = 5, y = 10

প্রোগ্রাম 4:

এখনও কেউ স্টাডি :: অদলবদল ব্যবহারের পরামর্শ দেয়নি।

std::swap(a, b);

আমি কোনও অস্থায়ী ভেরিয়েবল ব্যবহার করি না এবং ক এবং খ এর ধরণের উপর নির্ভর করে বাস্তবায়নের একটি বিশেষীকরণ থাকতে পারে যা হয় না। কোনও 'কৌশল' উপযুক্ত কিনা তা জেনেও বাস্তবায়নটি লিখতে হবে।

উপরোক্ত পদ্ধতিগুলির সাথে সমস্যাগুলি:

1) গুণমান এবং বিভাগ ভিত্তিক পদ্ধতির কাজ করে না 'যদি সংখ্যাগুলির মধ্যে একটি 0 হয় তবে অন্য সংখ্যা নির্বিশেষে পণ্য 0 হয়ে যায়।

2) উভয় গাণিতিক সমাধানগুলি পাটিগণিতের ওভারফ্লো হতে পারে। যদি x এবং y খুব বড় হয় তবে সংযোজন এবং গুণগুলি পূর্ণসংখ্যার ব্যাপ্তির বাইরে চলে যেতে পারে।

3) যখন আমরা কোনও ভেরিয়েবলের জন্য পয়েন্টার ব্যবহার করি এবং একটি ফাংশন অদলবদল করি, তখন উভয় পয়েন্টার একই ভেরিয়েবলের দিকে নির্দেশ করলে উপরের সমস্ত পদ্ধতি ব্যর্থ হয়। আসুন একবার দেখে নেওয়া যাক যদি উভয়ই একই ভেরিয়েবলের দিকে ইঙ্গিত করে তবে এই ক্ষেত্রে কী ঘটবে।

// বিটওয়াইস এক্সওআর ভিত্তিক পদ্ধতি

x = x ^ x; // x becomes 0
x = x ^ x; // x remains 0
x = x ^ x; // x remains 0

// পাটিগণিত ভিত্তিক পদ্ধতি

x = x + x; // x becomes 2x
x = x  x; // x becomes 0
x = x  x; // x remains 0

আসুন নীচের প্রোগ্রামটি দেখুন।

#include <stdio.h>
void swap(int *xp, int *yp)
{
    *xp = *xp ^ *yp;
    *yp = *xp ^ *yp;
    *xp = *xp ^ *yp;
}

int main()
{
  int x = 10;
  swap(&x, &x);
  printf("After swap(&x, &x): x = %d", x);
  return 0;
}

আউটপুট :

অদলবদলের পরে (& x, & x): x = 0

নিজের সাথে একটি ভেরিয়েবল অদলবদল করতে অনেক স্ট্যান্ডার্ড অ্যালগরিদমে প্রয়োজন হতে পারে। উদাহরণস্বরূপ, কুইকসোর্টের এই বাস্তবায়নটি দেখুন যেখানে আমরা নিজের সাথে একটি চলক অদলবদল করতে পারি। অদলবদল করার আগে একটি শর্ত রেখে উপরের সমস্যাটি এড়ানো যায়।

#include <stdio.h>
void swap(int *xp, int *yp)
{
    if (xp == yp) // Check if the two addresses are same
      return;
    *xp = *xp + *yp;
    *yp = *xp - *yp;
    *xp = *xp - *yp;
}
int main()
{
  int x = 10;
  swap(&x, &x);
  printf("After swap(&x, &x): x = %d", x);
  return 0;
}

আউটপুট :

অদলবদলের পরে (& x, & x): x = 10


0

টপিক বন্ধ হতে পারে তবে আপনি যদি জানেন যে আপনি দুটি ভিন্ন মানের মধ্যে একটি একক ভেরিয়েবল অদলবদল করছেন তবে আপনি অ্যারে লজিকটি করতে সক্ষম হতে পারেন। প্রতিবার এই লাইন কোডটি চালানো হলে এটি 1 এবং 2 এর মধ্যে মানটি অদলবদল করবে।

n = [2, 1][n - 1]

0

আপনি করতে পারেন:

std::tie(x, y) = std::make_pair(y, x);

অথবা দুটিরও বেশি ভেরিয়েবল অদলবদলের সময় make_tuple ব্যবহার করুন:

std::tie(x, y, z) = std::make_tuple(y, z, x);

তবে আমি নিশ্চিত না যে অভ্যন্তরীণভাবে std :: টাই একটি অস্থায়ী পরিবর্তনশীল ব্যবহার করে কিনা!


0

জাভাস্ক্রিপ্টে:

function swapInPlace(obj) {
    obj.x ^= obj.y
    obj.y ^= obj.x
    obj.x ^= obj.y
}

function swap(obj) {
    let temp = obj.x
    obj.x = obj.y
    obj.y = temp
}

উভয় বিকল্পের প্রয়োগের সময় সম্পর্কে সচেতন হন।

এই কোডটি চালিয়ে আমি এটি পরিমাপ করেছি।

console.time('swapInPlace')
swapInPlace({x:1, y:2})
console.timeEnd('swapInPlace') // swapInPlace: 0.056884765625ms

console.time('swap')
swap({x:3, y:6})
console.timeEnd('swap')        // swap: 0.01416015625ms

যেমন আপনি দেখতে পাচ্ছেন (এবং অনেকেই বলেছেন), অদলবদল (পরিবর্তন) অস্থায়ী ভেরিয়েবল ব্যবহার করে অন্য বিকল্পের চেয়ে অনেক বেশি সময় নেয় x


0

আর এডগার ডাব্লু ডিজকસ્ત્રা প্রস্তাবিত একটি যুগপত অ্যাসাইনমেন্ট অনুপস্থিত , প্রোগ্রামিং এর ডিসিপ্লাইন, 1976, ch.4, p.29। এটি একটি মার্জিত সমাধানের অনুমতি দেবে:

a, b    <- b, a         # swap
a, b, c <- c, a, b      # rotate right

-1
a = a + b - (b=a);

এটি খুব সহজ, তবে এটি একটি সতর্কতা জাগাতে পারে।


5
সতর্কতা হচ্ছে যে এটি কাজ করে না? আমরা জানি না b=aআগে বা পরে সঞ্চালিত হয় কিনা a + b
বো পারসন

-1

সি ভাষায় দুটি মান অদলবদলের জন্য একক লাইন সমাধান।

a=(b=(a=a+b,a-b),a-b);

ওভারফ্লোতে অপরিজ্ঞাত আচরণ।
কিথ থমসন 21

-1
second_value -= first_value;
first_value +=  second_value;
second_value -= first_value;
second_value *= -1;

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