Champaign फाउंटेन पहेली


30

निम्नलिखित क्रम में पानी के खाली गिलास की व्यवस्था की जाती है:

यहां छवि विवरण दर्ज करें

जब आप 1 ग्लास में तरल डालते हैं यदि यह भरा हुआ है, तो अतिरिक्त तरल को समान मात्रा में 2 और 3 गिलास में प्रवाहित किया जाएगा। जब ग्लास 2 भरा होता है, तो अतिरिक्त तरल को 4 और 5 में प्रवाहित किया जाएगा।

एक लीटर तरल और प्रत्येक ग्लास की अधिकतम क्षमता को देखते हुए 1 लीटर है, किसी भी ग्लास में मौजूद तरल की मात्रा दें यदि आप उस फ़ंक्शन को बाहर निकालकर ग्लास में एन लीटर तरल को खाली करते हैं getWaterInBucket(int N, int X)जहां एक्स ग्लास नंबर है। इसलिए उदाहरण के लिए अगर मुझे शुरुआत में 4 लीटर चाहिए और मैं ग्लास 3 में पानी ढूंढना चाहता हूं, तो यह कार्य हैgetWaterInBucket(4, 3)

मैं इस प्रोग्राम को कैसे हल करूं? मैंने पास्कल के त्रिकोण का उपयोग करके एक गणित समाधान खोजने की कोशिश की। यह काम नहीं किया। मैंने इसे एक पेड़ माना है इसलिए मैं इस तरह एक पैरामीटर जोड़ सकता हूं getWaterInBucket(BTree root, int N, int X)और फिर प्रत्येक स्तर के लिए कुछ पुनरावर्ती समाधान का प्रयास कर सकता हूं , लेकिन इस समस्या में मापदंडों की अनुमति नहीं है। क्या कुछ स्पष्ट है, कुछ चाल है?


18
मैं ऐसी कंपनी में काम नहीं करना चाहता जहाँ प्रबंधन की समस्याएँ शैंपेन फव्वारे के बारे में हों ...
mouviciel

क्या आप कभी भी ग्लास 1 के अलावा किसी अन्य ग्लास में डाल सकते हैं? यदि नहीं, तो प्रत्येक टियर में प्रत्येक ग्लास में समान मात्रा में पानी होगा। इस प्रकार, जब भी आप 1, 3, 6, 10 ... लीटर डालेंगे, तो आपके पास फुल टियर होगा। यदि आप 7 लीटर डालते हैं, तो चौथी पंक्ति में 4 गिलास होते हैं, इसलिए प्रत्येक 1/4 भरा होगा। इसके ऊपर के सभी टियर फुल होंगे।
ग्लेनपेटर्सन

5
@GlenPeterson कैसे मैं इसे पढ़ रहा हूँ मुझे नहीं लगता कि वे समान रूप से भरेंगे। हां, 2 और 3 समान रूप से भरेंगे क्योंकि उनके पास केवल एक चीज है जो उनमें डाली गई है, लेकिन एक बार जब वे पूर्ण 2 हो जाते हैं तो 4/5 में समान रूप से डालते हैं और 3 समान रूप से 5/6 में डालते हैं, इस प्रकार 5 4/6 के चूहे से दोगुना भर जाता है। । केंद्र कप हमेशा बाहरी कप की तुलना में तेजी से भर रहे हैं। जब तक 4/6 पूर्ण 8/9 होते हैं तब तक 25% पूर्ण होते हैं और 7/10 अभी भी खाली हैं।
ब्रैड

1
इसके अलावा, यह मुझे पास्कल के त्रिभुज की याद दिलाता है ..
ब्रैड

@ माउविचियल हाहा ग्लेनपेटर्सन - पहले डाला जाने वाला ग्लास हमेशा ग्लास 1 होता है। साक्षात्कारकर्ता ने इस जानकारी का उपयोग करने के लिए भी कहा। वह इस समस्या के सही उत्तर के बारे में जितना मुझे लगता था उससे कहीं अधिक उलझन में था।
Slartibartfast

जवाबों:


35

आपको केवल कुछ डालने की ज़रूरत है, जैसे कुछ डालना

void pour(double glasses[10], int glass, double quantity)
{
    glasses[glass] += quantity;
    if(glasses[glass] > 1.0)
    {
         double extra = glasses[glass] - 1.0;
         pour( glasses, left_glass(glass), extra / 2 );
         pour( glasses, right_glass(glass), extra / 2 );
         glasses[glass] = 1.0;
    }
}

