ওভারল্যাপের জন্য দুটি পূর্ণসংখ্যা ব্যাপ্তি পরীক্ষা করার সবচেয়ে কার্যকর উপায় কোনটি?


249

দুটি সমন্বিত পূর্ণসংখ্যার রেঞ্জ দেওয়া [x1: x2] এবং [y1: y2], যেখানে x1 ≤ x2 এবং y1 ≤ y2, দুটি রেঞ্জের কোনও ওভারল্যাপ রয়েছে কিনা তা পরীক্ষা করার সবচেয়ে কার্যকর উপায় কোনটি?

একটি সাধারণ বাস্তবায়ন নিম্নরূপ:

bool testOverlap(int x1, int x2, int y1, int y2) {
  return (x1 >= y1 && x1 <= y2) ||
         (x2 >= y1 && x2 <= y2) ||
         (y1 >= x1 && y1 <= x2) ||
         (y2 >= x1 && y2 <= x2);
}

তবে আমি আশা করি এটি গণনা করার আরও কার্যকর উপায় রয়েছে।

সবচেয়ে কম পরিচালনের ক্ষেত্রে কী পদ্ধতিটি সবচেয়ে দক্ষ হবে।


- পারে মজার কিছু সম্পর্কিত হতে stackoverflow.com/q/17138760/104380
VSync

উত্তর:


452

রেঞ্জগুলি ওভারল্যাপ করার অর্থ কী? এর অর্থ এখানে কিছু সংখ্যক সি বিদ্যমান রয়েছে যা উভয় ব্যাপ্তিতেই রয়েছে

x1 <= C <= x2

এবং

y1 <= C <= y2

এখন, যদি আমাদের ধরে নিতে দেওয়া হয় যে ব্যাপ্তিগুলি সুসংহত হয়েছে (যাতে x1 <= x2 এবং y1 <= y2) তবে এটি পরীক্ষা করার পক্ষে যথেষ্ট

x1 <= y2 && y1 <= x2

1
আমি বিশ্বাস করি এটা হওয়া উচিত x1 <= y2 && y1 >= x2, না?
ডেভিড বেক

8
@ ডেভিডবেক: না, যদি y1> x2 হয় তবে রেঞ্জগুলি অবশ্যই ওভারল্যাপ করে না (উদাঃ [1: 2] এবং [3: 4]: y1 = 3 এবং x2 = 2, সুতরাং y1> x2, তবে কোনও ওভারল্যাপ নেই) ।
সাইমন নিক্কারসন

8
যদি আপনি যুক্তিটি আরও কিছুটা ব্যাখ্যা করেন তবে এটি আরও ভাল উত্তর হতে পারে
২৩:১৩-এ

2
@ ভিনিত দেওরজ - আপনি কেন ভাবেন যে এটি কাজ করে না? x1 = 1, y1 = 1, x2 = 1, y2 = 1, সুতরাং x1 <= y2 &&Y1 <= x2 সত্য, সুতরাং, একটি ওভারল্যাপ রয়েছে।
ডিসিপি


137

দুটি রেঞ্জ দেওয়া হয়েছে [x1, x2], [y1, y2]

def is_overlapping(x1,x2,y1,y2):
    return max(x1,y1) <= min(x2,y2)

4
@ uyuyuy99 - কেবল এত দক্ষ নয়, কারণ যখন এই চেকটি প্রতি সেকেন্ডে অনেকবার করা হচ্ছে, কলিং ফাংশন এমন একটি বিষয় যা আপনি এড়াতে চান এবং
নিজেরাই

7
@vsync আধুনিক ব্রাউজারগুলি ম্যাথ.ম্যাক্সের মতো ফাংশনগুলিকে ইনলাইন এবং অনুকূলিত করবে, কার্য সম্পাদনের উপর কোনও লক্ষণীয় প্রভাব থাকতে হবে না।
অ্যাশটন ছয়

1
@ অ্যাশটনওয়ার - আকর্ষণীয় কী অন্তর্ভুক্ত হয় এবং কী নয় তা ব্যাখ্যা করার জন্য আপনার একটি নিবন্ধ আছে?
vsync

@vsync না, তবে আমি নিশ্চিত যে আপনি নিজে তথ্যটি খুঁজে পেতে পারবেন
অ্যাশটন সিক্স

6
এছাড়াও, নোট যা min(x2,y2) - max(x1,y1)আপনার প্রয়োজনের ক্ষেত্রে ওভারল্যাপের পরিমাণ সরবরাহ করে।
ব্যবহারকারী 1556435

58

