जांचें कि क्या तीन में से कम से कम दो बूलियन सच हैं


579

एक साक्षात्कारकर्ता ने हाल ही में मुझसे यह सवाल पूछा: तीन बूलियन चर, ए, बी और सी दिए गए हैं, अगर तीन में से कम से कम दो सच हैं तो वापस लौटें।

मेरा समाधान इस प्रकार है:

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if ((a && b) || (b && c) || (a && c)) {
        return true;
    }
    else{
        return false;
    }
}

उन्होंने कहा कि इसमें और सुधार किया जा सकता है, लेकिन कैसे?


170
रिटर्न स्टेटमेंट को इनलाइन करें।
फिंगलास

45
"हू-है-द-हाइ-आईक्यू" साक्षात्कार की तरह लगता है। मैं फेल हो जाता।
क्रिस ड्यूट्रो

79
atLeastTwo(iWantYou, iNeedYou, imEverGonnaLoveYou)
एंड्रयू ग्रिम

92
लोग सबसे तुच्छ सवालों का सामना क्यों करते हैं?
ब्लूराजा - डैनी पफ्लुगुफ्ट

46
सामान्य और आसान समझने वाले प्रश्न बहुत अधिक वोट प्राप्त करते हैं। ऐसे प्रश्न जो बहुत विशिष्ट हैं और तकनीकी नहीं हैं।
जय

जवाबों:


820

लिखने के बजाय:

if (someExpression) {
    return true;
} else {
    return false;
}

लिखो:

return someExpression;

अभिव्यक्ति के लिए ही, कुछ इस तरह से:

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    return a ? (b || c) : (b && c);
}

या यह (जो भी आप आसानी से समझ पाते हैं):

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    return a && (b || c) || (b && c);
}

यह परीक्षण करता है aऔर bठीक एक बार, और cअधिक से अधिक एक बार।

संदर्भ


144
+1: पहेली का प्यारा समाधान, लेकिन उम्मीद है कि हम वास्तविक दुनिया में ऐसा कुछ भी नहीं देखते हैं :)
जूलियट

124
@ जूलियट: मुझे नहीं पता, मुझे लगता है कि अगर यह वास्तविक दुनिया की आवश्यकता होती (असली चर नामों के साथ) तो यह बहुत अच्छी तरह से पढ़ी जाती। गौर कीजिए return hasGoodAttendance ? (passedCoursework || passed Exam) : (passedCoursework && passedExam), जो मुझे ठीक लगता है।
आंद्रेज डॉयल

18
मुझे नहीं लगता कि यह बुरा लग रहा है , लेकिन अगर डोमेन में आवश्यकता को "कम से कम दो" समझा जाता है, तो मुझे लगता है कि इसे पढ़ना आसान होगा atLeastTwo(hasgoodAttendance, passedCoursework, passedExam)। "कम से कम 2 बूल्स सच हैं" का विचार अपने स्वयं के फ़ंक्शन के लिए पर्याप्त सामान्य है।
केन

17
@Lese: इंटरव्यू का सामना करने के लिए सबसे सूक्ष्म अनुकूलित कोड पूछना अव्यावहारिक है, और मुझे लगता है कि बेकार है। माइक्रो-ऑप्टिमाइज़ेशन, जब आवश्यकता से प्रेरित होते हैं, तो रनटाइम प्रोफाइलिंग परिणामों द्वारा निर्देशित किया जाता है, न कि मानव प्रवृत्ति (जो कि भयानक होने के लिए जाना जाता है)। आप निश्चित रूप से साक्षात्कारकर्ताओं से वह प्रक्रिया पूछ सकते हैं जिसके द्वारा आप इसे आगे अनुकूलित करेंगे; यह परिणाम से अधिक महत्वपूर्ण है।
पॉलीजेन लुब्रिकेंट्स

17
टर्नरी ऑपरेटर एक सामान्य मुहावरा है जिसे आपको पढ़ने में सक्षम होना चाहिए। यदि आप इसे नहीं पढ़ सकते हैं तो आपको इसका अध्ययन तब तक करना चाहिए जब तक आप कर सकते हैं। टर्नेरी ऑपरेटर का उपयोग कुछ ऐसा नहीं है जिसे मैं अपमानजनक अर्थ में "चतुर" मानता हूं। लेकिन हाँ, मैं इसे एक विधि कॉल के शरीर के रूप में रखूँगा यदि आप आमतौर पर "कम से कम दो" तर्क का उपयोग कर रहे हैं।
स्टीफन पी।

493

एक अपेक्षाकृत सीधे-आगे की समस्या का जवाब देने के लिए XOR का उपयोग करने के लिए ...

return a ^ b ? c : a

159
वाह, शांत समाधान। लेकिन मेरे लिए इसका उल्टा संस्करण समझना आसान है: a == b? a: c
रॉटसर

5
क ^ ख? c: ए ^ बी? c: ए ^ बी? c: a
अलेक्जेंडरपस

4
हाँ, .. XOR को इतना बुरा प्रेस मिलता है और आपको शायद ही कभी इसका इस्तेमाल करने का मौका मिले।
EightyOne यूनाईटेड

18
@ Stimul8d शायद, क्योंकि बूलियन्स के लिए, यह वही है! = लेकिन कम पठनीय है? यह पता लगाना कि मेरे लिए एक यूरेका पल था ...
तिकोने जेल्विस

2
मैं विशुद्ध रूप से बाइनरी फॉर्म को पसंद करता हूं: रिटर्न ((ए ^ बी) और सी) | (ए और बी)। यह ब्रांच-लेस (तेज) और पढ़ने में आसान है: (या बी सही है और सी सत्य है) या (ए और बी केवल सच है)। ध्यान दें कि (ए | बी) और (ए बी) दोनों इस सूत्र के साथ काम करते हैं।
flanglet

217

क्यों नहीं इसे सचमुच लागू किया जाए? :)

(a?1:0)+(b?1:0)+(c?1:0) >= 2

सी में आप बस लिख सकते हैं a+b+c >= 2(या !!a+!!b+!!c >= 2बहुत सुरक्षित होने के लिए)।

TofuBeer की जावा बाइटकोड की तुलना के जवाब में , यहां एक सरल प्रदर्शन परीक्षण है:

class Main
{
    static boolean majorityDEAD(boolean a,boolean b,boolean c)
    {
        return a;
    }

    static boolean majority1(boolean a,boolean b,boolean c)
    {
        return a&&b || b&&c || a&&c;
    }

    static boolean majority2(boolean a,boolean b,boolean c)
    {
        return a ? b||c : b&&c;
    }

    static boolean majority3(boolean a,boolean b,boolean c)
    {
        return a&b | b&c | c&a;
    }

    static boolean majority4(boolean a,boolean b,boolean c)
    {
        return (a?1:0)+(b?1:0)+(c?1:0) >= 2;
    }

    static int loop1(boolean[] data, int i, int sz1, int sz2)
    {
        int sum = 0;
        for(int j=i;j<i+sz1;j++)
        {
            for(int k=j;k<j+sz2;k++)
            {
                sum += majority1(data[i], data[j], data[k])?1:0; 
                sum += majority1(data[i], data[k], data[j])?1:0; 
                sum += majority1(data[j], data[k], data[i])?1:0; 
                sum += majority1(data[j], data[i], data[k])?1:0; 
                sum += majority1(data[k], data[i], data[j])?1:0; 
                sum += majority1(data[k], data[j], data[i])?1:0; 
            }
        }
        return sum;
    }

    static int loop2(boolean[] data, int i, int sz1, int sz2)
    {
        int sum = 0;
        for(int j=i;j<i+sz1;j++)
        {
            for(int k=j;k<j+sz2;k++)
            {
                sum += majority2(data[i], data[j], data[k])?1:0; 
                sum += majority2(data[i], data[k], data[j])?1:0; 
                sum += majority2(data[j], data[k], data[i])?1:0; 
                sum += majority2(data[j], data[i], data[k])?1:0; 
                sum += majority2(data[k], data[i], data[j])?1:0; 
                sum += majority2(data[k], data[j], data[i])?1:0; 
            }
        }
        return sum;
    }

    static int loop3(boolean[] data, int i, int sz1, int sz2)
    {
        int sum = 0;
        for(int j=i;j<i+sz1;j++)
        {
            for(int k=j;k<j+sz2;k++)
            {
                sum += majority3(data[i], data[j], data[k])?1:0; 
                sum += majority3(data[i], data[k], data[j])?1:0; 
                sum += majority3(data[j], data[k], data[i])?1:0; 
                sum += majority3(data[j], data[i], data[k])?1:0; 
                sum += majority3(data[k], data[i], data[j])?1:0; 
                sum += majority3(data[k], data[j], data[i])?1:0; 
            }
        }
        return sum;
    }

    static int loop4(boolean[] data, int i, int sz1, int sz2)
    {
        int sum = 0;
        for(int j=i;j<i+sz1;j++)
        {
            for(int k=j;k<j+sz2;k++)
            {
                sum += majority4(data[i], data[j], data[k])?1:0; 
                sum += majority4(data[i], data[k], data[j])?1:0; 
                sum += majority4(data[j], data[k], data[i])?1:0; 
                sum += majority4(data[j], data[i], data[k])?1:0; 
                sum += majority4(data[k], data[i], data[j])?1:0; 
                sum += majority4(data[k], data[j], data[i])?1:0; 
            }
        }
        return sum;
    }

    static int loopDEAD(boolean[] data, int i, int sz1, int sz2)
    {
        int sum = 0;
        for(int j=i;j<i+sz1;j++)
        {
            for(int k=j;k<j+sz2;k++)
            {
                sum += majorityDEAD(data[i], data[j], data[k])?1:0; 
                sum += majorityDEAD(data[i], data[k], data[j])?1:0; 
                sum += majorityDEAD(data[j], data[k], data[i])?1:0; 
                sum += majorityDEAD(data[j], data[i], data[k])?1:0; 
                sum += majorityDEAD(data[k], data[i], data[j])?1:0; 
                sum += majorityDEAD(data[k], data[j], data[i])?1:0; 
            }
        }
        return sum;
    }

    static void work()
    {
        boolean [] data = new boolean [10000];
        java.util.Random r = new java.util.Random(0);
        for(int i=0;i<data.length;i++)
            data[i] = r.nextInt(2) > 0;
        long t0,t1,t2,t3,t4,tDEAD;
        int sz1 = 100;
        int sz2 = 100;
        int sum = 0;

        t0 = System.currentTimeMillis();

        for(int i=0;i<data.length-sz1-sz2;i++)
            sum += loop1(data, i, sz1, sz2);

        t1 = System.currentTimeMillis();

        for(int i=0;i<data.length-sz1-sz2;i++)
            sum += loop2(data, i, sz1, sz2);

        t2 = System.currentTimeMillis();

        for(int i=0;i<data.length-sz1-sz2;i++)
            sum += loop3(data, i, sz1, sz2);

        t3 = System.currentTimeMillis();

        for(int i=0;i<data.length-sz1-sz2;i++)
            sum += loop4(data, i, sz1, sz2);

        t4 = System.currentTimeMillis();

        for(int i=0;i<data.length-sz1-sz2;i++)
            sum += loopDEAD(data, i, sz1, sz2);

        tDEAD = System.currentTimeMillis();

        System.out.println("a&&b || b&&c || a&&c : " + (t1-t0) + " ms");
        System.out.println("   a ? b||c : b&&c   : " + (t2-t1) + " ms");
        System.out.println("   a&b | b&c | c&a   : " + (t3-t2) + " ms");
        System.out.println("   a + b + c >= 2    : " + (t4-t3) + " ms");
        System.out.println("       DEAD          : " + (tDEAD-t4) + " ms");
        System.out.println("sum: "+sum);
    }

    public static void main(String[] args) throws InterruptedException
    {
        while(true)
        {
            work();
            Thread.sleep(1000);
        }
    }
}