double getWaterInGlass(int N, int X)
{
    double glasses[10] = {0,0,0,0,0,0};
    pour(glasses, 0, X);
    return glasses[N];
}

जैसा कि यह खड़ा है, यह एक पेड़ नहीं है। क्योंकि अलग-अलग ग्लास एक ही गिलास में डालते हैं, जो इसे एक पेड़ होने से रोकता है।


16
+1 महान अवलोकन के लिए कि यह एक पेड़ नहीं है।
मिहाई दानिला

2
अच्छा उत्तर। एक साक्षात्कार में, आपको यह कहना चाहिए कि इससे स्केलेबिलिटी की समस्या हो सकती है क्योंकि यह सभी चश्मे की सामग्री की गणना करता है। इसके अलावा, आपको उस मामले को संभालने की आवश्यकता है जहां पानी चश्मे की निचली पंक्ति से बाहर निकलता है। और आप चाहते हैं return glasses[N-1], क्योंकि ग्लास नंबर 0. के बजाय 1 पर शुरू होते हैं
टॉम पैनिंग

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

यह वास्तव में एक सुंदर समाधान है। धन्यवाद। यदि आप विचार प्रक्रिया में प्रत्येक चरण का संकेत देने के लिए कोड की पंक्तियों में टिप्पणियां जोड़ने के लिए इसे संपादित कर सकते हैं, तो मैं आभारी रहूंगा। इसके अलावा चश्मे की संख्या 10. तक सीमित नहीं है। यह कुछ भी हो सकता है
Slartibartfast

1
आप बाएं और दाएं चश्मा कैसे ढूंढते हैं?
kiewic

7

यहाँ मैं एक साक्षात्कार की स्थिति में इस प्रश्न का उत्तर कैसे दूंगा (मैंने पहले इस प्रश्न को नहीं देखा है, और जब तक मेरे पास कोई समाधान नहीं था तब तक मैं अन्य उत्तरों को नहीं देखता):

सबसे पहले, मैंने इसे जानने का प्रयास किया (जिसे आपने "गणित समाधान" कहा था) और जब मुझे ग्लास 8 मिला तो मैंने महसूस किया कि यह कठिन लग रहा था क्योंकि ऐसा लगता है कि ग्लास 5 ग्लास से पहले ओवरफ्लो करना शुरू कर देता है 4. उस समय मैं पुनरावृत्ति मार्ग पर जाने का निर्णय लिया (बस एक FYI करें, बहुत सारे प्रोग्रामिंग साक्षात्कार प्रश्नों को हल करने के लिए पुनरावृत्ति या प्रेरण की आवश्यकता होती है)।

पुनरावर्ती सोचकर, समस्या बहुत आसान हो जाती है: ग्लास 8 में कितना पानी है? उस राशि का आधा जो चश्मे 4 और 5 से बाहर फैला है (जब तक कि यह भरा हुआ नहीं है)। बेशक, इसका मतलब है कि हमें इस बात का जवाब देना होगा कि चश्मा 4 और 5 से बाहर कितना फैला है, लेकिन यह पता चला है कि यह बहुत कठिन भी नहीं है। ग्लास 5 से बाहर कितना फैला है? हालाँकि, ग्लास 2 और 3 में से आधे से अधिक, शून्य से लीटर है जो ग्लास 5 में रहता है।

इसे पूरी तरह (और गन्दा तरीके से हल करना) देता है:

#include <iostream>
#include <cmath>
using namespace std;

double howMuchSpilledOutOf(int liters, int bucketId) {
    double spilledInto = 0.0;
    switch (bucketId) {
        case 1:
            spilledInto = liters; break;
        case 2:
            spilledInto = 0.5 * howMuchSpilledOutOf(liters, 1); break;
        case 3:
            spilledInto = 0.5 * howMuchSpilledOutOf(liters, 1); break;
        case 4:
            spilledInto = 0.5 * howMuchSpilledOutOf(liters, 2); break;
        case 5:
            spilledInto = 0.5 * howMuchSpilledOutOf(liters, 2) + 0.5 * howMuchSpilledOutOf(liters, 3); break;
        case 6:
            spilledInto = 0.5 * howMuchSpilledOutOf(liters, 3); break;
        default:
            cerr << "Invalid spill bucket ID " << bucketId << endl;
    }
    return max(0.0, spilledInto - 1.0);
}