এটি সহজেই একটি সাধারণ মানুষের মস্তিষ্ককে ছেঁটে ফেলতে পারে, তাই আমি বুঝতে আরও সহজ করার জন্য একটি চাক্ষুষ দৃষ্টিভঙ্গি পেয়েছি:

ওভারল্যাপ উন্মাদনা

লে ব্যাখ্যা

দুটি সীমা যদি একটি স্লটে ফিট করতে "খুব চর্বি" হয় তবে এটি উভয়ের প্রস্থের সমষ্টি, তবে সেগুলি ওভারল্যাপ করে।

ব্যাপ্তিগুলির জন্য [a1, a2]এবং [b1, b2]এটি হ'ল :

/**
 * we are testing for:
 *     max point - min point < w1 + w2    
 **/
if max(a2, b2) - min(a1, b1) < (a2 - a1) + (b2 - b1) {
  // too fat -- they overlap!
}

2
আপনার ছবিতে চিত্রিতের চেয়ে আরও বেশি কেস রয়েছে। উদাহরণস্বরূপ, ডাব্লু 2 যদি ডাব্লু 1 এর আগে শুরু হয় এবং ডাব্লু 1 পরে শেষ হয় তবে কী হবে?
উইলিয়াম কেএফ 19:34

6
@ উইলিয়াম কেএফ যুক্তিটি সত্য
ফ্লোটিংরক

2
সম্মত, তবে আমি মনে করি এটি তৃতীয় চিত্র সরবরাহ করতে সহায়তা করবে।
উইলিয়াম কেএফ

3
@ উইলিয়াম কেএফ এর পরে আপনার আরও অনেকগুলি চিত্রের প্রয়োজন আছে সেখানে 16 টি বিভিন্ন সংমিশ্রণ রয়েছে যা 2 টি রেঞ্জ স্থাপন করা যেতে পারে ...
পিটার

3
আপনি যদি এই পদ্ধতিটি ব্যবহার করেন তবে সাবধান হন কারণ সমষ্টিটি a2 - a1 + b2 - b1উপচে পড়তে পারে। এটি ঠিক করার জন্য, সূত্রটি পুনরায় সাজান max(a2, b2) - a2 - b2 < min(a1, b1) - a1 - b1, যা সহজতর করে max(a1, b1) < min(a2, b2)কিছু গাণিতিক সংরক্ষণ করে এবং কোনও সম্ভাব্য ওভারফ্লো এড়ানো (এটি নীচে AX-Labs এর উত্তর)। আপনি যে বিশেষ ক্ষেত্রে জানেন সেখানে b2-b1=a2-a1ফ্লোটিংরকের সূত্রের আর একটি দরকারী পুনর্বিন্যাস হ'ল max(a2, b2) - min(a1, b1) - (b2 - b1) < a2-a1, যা হয়ে ওঠে abs(b1-a1) < a2 - a1
পাওলো বনজিণী 12

44

সাইমন এর দুর্দান্ত উত্তর , তবে আমার পক্ষে বিপরীত মামলা সম্পর্কে চিন্তা করা সহজ হয়েছিল।

2 রেঞ্জগুলি কখন ওভারল্যাপ হয় না? অন্যগুলির শেষ হওয়ার পরে যখন তাদের মধ্যে একটি শুরু হয় তখন তারা ওভারল্যাপ করে না:

dont_overlap = x2 < y1 || x1 > y2

তারা যখন ওভারল্যাপ করে তখন তা প্রকাশ করা সহজ:

overlap = !dont_overlap = !(x2 < y1 || x1 > y2) = (x2 >= y1 && x1 <= y2)

1
আমার কাছে, এক্সপ্রেশনটি বোঝা সহজ: x2 <y1 || y2 <x1 // যেখানে আমি "এর চেয়ে বড়" এর পরিবর্তে 'কম' ব্যবহার করি।
পার্ক জংবাম

24

শুরুর সর্বাধিক থেকে রেঞ্জের সর্বনিম্ন সর্বনিম্ন বিয়োগ করা কৌশলটি মনে হচ্ছে। ফলাফলটি শূন্যের চেয়ে কম বা সমান হলে আমাদের একটি ওভারল্যাপ থাকে। এটি এটিকে ভালভাবে রূপায়িত করে:

এখানে চিত্র বর্ণনা লিখুন


1
এটি সমস্ত ক্ষেত্রে কভার করে
ব্যবহারকারীর 3290180

10

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

সাধারণ ক্ষেত্রে:

static inline bool check_ov1(int x1, int x2, int y1, int y2){
    // insetead of x1 < y2 && y1 < x2
    return (bool)(((unsigned int)((y1-x2)&(x1-y2))) >> (sizeof(int)*8-1));
};