यह मेरी मशीन पर निम्नलिखित प्रिंट करता है (हॉट कोर सर्वर वीएम (14.1-b02, मिश्रित मोड के साथ इंटेल कोर 2 + सन जावा 1.6.0_15-b03 पर Ubuntu चल रहा है):

पहला और दूसरा पुनरावृत्तियों:

a&&b || b&&c || a&&c : 1740 ms
   a ? b||c : b&&c   : 1690 ms
   a&b | b&c | c&a   : 835 ms
   a + b + c >= 2    : 348 ms
       DEAD          : 169 ms
sum: 1472612418

बाद में पुनरावृत्तियों:

a&&b || b&&c || a&&c : 1638 ms
   a ? b||c : b&&c   : 1612 ms
   a&b | b&c | c&a   : 779 ms
   a + b + c >= 2    : 905 ms
       DEAD          : 221 ms

मुझे आश्चर्य है, जावा वीएम (+ b + c> = 2) मामले के लिए समय के साथ प्रदर्शन को कम कर सकता है ।

और अगर -clientवीएम स्विच के साथ जावा चलाते हैं तो यहां क्या होता है :

a&&b || b&&c || a&&c : 4034 ms
   a ? b||c : b&&c   : 2215 ms
   a&b | b&c | c&a   : 1347 ms
   a + b + c >= 2    : 6589 ms
       DEAD          : 1016 ms

रहस्य ...

और अगर मैं इसे जीएनयू जावा इंटरप्रेटर में चलाता हूं , तो यह लगभग 100 गुना धीमा हो जाता है, लेकिन a&&b || b&&c || a&&cसंस्करण तब जीतता है।

Tofubeer के परिणाम OS X चलाने वाले नवीनतम कोड के साथ:

a&&b || b&&c || a&&c : 1358 ms
   a ? b||c : b&&c   : 1187 ms
   a&b | b&c | c&a   : 410 ms
   a + b + c >= 2    : 602 ms
       DEAD          : 161 ms

एक मैक जावा 1.6.0_26-b03-383-11A511 के साथ पॉल वैगलैंड के परिणाम

a&&b || b&&c || a&&c : 394 ms 
   a ? b||c : b&&c   : 435 ms
   a&b | b&c | c&a   : 420 ms
   a + b + c >= 2    : 640 ms
   a ^ b ? c : a     : 571 ms
   a != b ? c : a    : 487 ms
       DEAD          : 170 ms

4
a+b+c >= 2: यह नकारात्मक के साथ काम नहीं करता है, है ना? बात आपको करनी पड़ सकती है !!a, मुझे यकीन नहीं है।
पॉलीजेन लुब्रिकेंट्स

8
<s> -1। आपको सी के लिए ऐसा कभी नहीं करना चाहिए। आपको नहीं पता कि सच का मूल्य क्या है (यह आसानी से -1 हो सकता है)। </ s> वास्तव में मुझे लगता है कि C99 अपने मानक में शामिल है कि सच को 1 के रूप में परिभाषित किया गया है। मैं अब भी ऐसा नहीं करूंगा।
मार्क पीटर्स

1
क्या यह संभव है यदि आपका इनपुट बूलियन ऑपरेशन का परिणाम है? और क्या यह C ++ में "बूल" प्रकार के लिए संभव है?
रॉटर्स

2
@ रॉटर्स: किसी ने भी नहीं कहा कि इनपुट बूलियन ऑपरेशन का परिणाम है। यहां तक ​​कि नकारात्मक के बिना आप आग से खेल रहे हैं, जैसे कि यदि आप इसे 2 के रूप में परिभाषित करते हैं तो आपकी स्थिति झूठी सकारात्मक होगी। लेकिन मुझे इस बात की कोई परवाह नहीं है कि मैं बूलियन्स को अंकगणित में समझने के विचार को नापसंद करता हूं। आपका जावा समाधान स्पष्ट है कि यह बूलियन से पूर्णांक प्रकार तक की बारीकियों पर निर्भर नहीं करता है।
मार्क पीटर्स

7
Microbenchmark से सावधान रहें: java.sun.com/docs/hotspot/HotSpotFAQ.html#benchmarking_simple
BalusC

143

इस तरह के प्रश्नों को कर्णघट मानचित्र के साथ हल किया जा सकता है :

      | C | !C
------|---|----
 A  B | 1 | 1 
 A !B | 1 | 0
!A !B | 0 | 0
!A  B | 1 | 0

जिसमें से आप अनुमान लगाते हैं कि आपको पहली पंक्ति के लिए एक समूह और पहले कॉलम के लिए दो समूहों की आवश्यकता है, पॉलीजेनबायबैलेंट का इष्टतम समाधान प्राप्त करना:

(C && (A || B)) || (A && B)  <---- first row
       ^
       |
   first column without third case

10
@ जस्टिन, कर्णघ मानचित्र ने 3 ANDs और 2 ORs से 2 ANDs और 2 वर्ग तक तार्किक परिचालनों की संख्या कम की। @ जेक, मुझे कर्णघट मानचित्र के अस्तित्व की याद दिलाने के लिए धन्यवाद।
टैची

14
कुछ नया करने के लिए +1। मेरी अगली कार्यात्मक कल्पना में के-मैप शामिल होगा, चाहे उसे इसकी आवश्यकता हो या इसे।
जस्टिन आर।

2
हो सकता है कि खराब पठनीयता को टिप्पणी में (1) उपयुक्त तालिका द्वारा और स्कूल में सीखी गई कुछ उपयोगी चीजों के लिए उपयुक्त इकाई परीक्षण ... +1 द्वारा मुआवजा दिया जा सके।
मूला

140

पठनीयता लक्ष्य होना चाहिए। कोड को पढ़ने वाला कोई व्यक्ति आपके इरादे को तुरंत समझ लेगा। तो यहाँ मेरा समाधान है।

int howManyBooleansAreTrue =
      (a ? 1 : 0)
    + (b ? 1 : 0)
    + (c ? 1 : 0);

return howManyBooleansAreTrue >= 2;

21
मैं आधार से सहमत हूं, लेकिन (a && b) || (b && c) || (a && c) आपके समाधान IMHO की तुलना में बहुत अधिक पठनीय है।
एड्रियन ग्रिगोर

62
हम्म, अब मुझे "फोर बूलियंस में से दो" संस्करण की आवश्यकता है ... डैनटेल का संस्करण अब बहुत आसान है।
अराफंगियन

6
या स्काला में:Seq(true, true, false).map(if (_) 1 else 0).sum >= 2
रेट्रो

5
@ ग्रेटोनिअम: हम्म, नहीं। जावा तरीका स्काला में ठीक काम करता है और अधिक पठनीय और अधिक कुशल दोनों है।
Seun Osewa

134
return (a==b) ? a : c;

स्पष्टीकरण:

यदि a==b, तो दोनों सत्य हैं या दोनों झूठे हैं। यदि दोनों सत्य हैं, तो हमने अपने दो सच्चे बूलियन ढूंढ लिए हैं, और (वापस लौटकर a) सच हो सकते हैं । यदि दोनों झूठे हैं तो दो सच्चे बूलियन नहीं हो सकते भले ही cवह सच हो, इसलिए हम झूठे (वापस लौटकर a) आते हैं । वह (a==b) ? aहिस्सा है। किस बारे में : c? ठीक है, अगर a==bगलत है, तो वास्तव में एक aया bसही होना चाहिए, इसलिए हमने पहला सच्चा बूलियन पाया है, और केवल एक चीज जो बची है वह यह है कि अगर cयह भी सच है, तो हम cजवाब के रूप में वापस आते हैं ।


8
c का कभी परीक्षण भी नहीं किया गया ... शानदार!
कर्टनडॉग

समानता और इस तथ्य के सकर्मक संबंध का उपयोग करता है कि एक बूलियन या तो सही है या गलत +1
क्रिस्टोफ रूसो

3
कितने शालीन! मुझे यह मानने के लिए कलम और कागज की जाँच करनी पड़ी :) कुडोस टू यू सर!
एड्रियन

