आर्ट ऑफ़ कंप्यूटर प्रोग्रामिंग वॉल्यूम 4: फ़ासिकल 3 में इनमें से एक टन है जो आपके विशेष स्थिति को मेरे वर्णन से बेहतर हो सकता है।
ग्रे कोड्स
एक मुद्दा जो आपके सामने आएगा वह निश्चित रूप से स्मृति और बहुत जल्दी है, आपको अपने सेट में 20 तत्वों द्वारा समस्याएं होंगी - 20 सी 3 = 1140. और यदि आप सेट पर पुनरावृति करना चाहते हैं तो संशोधित ग्रे का उपयोग करना सबसे अच्छा है कोड एल्गोरिथ्म तो आप स्मृति में उन सभी को पकड़ नहीं रहे हैं। ये पिछले से अगला संयोजन उत्पन्न करते हैं और दोहराव से बचते हैं। विभिन्न उपयोगों के लिए इनमें से कई हैं। क्या हम क्रमिक संयोजनों के बीच अंतर को अधिकतम करना चाहते हैं? छोटा करना? et cetera
ग्रे कोड्स का वर्णन करने वाले कुछ मूल कागजात:
- कुछ हैमिल्टन पथ और एक न्यूनतम परिवर्तन एल्गोरिथम
- आसन्न इंटरचेंज संयोजन संयोजन एल्गोरिथ्म
इस विषय को कवर करने वाले कुछ अन्य कागजात हैं:
- Eades के एक कुशल कार्यान्वयन, Hickey, निकटवर्ती इंटरचेंज संयोजन पीढ़ी एल्गोरिदम पढ़ें (पीडीएफ, पास्कल में कोड के साथ)
- संयोजन जनक
- कॉम्बिनेटर ग्रे कोड्स (पोस्टस्क्रिप्ट) का सर्वेक्षण
- ग्रे कोड्स के लिए एक एल्गोरिथम
चेस ट्वीडल (एल्गोरिथम)
फिलिप जे चेज़, ` एल्गोरिथम 382: एम आउट ऑफ एन ऑब्जेक्ट्स ’ (1970)
सी में एल्गोरिथ्म ...
लेक्सोग्राफिक ऑर्डर में संयोजन का सूचकांक (बकस एल्गोरिथ्म 515)
आप इसके सूचकांक द्वारा एक संयोजन का संदर्भ भी दे सकते हैं (लेक्सिकोग्राफ़िक क्रम में)। यह महसूस करते हुए कि सूचकांक के आधार पर सूचकांक में दाईं ओर से बाईं ओर कुछ बदलाव होना चाहिए, हम कुछ का निर्माण कर सकते हैं जो एक संयोजन को पुनर्प्राप्त करना चाहिए।
तो, हमारे पास एक सेट {1,2,3,4,5,6} है ... और हम तीन तत्व चाहते हैं। मान लें कि {1,2,3} हम कह सकते हैं कि तत्वों के बीच अंतर एक और क्रम में और न्यूनतम है। {1,2,4} में एक परिवर्तन है और लेक्सोग्राफिक रूप से नंबर 2 है। इसलिए लेक्सोग्राफिक ऑर्डरिंग में एक परिवर्तन के लिए अंतिम स्थान में 'परिवर्तन' की संख्या है। एक परिवर्तन {1,3,4} के साथ दूसरे स्थान पर एक परिवर्तन है, लेकिन अधिक परिवर्तन के लिए जिम्मेदार है क्योंकि यह दूसरे स्थान पर है (मूल सेट में तत्वों की संख्या के अनुपात में)।
जिस विधि का मैंने वर्णन किया है वह एक डिकंस्ट्रक्शन है, जैसा कि ऐसा लगता है, सेट से इंडेक्स तक, हमें रिवर्स करने की आवश्यकता है - जो बहुत पेचीदा है। इस तरह से बकल्स समस्या का हल करता है। मैंने कुछ सी लिखने के लिए उन्हें मामूली बदलावों के साथ गणना की - मैंने सेट का प्रतिनिधित्व करने के लिए एक संख्या सीमा के बजाय सेट के सूचकांक का उपयोग किया, इसलिए हम हमेशा 0 ... n से काम कर रहे हैं। ध्यान दें:
- चूंकि संयोजन अनियंत्रित होते हैं, {1,3,2} = {1,2,3} - हम उन्हें लेक्सोग्राफ़िक होने का आदेश देते हैं।
- इस विधि में पहले अंतर के लिए सेट शुरू करने के लिए एक निहित 0 है।
लेक्सोग्राफिक ऑर्डर में संयोजन का सूचकांक (मैकक्रेफ)
एक और तरीका है : इसकी अवधारणा को समझ और प्रोग्राम करना आसान है, लेकिन यह बकल के अनुकूलन के बिना है। सौभाग्य से, यह भी नकली संयोजनों का उत्पादन नहीं करता है:
वह सेट जहां अधिकतम होता है , जहां ।
एक उदाहरण के लिए 27 = C(6,4) + C(5,3) + C(2,2) + C(1,1)
:। तो, चार चीजों का २ le वाँ कोशिक संयोजन है: {१,२,५,६}, वे जो भी सेट आप देखना चाहते हैं, उनके सूचकांक हैं। नीचे उदाहरण (OCaml), choose
फ़ंक्शन की आवश्यकता है, पाठक के लिए छोड़ दिया गया है:
(* this will find the [x] combination of a [set] list when taking [k] elements *)
let combination_maccaffery set k x =
(* maximize function -- maximize a that is aCb *)
(* return largest c where c < i and choose(c,i) <= z *)
let rec maximize a b x =
if (choose a b ) <= x then a else maximize (a-1) b x
in
let rec iterate n x i = match i with
| 0 -> []
| i ->
let max = maximize n i x in
max :: iterate n (x - (choose max i)) (i-1)
in
if x < 0 then failwith "errors" else
let idxs = iterate (List.length set) x k in
List.map (List.nth set) (List.sort (-) idxs)
एक छोटा और सरल संयोजन पुनरावृत्ति
निम्नलिखित दो एल्गोरिदम दिमागी उद्देश्यों के लिए प्रदान किए जाते हैं। वे एक पुनरावृत्ति और (अधिक सामान्य) फ़ोल्डर समग्र संयोजनों को लागू करते हैं। वे ओ ( एन सी के ) की जटिलता वाले होने के रूप में तेजी से संभव हैं । स्मृति खपत द्वारा बाध्य है k
।
हम इट्रेटर के साथ शुरू करेंगे, जो प्रत्येक संयोजन के लिए एक उपयोगकर्ता प्रदान किए गए फ़ंक्शन को कॉल करेगा
let iter_combs n k f =
let rec iter v s j =
if j = k then f v
else for i = s to n - 1 do iter (i::v) (i+1) (j+1) done in
iter [] 0 0
एक अधिक सामान्य संस्करण प्रारंभिक अवस्था से शुरू होने वाले राज्य चर के साथ उपयोगकर्ता प्रदान किए गए फ़ंक्शन को कॉल करेगा। चूंकि हमें अलग-अलग राज्यों के बीच राज्य को पारित करने की आवश्यकता है, हम फॉर-लूप का उपयोग नहीं करेंगे, लेकिन इसके बजाय, पुनरावर्तन का उपयोग करें,
let fold_combs n k f x =
let rec loop i s c x =
if i < n then
loop (i+1) s c @@
let c = i::c and s = s + 1 and i = i + 1 in
if s < k then loop i s c x else f c x
else x in
loop 0 0 [] x