বা, এই ক্ষেত্রে:

static inline bool check_ov2(int x1, int x2, int y1, int y2){
    // insetead of x1 <= y2 && y1 <= x2
    return (bool)((((unsigned int)((x2-y1)|(y2-x1))) >> (sizeof(int)*8-1))^1);
};

7
আপনার সংকলক বিশ্বাস করুন। যুক্তিযুক্ত দক্ষ সংকলক এবং সিপিইউ আর্কিটেকচার (এমনকি ২০১০ সালে) ধরে নিয়ে ভাব প্রকাশের x1 <= y2 && y1 <= x2 কোনও শাখা নেই । প্রকৃতপক্ষে, x86-এ, উত্পন্ন কোডটি মূল উত্তরটির তুলনায় কোডটি সাধারণ অভিব্যক্তির জন্য অভিন্ন।
সেরেন লভবর্গ


4

আপনি যদি একই সাথে একই সাথে দু'টি সীমা [x1:x2]এবং [y1:y2]প্রাকৃতিক / প্রাকৃতিক-প্রাকৃতিক অর্ডার রেঞ্জ দিয়ে থাকেন তবে:

  • প্রাকৃতিক ক্রম: x1 <= x2 && y1 <= y2 বা
  • প্রাকৃতিক বিরোধী আদেশ: x1 >= x2 && y1 >= y2

তাহলে আপনি এটি পরীক্ষা করতে ব্যবহার করতে পারেন:

সেগুলি ওভারল্যাপ করা হয়েছে <=> (y2 - x1) * (x2 - y1) >= 0

যেখানে কেবল চারটি অপারেশন জড়িত:

  • দুটি বিয়োগ
  • এক গুণ
  • একটি তুলনা

1

যদি কেউ এমন কোনও ওলাইনার সন্ধান করে যা প্রকৃত ওভারল্যাপ গণনা করে:

int overlap = ( x2 > y1 || y2 < x1 ) ? 0 : (y2 >= y1 && x2 <= y1 ? y1 : y2) - ( x2 <= x1 && y2 >= x1 ? x1 : x2) + 1; //max 11 operations

আপনি যদি কিছু কম অপারেশন চান তবে আরও কয়েকটি ভেরিয়েবল:

bool b1 = x2 <= y1;
bool b2 = y2 >= x1;
int overlap = ( !b1 || !b2 ) ? 0 : (y2 >= y1 && b1 ? y1 : y2) - ( x2 <= x1 && b2 ? x1 : x2) + 1; // max 9 operations

1

বিপরীতমুখী ভাবে ভাবেন : কীভাবে 2 রেঞ্জগুলি ওভারল্যাপ না করে যায় ? প্রদত্ত [x1, x2], তারপরে বাইরে[y1, y2] হওয়া উচিত , যা সমান [x1, x2]y1 < y2 < x1 or x2 < y1 < y2y2 < x1 or x2 < y1

সুতরাং, 2 ব্যাপ্তিকে ওভারল্যাপ করার শর্তটি: not(y2 < x1 or x2 < y1)যা সমান y2 >= x1 and x2 >= y1(সাইমন কর্তৃক গৃহীত উত্তরের সাথে সমান)।