3
मैं इस बारे में सोचता हूं कि "अगर aऔर bसहमत हैं, तो उनके पास बहुमत का वोट है, इसलिए जो कुछ भी है, उसके साथ जाएं, वे असहमत हैं, इसलिए cनिर्णायक वोट है"
बेन मिलवुड

34

आपको ऑपरेटर्स के शॉर्ट सर्कुलेटिंग फॉर्म का उपयोग करने की आवश्यकता नहीं है।

return (a & b) | (b & c) | (c & a);

यह आपके संस्करण के समान तर्क संचालन करता है, हालांकि पूरी तरह से शाखाहीन है।


11
जब आप 1 मूल्यांकन कर सकते हैं तो आप 5 मूल्यांकन क्यों करना चाहेंगे? यह वास्तव में तर्क संचालन की समान संख्या को सच नहीं करता है। वास्तव में, यह हमेशा अधिक प्रदर्शन करेगा ।
मार्क पीटर्स

2
मुझे लगता है कि द्विआधारी अंकगणित और बूलियन अंकगणित का मिश्रण एक बुरा विचार है। यह दीवार में रिंच के साथ ड्राइविंग शिकंजा की तरह है। सबसे बुरा यह है कि उनके पास अलग-अलग शब्दार्थ हैं।
पीटर टिलमन्स

12
@ मर्क - यह तेजी से हो सकता है ... सीपीयू पाइपलाइन पर एक गलत शाखा भविष्यवाणी के प्रभाव पर निर्भर करता है। हालांकि, इस तरह के माइक्रो-ऑप्टिमाइजेशन को जेआईटी कंपाइलर पर छोड़ना सबसे अच्छा है।
स्टीफन सी

4
यह जावा (या किसी अन्य भाषा) में ऐसा कुछ करने के लिए ठीक है ... युगल के एक जोड़े के साथ: 1) इसे तेज करने की आवश्यकता है (इस मामले में, मेरा मानना ​​है कि यह है, मेरा दूसरा जवाब देखें) 2) बेहतर काफी तेजी से (निश्चित नहीं कि अगर ऐसा है), 3) सबसे महत्वपूर्ण रूप से प्रलेखित है क्योंकि यह "विषम" है। जब तक यह एक उद्देश्य की पूर्ति करता है और इसे प्रलेखित किया जाता है, जब यह समझ में आता है तो "नियमों को तोड़ना" ठीक है।
टोफूबीर

11
@Peter Tillemans बाइनरी ऑपरेटरों के साथ कोई मिश्रण नहीं है, जावा में ये बूलियन ऑपरेटर हैं।
स्टारबेल

27

यहां एक परीक्षण-संचालित, सामान्य दृष्टिकोण है। अब तक की पेशकश के रूप में "कुशल" के रूप में नहीं, लेकिन स्पष्ट, परीक्षण, काम और सामान्यीकृत।

public class CountBooleansTest extends TestCase {
    public void testThreeFalse() throws Exception {
        assertFalse(atLeastTwoOutOfThree(false, false, false));
    }

    public void testThreeTrue() throws Exception {
        assertTrue(atLeastTwoOutOfThree(true, true, true));
    }

    public void testOnes() throws Exception {
        assertFalse(atLeastTwoOutOfThree(true, false, false));
        assertFalse(atLeastTwoOutOfThree(false, true, false));
        assertFalse(atLeastTwoOutOfThree(false, false, true));
    }

    public void testTwos() throws Exception {
        assertTrue(atLeastTwoOutOfThree(false, true, true));
        assertTrue(atLeastTwoOutOfThree(true, false, true));
        assertTrue(atLeastTwoOutOfThree(true, true, false));
    }

    private static boolean atLeastTwoOutOfThree(boolean b, boolean c, boolean d) {
        return countBooleans(b, c, d) >= 2;
    }

    private static int countBooleans(boolean... bs) {
        int count = 0;
        for (boolean b : bs)
            if (b)
                count++;
        return count;
    }
}

8
वाह, मैंने इसे देखने से पहले कभी भी पूरी तरह से परीक्षण विधि नहीं देखी है ।
रॉटर्स

51
मैं व्यक्तिगत रूप से इतने सारे कारणों के लिए इस कोड को भयानक लगता हूं। मैं नीच नहीं जा रहा हूं, लेकिन अगर मैंने कभी इसे उत्पादन कोड में देखा तो मैं शाप दे दूंगा। एक अत्यंत सरल बूलियन ऑपरेशन को इस तरह से जटिल होने की आवश्यकता नहीं है।
CaptainCasey