double getWaterInBucket(int liters, int bucketId) {
    double contents = 0.0;
    switch (bucketId) {
        case 1:
            contents = liters; break;
        case 2:
            contents = 0.5 * howMuchSpilledOutOf(liters, 1); break;
        case 3:
            contents = 0.5 * howMuchSpilledOutOf(liters, 1); break;
        case 4:
            contents = 0.5 * howMuchSpilledOutOf(liters, 2); break;
        case 5:
            contents = 0.5 * howMuchSpilledOutOf(liters, 2) + 0.5 * howMuchSpilledOutOf(liters, 3); break;
        case 6:
            contents = 0.5 * howMuchSpilledOutOf(liters, 3); break;
        case 7:
            contents = 0.5 * howMuchSpilledOutOf(liters, 4); break;
        case 8:
            contents = 0.5 * howMuchSpilledOutOf(liters, 4) + 0.5 * howMuchSpilledOutOf(liters, 5); break;
        case 9:
            contents = 0.5 * howMuchSpilledOutOf(liters, 5) + 0.5 * howMuchSpilledOutOf(liters, 6); break;
        case 10:
            contents = 0.5 * howMuchSpilledOutOf(liters, 6); break;
        default:
            cerr << "Invalid contents bucket ID" << bucketId << endl;
    }
    return min(1.0, contents);
}

int main(int argc, char** argv)
{
    if (argc == 3) {
        int liters = atoi(argv[1]);
        int bucket = atoi(argv[2]);
        cout << getWaterInBucket(liters, bucket) << endl;
    }
    return 0;
}

इस बिंदु पर (या के रूप में मैं यह पता लिख रहा था), मैं साक्षात्कारकर्ता बताते हैं कि इस उत्पादन में आदर्श समाधान नहीं है जाएगा: वहाँ के बीच डुप्लिकेट कोड है howMuchSpilledOutOf()और getWaterInBucket(); एक केंद्रीय स्थान होना चाहिए जो अपने "फीडर" के लिए बाल्टी को मैप करता है। लेकिन एक साक्षात्कार में, जहां कार्यान्वयन की गति और सटीकता अधिक महत्वपूर्ण है कि निष्पादन और रखरखाव की गति (जब तक कि अन्यथा संकेत नहीं दिया गया है), यह समाधान बेहतर है। फिर मैं कोड को रिफलेक्टर करने की पेशकश करूंगा जो मैं उत्पादन-गुणवत्ता पर विचार करता हूं, और साक्षात्कारकर्ता को तय करने देता हूं।

अंतिम नोट: मुझे यकीन है कि मेरे कोड में कहीं एक टाइपो है; मैं उस साक्षात्कारकर्ता का भी उल्लेख करूंगा और यह कहूंगा कि मैं इसे या तो आत्मसात करने के बाद या इकाई-परीक्षण के बाद इस पर अधिक विश्वास महसूस करूंगा।


6
यह समाधान उदाहरण के लिए हार्ड-कोडेड है। चश्मा जोड़ने का अर्थ है स्विच में "केस" जोड़ना ... मुझे नहीं लगता कि यह एक अच्छा समाधान है।
लुइगी मस्सा गैलेरानो

2
@LuigiMassaGallerano - यह इस मामले में ठीक है क्योंकि यह एक साक्षात्कार प्रश्न है; यह एक आदर्श समाधान नहीं माना जाता है। साक्षात्कारकर्ता उम्मीदवार की विचार प्रक्रिया की बेहतर समझ प्राप्त करने की कोशिश कर रहा है। और टॉम पहले से ही बताते हैं कि this isn't the ideal solution

1
यह ईमानदारी से नहीं है। मैं आपको विश्वास दिलाता हूं कि इस परिदृश्य को कठोर कोडित करने का इरादा नहीं था। अगर मैंने एक साक्षात्कार प्रश्न पूछा और एक परीक्षण मामले का परिदृश्य तैयार किया, जो साक्षात्कारकर्ता ने एक कठिन कोडित समाधान प्रस्तुत किया, तो वह बेहतर रूप से एक सामान्य समाधान प्रस्तुत करने के लिए तैयार हो सकता है या वह शायद साक्षात्कार को पास नहीं करने वाला है।
रिग

5

एक पेड़ की समस्या के रूप में इस बारे में सोचना एक रेड-हेरिंग है, यह वास्तव में एक निर्देशित ग्राफ है। लेकिन यह सब भूल जाओ।

ऊपर के नीचे कहीं भी एक ग्लास के बारे में सोचो। इसके ऊपर एक या दो ग्लास होंगे जो इसमें ओवरफ्लो कर सकते हैं। समन्वय प्रणाली के उचित विकल्प के साथ (चिंता न करें, अंत देखें) हम किसी भी दिए गए ग्लास के लिए "माता-पिता" चश्मा प्राप्त करने के लिए एक फ़ंक्शन लिख सकते हैं।