@ দামলুয়ার জবাব যেমন দিয়েছিল ঠিক তেমনটাই মনে হচ্ছে (মার্চ 2 '16 এ 17:36)
নাকিলন

0

আপনার ইতিমধ্যে সর্বাধিক দক্ষ উপস্থাপনা রয়েছে - x1 <x2 ইত্যাদি আপনি যদি নিশ্চিত না জানেন তবে এটি খালি ন্যূনতম যাচাই করা দরকার, তারপরে অন্যরা প্রদত্ত সমাধানগুলি ব্যবহার করুন।

আপনার সম্ভবত লক্ষ্য করা উচিত যে কিছু সংকলক প্রকৃতপক্ষে আপনার জন্য এটি অনুকূল করে তুলবে - এই 4 টির মধ্যে যে কোনও এক্সপ্রেশন সত্য হিসাবে প্রত্যাবর্তনের সাথে সাথে ফিরে আসবে। যদি কোনওটি সত্যটি প্রত্যাবর্তন করে তবে এর ফলাফলও শেষ হবে - যাতে অন্য চেকগুলি এড়িয়ে যেতে পারে।


2
সমস্ত সংকলক হবে। সি-স্টাইল সিনট্যাক্স (সি, সি ++, সি #, জাভা ইত্যাদি) সহ বর্তমানে ব্যবহৃত সমস্ত ভাষা (স্বীকৃত) শর্ট সার্কিটযুক্ত বুলিয়ান অপারেটরদের নিয়োগ দেয় এবং এটি বিভিন্ন ভাষাগুলি পরিচালনা করে এমন বিভিন্ন মানের অংশ। অপারেশনের ফলাফল নির্ধারণের জন্য যদি বাম হাতের মানটির ফলাফলটি যথেষ্ট হয় তবে ডান হাতের মানটি মূল্যায়ন করা হয় না।
জোনাথন গ্রিনস্পান

1
মার্ক এইচ - সংকলক এটি করতে পারলে দ্বিতীয় ধারাটিতে এড়িয়ে যাবে: সুতরাং আপনার যদি এমন কোনও ফাংশন থাকে যা বলে: foo (int c) {int i = 0; যদি (সি <3 || ++ i == আরজিসি) প্রিন্টফ ("ভিতরে \ n"); প্রিন্টফ ("আমি% d \ n", i); ফু (2) মুদ্রণ করবে: ভিতরে আমি 0 এবং ফু (4) মুদ্রণ করবে: আমি 1 (জিসিসি 4.4.3 এ পরীক্ষিত, তবে আমি আইসিসি-তে কিছু কুৎসিত কোডের জন্যও এই আচরণের উপর নির্ভর করেছি)
জে টেলার

0

আমার কেস আলাদা। আমি দুটি সময়সীমা ওভারল্যাপ চেক করতে চাই। সেখানে ইউনিট টাইম ওভারল্যাপ হওয়া উচিত নয়। এখানে গো বাস্তবায়ন হয়।

    func CheckRange(as, ae, bs, be int) bool {
    return (as >= be) != (ae > bs)
    }

পরীক্ষার মামলা

if CheckRange(2, 8, 2, 4) != true {
        t.Error("Expected 2,8,2,4 to equal TRUE")
    }

    if CheckRange(2, 8, 2, 4) != true {
        t.Error("Expected 2,8,2,4 to equal TRUE")
    }

    if CheckRange(2, 8, 6, 9) != true {
        t.Error("Expected 2,8,6,9 to equal TRUE")
    }

    if CheckRange(2, 8, 8, 9) != false {
        t.Error("Expected 2,8,8,9 to equal FALSE")
    }

    if CheckRange(2, 8, 4, 6) != true {
        t.Error("Expected 2,8,4,6 to equal TRUE")
    }

    if CheckRange(2, 8, 1, 9) != true {
        t.Error("Expected 2,8,1,9 to equal TRUE")
    }

    if CheckRange(4, 8, 1, 3) != false {
        t.Error("Expected 4,8,1,3 to equal FALSE")
    }

    if CheckRange(4, 8, 1, 4) != false {
        t.Error("Expected 4,8,1,4 to equal FALSE")
    }

    if CheckRange(2, 5, 6, 9) != false {
        t.Error("Expected 2,5,6,9 to equal FALSE")
    }

    if CheckRange(2, 5, 5, 9) != false {
        t.Error("Expected 2,5,5,9 to equal FALSE")
    }

সীমানার তুলনায় আপনি দেখতে পারবেন এক্সওআর প্যাটার্ন


-10

এখানে আমার সংস্করণ:

int xmin = min(x1,x2)
  , xmax = max(x1,x2)
  , ymin = min(y1,y2)
  , ymax = max(y1,y2);

for (int i = xmin; i < xmax; ++i)
    if (ymin <= i && i <= ymax)
        return true;

return false;

আপনি কোটি কোটি বিস্তৃত ব্যবধানের পূর্ণসংখ্যার উপর কিছু উচ্চ-পারফরম্যান্স রেঞ্জ-চেকার চালা না করে আমাদের সংস্করণগুলিকে একইভাবে সঞ্চালন করা উচিত। আমার বক্তব্যটি হ'ল এটি মাইক্রো-অপটিমাইজেশন।


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

12
-1: এটি মাইক্রো-অপ্টিমাইজেশন নয়; এটি একটি উপযুক্ত অ্যালগরিদম চয়ন করছে। যখন সাধারণ ও (1) পছন্দ থাকে তখন আপনার অ্যালগরিদম হল ও (এন) হয়।
সাইমন নিকারসন

এটি ঘটে যখন "অকালীন অপটিমাইজেশন সমস্ত অশুভের মূল" "আচরণের মাঝে মাঝে কিছু প্যাটার্নের উপর অর্ধ-গুরুতর মন্তব্য করার পরিবর্তে অযোগ্যদের জন্য একটি অলঙ্ঘনীয় ধর্মীয় শিষ্য হয়ে ওঠে।
rghome
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.