10
मुझे आपके कारणों को जानने में बहुत रुचि होगी, @CaptainCasey। मुझे लगता है कि यह बहुत अच्छा कोड है। एक अच्छा सामान्यीकृत फ़ंक्शन है जो समझना आसान है, सत्यापित करना आसान है, और एक विशिष्ट फ़ंक्शन जो इसका लाभ उठाता है, समझना और सत्यापित करना भी आसान है। वास्तविक दुनिया में, मैं उन्हें सार्वजनिक करूँगा और उन्हें दूसरी कक्षा में रखूँगा; इसके अलावा - मैं खुशी से इस कोड को उत्पादन में डालूंगा। ओह - हाँ - मैं countBueeans () का नाम बदलूंगा।
कार्ल मैनस्टर

5
यदि इसके प्रदर्शन के बारे में नहीं है, तो यह समाधान मेरे लिए लगभग सही लगता है: पढ़ने में आसान और विस्तार योग्य। Thats वास्तव में क्या var-args के लिए बने हैं।
एटमान्रोमैन

7
क्या नर्क है, लोग? यह स्पष्ट और अच्छी तरह से परीक्षण किया गया कोड है, और एकमात्र कारण यह बहुत कुछ दिखता है, क्योंकि इसमें परीक्षण शामिल हैं। A +++, फिर से बढ़ेगा।
क्रिस्टोफ़र हैमरस्ट्रॉम

24

इसे जोड़ो। इसे एक कारण के लिए बूलियन बीजगणित कहा जाता है:

  0 x 0 = 0
  1 x 0 = 0
  1 x 1 = 1

  0 + 0 = 0
  1 + 0 = 1
  1 + 1 = 0 (+ carry)

यदि आप वहां की सत्य तालिकाओं को देखते हैं, तो आप देख सकते हैं कि गुणन बूलियन और है, और बस जोड़ xor है।

तुम्हारे प्रश्न का उत्तर देने के लिए:

return (a + b + c) >= 2

2
मेरी राय में, यह सबसे सुरुचिपूर्ण समाधान है।
Torbjørn Kristoffersen

9
धोखेबाज़ गलती हालांकि, एक बूलियन मान 0 नहीं है, इसका मतलब यह नहीं है कि इसका हमेशा 1.
टोमडेमुइट

13
सिवाय इसके कि पोस्ट पर टैग "जावा" कहता है, और जब आप जावा में बूलियन के रूप में परिभाषित होते हैं, तो आप "a + b + c" नहीं लिख सकते।
Jay

जावा में काम करने के लिए, यह होना चाहिए return ((a?1:0) + (b?1:0) + (c?1:0)) >= 2
डेविड आर ट्रिबल

Duh, मैंने इसे वोट किया क्योंकि मुझे लगा कि यह C ++ प्रश्न था ... मैं जावा प्रश्न क्यों पढ़ रहा हूं? : /
कार्लो वुड


15

यह वास्तव में निर्भर करता है कि आप "बेहतर" से क्या मतलब है:

स्पष्ट?

boolean twoOrMoreAreTrue(boolean a, boolean b, boolean c)
{
    return (a && b) || (a && c) || (b && c);
}

Terser?

boolean moreThanTwo(boolean a, boolean b, boolean c)
{
    return a == b ? a : c;
}

ज़्यादा सामान्य?

boolean moreThanXTrue(int x, boolean[] bs)
{
    int count = 0;

    for(boolean b : bs)
    {
        count += b ? 1 : 0;

        if(count > x) return true;
    }

    return false;
}

अधिक स्केलेबल?

boolean moreThanXTrue(int x, boolean[] bs)
{
    int count = 0;

    for(int i < 0; i < bs.length; i++)
    {
        count += bs[i] ? 1 : 0;

        if(count > x) return true;

        int needed = x - count;
        int remaining = bs.length - i;

        if(needed >= remaining) return false;
    }

    return false;
}

और तेज?

// Only profiling can answer this.

कौन सा "बेहतर" स्थिति पर बहुत अधिक निर्भर करता है।


14

यहाँ मानचित्र / कम का उपयोग करते हुए एक और कार्यान्वयन किया गया है। यह एक वितरित वातावरण में अरबों बुलियन © के लिए अच्छी तरह से तराजू है। MongoDB का उपयोग करना:

valuesबुलियन का एक डेटाबेस बनाना :

db.values.insert({value: true});
db.values.insert({value: false});
db.values.insert({value: true});

नक्शा बनाना, कार्यों को कम करना:

संपादित करें : मुझे जेनेरिक सूचियों पर नक्शा / कम लागू करने के बारे में कर्टनडॉग का जवाब पसंद है , इसलिए यहां एक मानचित्र फ़ंक्शन होता है जो एक कॉलबैक लेता है जो निर्धारित करता है कि मूल्य की गणना की जानी चाहिए या नहीं।

var mapper = function(shouldInclude) {
    return function() {
        emit(null, shouldInclude(this) ? 1 : 0);
    };
}

var reducer = function(key, values) {
    var sum = 0;
    for(var i = 0; i < values.length; i++) {
        sum += values[i];
    }
    return sum;
}

चल नक्शा / कम करें:

var result = db.values.mapReduce(mapper(isTrue), reducer).result;

containsMinimum(2, result); // true
containsMinimum(1, result); // false


function isTrue(object) {
    return object.value == true;
}

function containsMinimum(count, resultDoc) {
    var record = db[resultDoc].find().next();
    return record.value >= count;
}

@ अनुराग: जितना मैं M / R से प्यार करता हूं और जितना एक्सपोजर हाल ही में Google ने दिया है (भले ही वह FP से एक भी सच्चा M / R नहीं है), मैं आपके जवाब पर बकवास नहीं कहूंगा। रियल-वर्ल्ड [TM] "स्टफिंग" कोड की अरबों और अरबों पंक्तियाँ हैं जहाँ उपयोग की जाने वाली मैप / कम की एक भी लाइन नहीं है। किसी के साथ इस तरह के एक सवाल का जवाब देने के लिए इस : निश्चित रूप से के रूप में मेरी किताब का झंडा लगा हुआ है "Smartie खेलने की कोशिश" । उल्लेख करने के लिए नहीं अधिकांश साक्षात्कारकर्ताओं को यह बताने में सक्षम नहीं होगा कि क्या आप उन्हें बकवास करने की कोशिश कर रहे हैं या नहीं, क्योंकि उन्होंने वास्तव में अपने करियर में एम / आर का उपयोग करके एक भी कार्यक्रम नहीं लिखा था।
सिंटैक्सटैक्स 3rrr