अब हम एक ग्लास में डाले गए तरल की मात्रा प्राप्त करने के लिए एक एल्गोरिथ्म के बारे में सोच सकते हैं, चाहे उस ग्लास से ओवरफ्लो हो। हालांकि इसका जवाब है कि प्रत्येक माता-पिता ग्लास में संग्रहीत राशि को प्रत्येक माता-पिता माइनस में डालते हैं, 2. सभी योगों के लिए। यह एक राशि के शरीर के अजगर टुकड़े के रूप में लिख रहा है_पूर्वी_इंटो () फ़ंक्शन:

# p is coords of the current glass
amount_in = 0
for pp in parents(p):
    amount_in += max((amount_poured_into(total, pp) - 1.0)/2, 0)

अधिकतम () यह सुनिश्चित करने के लिए है कि हमें अतिप्रवाह की नकारात्मक राशि न मिले।

हम लगभग समाप्त हो चुके हैं! हम पृष्ठ के नीचे 'y' के साथ एक समन्वय प्रणाली चुनते हैं, पहली पंक्ति का चश्मा 0 है, दूसरी पंक्ति 1 है, आदि 'x' निर्देशांक में शीर्ष पंक्ति के ग्लास के नीचे एक शून्य है और दूसरी पंक्ति में -1 का x निर्देशांक है। +1, तीसरी पंक्ति -2, 0, +2, और इसी तरह। महत्वपूर्ण बिंदु यह है कि लेवल y में लेफ्ट या राइट-मोस्ट ग्लास में abs (x) = y होगा।

अजगर (2.x) में सभी लपेटकर, हमारे पास है:

def parents(p):
    """Get parents of glass at p"""

    (x, y) = p
    py = y - 1          # parent y
    ppx = x + 1         # right parent x
    pmx = x - 1         # left parent x

    if abs(ppx) > py:
        return ((pmx,py),)
    if abs(pmx) > py:
        return ((ppx,py),)
    return ((pmx,py), (ppx,py))

def amount_poured_into(total, p):
    """Amount of fluid poured into glass 'p'"""

    (x, y) = p
    if y == 0:    # ie, is this the top glass?
        return total

    amount_in = 0
    for pp in parents(p):
        amount_in += max((amount_poured_into(total, pp) - 1.0)/2, 0)

    return amount_in

def amount_in(total, p):
    """Amount of fluid left in glass p"""

    return min(amount_poured_into(total, p), 1)

इसलिए राशि को वास्तव में पी में एक गिलास में प्राप्त करने के लिए, राशि_ का उपयोग करें (कुल, पी)।

यह ओपी से स्पष्ट नहीं है, लेकिन के बारे में "आप नहीं कर सकते पैरामीटर जोड़" बिट मूल प्रश्न कांच के मामले में जवाब हो गया है मतलब हो सकता है नंबर दिखाया गया है। यह शो ग्लास नंबरों से ऊपर इस्तेमाल किए गए आंतरिक समन्वय प्रणाली में एक मैपिंग फ़ंक्शन लिखकर हल किया जाता है। यह फिडली है, लेकिन या तो एक पुनरावृत्त या गणितीय समाधान का उपयोग किया जा सकता है। पुनरावृत्त समारोह को समझने में आसान:

def p_from_n(n):
    """Get internal coords from glass 'number'"""

    for (y, width) in enumerate(xrange(1, n+1)):
        if n > width:
            n -= width
        else:
            x = -y + 2*(n-1)
            return (x, y)

अब बस एक ग्लास नंबर को स्वीकार करने के लिए उपरोक्त राशि_ () फ़ंक्शन को फिर से लिखें:

def amount_in(total, n):
    """Amount of fluid left in glass number n"""

    p = p_from_n(n)
    return min(amount_poured_into(total, p), 1)

2

दिलचस्प।

यह सिमुलेशन दृष्टिकोण लेता है।

private void test() {
  double litres = 6;
  for ( int i = 1; i < 19; i++ ) {
    System.out.println("Water in glass "+i+" = "+getWater(litres, i));
  }
}

private double getWater(double litres, int whichGlass) {
  // Don't need more glasses than that.
  /*
   * NB: My glasses are numbered from 0.
   */
  double[] glasses = new double[whichGlass];
  // Pour the water in.
  pour(litres, glasses, 0);
  // Pull out the glass amount.
  return glasses[whichGlass-1];
}

