2010-05-08 10 views
5

मेरे पास एक फ़ंक्शन के नीचे है (previous question से जो अनुत्तरित नहीं हुआ) जो कि मानों की संख्या के साथ एक सरणी बनाता है। सरणी का योग $ अधिकतम के बराबर है।नए यादृच्छिक रूप से जेनरेट किए गए मानों के साथ सरणी में डुप्लिकेट मान बदलें

function randomDistinctPartition($n, $max) { 
    $partition= array(); 
    for ($i = 1; $i < $n; $i++) { 
    $maxSingleNumber = $max - $n; 
    $partition[] = $number = rand(1, $maxSingleNumber); 
    $max -= $number; 
    } 
    $partition[] = $max; 
    return $partition; 
} 

उदाहरण के लिए: यदि मैं $ n = 4 और $ max = 30 सेट करता हूं। तो मुझे निम्न प्राप्त करना चाहिए।

array(5, 7, 10, 8); 

हालांकि, यह फ़ंक्शन खाता डुप्लीकेट और 0s में नहीं लेता है। मैं क्या चाहता हूं - और पूरा करने की कोशिश कर रहा हूं - अद्वितीय संख्याओं के साथ एक सरणी उत्पन्न करना है जो मेरे पूर्व निर्धारित चर $ अधिकतम तक जोड़ता है। कोई डुप्लिकेट संख्या और नहीं 0 और/या नकारात्मक पूर्णांक

उत्तर

13

ठीक है, यह समस्या वास्तव में रैखिक अनुक्रमों के चारों ओर घूमती है।

f(n) = 1 + 2 + ... + n - 1 + n 

इस तरह के एक दृश्य की राशि के बराबर है:: 1 की एक न्यूनतम मूल्य के साथ अनुक्रम पर विचार

f(n) = n * (n + 1)/2 

तो एन = 4 के लिए, एक उदाहरण के रूप, योग 10 है इसका मतलब है कि यदि आप 4 अलग-अलग संख्याओं का चयन कर रहे हैं तो न्यूनतम शून्य कुल शून्य नहीं है और कोई नकारात्मक नहीं है 10. अब रिवर्स में जाएं: यदि आपके पास कुल 10 और 4 संख्याएं हैं तो केवल संयोजन (1,2, 3,4)।

तो सबसे पहले आपको यह जांचने की आवश्यकता है कि आपका कुल कम से कम इस निचले बाउंड के रूप में उच्च है या नहीं। यदि यह कम है तो कोई संयोजन नहीं है। यदि यह बराबर है, तो एक संयोजन ठीक है। यदि यह अधिक है तो यह अधिक जटिल हो जाता है।

अब कल्पना करें कि आपकी बाधाएं कुल संख्या 12 के साथ हैं। हमने पाया है कि f (4) = 10. लेकिन क्या होगा यदि पहला (निम्नतम) संख्या 2 है?

2 + 3 + 4 + 5 = 14 

तो पहला नंबर 1 से अधिक नहीं हो सकता है। आप अपना पहला नंबर जानते हैं। अब आप कुल संख्या 11 के साथ 3 संख्याओं का अनुक्रम उत्पन्न करते हैं (12 - 1 होने के नाते)।

1 + 2 + 3 = 6 
2 + 3 + 4 = 9 
3 + 4 + 5 = 12 

दूसरा नंबर 2 होना चाहिए क्योंकि यह एक नहीं हो सकता है। यह 3 नहीं हो सकता है क्योंकि 3 से शुरू होने वाली तीन संख्याओं की न्यूनतम संख्या 12 है और हमें 11.

अब हमें दो संख्याएं मिलती हैं जो 9 (12 - 1 - 2) तक 3 होती हैं सबसे कम संभव है।

3 + 4 = 7 
4 + 5 = 9 

तीसरा नंबर 3 या 4 हो सकता है। तीसरे नंबर के साथ अंतिम तय किया गया है। दो संभावित संयोजन हैं:

1, 2, 3, 6 
1, 2, 4, 5 

आप इसे एक सामान्य एल्गोरिदम में बदल सकते हैं।इस पुनरावर्ती कार्यान्वयन पर विचार करें:

$all = all_sequences(14, 4); 
echo "\nAll sequences:\n\n"; 
foreach ($all as $arr) { 
    echo implode(', ', $arr) . "\n"; 
} 

function all_sequences($total, $num, $start = 1) { 
    if ($num == 1) { 
    return array($total); 
    } 
    $max = lowest_maximum($start, $num); 
    $limit = (int)(($total - $max)/$num) + $start; 
    $ret = array(); 
    if ($num == 2) { 
    for ($i = $start; $i <= $limit; $i++) { 
     $ret[] = array($i, $total - $i); 
    } 
    } else { 
    for ($i = $start; $i <= $limit; $i++) { 
     $sub = all_sequences($total - $i, $num - 1, $i + 1); 
     foreach ($sub as $arr) { 
     array_unshift($arr, $i); 
     $ret[] = $arr; 
     } 
    } 
    } 
    return $ret; 
} 

function lowest_maximum($start, $num) { 
    return sum_linear($num) + ($start - 1) * $num; 
} 

function sum_linear($num) { 
    return ($num + 1) * $num/2; 
} 

आउटपुट:

इस के
All sequences: 

1, 2, 3, 8 
1, 2, 4, 7 
1, 2, 5, 6 
1, 3, 4, 6 
2, 3, 4, 5 

एक कार्यान्वयन सभी दृश्यों हो और आकस्मिक एक का चयन करने के लिए किया जाएगा। इसका लाभ सभी संभव संयोजनों को समान रूप से भारित करने का लाभ है, जो आप जो कर रहे हैं उसके लिए उपयोगी या आवश्यक हो सकता है या नहीं।

यह बड़े योग या बड़ी संख्या में तत्वों के साथ अनावश्यक हो जाएगा, इस मामले में उपर्युक्त एल्गोरिदम को $start से $limit से प्रत्येक मान के बजाय श्रेणी में एक यादृच्छिक तत्व वापस करने के लिए संशोधित किया जा सकता है।

+0

@Russell कोड नमूना देखें। – cletus

+0

धन्यवाद क्लेटस। यह एक शर्म की बात है कि मैं केवल एक बार आप को ऊपर उठा सकता हूं। –

+0

यदि मैं सही ढंग से पढ़ता हूं, तो यह डुप्लीकेट के बिना एक semirandomly वितरित श्रृंखला उत्पन्न करता है। मुझे लगता है कि अगर कई उत्पन्न अनुक्रमों के मूल्यों की साजिश करके इसका परीक्षण किया जाता है, तो उनके वितरण में डुबकी/गांठ दिखाई दे सकते हैं। मैंने एक ऐसा जवाब दिया है जो ऐसा नहीं करना चाहिए, लेकिन स्वीकार्य रूप से मूल्य बदल सकते हैं जब किसी को वास्तविक रूप से बदलने की आवश्यकता नहीं होती है। – strainer

2

मैं 'त्रिकोण के तहत क्षेत्र' ... वैसे भी प्रयोग करेंगे सूत्र cletus की तरह (!?) इम वास्तव में करने वाला है चीजों को और अधिक ध्यान दे शुरू करने के लिए ...

, मुझे लगता है कि यह समाधान है अब बहुत सुंदर है, यह सभी तत्वों के बीच वांछित न्यूनतम अंतर को लागू करता है, समान रूप से, मूल योग को बनाए रखने के लिए समान रूप से अंतराल (वितरण) को स्केल करता है और नौकरी को गैर-पुनरावर्ती (क्रमबद्ध करने के अलावा) करता है:

एक सरणी को देखते हुए() लंबाई की यादृच्छिक संख्या n

एक सॉर्ट इंडेक्स उत्पन्न करें()

और सॉर्ट किए गए अंतराल पर एक (एस (0)) - ए (एस (1)), ए (एस (1)) - ए (एस (2)) आदि

  1. वृद्धि द्वारा प्रत्येक अंतराल वांछित न्यूनतम जुदाई आकार जैसे 1

  2. कमी (इस जरूरी उनके 'अनियमितता' warps) एक कारक को श्रृंखला का योग बहाल करने के लिए गणना की द्वारा प्रत्येक अंतराल क्या यह रिक्ति के बिना है। लेन * (LEN +1)/2:

हम एक श्रृंखला से प्रत्येक के लिए 1 जोड़ देते हैं तो हम 1 * लेन

1 श्रृंखला के अंतराल में से प्रत्येक के लिए जोड़ा द्वारा श्रृंखला योग में वृद्धि द्वारा राशि बढ़ जाती है // (? पास्कल त्रिकोण)

ड्राफ्ट कोड:

$series($length);  //the input sequence 
$seriesum=sum($series); //its sum 
$minsepa=1;    //minimum separation 

$sorti=sort_index_of($series) //sorted index - php haz function? 

$sepsum=$minsepa*($length*($length+1))/2; 
//sum of extra separation 

$unsepfactor100=($seriesum*100)/($seriesum+sepsum); 
//scale factor for original separation to maintain size 
//(*100~ for integer arithmetic) 

$px=series($sorti(0)); //for loop needs the value of prev serie 

for($x=1 ; $x < length; $x++) 
{ $tx=$series($sorti($x));    //val of serie to 
    $series($sorti($x))= ($minsepa*$x) //adjust relative to prev 
        + $px 
        + (($tx-$px)*$unsepfactor100)/100; 

    $px=$tx;        //store for next iteration 
    } 
    सभी अंतराल
  • एक सह द्वारा कम कर रहे हैं nstant (गैर यादृच्छिक warping कारक)
  • जुदाई अन्य एक
  • implementantions से मूल्यों के लिए सेट किया जा सकता carefuly बदलाव (मैं आमतौर पर परीक्षण & 'कैलिब्रेट')
    समायोजित करने के लिए राउंडिंग त्रुटियों की जरूरत है। संभवतः ~ 15 द्वारा सबकुछ स्केल करें और फिर बाद में नीचे जाएं। सही होने पर अंतराल जीवित रहना चाहिए।

सॉर्ट इंडेक्स जेनरेट होने के बाद, इंडेक्स के क्रम को क्रमबद्ध श्रृंखला के अनुक्रम में रनों से बचने के लिए मूल्यों को डुप्लिकेट करने के क्रम को घुमाएं। (या बस अंतिम आउटपुट शफ़ल अगर आदेश कभी नहीं मायने रखता)

ड्यूप्स की घसीटना अनुक्रमित:

for($x=1; $x<$len; $x++)     
{ if ($series($srt($x))==$series($srt($x-1))) 
    { if(random(0,1)) 
    { $sw= $srt($x); 
     $srt($x)= $srt($x-1); 
     $srt($x-1)= $sw; 
    } } } 

न्यूनतम अशांति एक तरह का सिर्फ अलग ड्यूप्स द्वारा एक 'यादृच्छिक अनुक्रम' के लिए किया जा सकता है कम से कम उन्हें छोड़कर, न्यूनतम 'यादृच्छिक' राशि जो प्रश्न द्वारा मांगी गई थी, न्यूनतम आवश्यक है।

यहां कोड प्रत्येक तत्व को अलग-अलग अलगाव से अलग करता है, भले ही डुप्लिकेट हो या नहीं, जो कि थोड़ी सी भी होनी चाहिए, लेकिन शायद अतिदेय हो। कोड को केवल उनके लिए श्रृंखला (sorti (n0: n1..len)) को देखकर डुप्लिक को अलग करने के लिए संशोधित किया जा सकता है और प्रत्येक डुप्लिकेट के लिए सेप्सम की गणना + = minsep * (len-n) के रूप में की जा सकती है। फिर एडजस्टमेंट लूप को समायोजन लागू करने से पहले डुप्ली के लिए फिर से परीक्षण करना होगा।

+0

क्या असामान्य कोड शैली है। – Gumbo

+0

जब तक मैं स्कोरिंग अंक शुरू नहीं करता, बीमार को यह संकेत मिलता है कि इसे सामान्यीकरण की आवश्यकता है:] – strainer

+0

मैंने php आंखों को खुश करने के लिए कई $ जोड़े। – strainer