2
@ सिंथ- हर कोई अपनी राय का हकदार है। मेरा जवाब समस्या को देखने का सिर्फ एक तरीका है। ज़रूर, यह 3 बूलियन मूल्यों के लिए अतिरंजित लगता है, लेकिन इसका मतलब यह नहीं है कि मैं यहां स्मार्ट-पैंट बनने की कोशिश कर रहा हूं। यह समस्या को हल करने के लिए एक सामान्य दृष्टिकोण है जिसका उपयोग हर कोई करता है - समस्या को छोटे टुकड़ों में तोड़ दें। यही गणितीय प्रेरण काम करता है, यही कारण है कि सबसे अधिक पुनरावर्ती एल्गोरिदम काम करते हैं, और यह है कि लोग सामान्य रूप से समस्याओं को कैसे हल करते हैं।
अनुराग

13

यहाँ (अब तक) जवाब लेना:

public class X
{
    static boolean a(final boolean a, final boolean b, final boolean c)
    {
    return ((a && b) || (b && c) || (a && c));
    }

    static boolean b(final boolean a, final boolean b, final boolean c)
    {
    return a ? (b || c) : (b && c);
    }

    static boolean c(final boolean a, final boolean b, final boolean c)
    {
    return ((a & b) | (b & c) | (c & a));
    }

    static boolean d(final boolean a, final boolean b, final boolean c)
    {
    return ((a?1:0)+(b?1:0)+(c?1:0) >= 2);
    }
}

और उन्हें decompiler के माध्यम से चला रहे हैं (javap -c X> results.txt):

Compiled from "X.java"
public class X extends java.lang.Object{
public X();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

static boolean a(boolean, boolean, boolean);
  Code:
   0:   iload_0
   1:   ifeq    8
   4:   iload_1
   5:   ifne    24
   8:   iload_1
   9:   ifeq    16
   12:  iload_2
   13:  ifne    24
   16:  iload_0
   17:  ifeq    28
   20:  iload_2
   21:  ifeq    28
   24:  iconst_1
   25:  goto    29
   28:  iconst_0
   29:  ireturn

static boolean b(boolean, boolean, boolean);
  Code:
   0:   iload_0
   1:   ifeq    20
   4:   iload_1
   5:   ifne    12
   8:   iload_2
   9:   ifeq    16
   12:  iconst_1
   13:  goto    33
   16:  iconst_0
   17:  goto    33
   20:  iload_1
   21:  ifeq    32
   24:  iload_2
   25:  ifeq    32
   28:  iconst_1
   29:  goto    33
   32:  iconst_0
   33:  ireturn

static boolean c(boolean, boolean, boolean);
  Code:
   0:   iload_0
   1:   iload_1
   2:   iand
   3:   iload_1
   4:   iload_2
   5:   iand
   6:   ior
   7:   iload_2
   8:   iload_0
   9:   iand
   10:  ior
   11:  ireturn

static boolean d(boolean, boolean, boolean);
  Code:
   0:   iload_0
   1:   ifeq    8
   4:   iconst_1
   5:   goto    9
   8:   iconst_0
   9:   iload_1
   10:  ifeq    17
   13:  iconst_1
   14:  goto    18
   17:  iconst_0
   18:  iadd
   19:  iload_2
   20:  ifeq    27
   23:  iconst_1
   24:  goto    28
   27:  iconst_0
   28:  iadd
   29:  iconst_2
   30:  if_icmplt   37
   33:  iconst_1
   34:  goto    38
   37:  iconst_0
   38:  ireturn
}

आप देख सकते हैं कि?: वाले थोड़े बेहतर हैं तो आपके मूल का निश्चित संस्करण। जो सबसे अच्छा है वह वही है जो पूरी तरह से ब्रांचिंग से बचता है। यह कम निर्देशों (ज्यादातर मामलों में) के दृष्टिकोण से अच्छा है और सीपीयू के शाखा पूर्वानुमान भागों के लिए बेहतर है, क्योंकि शाखा भविष्यवाणी में गलत अनुमान सीपीयू स्टालिंग का कारण बन सकता है।

मैं कहता हूं कि सबसे कुशल एक है जो समग्र रूप से चांदनी से है। यह औसतन सबसे कम निर्देशों का उपयोग करता है और सीपीयू में पाइपलाइन स्टालों के लिए मौका कम कर देता है।

100% सुनिश्चित करने के लिए आपको प्रत्येक निर्देश के लिए लागत (सीपीयू चक्रों में) का पता लगाना होगा, जो दुर्भाग्य से आसानी से उपलब्ध नहीं है (आपको हॉटस्पॉट के लिए स्रोत को देखना होगा और फिर सीपीयू विक्रेताओं को समय के लिए चश्मा देना होगा। प्रत्येक उत्पन्न निर्देश के लिए लिया गया)।

कोड के रनटाइम विश्लेषण के लिए रॉटर द्वारा अपडेट किया गया उत्तर देखें।


5
आप केवल बायटेकोड को देख रहे हैं। आप सभी जानते हैं, जेआईटी, बायटेकोड में शाखाओं के साथ एक संस्करण लेगा और इसे मूल कोड में शाखाओं वाले संस्करण में बदल देगा। लेकिन कोई यह सोचता है कि बाईटकोड में कम शाखाएं बेहतर होंगी।
डेविड कॉनरेड

13

प्रत्यक्ष कोड का एक और उदाहरण:

int  n = 0;
if (a) n++;
if (b) n++;
if (c) n++;
return (n >= 2);

यह स्पष्ट रूप से सबसे रसीला कोड नहीं है।

परिशिष्ट

इसका एक और (थोड़ा अनुकूलित) संस्करण:

int  n = -2;
if (a) n++;
if (b) n++;
if (c) n++;
return (n >= 0);

यह थोड़ा तेज हो सकता है, यह मानते हुए कि 0 के मुकाबले तुलना 2 के मुकाबले तुलना में तेज (या शायद कम) कोड का उपयोग करेगी।


