N के साथ NXP स्टैक के एक सेट को देखते हुए स्टैक की संख्या, और P स्टैक की क्षमता होने के कारण, मैं स्थान A में कुछ नोड से कुछ मनमाने स्थान B पर जाने के लिए आवश्यक स्वैप की न्यूनतम संख्या की गणना कैसे कर सकता हूं? मैं एक गेम डिजाइन कर रहा हूं, और अंतिम लक्ष्य सभी ढेर को क्रमबद्ध करना है ताकि वे सभी एक ही रंग के हों।
# Let "-" represent blank spaces, and assume the stacks are
stacks = [
['R', 'R', 'R', 'R'],
['Y', 'Y', 'Y', 'Y'],
['G', 'G', 'G', 'G'],
['-', '-', '-', 'B'],
['-', 'B', 'B', 'B']
]
अगर मैं stacks[1][1]
इस तरह से "बी" सम्मिलित करना चाहता हूं stacks[1] = ["-", "B", "Y", "Y"]
। मैं ऐसा करने के लिए आवश्यक न्यूनतम कदम कैसे निर्धारित कर सकता हूं?
मैं कई दृष्टिकोणों को देख रहा हूं, मैंने आनुवंशिक एल्गोरिदम की कोशिश की है जो एक राज्य से सभी संभव चालें उत्पन्न करता है, उन्हें स्कोर करता है, और फिर सबसे अच्छा स्कोरिंग पथ नीचे जारी रखता है, मैंने समस्या पर पाथफाइंडिंग के लिए Djikstra के एल्गोरिथ्म को चलाने का भी प्रयास किया है । यह निराशाजनक रूप से सरल लगता है, फिर भी मैं इसे घातीय समय के अलावा किसी और चीज में चलाने का तरीका नहीं समझ सकता। क्या एक एल्गोरिथ्म मैं याद कर रहा हूँ जो यहाँ लागू है?
संपादित करें
मैंने यह फ़ंक्शन आवश्यक संख्याओं की न्यूनतम संख्या की गणना करने के लिए लिखा है: स्टैक: स्टैक में टुकड़ों का प्रतिनिधित्व करने वाले वर्णों की सूची, स्टैक [0] [0] स्टैक के शीर्ष [0] स्टैक_इंड: सूचकांक स्टैक कि टुकड़ा को__पीस में जोड़ा जाएगा: वह टुकड़ा जिसे स्टैक की जरूरत के लिए जोड़ा जाना चाहिए_इंडेक्स: वह इंडेक्स जहां टुकड़ा स्थित होना चाहिए
def calculate_min_moves(stacks, stack_ind, needs_piece, needs_index):
# Minimum moves needed to empty the stack that will receive the piece so that it can hold the piece
num_removals = 0
for s in stacks[stack_ind][:needs_index+1]:
if item != "-":
num_removals += 1
min_to_unlock = 1000
unlock_from = -1
for i, stack in enumerate(stacks):
if i != stack_ind:
for k, piece in enumerate(stack):
if piece == needs_piece:
if k < min_to_unlock:
min_to_unlock = k
unlock_from = i
num_free_spaces = 0
free_space_map = {}
for i, stack in enumerate(stacks):
if i != stack_ind and i != unlock_from:
c = stack.count("-")
num_free_spaces += c
free_space_map[i] = c
if num_removals + min_to_unlock <= num_free_spaces:
print("No shuffling needed, there's enough free space to move all the extra nodes out of the way")
else:
# HERE
print("case 2, things need shuffled")
संपादित करें: स्टैक पर परीक्षण के मामले:
stacks = [
['R', 'R', 'R', 'R'],
['Y', 'Y', 'Y', 'Y'],
['G', 'G', 'G', 'G'],
['-', '-', '-', 'B'],
['-', 'B', 'B', 'B']
]
Case 1: stacks[4][1] should be 'G'
Move 'B' from stacks[4][1] to stacks[3][2]
Move 'G' from stacks[2][0] to stacks[4][1]
num_removals = 0 # 'G' is directly accessible as the top of stack 2
min_to_unlock = 1 # stack 4 has 1 piece that needs removed
free_spaces = 3 # stack 3 has free spaces and no pieces need moved to or from it
moves = [[4, 3], [2, 4]]
min_moves = 2
# This is easy to calculate
Case 2: stacks[0][3] should be 'B'
Move 'B' from stacks[3][3] to stack[4][0]
Move 'R' from stacks[0][0] to stacks[3][3]
Move 'R' from stacks[0][1] to stacks[3][2]
Move 'R' from stacks[0][2] to stacks[3][1]
Move 'R' from stacks[0][3] to stacks[3][0]
Move 'B' from stacks[4][0] to stacks[0][3]
num_removals = 0 # 'B' is directly accessible
min_to_unlock = 4 # stack 0 has 4 pieces that need removed
free_spaces = 3 # If stack 3 and 4 were switched this would be 1
moves = [[3, 4], [0, 3], [0, 3], [0, 3], [0, 3], [4, 0]]
min_moves = 6
#This is hard to calculate
वास्तविक कोड कार्यान्वयन वह हिस्सा नहीं है जो मुश्किल है, यह एक एल्गोरिदम को लागू करने का तरीका निर्धारित कर रहा है जो उस समस्या को हल करता है जिसके साथ मैं संघर्ष कर रहा हूं।
प्रति @ YonIif के अनुरोध के रूप में मैं एक बना लिया है सार समस्या के लिए।
जब यह चलता है, यह ढेर का एक यादृच्छिक सरणी उत्पन्न करता है, और एक यादृच्छिक टुकड़ा चुनता है जिसे यादृच्छिक स्थान पर यादृच्छिक स्टैक में डालने की आवश्यकता होती है।
इसे चलाने से कंसोल में इस प्रारूप का कुछ हिस्सा प्रिंट होता है।
All Stacks: [['-', '-', 'O', 'Y'], ['-', 'P', 'P', 'O'], ['-', 'P', 'O', 'Y'], ['Y', 'Y', 'O', 'P']]
Stack 0 is currently ['-', '-', 'O', 'Y']
Stack 0 should be ['-', '-', '-', 'P']
स्थिति अपडेट
मैं किसी भी तरह इस समस्या को हल करने के लिए बहुत दृढ़ हूं ।
ध्यान रखें कि इस तरह के मामलों को कम करने के तरीके हैं, जैसे कि @Hans Olsson ने टिप्पणियों में उल्लेख किया है। इस समस्या के लिए मेरा सबसे हालिया दृष्टिकोण, उल्लिखित नियमों के समान नियमों का एक समूह विकसित करना है, और उन्हें एक सामान्य एल्गोरिथ्म में नियोजित करना है।
नियम जैसे:
एक चाल कभी उल्टा मत करो। 1-> 0 से जाओ तो 0-> 1 (कोई मतलब नहीं है)
कभी भी एक पंक्ति में दो बार टुकड़ा न चलाएं। कभी 0 -> 1 से तो कभी 1 -> 3 से हटो
स्टैक्स [X] से स्टैक [Y] की कुछ चाल को देखते हुए, फिर कुछ संख्या में कदम, फिर स्टैक से एक कदम [Y] स्टैक से [Z], यदि स्टैक्स [Z] उसी अवस्था में है जैसा कि कदम था स्टैक [X] से स्टैक [Y] हुआ, स्टैक से हटकर एक चाल को समाप्त किया जा सकता था [X] सीधे स्टैक्स से [Z]
वर्तमान में, मैं पर्याप्त नियम बनाने के प्रयास के साथ इस समस्या से संपर्क कर रहा हूं, कि यह "वैध" चालों की संख्या को कम करता है, पर्याप्त है ताकि एक जेनेरिक एल्गोरिथम का उपयोग करके उत्तर की गणना की जा सके। यदि कोई अतिरिक्त नियमों के बारे में सोच सकता है, तो मैं उन्हें टिप्पणियों में सुनने में दिलचस्पी लूंगा।
अपडेट करें
@RootTwo के जवाब की बदौलत मुझे थोड़ी सफलता मिली है, जिसे मैं यहां बताऊंगा।
सफलता पर
लक्ष्य की ऊंचाई को परिभाषित करें क्योंकि लक्ष्य टुकड़ा को गहराई से गंतव्य स्टैक में रखा जाना चाहिए।
जब भी कुछ गोल टुकड़ा इंडेक्स <= stack_height - गोल ऊंचाई पर रखा जाता है, तो हमेशा clear_path () पद्धति के माध्यम से जीत का सबसे छोटा रास्ता होगा।
Let S represent some solid Piece.
अर्थात
Stacks = [ [R, R, G], [G, G, R], [-, -, -] ]
Goal = Stacks[0][2] = R
Goal Height = 2.
Stack Height - Goal Height = 0
कुछ ऐसे स्टैक को देखते हुए stack[0] = R
, खेल को जीत लिया जाता है।
GOAL
[ [ (S | -), (S | -), (S | -) ], [R, S, S], [(S | - ), (S | -), (S | -)] ]
चूंकि यह ज्ञात है कि उनके पास हमेशा कम से कम स्टैक_हाइट रिक्त स्थान उपलब्ध होते हैं, इसलिए सबसे खराब संभव मामला होगा:
[ [ S, S, !Goal ], [R, S, S], [-, -, -]
चूँकि हम जानते हैं कि लक्ष्य का टुकड़ा लक्ष्य गंतव्य में नहीं हो सकता है या खेल जीत गया है। जिस स्थिति में आवश्यक कदमों की न्यूनतम संख्या होगी, वे हैं:
(0, 2), (0, 2), (0, 2), (1, 0)
Stacks = [ [R, G, G], [-, R, R], [-, -, G] ]
Goal = Stack[0][1] = R
Stack Height - Goal Height = 1
कुछ ऐसे स्टैक को देखते हुए stack[1] = R
, खेल को जीत लिया जाता है।
GOAL
[ [ (S | -), (S | -), S], [ (S | -), R, S], [(S | -), (S | -), (S | -)]
हम जानते हैं कि कम से कम 3 रिक्त स्थान उपलब्ध हैं, इसलिए सबसे खराब स्थिति यह होगी:
[ [ S, !Goal, S], [S, R, S], [ -, -, - ]
इस मामले में चाल की न्यूनतम संख्या चाल होगी:
(1, 2), (0, 2), (0, 2), (1, 0)
यह सभी मामलों के लिए होगा।
इस प्रकार, लक्ष्य की ऊंचाई पर या उसके ऊपर गोल टुकड़े को रखने के लिए आवश्यक न्यूनतम चालों को खोजने की समस्या को कम किया गया है।
यह समस्या को उप-समस्याओं की एक श्रृंखला में विभाजित करता है:
जब गंतव्य स्टैक का अपना सुलभ टुकड़ा होता है! = लक्ष्य टुकड़ा, यह निर्धारित करते हुए कि उस टुकड़े के लिए एक वैध स्थान है, या यदि टुकड़ा वहाँ रहना चाहिए, जबकि दूसरा टुकड़ा स्वैप किया गया हो।
जब गंतव्य स्टैक में अपना सुलभ टुकड़ा == गोल टुकड़ा होता है, तो यह निर्धारित करते हुए कि क्या इसे हटाया जा सकता है और आवश्यक लक्ष्य ऊंचाई पर रखा जा सकता है, या यदि टुकड़ा दूसरे के स्वैप रहने के दौरान रहना चाहिए।
जब उपरोक्त दो मामलों में एक और टुकड़े की अदला-बदली की आवश्यकता होती है, तो यह निर्धारित करने के लिए कि किस टुकड़े को स्वैप करना है ताकि गोल टुकड़ा के लिए लक्ष्य ऊंचाई तक पहुंचने के लिए संभव हो सके।
गंतव्य स्टैक को हमेशा अपने मामलों का पहले मूल्यांकन करना चाहिए।
अर्थात
stacks = [ [-, R, G], [-, R, G], [-, R, G] ]
Goal = stacks[0][1] = G
लक्ष्य स्टैक की जाँच पहले होती है:
(0, 1), (0, 2), (1, 0), (2, 0) = 4 Moves
लक्ष्य की अनदेखी:
(1, 0), (1, 2), (0, 1), (0, 1), (2, 0) = 5 Moves