// Simple non-math calculator for which glass to overflow into.
// Each glass overflows into this one and the one after.
// Only covers up to 10 glasses (0 - 9).
int[] overflowsInto = 
{1, 
 3, 4, 
 6, 7, 8, 
 10, 11, 12, 13, 
 15, 16, 17, 18, 19};

private void pour(double litres, double[] glasses, int which) {
  // Don't care about later glasses.
  if ( which < glasses.length ) {
    // Pour up to 1 litre in this glass.
    glasses[which] += litres;
    // How much overflow.
    double overflow = glasses[which] - 1;
    if ( overflow > 0 ) {
      // Remove the overflow.
      glasses[which] -= overflow;
      // Split between two.
      pour(overflow / 2, glasses, overflowsInto[which]);
      pour(overflow / 2, glasses, overflowsInto[which]+1);
    }
  }
}

जो प्रिंट (6 लीटर के लिए):

Water in glass 1 = 1.0
Water in glass 2 = 1.0
Water in glass 3 = 1.0
Water in glass 4 = 0.75
Water in glass 5 = 1.0
Water in glass 6 = 0.75
Water in glass 7 = 0.0
Water in glass 8 = 0.25
Water in glass 9 = 0.25
Water in glass 10 = 0.0
...

जो सही के बारे में लगता है।


-1

यह द्विपद कार्य है। स्तर N के चश्मे के बीच के पानी के अनुपात को स्तर में प्रत्येक ग्लास के लिए nCr का उपयोग करके खोजा जा सकता है। इसके अलावा, स्तर एन से पहले चश्मे की कुल संख्या 1 से (एन - 1) का योग है, एक ऐसा सूत्र जिसके लिए आपको आसानी से उपलब्ध होने में सक्षम होना चाहिए। इस प्रकार, एक्स को देखते हुए, आप इसे स्तर निर्धारित करने में सक्षम होना चाहिए, और उस स्तर के लिए चश्मे के अनुपात की जांच करने के लिए nCr का उपयोग करें, और इस तरह निर्धारित करें कि एक्स में कितना पानी है, अगर वहाँ वैसे भी एक्स के नीचे जाने के लिए पर्याप्त लीटर हैं।

दूसरे, BTREE का उपयोग कर के अपने विचार है, ठीक है, यह सिर्फ इतना है कि BTREE एक आंतरिक चर, है एक बाहरी पैरामीटर।

IOW, यदि आपने इस गणित को अपनी शिक्षा में कवर किया है (यहाँ ब्रिटेन में इसे विश्वविद्यालय से पहले पढ़ाया गया है) तो आपको इसे बहुत अधिक समस्या के बिना हल करने में सक्षम होना चाहिए।


1
मुझे नहीं लगता कि यह द्विपदीय कार्य है। यह 1,2,1 के अनुपात में तीसरे स्तर तक पहुंच जाता है क्योंकि द्विपद कार्य का सुझाव देगा, लेकिन मध्य कांच पहले भर जाता है और उसके बाद पैटर्न टूट जाता है।
विंस्टन इर्वर्ट

समय सिमुलेशन का हिस्सा नहीं है, और यह अंतिम परिणामों को प्रभावित नहीं करेगा।
डेडएमजी

4
चूंकि इसका मॉडलिंग लिक्विड फिल करना और चश्मे से बहना है, इसलिए मुझे उस समय को बनाए रखना होगा, जो अनुकरण का एक हिस्सा है। 5 लीटर में, 4 और 6 आधा भरा हुआ होगा, और 5 सभी भरा हुआ होगा। जब छठा लीटर जोड़ा जाता है, तो यह 8 और 9 में डालना शुरू कर देगा, लेकिन 7 और 10 को कोई पानी नहीं मिलेगा क्योंकि 4 और 6 ने अभी तक क्षमता नहीं मारा है। इस प्रकार, द्विपद फ़ंक्शन सही मानों की भविष्यवाणी नहीं करेगा।
विंस्टन एवर्ट

3
-1, यह गलत है। स्तर समान रूप से नहीं भरे जाएंगे।
dan_waterworth

आप सही हैं, मैंने इस पर विचार नहीं किया। लेकिन जब मैंने कुछ समय के लिए इसके बारे में सोचा, तो मुझे एहसास हुआ कि आप सही थे। यह सुनिश्चित करने के लिए नहीं कि इसे ध्यान में रखने के सूत्र को कैसे समायोजित किया जाए।
डेडएमजेड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.