+1 @ लॉर्डमास्टर, मुझे क्षमा करें, लेकिन आप गलत हैं! यह यहां का सबसे रसीला जवाब है। (यानी संक्षेप में और स्पष्ट रूप से व्यक्त);)
ऐश


@ एम। मिम्पेन: केवल क्लास ऑब्जेक्ट्स के लिए। आदिम प्रकारों (जैसे nऊपर) के लिए, कोई भी सभ्य संकलक प्रत्येक ++ऑपरेशन को एक एकल सीपीयू निर्देश में संकलित करेगा , चाहे वह पूर्व या पोस्ट हो।
डेविड आर ट्रिबल

12

अभी तक यह करने के लिए एक और तरीका है, लेकिन एक बहुत अच्छा नहीं:

return (Boolean.valueOf(a).hashCode() + Boolean.valueOf(b).hashCode() + Boolean.valueOf(c).hashCode()) < 3705);

BooleanHashCode मूल्यों सच्चे और झूठे तो के लिए 1237 के लिए 1231 में तय कर रहे हैं समान रूप से इस्तेमाल किया जा सकता था<= 3699


1
या (ए! 1: 0) + (बी? 1: 0) + (सी? 1: 0)> = 2
पीटर लॉरी

12

सुधार का सबसे स्पष्ट सेट हैं:

// There is no point in an else if you already returned.
boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if ((a && b) || (b && c) || (a && c)) {
        return true;
    }
    return false;
}

और फिर

// There is no point in an if(true) return true otherwise return false.
boolean atLeastTwo(boolean a, boolean b, boolean c) {
    return ((a && b) || (b && c) || (a && c));
}

लेकिन वे सुधार मामूली हैं।


10

मुझे टर्नरी ( return a ? (b || c) : (b && c);शीर्ष उत्तर से) पसंद नहीं है, और मुझे नहीं लगता कि मैंने किसी को इसका उल्लेख करते देखा है। यह इस तरह लिखा है:

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if (a) {
        return b||c;
    } 
    else {
        return b&&C;
    }

8

में Clojure :

(defn at-least [n & bools]
  (>= (count (filter true? bools)) n)

उपयोग:

(at-least 2 true false true)

2
+1 ग्रेट जेनेरिक संस्करण लिस्प्स की शक्ति को दर्शाता है। धन्यवाद,
dsmith

6

मुझे नहीं लगता कि मैंने यह समाधान अभी तक देखा है:

boolean atLeast(int howMany, boolean[] boolValues) {
  // check params for valid values

  int counter = 0;
  for (boolean b : boolValues) {
    if (b) {
      counter++;

      if (counter == howMany) {
        return true;
      }
    }
  }
  return false;
}

इसका लाभ यह है कि एक बार यह उस संख्या तक पहुंच जाता है जिसे आप खोज रहे हैं, यह टूट जाता है। इसलिए यदि यह "इस 1,000,000 मूल्यों में से कम से कम 2 सत्य हैं" जहां पहले दो वास्तव में सच हैं, तो इसे कुछ अधिक "सामान्य" समाधानों की तुलना में तेजी से बढ़ना चाहिए।


यह शायद होना चाहिए: अगर (++ काउंटर == howMany) वेतन वृद्धि के बजाय और फिर अलग से जाँच।
जो एनोस

2
या इससे भी कम: यदि (b && (++ काउंटर == howMany))
जो एनोस

1
मैं ऐसा करना boolean ... boolValuesआसान कहूंगा, लेकिन अभी भी एक सरणी है
स्टीफन

मैं अपने जावा पर अद्यतित नहीं हूं - मुझे नहीं पता था कि अस्तित्व में है। एक अजीब वाक्यविन्यास की तरह, लेकिन यह उपयोगी है - हर बार एक समय में मैं इसे सी # (कीवर्ड कीवर्ड) में करूंगा, और यह चीजों को कॉल करने के लिए अच्छा बनाता है। या, मुझे जावा के बारे में पता नहीं है, लेकिन .NET में, सरणियाँ और सभी संग्रह IEnumerable <T> को लागू करते हैं, इसलिए मैं संभवतः जावा के समकक्ष जो भी उपयोग करूंगा।
जो एनोस

इस के प्रदर्शन की तुलना 2of3 उदाहरण के खिलाफ कैसे की जाती है? एक वापसी? (b || c): (b && c);
इयोन स्पैन

6

हम बूलर्स को पूर्णांक में बदल सकते हैं और यह आसान जांच कर सकते हैं:

(int(a) + int(b) + int(c)) >= 2

6

चूंकि यह निर्दिष्ट नहीं किया गया था कि कोड को कैसे सुधारना चाहिए, इसलिए मैं इसे और अधिक मनोरंजक बनाकर कोड को बेहतर बनाने का प्रयास करूंगा। यहाँ मेरा समाधान है:

boolean atLeastTwo(boolean t, boolean f, boolean True) {
    boolean False = True;
    if ((t || f) && (True || False)) 
        return "answer" != "42";
    if (t && f) 
        return !"France".contains("Paris");
    if (False == True) 
        return true == false;
    return Math.random() > 0.5;
}

यदि यह कोड काम करता है तो किसी की सोच में, यहाँ तर्क का उपयोग करके सरलीकरण किया गया है:

boolean atLeastTwo(boolean a, boolean b, boolean c) {
    if ((a || b) && (c)) 
        return true;
    if (a && b) 
        return true;
    if (true) 
        return false;
    // The last line is a red herring, as it will never be reached:
    return Math.random() > 0.5; 

}

इसे आगे निम्न में उबाला जा सकता है:

return ((a || b) && (c)) || (a && b);

लेकिन अब यह कोई मज़ेदार नहीं है।


5
Function ReturnTrueIfTwoIsTrue(bool val1, val2, val3))
{
     return (System.Convert.ToInt16(val1) +
             System.Convert.ToInt16(val2) +
             System.Convert.ToInt16(val3)) > 1;
}

ऐसा करने के कई तरीके ...


3
C # की तरह देखें। इस सवाल के जावा-लक्षित :) के उत्तर में इस तरह के रूप में उल्लेख किया जाना चाहिए :)
BalusC

5

एसी का घोल।

