किसी लीडरशिप समिट या बड़े पैमाने के नेटवर्किंग इवेंट का आयोजन अपने साथ एक अनोखी व्यवस्थागत चुनौती लेकर आता है: आप प्रतिभागियों के बीच आपसी संवाद (interactions) को अधिकतम कैसे करें?
यदि आपके पास टेबल चर्चाओं के कई राउंड हैं, तो आप यह सुनिश्चित करना चाहेंगे कि लोग लगातार नए चेहरों से मिल रहे हों। आदर्श रूप से, किसी भी व्यक्ति को उसी टेबल पर किसी ऐसे व्यक्ति के साथ नहीं बैठना चाहिए जिससे वह पिछले किसी राउंड में पहले ही मिल चुका हो।
यह चुनौती कॉम्बिनेटरिक्स (combinatorics) की एक क्लासिक पहेली है (जो Social Golfer Problem से काफी मिलती-जुलती है)। इस पोस्ट में, हम Go में लिखे गए एक बैकट्रैकिंग (backtracking) समाधान का पता लगाएंगे जो बिना किसी दोहराव वाली जोड़ी के, अधिकतम राउंड के लिए, प्रत्येक में लोगों के साथ टेबल असाइन कर सकता है।
कोड में उतरने से पहले, आइए राउंड की वह अधिकतम संख्या निर्धारित करें जिसे हम जोड़ों के दोहराव के गणितीय रूप से अपरिहार्य होने से पहले शेड्यूल कर सकते हैं।
राउंड की अधिकतम संख्या है।
प्रमाण (The Proof): कल्पना कीजिए कि हमारे पास टेबल हैं, और प्रत्येक टेबल पर लोग बैठते हैं। इससे हमें कुल (या ) प्रतिभागी मिलते हैं।
अब, एक एकल प्रतिभागी, व्यक्ति A (Person A) के दृष्टिकोण से इस इवेंट को देखें:
राउंड के बाद, हर कोई बाकी सभी के साथ पूरी तरह से नेटवर्किंग कर चुका होगा।
इसे कुशलतापूर्वक हल करने के लिए, हम बैकट्रैकिंग एल्गोरिदम का उपयोग कर सकते हैं। हालांकि, सर्च स्पेस को काफी हद तक कम करने और निष्पादन (execution) की गति बढ़ाने के लिए, हम एक स्मार्ट ट्रिक का उपयोग करके पहले दो राउंड को हार्डकोड कर सकते हैं:
हमारे बैकट्रैकिंग की प्रगति को ट्रैक करने के लिए, हम एक State स्ट्रक्ट (struct) का उपयोग करते हैं जो वर्तमान टेबल, राउंड और यह ट्रैक करने के लिए मैप्स रखता है कि किसने किसके साथ बातचीत की है।
यहाँ मुख्य लॉजिक को तीन भागों में बांटा गया है: सर्च लूप, टकराव सत्यापन (conflict validation), और स्टेट मैनेजमेंट।
solveImpl फ़ंक्शन अगली उपलब्ध सीट पर किसी व्यक्ति को असाइन करने के लिए रिकर्सिव (recursive) रूप से प्रयास करता है। यदि किसी पथ के परिणामस्वरूप टकराव होता है, तो यह पीछे हट जाता है (unset) और अगले व्यक्ति को आज़माता है।
func solveImpl(state *State) bool {
if state.solved {
return true
}
// For the first round, consider all people
start := 0
end := state.people
// From the second round onwards, restrict the search space
if len(state.res) > 0 {
start = len(state.table) * state.tableSize
end = start + state.tableSize
}
for person := start; person < end; person++ {
if !valid(state, person) {
continue // Skip if this assignment causes a conflict
}
set(state, person) // Assign the seat
if solveImpl(state) {
return true // Success!
}
unset(state, person) // Backtrack
}
return false
}
एक असाइनमेंट अमान्य है (टकराव होता है) यदि:
func valid(state *State, person int) bool {
// Has this person already been seated in this round?
if state.usedPerson[person] {
return false
}
// Has this person sat with anyone currently at this table before?
for _, there := range state.table {
first := min(there, person)
second := max(there, person)
if state.usedPair[first][second] {
return false
}
}
return true
}
set और unset)
🔗जब हम किसी व्यक्ति को सीट असाइन करते हैं, तो हमें अपने स्टेट ट्रैकर को अपडेट करना होता है। यदि कोई टेबल भर जाती है, तो हम अगली टेबल पर जाते हैं। यदि कोई राउंड भर जाता है, तो हम अगले राउंड पर जाते हैं।
func set(state *State, person int) {
state.usedPerson[person] = true
// Mark this person as having paired with everyone currently at the table
for _, there := range state.table {
first := min(there, person)
second := max(there, person)
if _, ok := state.usedPair[first]; !ok {
state.usedPair[first] = map[int]bool{}
}
state.usedPair[first][second] = true
}
state.table = append(state.table, person)
// Move to next table if full
if len(state.table) != state.tableSize {
return
}
state.round = append(state.round, state.table)
state.table = []int{}
// Move to next round if all tables are full
if len(state.round) != state.numTables {
return
}
state.res = append(state.res, state.round)
state.round = [][]int{}
state.usedPeople = append(state.usedPeople, state.usedPerson)
state.usedPerson = map[int]bool{}
// Check if we are completely done
if len(state.res) != state.numRounds {
return
}
state.solved = true
}
unset फ़ंक्शन इसका ठीक उल्टा है, जो हमारे रिकर्सिव ट्री के किसी बंद सिरे (dead end) पर पहुँचने पर सावधानीपूर्वक स्टेट को वापस पहले जैसा करता है।
func unset(state *State, person int) {
state.solved = false
// If the current table is empty, step back to the previous table
if len(state.table) == 0 {
if len(state.round) == 0 {
last := len(state.res) - 1
state.round = state.res[last]
state.res = state.res[:last]
state.usedPerson = state.usedPeople[last]
state.usedPeople = state.usedPeople[:last]
}
last := len(state.round) - 1
state.table = state.round[last]
state.round = state.round[:last]
}
// Remove the person from the table
state.table = state.table[:len(state.table)-1]
// Unmark pairings
for _, there := range state.table {
first := min(there, person)
second := max(there, person)
state.usedPair[first][second] = false
}
state.usedPerson[person] = false
}
यहाँ एक छोटे समिट के लिए आउटपुट दिया गया है। ध्यान दें कि कैसे राउंड 0 में संख्याएँ टेबलों में क्रमिक रूप से आगे बढ़ती हैं, और राउंड 1 में वे पिछली टेबलों में क्रमिक रूप से नीचे की ओर जाती हैं।
round 0:
table 0: 0 1 2 3
table 1: 4 5 6 7
table 2: 8 9 10 11
table 3: 12 13 14 15
round 1:
table 0: 0 4 8 12
table 1: 1 5 9 13
table 2: 2 6 10 14
table 3: 3 7 11 15
round 2:
table 0: 0 5 10 15
table 1: 1 4 11 14
table 2: 2 7 8 13
table 3: 3 6 9 12
round 3:
table 0: 0 6 11 13
table 1: 1 7 10 12
table 2: 2 4 9 15
table 3: 3 5 8 14
round 4:
table 0: 0 7 9 14
table 1: 1 6 8 15
table 2: 2 5 11 12
table 3: 3 4 10 13
क्योंकि हम पहले दो राउंड को पहले से भरकर अपने सर्च ट्री को समझदारी से छाँट (prune) लेते हैं, इसलिए एल्गोरिदम बड़े समूहों के लिए भी अच्छी तरह से काम करता है। नीचे 8 टेबलों में फैले 64 प्रतिभागियों के लिए समाधान दिया गया है।
round 0:
table 0: 0 1 2 3 4 5 6 7
table 1: 8 9 10 11 12 13 14 15
table 2: 16 17 18 19 20 21 22 23
table 3: 24 25 26 27 28 29 30 31
table 4: 32 33 34 35 36 37 38 39
table 5: 40 41 42 43 44 45 46 47
table 6: 48 49 50 51 52 53 54 55
table 7: 56 57 58 59 60 61 62 63
round 1:
table 0: 0 8 16 24 32 40 48 56
table 1: 1 9 17 25 33 41 49 57
table 2: 2 10 18 26 34 42 50 58
table 3: 3 11 19 27 35 43 51 59
table 4: 4 12 20 28 36 44 52 60
table 5: 5 13 21 29 37 45 53 61
table 6: 6 14 22 30 38 46 54 62
table 7: 7 15 23 31 39 47 55 63
round 2:
table 0: 0 9 18 27 36 45 54 63
table 1: 1 8 19 26 37 44 55 62
table 2: 2 11 16 25 38 47 52 61
table 3: 3 10 17 24 39 46 53 60
table 4: 4 13 22 31 32 41 50 59
table 5: 5 12 23 30 33 40 51 58
table 6: 6 15 20 29 34 43 48 57
table 7: 7 14 21 28 35 42 49 56
round 3:
table 0: 0 10 20 30 35 41 55 61
table 1: 1 11 21 31 34 40 54 60
table 2: 2 8 22 28 33 43 53 63
table 3: 3 9 23 29 32 42 52 62
table 4: 4 14 16 26 39 45 51 57
table 5: 5 15 17 27 38 44 50 56
table 6: 6 12 18 24 37 47 49 59
table 7: 7 13 19 25 36 46 48 58
round 4:
table 0: 0 11 22 29 39 44 49 58
table 1: 1 10 23 28 38 45 48 59
table 2: 2 9 20 31 37 46 51 56
table 3: 3 8 21 30 36 47 50 57
table 4: 4 15 18 25 35 40 53 62
table 5: 5 14 19 24 34 41 52 63
table 6: 6 13 16 27 33 42 55 60
table 7: 7 12 17 26 32 43 54 61
round 5:
table 0: 0 12 19 31 38 42 53 57
table 1: 1 13 18 30 39 43 52 56
table 2: 2 14 17 29 36 40 55 59
table 3: 3 15 16 28 37 41 54 58
table 4: 4 8 23 27 34 46 49 61
table 5: 5 9 22 26 35 47 48 60
table 6: 6 10 21 25 32 44 51 63
table 7: 7 11 20 24 33 45 50 62
round 6:
table 0: 0 13 17 28 34 47 51 62
table 1: 1 12 16 29 35 46 50 63
table 2: 2 15 19 30 32 45 49 60
table 3: 3 14 18 31 33 44 48 61
table 4: 4 9 21 24 38 43 55 58
table 5: 5 8 20 25 39 42 54 59
table 6: 6 11 23 26 36 41 53 56
table 7: 7 10 22 27 37 40 52 57
round 7:
table 0: 0 14 23 25 37 43 50 60
table 1: 1 15 22 24 36 42 51 61
table 2: 2 12 21 27 39 41 48 62
table 3: 3 13 20 26 38 40 49 63
table 4: 4 10 19 29 33 47 54 56
table 5: 5 11 18 28 32 46 55 57
table 6: 6 8 17 31 35 45 52 58
table 7: 7 9 16 30 34 44 53 59
round 8:
table 0: 0 15 21 26 33 46 52 59
table 1: 1 14 20 27 32 47 53 58
table 2: 2 13 23 24 35 44 54 57
table 3: 3 12 22 25 34 45 55 56
table 4: 4 11 17 30 37 42 48 63
table 5: 5 10 16 31 36 43 49 62
table 6: 6 9 19 28 39 40 50 61
table 7: 7 8 18 29 38 41 51 60
अगली बार जब आपको किसी नेटवर्किंग इवेंट की मेज़बानी करनी हो, तो मैन्युअल स्प्रेडशीट छोड़ें और बैकट्रैकिंग एल्गोरिदम को अपने लिए यह भारी काम करने दें!
काउए की जीवनशैली का क्यूरेटेड ऑफ़लाइन संस्करण प्राप्त करें—🍏 स्वास्थ्य, 💰 धन, ❤️ प्रेम और 🧘 अर्थ को बेहतर बनाने के लिए एक व्यावहारिक मार्गदर्शिका।
जब भी मैं बेहतर जीवन जीने पर नए निबंध, पुस्तक सारांश और व्यावहारिक गाइड प्रकाशित करूँ, तो सूचना प्राप्त करें। कोई स्पैम नहीं—कभी भी सदस्यता समाप्त करें।
क्या आपका कोई प्रश्न, दृष्टिकोण या सुझाव है? नीचे अपने विचार साझा करें। टिप्पणियाँ GitHub Discussions (विज्ञापन-मुक्त और स्पैम-मुक्त) द्वारा संचालित हैं—टिप्पणी करने या प्रतिक्रिया देने के लिए नीचे Sign in with GitHub पर क्लिक करें (निःशुल्क GitHub खाता बनाने में एक मिनट से भी कम समय लगता है)।
अंतिम अपडेट: 11 अक्टू॰ 2026.
अस्वीकरण (DISCLAIMER): इस साइट की सामग्री केवल सूचनात्मक और शैक्षिक उद्देश्यों के लिए है और यह चिकित्सा, मनोवैज्ञानिक, वित्तीय, निवेश, कर या कानूनी सलाह का गठन नहीं करती है। यहाँ प्रस्तुत विचार, संकलन और राय पूरी तरह से मेरे अपने हैं और मेरे नियोक्ता का प्रतिनिधित्व नहीं करते हैं। पुस्तकों, व्याख्यानों और लेखों के सारांश स्वतंत्र शैक्षिक टिप्पणियाँ हैं और उनके संबंधित लेखकों की बौद्धिक संपदा बने रहते हैं। संपादन, स्वरूपण और संश्लेषण में सहायता के लिए AI उपकरणों का उपयोग किया जा सकता है; यद्यपि सटीकता सुनिश्चित करने का हर संभव प्रयास किया जाता है, फिर भी त्रुटियाँ हो सकती हैं। गोपनीयता (PRIVACY): यह साइट वैकल्पिक न्यूज़लेटर सदस्यता (follow.it), टिप्पणियों (giscus / GitHub Discussions) और एम्बेडेड मीडिया (YouTube) के लिए तृतीय-पक्ष सेवाओं का उपयोग करती है, जो अपनी संबंधित गोपनीयता नीतियों के अनुसार आगंतुकों के IP पते और कुकीज़ को संसाधित कर सकती हैं।