int two(int a, int b, int c) {
  return !a + !b + !c < 2;
}

या आप पसंद कर सकते हैं:

int two(int a, int b, int c) {
  return !!a + !!b + !!c >= 2;
}

4
return 1 << $a << $b << $c >= 1 << 2;

यह देखने से पहले सुवेगा का जवाब नहीं देखा, बहुत ही एक ही बात है।
केविन

क्या यह वास्तव में काम करता है? मुझे लगता है कि यह PHP है, लेकिन मेरे पास इसका उपयोग नहीं है, लेकिन मैं आपसे केवल यह पूछूंगा: यदि $ 0 है तो क्या होता है?
मार्क एडगर

@ मर्क वास्तव में $ a है तो यह काम नहीं करता है। यह एक निरीक्षण था। यह बात बताने के लिए धन्यवाद। :)
केविन

4

सबसे सरल तरीका (IMO) जो भ्रामक नहीं है और पढ़ने में आसान है:

// Three booleans, check if two or more are true

return ( a && ( b || c ) ) || ( b && c );

कार्यात्मक रूप से, यह समान है। Syntactically, यह उन लोगों के लिए पढ़ना आसान बनाता है जो प्रश्न चिह्न सशर्त संचालक के उपयोग के आदी हैं। मैं शर्त लगाने के लिए तैयार हूं कि अधिक लोग जानते हैं कि कैसे और ओआर या ऑपरेटर्स को उन लोगों की संख्या की तुलना में पता है जो प्रश्न चिह्न सशर्त ऑपरेटरों का उपयोग करना जानते हैं। मूल प्रश्न एक "बेहतर उत्तर" के लिए पूछता है .. स्वीकृत उत्तर उत्तर को सरल करता है, लेकिन एक बहुत ही दिलचस्प प्रश्न उठाता है कि इसमें क्या सुधार होता है। क्या आप सार्वभौमिक पठनीयता के लिए या सादगी के लिए कार्यक्रम करते हैं? मेरे लिए, यह स्वीकृत उत्तर पर सुधार है :)
abelito

व्यक्तिगत वरीयताओं। मेरे लिए इस समाधान की तुलना में क्लीनर टर्नरी ऑपरेटर को समझना अधिक आसान है।
निको

1
आह, मैंने इस समस्या को देखा और सोच रहा था कि किसी और ने इस समाधान का उल्लेख क्यों नहीं किया। यदि आप ओपी के तर्क को बूलियन बीजगणित के रूप में लिखते हैं, तो आपको ए बी + ए सी + बी सी मिलता है, जिसमें पांच ऑपरेशन होते हैं। साहचर्य संपत्ति द्वारा, आप ए * (बी + सी) + बी सी लिख सकते हैं , जिसमें चार ऑपरेशन हैं।
विवियन नदी

यह जैक के उत्तर (जून 19) के समान ही है। (C && (A || B)) || (A && B)* चर * नाम बदल गए ...
user85421

4

सभी प्रमुख भाषाओं में एक शाब्दिक व्याख्या काम करेगी:

return (a ? 1:0) + (b ? 1:0) + (c ? 1:0) >= 2;

लेकिन मैं शायद लोगों के लिए पढ़ना आसान बनाऊंगा, और तीन से अधिक के लिए विस्तार योग्य - ऐसा कुछ जो कई प्रोग्रामर द्वारा भूल जाना प्रतीत होता है:

boolean testBooleans(Array bools)
{
     int minTrue = ceil(bools.length * .5);
     int trueCount = 0;

     for(int i = 0; i < bools.length; i++)
     {
          if(bools[i])
          {
               trueCount++;
          }
     }
     return trueCount >= minTrue;
}

4

@TofuBeer TofuBeer की उत्कृष्ट पोस्ट के अतिरिक्त, @pdox pdox के उत्तर पर विचार करें:

static boolean five(final boolean a, final boolean b, final boolean c)
{
    return a == b ? a : c;
}

"जावप -c" द्वारा दिए गए इसके असंतुष्ट संस्करण पर भी विचार करें:

static boolean five(boolean, boolean, boolean);
  Code:
    0:    iload_0
    1:    iload_1
    2:    if_icmpne    9
    5:    iload_0
    6:    goto    10
    9:    iload_2
   10:    ireturn

pdox का उत्तर पिछले उत्तरों में से किसी से भी कम बाइट कोड को संकलित करता है। इसका निष्पादन समय दूसरों की तुलना कैसे करता है?

one                5242 ms
two                6318 ms
three (moonshadow) 3806 ms
four               7192 ms
five  (pdox)       3650 ms

कम से कम मेरे कंप्यूटर पर, pdox का उत्तर @moonshadow moonshadow के उत्तर की तुलना में थोड़ा तेज है, जिससे pdox सबसे तेज (मेरे HP / Intel लैपटॉप पर) सबसे तेज है।


3

रूबी में:

[a, b, c].count { |x| x } >= 2

जिसे JavaVM पर JRuby में चलाया जा सकता है। ;-)


3

वह शायद बिटवाइज़ तुलना ऑपरेटरों की तरह कुछ भी नहीं देख रहा है (सामान्य रूप से जटिल नहीं है, लेकिन बूलियन्स के साथ, यह बिटवाइज़ ऑपरेटरों का उपयोग करने के लिए बेहद अजीब है) या ऐसा कुछ है जो बहुत गोलमटोल है जैसे इंट को बदलने और उन्हें समेटने के लिए।

इसे हल करने का सबसे सीधा और प्राकृतिक तरीका इस तरह की अभिव्यक्ति के साथ है:

a ? (b || c): (b && c)

यदि आप चाहें तो इसे किसी फ़ंक्शन में रखें, लेकिन यह बहुत जटिल नहीं है। समाधान तार्किक रूप से संक्षिप्त और कुशल है।


3

सी में:

return !!a + !!b + !!c >= 2;

दरअसल, यह उत्तर गलत है ... यह = 2 होना चाहिए, क्योंकि आपको कम से कम दो सच्चे बूलियन्स की आवश्यकता है, बिल्कुल दो नहीं।
पॉल वैगलैंड

@Paul वैगलैंड: पकड़ने के लिए धन्यवाद।
मैट जॉइनर

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