कैसे घर के रास्ते पर एक शराबी को धीमा करने के लिए


15

N ग्रिड ग्राफ द्वारा एक वर्ग n पर विचार करें जो इस तरह दिखता है।

ग्रिड ग्राफ

यह नोट करना महत्वपूर्ण है कि यह ग्राफ 11 बाई 11 है

किसी भी बिंदु पर एक आदमी एक चौराहे पर खड़ा होता है और वह केवल कभी-कभी अगले चौराहे पर एक कदम से लंबवत या क्षैतिज रूप से आगे बढ़ता है। अफसोस की बात है कि वह थोड़ा बहुत नशे में है, इसलिए वह उस दिशा को चुनता है जिसे वह बेतरतीब ढंग से 4 संभावित दिशाओं (ऊपर, नीचे, बाएं, दाएं) से स्थानांतरित करता है। यह 4 तक है जैसे कि वह एक दीवार पर खड़ा है, उसके पास केवल 3 विकल्प हैं और एक कोने में उसके पास केवल 2 हैं।

वह नीचे बाएं हाथ के कोने में शुरू होता है और उसका लक्ष्य घर पहुंचना होता है जो शीर्ष दाहिने हाथ का कोने है। समय बस कदम की संख्या है जो उसे ले जाता है।

हालाँकि, आप एक दुर्भावनापूर्ण विरोधी हैं जो चाहते हैं कि वह धीरे-धीरे घर पर आए। आप पैदल चलने के दौरान किसी भी समय किसी भी संख्या के किनारों को ग्राफ़ से हटा सकते हैं। एकमात्र प्रतिबंध यह है कि आपको घर जाने के लिए हमेशा कुछ रास्ता छोड़ना चाहिए और आप पहले से उपयोग की गई एक किनारे को नहीं हटा सकते।

चुनौती यह है कि जितना संभव हो उतना दुर्भावनापूर्ण विरोधी के रूप में तैयार किया जाए और फिर एक यादृच्छिक शराबी वॉकर के साथ 100 पर 20 20 ग्राफ द्वारा 100 का परीक्षण करें । आपका स्कोर औसत समय है जब यह यादृच्छिक वॉकर को 10 1000 से अधिक रन बनाने के लिए घर ले जाता है ।

आप किसी भी भाषा और पुस्तकालयों का उपयोग तब तक कर सकते हैं जब तक वे स्वतंत्र रूप से उपलब्ध हों और लिनक्स में आसानी से इंस्टॉल किए जा सकें।

मुझे क्या लागू करने की आवश्यकता है?

आपको रैंडम वॉकर के लिए कोड लागू करना चाहिए और विरोधी के लिए भी और कोड को संयोजित किया जाना चाहिए ताकि जब रन किया जाए तो आउटपुट केवल आपके विरोधी कोड का उपयोग करके 1000 रन का औसत हो। यादृच्छिक वाकर कोड को लिखना बहुत ही सरल होना चाहिए क्योंकि वह सिर्फ (x-1, y), (x + 1, y), (x, y-1), और (x, y + 1) को चुनकर सुनिश्चित करता है कि उनमें से कोई भी हटा दिया गया है या सीमा से बाहर हैं।

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


परिशिष्ट 10 रन वास्तव में पर्याप्त नहीं है, लेकिन मैं उन लोगों को दंडित नहीं करना चाहता था जो वास्तव में लंबे समय तक चलने में कामयाब रहे। मैंने लोकप्रिय अनुरोध के कारण इसे बढ़ाकर अब 1000 कर दिया है। हालाँकि, अगर आपका चलना इतना लंबा है, तो आप यथार्थवादी समय में 1000 रन नहीं कर सकते हैं, तो कृपया अपने अधिकतम रनों की अधिकतम संख्या की रिपोर्ट करें।


100 से 100 के लिए उच्च अंक तालिका।

  • 976124.754 ऑप्टिमाइज़र द्वारा।
  • पीटर टेलर द्वारा 103000363.218।

संपादित करें 1. लोगों के परीक्षणों के चलने के समय में मदद करने के लिए ग्राफ का आकार 20 से 20 तक बदल दिया। मैं उस आकार के लिए एक नया उच्च तालिका स्कोर बनाऊंगा क्योंकि लोग स्कोर जमा करते हैं।

20 से 20 के लिए उच्च अंक तालिका।

230,794.38 (100k runs) by justhalf
227,934 by Sparr 
213,000 (approx) by Peter Taylor
199,094.3 by stokastic
188,000 (approx) by James_pic
 64,281 by Geobits

2
मुझे समझ नहीं आया; क्या आप शुरुआत में उन सभी किनारों को नहीं हटा सकते हैं, जो सबसे लंबा रास्ता बनाते हैं?
पीटर ओल्सन

3
मुझे यह दिखाते हुए कोई नियम नहीं है कि शराबी एक ही किनारे पर दो बार फिर से नहीं चल सकता है। यदि वह दो बार दो बिंदुओं के बीच एक ही पथ ले सकता है, और यादृच्छिक रूप से चुनता है, तो तार्किक रूप से सबसे लंबे औसत (यादृच्छिक) ट्रैवर्सल के साथ सबसे किनारों वाला ग्राफ नहीं है? यही है, इष्टतम (सबसे लंबा) ग्राफ नहीं हटाई गई किनारों के साथ एक होगा?
मिलिनन

3
मैं पहिया (वॉकर) को सुदृढ़ करने के लिए हर प्रविष्टि की आवश्यकता का प्रशंसक नहीं हूं। अगर कोई टेस्ट हार्नेस / फ्रेमवर्क पोस्ट करता है तो मैं उन्हें अपग्रेड करूंगा और उसका इस्तेमाल करूंगा।
शपथ

1
किसी पथ के एक भाग को हटाने का लाभ उसे वापस ले जाने के लिए लंबे रास्ते के चारों ओर पूरी तरह से खो जाने पर होता है जब उसका मार्ग यादृच्छिक होता है; माना जाता है कि यह समान रूप से संभावना है कि वह आपको एक किनारे हटाने की आवश्यकता के बिना किसी बिंदु पर वापस मुड़ जाएगा। मैं कुछ परीक्षण डेटा देखना चाहता हूं जिसमें बिना किनारों को हटाए औसत समय दिखाया गया है, और फिर कुछ किनारों को हटा दिया गया है जैसा कि आप सुझाव देते हैं। जहां तक ​​इस चुनौती की बात है, मुझे लगता है कि अगर शराबी का रास्ता निर्धारक होता तो यह ज्यादा दिलचस्प होता।
मिलिनन

3
10 राउंड लगभग पर्याप्त नहीं हैं। यहां तक ​​कि एक स्थिर 10x10 भूलभुलैया के साथ, अकेले एक बुद्धिमान विरोधी और 100x100 भूलभुलैया दें, मानक विचलन औसत मामले का लगभग 50% है। मैं 10000 राउंड चला रहा हूँ और मैं अभी भी परिणामों की तुलना के योग्य नहीं हूँ।
23

जवाबों:


10

20x20 पर 230,794.38, 100k रन

नवीनतम अद्यतन: मैं अंत में सही गतिशील 2-पथ समाधान बनाया। मैंने कहा कि चूंकि पिछला संस्करण वास्तव में सममित नहीं है, इसलिए अधिक लंबा रास्ता तय करना आसान था अगर शराबी एक रास्ते को दूसरे पर ले जाए। वर्तमान एक सममित है, इसलिए यह उच्च स्तर की अपेक्षित संख्या प्राप्त कर सकता है। कुछ परीक्षणों के बाद, यह 230k के आसपास लगता है, पिछले एक पर सुधार जो 228k के बारे में है। लेकिन सांख्यिकीय रूप से उन संख्याओं को बोलना अभी भी उनके भारी विचलन के भीतर है, इसलिए मैं यह दावा नहीं करता कि यह काफी बेहतर है, लेकिन मेरा मानना ​​है कि यह पिछले संस्करण की तुलना में बेहतर होना चाहिए।

इस पोस्ट में सबसे नीचे कोड होता है। इसे अपडेट किया जाता है ताकि यह पिछले संस्करण की तुलना में बहुत तेज़ हो, 23 में 1000 रन पूरे कर सके।

नीचे नमूना रन और नमूना भूलभुलैया है:

परफेक्ट वॉकर
औसत: 230794.384
अधिकतम: 1514506
न्यूनतम: 25,860
2317.374 में पूरा हुआ
 _ _ _ _ _ _ _ _ _ _ _ _। 
| | | | | | | | | | | | | | | _ _ _ _ _  
| | | | | | | | | | | | | | | | _ _ _ _  
| | | | | | | | | | | | | | | _ _ _ _ |
| | | | | | | | | | | | | | | | _ _ _ _  
| | | | | | | | | | | | | | | _ _ _ _ |
| | | | | | | | | | | | | | | | _ _ _ _  
| | | | | | | | | | | | | | | _ _ _ _ |
| | | | | | | | | | | | | | _ | | _ _ _ _  
| | | | | | | | | | | | | _ _ _ _ _ _ _ |
| | | | | | | | | | | | | | _ _ _ _ _ _ _  
| | | | | | | | | | | | | _ _ _ _ _ _ _ |
| | | | | | | | | | | | | | _ _ _ _ _ _ _  
| | | | | | | | | | | | | _ _ _ _ _ _ _ |
| | | | | | _ | | _ | | _ | | _ | | _ _ _ _ _ _ _  
| | | | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | | | | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _  
| | | | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | _ | | _ | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _  
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | 


पिछली प्रस्तुतियाँ

अंत में मैं स्पर्म के परिणाम का मिलान कर सकता हूं! = D

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

इसलिए अपनी DOUBLE_PATHरणनीति के आधार पर , मैंने एक और निर्माण किया, जो DOUBLE_PATHनशे की गति के आधार पर भूलभुलैया (मेरी भूलभुलैया आसानी से परिवर्तनीय था) को बदल देता है। चूंकि वह एक से अधिक उपलब्ध विकल्पों के साथ एक रास्ता अपनाता है, इसलिए मैं केवल दो संभावित विकल्पों (जिसमें से वह आया था, एक और असत्य) को छोड़ने के लिए रास्ते बंद कर दूंगा।

यह वही दिखता है जो स्पर्म ने हासिल किया है, जैसा कि परिणाम दिखाता है। उसके साथ अंतर बेहतर माना जाने के लिए बहुत छोटा है, लेकिन मैं कहूंगा कि मेरा दृष्टिकोण उससे अधिक गतिशील है, क्योंकि मेरा भूलभुलैया स्पियर = की तुलना में अधिक परिवर्तनीय है)

एक नमूना अंतिम भूलभुलैया के साथ परिणाम:

EXTREME_DOUBLE_PATH
औसत: 228034.89
अधिकतम: 1050816
न्यूनतम: 34,170
396.728 में पूरा हुआ
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
 _ _ _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
 _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |


प्रयोग अनुभाग

सबसे अच्छा स्टोकैस्टिक के रूप में एक ही रणनीति निकलती है, मैं विभिन्न रणनीतियों का उपयोग करने और अच्छे आउटपुट प्रिंट करने में गर्व करता हूं :)

नीचे मुद्रित भूलभुलैया में से प्रत्येक आखिरी भूलभुलैया है जो शराबी के घर पहुंचने के बाद है, इसलिए वे शराबी आंदोलन में बेतरतीबपन और प्रतिकूलता की गंभीरता के कारण रन से थोड़ा अलग हो सकते हैं।

मैं प्रत्येक रणनीति का वर्णन करूँगा:

सिंगल पाथ

यह सबसे सरल दृष्टिकोण है, जो प्रवेश से बाहर निकलने तक एक ही रास्ता बनाएगा।

SINGLE_PATH
औसत: 162621.612
अधिकतम: 956694
न्यूनतम: 14,838
149.430 में पूरा हुआ
 _ _ _ _ _ _ _ _ _ _ _
| | _ | | _ | | _ | | _ | | _ | | _ | | _ | | _ | | _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |

द्वीप (स्तर 0)

यह एक दृष्टिकोण है जो शराबी को लगभग अलग-थलग द्वीप में फंसाने की कोशिश करता है। मेरी अपेक्षा के अनुसार काम नहीं करता है, लेकिन यह मेरे पहले विचारों में से एक है, इसलिए मैं इसे शामिल करता हूं।

बाहर निकलने के लिए दो रास्ते हैं, और जब शराबी उनमें से एक के पास जाता है, तो विरोधी उसे बंद कर देता है, जिससे वह दूसरे निकास को खोजने के लिए मजबूर हो जाता है (और संभवतः द्वीप में फिर से फंस जाता है)

द्वीप
औसत: 74626.070
अधिकतम: 428560
मिन: 1528
122.512 में पूरा हुआ
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _   
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |

डबल पाथ

यह सबसे चर्चित रणनीति है, जिसमें बाहर निकलने के लिए दो समान लंबाई वाले रास्ते हैं, और उनमें से एक को बंद करना क्योंकि शराबी उनमें से एक के पास जाता है।

DOUBLE_PATH
औसत: 197743.472
अधिकतम: 1443406
न्यूनतम: 21,516
308.177 में पूरा हुआ
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
 _ _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
 _ _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
 _ _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
 _ _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
 _ _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
 _ _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
 _ _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
 _ _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |

द्वीप (स्तर 1)

द्वीप के कई रास्तों से प्रेरित और एकल पथ में उच्च पैदल गणना, हम द्वीप को निकास से जोड़ते हैं और द्वीप में एकल पथ भूलभुलैया बनाते हैं, जिससे बाहर निकलने के लिए कुल तीन रास्ते बनते हैं, और पिछले मामले के समान, किसी भी मार्ग को बंद करें शराबी के पास से बाहर निकल जाता है।

यह शुद्ध एकल पथ की तुलना में थोड़ा बेहतर काम करता है, लेकिन फिर भी दोहरे पथ को नहीं हराता है।

द्वीप
औसत: 166265.132
अधिकतम: 1162966
न्यूनतम: 19,544
471.982 में पूरा हुआ
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ | |
| | | _ | | _ | | _ | | _ | | _ | | _ | | _ | | _ | |  
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |

द्वीप (स्तर 2)

पिछले विचार का विस्तार करने की कोशिश करते हुए, मैंने नेस्टेड द्वीप बनाया, कुल पांच रास्तों में निर्माण किया, लेकिन यह अच्छी तरह से काम नहीं करता है।

द्वीप
औसत: 164222.712
अधिकतम: 927608
न्यूनतम: 22,024
793.591 में पूरा हुआ
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ | _ | | |  
| | | | _ | | _ | | _ | | _ | | _ | | _ | | _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| _ | _ | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |

द्वीप (स्तर 3)

यह देखते हुए कि डबल पाथ वास्तव में सिंगल पाथ से बेहतर काम करता है, आइए द्वीप को डबल पाथ बनाते हैं!

परिणाम द्वीप (स्तर 1) पर एक सुधार है, लेकिन यह अभी भी शुद्ध डबल पथ को हरा नहीं करता है।

तुलना के लिए, द्वीप के आकार के दोहरे पथ का परिणाम औसतन 131,134.42 चाल है। तो यह काफी महत्वपूर्ण संख्या (40k के आसपास) को जोड़ता है, लेकिन दोहरे पथ को हरा देने के लिए पर्याप्त नहीं है।

द्वीप
औसत: 171730.090
अधिकतम: 769080
न्यूनतम: 29,760
587.646s में पूरा हुआ
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |  
| _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| _ _ _ _ _ _ _ _ | | | _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |

द्वीप (स्तर 4)

फिर से नेस्टेड द्वीप के साथ प्रयोग करना, और फिर से यह इतनी अच्छी तरह से काम नहीं करता है।

द्वीप
औसत: 149723.068
अधिकतम: 622106
न्यूनतम: 25,752
830.889 में पूरा हुआ
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _    
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | | |  
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ | | |
| | _ | _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | | |
| _ | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |

निष्कर्ष

सब सब में, यह साबित होता है कि शराबी की वर्तमान स्थिति से बाहर निकलने के लिए एक एकल लंबा रास्ता सबसे अच्छा काम करता है, जिसे डबल पथ रणनीति द्वारा हासिल किया जाता है, क्योंकि बाहर निकलने के बाद, शराबी को अधिकतम दूरी की यात्रा करना होगा। निकास।

यह आगे संकेत देता है कि मूल रणनीति अभी भी डबल पथ होनी चाहिए, और हम केवल यह संशोधित कर सकते हैं कि पथ कैसे गतिशील बनाए गए हैं, जो कि Sparr द्वारा किया गया है। इसलिए मेरा मानना ​​है कि उनकी रणनीति रास्ता तय करना है!

कोड

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.TreeSet;

public class Walker {

    enum Strategy{
        SINGLE_PATH,
        ISLAND,
        DOUBLE_PATH,
        EXTREME_DOUBLE_PATH,
        PERFECT_DOUBLE_PATH,
    }

    int width,height;
    int x,y; //walker's position
    int dX,dY; //destination
    Point[][] points;
    int stepCount = 0;

    public static void main(String[]args){
        int side = 20;
//      runOnce(side, Strategy.EXTREME_DOUBLE_PATH, 0);
        runOnce(side, Strategy.PERFECT_DOUBLE_PATH, 0);
//      for(Strategy strategy: Strategy.values()){
//          runOnce(side, strategy, 0);
//      }
//      runOnce(side, Strategy.ISLAND, 1);
//      runOnce(side, Strategy.ISLAND, 2);
//      Scanner scanner = new Scanner(System.in);
//      System.out.println("Enter side, strategy (SINGLE_PATH, ISLAND, DOUBLE_PATH, EXTREME_DOUBLE_PATH), and level:");
//      while(scanner.hasNext()){
//          side = scanner.nextInt();
//          Strategy strategy = Strategy.valueOf(scanner.next());
//          int level = scanner.nextInt();
//          scanner.nextLine();
//          runOnce(side, strategy, level);
//          System.out.println("Enter side, strategy (SINGLE_PATH, ISLAND, DOUBLE_PATH, EXTREME_DOUBLE_PATH), and level:");
//      }
//      scanner.close();
    }

    private static Walker runOnce(int side, Strategy strategy, int level) {
        Walker walker = null;
        long total = 0;
        int max = 0;
        int min = Integer.MAX_VALUE;
        double count = 1000;
        long start = System.currentTimeMillis();
        for(int i=0; i<count; i++){
            walker = new Walker(0,0,side,side,side-1,side-1, strategy, level, false);
            total += walker.stepCount;
            max = Math.max(walker.stepCount, max);
            min = Math.min(walker.stepCount, min);
//          System.out.println("Iteration "+i+": "+walker.stepCount);
        }
        System.out.printf("%s\nAverage: %.3f\nMax: %d\nMin:%d\n",strategy, total/count, max, min);
        System.out.printf("Completed in %.3fs\n", (System.currentTimeMillis()-start)/1000.0);
        walker.printPath();
        return walker;
    }

    private void createIsland(int botLeftX, int botLeftY, int topRightX, int topRightY){
        for(int i=botLeftY+1; i<topRightY; i++){
            if(i>botLeftY+1) deletePath(points[botLeftX][i].right());
            if(i<topRightY-1) deletePath(points[topRightX][i].left());
        }
        for(int i=botLeftX+1; i<topRightX; i++){
            if(i>botLeftX+1) deletePath(points[i][botLeftY].up());
            if(i<topRightX-1) deletePath(points[i][topRightY].down());
        }
    }

    private void createSinglePath(int botLeftX, int botLeftY, int topRightX, int topRightY){
        for(int i=botLeftY; i<topRightY; i++){
            if(i==topRightY-1 && (topRightY+1-botLeftY)%2==0){
                for(int j=botLeftX; j<topRightX; j++){
                    if(j==topRightX-1 && (j-botLeftX)%2==0){
                        deletePath(points[topRightX][topRightY].down());
                    } else {
                        deletePath(points[j][topRightY-1+((j-botLeftX)%2)].right());
                    }
                }
            } else {
                for(int j=botLeftX+(i-botLeftY)%2; j<topRightX+((i-botLeftY)%2); j++){
                    deletePath(points[j][i].up());
                }
            }
        }
    }

    private void createDoublePath(int botLeftX, int botLeftY, int topRightX, int topRightY){
        for(int i=botLeftY; i<topRightY; i++){
            if(i>botLeftY && (width%4!=1 || i<topRightY-1)) deletePath(points[width/2-1][i].right());
            if(i==topRightY-1 && (topRightY+1-botLeftY)%2==1){
                for(int j=botLeftX; j<topRightX; j++){
                    if((j-botLeftX)%2==0 || j<topRightX-1){
                        deletePath(points[j][topRightY-1+((j-botLeftX)%2)].right());
                    } else {
                        deletePath(points[topRightX-1][topRightY-1].right());
                    }
                }
            } else {
                if((i-botLeftY)%2==0){
                    for(int j=botLeftX+1; j<topRightX; j++){
                        deletePath(points[j][i].up());
                    }
                } else {
                    for(int j=botLeftX; j<topRightX+1; j++){
                        if(j!=width/2 && j!=width/2-1){
                            deletePath(points[j][i].up());
                        }
                    }
                }
            }
        }
    }

    public Walker(int startingX,int startingY, int Width, int Height, int destinationX, int destinationY, Strategy strategy, int level, boolean animate){
        width = Width;
        height = Height;
        dX = destinationX;
        dY = destinationY;
        x=startingX;
        y=startingY;
        points = new Point[width][height];
        for(int y=0; y<height; y++){
            for(int x=0; x<width; x++){
                points[x][y] = new Point(x,y);
            }
        }
        for(int y=0; y<height; y++){
            for(int x=0; x<width; x++){
                if(x<width-1) new Edge(points[x][y], points[x+1][y]);
                if(y<height-1) new Edge(points[x][y], points[x][y+1]);
            }
        }

        if(strategy == Strategy.SINGLE_PATH) createSinglePath(0,0,width-1,height-1);

        if(strategy == Strategy.DOUBLE_PATH) createDoublePath(0,0,width-1,height-1);

        List<EdgeList> edgeLists = new ArrayList<EdgeList>();
        if(strategy == Strategy.ISLAND){
            List<Edge> edges = new ArrayList<Edge>();
            if(level==0){
                createIsland(0,0,width-1,height-1);
                deletePath(points[width-2][height-2].right());
                deletePath(points[width-2][height-2].up());
            } else {
                for(int i=0; i<level; i++){
                    createIsland(i,i,width-1-i, height-1-i);
                }
                createDoublePath(level,level,width-1-level,height-1-level);
                for(int i=height-1; i>=height-level; i--){
                    edges.add(points[i-2][i].right());
                    edges.add(points[i][i-2].up());
                    edgeLists.add(new EdgeList(points[i-1][i].right(), points[i][i-1].up()));
                }
            }
            edges.add(points[width-1-level][height-1-level].down());
            edges.add(points[width-1-level][height-1-level].left());
            edgeLists.add(new EdgeList(edges.toArray(new Edge[0])));
        }

        int[] availableVerticals = new int[height];
        if(strategy == Strategy.EXTREME_DOUBLE_PATH){
            for(int i=1; i<width-1; i++){
                deletePath(points[i][0].up());
            }
            availableVerticals[0] = 2;
            for(int i=1; i<height; i++){
                availableVerticals[i] = width;
            }
        }

        boolean[][] available = new boolean[width][height];
        if(strategy == Strategy.PERFECT_DOUBLE_PATH){
            for(int x=0; x<width; x++){
                for(int y=0; y<height; y++){
                    if(x%2==1 && y%2==1){
                        available[x][y] = true;
                    } else {
                        available[x][y] = false;
                    }
                }
            }
        }
//      printPath();
        while(!walk()){
            if(animate)try{Thread.sleep(500);}catch(InterruptedException e){}
            if(strategy == Strategy.ISLAND){
                if(x==y && (x==1 || (x>=2 && x<=level))){
                    if(!hasBeenWalked(points[x][x].down())){
                        deletePath(points[x][x].down());
                    } else if(!hasBeenWalked(points[x][x].left())){
                        deletePath(points[x][x].left());
                    }
                }
            }
            if(strategy == Strategy.EXTREME_DOUBLE_PATH){
                Point cur = points[x][y];
                int untravelled = 0;
                for(Edge edge: cur.edges) if(edge!=null && !edge.walked) untravelled++;
                if(untravelled>1){
                    if(cur.up()!=null && availableVerticals[y]>2 && !cur.up().walked){
                        deletePath(cur.up());
                        availableVerticals[y]--;
                    }
                    if(cur.down()!=null && !cur.down().walked){
                        deletePath(cur.down());
                        availableVerticals[y-1]--;
                    }
                    if(cur.up()!=null && cur.left()!=null && !cur.left().walked){
                        deletePath(cur.left());
                        deletePath(points[x][y+1].left());
                    }
                    if(cur.up()!=null && cur.right()!=null && !cur.right().walked){
                        deletePath(cur.right());
                        if(y<height-1) deletePath(points[x][y+1].right());
                    }
                }
            }
            if(strategy == Strategy.PERFECT_DOUBLE_PATH){
                Point cur = points[x][y];
                int untravelled = 0;
                for(Edge edge: cur.edges) if(edge!=null && !edge.walked) untravelled++;
                if(x%2!=1 || y%2!=1){
                    if(untravelled>1){
                        if(cur.down()==null && hasBeenWalked(cur.right())){
                            if(canBeDeleted(cur.up())) deletePath(cur.up());
                        }
                        if(cur.down()==null && hasBeenWalked(cur.left())){
                            if(x%2==0 && y%2==1 && canBeDeleted(cur.right())) deletePath(cur.right());
                            else if(cur.right()!=null && canBeDeleted(cur.up())) deletePath(cur.up());
                        }
                        if(cur.left()==null && hasBeenWalked(cur.up())){
                            if(canBeDeleted(cur.right())) deletePath(cur.right());
                        }
                        if(cur.left()==null && hasBeenWalked(cur.down())){
                            if(x%2==1 && y%2==0 && canBeDeleted(cur.up())) deletePath(cur.up());
                            else if (cur.up()!=null && canBeDeleted(cur.right())) deletePath(cur.right());
                        }
                    }
                } else {
                    if(!hasBeenWalked(cur.left())){
                        if(x>1 && available[x-2][y]){
                            if(untravelled>1){
                                available[x-2][y] = false;
                                deletePath(cur.up());
                            }
                        } else if(cur.up()!=null){
                            if(canBeDeleted(cur.left())) deletePath(cur.left());
                            if(canBeDeleted(points[x][y+1].left())) deletePath(points[x][y+1].left());
                        }
                    }
                    if(!hasBeenWalked(cur.down())){
                        if(y>1 && available[x][y-2]){
                            if(untravelled>1){
                                available[x][y-2] = false;
                                deletePath(cur.right());
                            }
                        } else if(cur.right()!=null){
                            if(canBeDeleted(cur.down())) deletePath(cur.down());
                            if(canBeDeleted(points[x+1][y].down())) deletePath(points[x+1][y].down());
                        }
                    }
                }
            }
            if(strategy == Strategy.DOUBLE_PATH || strategy == Strategy.EXTREME_DOUBLE_PATH
                    || strategy == Strategy.PERFECT_DOUBLE_PATH){
                if(x==width-2 && y==height-1 && points[width-1][height-1].down()!=null){
                    deletePath(points[width-1][height-1].left());
                }
                if(x==width-1 && y==height-2 && points[width-1][height-1].left()!=null){
                    deletePath(points[width-1][height-1].down());
                }
            } else if(strategy == Strategy.ISLAND){
                for(EdgeList edgeList: edgeLists){
                    boolean deleted = false;
                    for(Edge edge: edgeList.edges){
                        if(edge.start.x == x && edge.start.y == y){
                            if(!hasBeenWalked(edge)){
                                deletePath(edge);
                                edgeList.edges.remove(edge);
                                if(edgeList.edges.size() == 1){
                                    edgeLists.remove(edgeList);
                                }
                                deleted = true;
                                break;
                            }
                        }
                    }
                    if(deleted) break;
                }
            }
            if(animate)printPath();
        }
    }

    public boolean hasBeenWalked(Edge edge){
        if(edge == null) return false;
        return edge.walked;
    }

    public boolean canBeDeleted(Edge edge){
        if(edge == null) return false;
        return !edge.walked;
    }

    public List<Edge> getAdjacentUntravelledEdges(){
        List<Edge> result = new ArrayList<Edge>();
        for(Edge edge: points[x][y].edges){
            if(edge!=null && !hasBeenWalked(edge)) result.add(edge); 
        }
        return result;
    }

    public void printPath(){
        StringBuilder builder = new StringBuilder();
        for(int y=height-1; y>=0; y--){
            for(int x=0; x<width; x++){
                Point point = points[x][y];
                if(this.x==x && this.y==y){
                    if(point.up()!=null) builder.append('?');
                    else builder.append('.');
                } else {
                    if(point.up()!=null) builder.append('|');
                    else builder.append(' ');
                }
                if(point.right()!=null) builder.append('_');
                else builder.append(' ');
            }
            builder.append('\n');
        }
        System.out.print(builder.toString());
    }

    public boolean walk(){
        ArrayList<Edge> possibleMoves = new ArrayList<Edge>();
        Point cur = points[x][y];
        for(Edge edge: cur.edges){
            if(edge!=null) possibleMoves.add(edge);
        }
        int random = (int)(Math.random()*possibleMoves.size());
        Edge move = possibleMoves.get(random);
        move.walked = true;
        if(move.start == cur){
            x = move.end.x;
            y = move.end.y;
        } else {
            x = move.start.x;
            y = move.start.y;
        }
        stepCount++;
        if(x==dX && y == dY){
            return true;
        } else {
            return false;
        }
    }

    public boolean isSolvable(){
        TreeSet<Point> reachable = new TreeSet<Point>();
        Queue<Point> next = new LinkedList<Point>();
        next.offer(points[x][y]);
        reachable.add(points[x][y]);
        while(next.size()>0){
            Point cur = next.poll();
            ArrayList<Point> neighbors = new ArrayList<Point>();
            if(cur.up()!=null) neighbors.add(cur.up().end);
            if(cur.right()!=null) neighbors.add(cur.right().end);
            if(cur.down()!=null) neighbors.add(cur.down().start);
            if(cur.left()!=null) neighbors.add(cur.left().start);
            for(Point neighbor: neighbors){
                if(!reachable.contains(neighbor)){
                    if(neighbor == points[dX][dY]) return true;
                    reachable.add(neighbor);
                    next.offer(neighbor);
                }
            }
        }
        return false;
    }

    public boolean deletePath(Edge toDelete){
        if(toDelete == null) return true;
//      if(toDelete.walked){
//          System.err.println("Edge already travelled!");
//          return false;
//      }
        int startIdx = toDelete.getStartIdx();
        int endIdx = toDelete.getEndIdx();
        toDelete.start.edges[startIdx] = null;
        toDelete.end.edges[endIdx] = null;
//      if(!isSolvable()){
//          toDelete.start.edges[startIdx] = toDelete;
//          toDelete.end.edges[endIdx] = toDelete;
//          System.err.println("Invalid deletion!");
//          return false;
//      }
        return true;
    }

    static class EdgeList{
        List<Edge> edges;

        public EdgeList(Edge... edges){
            this.edges = new ArrayList<Edge>();
            this.edges.addAll(Arrays.asList(edges));
        }
    }

    static class Edge implements Comparable<Edge>{
        Point start, end;
        boolean walked;

        public Edge(Point start, Point end){
            walked = false;
            this.start = start;
            this.end = end;
            this.start.edges[getStartIdx()] = this;
            this.end.edges[getEndIdx()] = this;
            if(start.compareTo(end)>0){
                Point tmp = end;
                end = start;
                start = tmp;
            }
        }

        public Edge(int x1, int y1, int x2, int y2){
            this(new Point(x1,y1), new Point(x2,y2));
        }

        public boolean exists(){
            return start.edges[getStartIdx()] != null || end.edges[getEndIdx()] != null;
        }

        public int getStartIdx(){
            if(start.x == end.x){
                if(start.y < end.y) return 0;
                else return 2;
            } else {
                if(start.x < end.x) return 1;
                else return 3;
            }
        }

        public int getEndIdx(){
            if(start.x == end.x){
                if(start.y < end.y) return 2;
                else return 0;
            } else {
                if(start.x < end.x) return 3;
                else return 1;
            }
        }

        public boolean isVertical(){
            return start.x==end.x;
        }

        @Override
        public int compareTo(Edge o) {
            int result = start.compareTo(o.start);
            if(result!=0) return result;
            return end.compareTo(o.end);
        }
    }

    static class Point implements Comparable<Point>{
        int x,y;
        Edge[] edges;

        public Point(int x, int y){
            this.x = x;
            this.y = y;
            edges = new Edge[4];
        }

        public Edge up(){ return edges[0]; }
        public Edge right(){ return edges[1]; }
        public Edge down(){ return edges[2]; }
        public Edge left(){ return edges[3]; }

        public int compareTo(Point o){
            int result = Integer.compare(x, o.x);
            if(result!=0) return result;
            result = Integer.compare(y, o.y);
            if(result!=0) return result;
            return 0;
        }
    }
}

यह बहुत प्रभावशाली है। इसे चलाने में कितना समय लगता है? यदि जीतने वाली प्रविष्टियां इस नज़दीक रहती हैं, तो हमें यह देखने के लिए रन की संख्या बढ़ानी होगी कि क्या हम उन्हें अलग कर सकते हैं।

1
स्निपेट में समय पहले से ही शामिल है। 1000 रन के लिए 400 के आसपास। यह प्रत्येक पथ विलोपन पर सॉल्वेबिलिटी चेक सहित है। मैं 1000 रन के लिए 170 के आसपास है कि निकाल सकते हैं। इसलिए मैं लगभग एक घंटे में 20k रन कर सकता हूं।
9

वास्तव में आगे अनुकूलन मैं 3.5 घंटे में 100k चलाने में सक्षम हो सकता है।
9

मेरा स्कोर 100k रन के साथ है और इसमें 10 मिनट का समय लगता है। @ लचीली डबल पाथ भूलभुलैया पर बहुत अच्छा। मुझे पता है कि एक और भी बेहतर कैसे बनाया जाए, लेकिन अभी इसे लागू करने का धैर्य नहीं है।
स्पर

2
लागू किए गए सममित समाधान को देखकर प्रसन्नता हुई। मुझे इस समाधान को बेहतर बनाने के लिए अभी तक एक और विचार मिला है, और इस बार मुझे लगता है कि मैं इसे स्वयं लागू कर सकता हूं :)
शुक्राणु 15'14

10

227934 (20x20)

मेरा तीसरा प्रयास। निकास के लिए दो रास्तों के साथ @stokastic के समान सामान्य दृष्टिकोण का उपयोग करता है। जब वॉकर एक रास्ते के अंत तक पहुँचता है, तो वह बंद हो जाता है, जिससे उसे बाहर निकलने के लिए दूसरे रास्ते के अंत में वापस जाने की आवश्यकता होती है। मेरा सुधार पथों को उत्पन्न करने के लिए है क्योंकि वॉकर आगे बढ़ता है, ताकि जो भी वह आगे की प्रक्रिया के पहले आधे रास्ते में आगे बढ़ रहा है वह दूसरे मार्ग की तुलना में अधिक लंबा हो।

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <iostream>

#define DEBUG 0
#define ROUNDS 10000

#define Y 20
#define X 20
#define H (Y*2+1)
#define W (X*2+1)

int maze[H][W];
int scores[ROUNDS];

int x, y;

void print_maze(){
    char line[W+2];
    line[W+1]=0;
    for(int row=0;row<H;row++) {
        for(int col=0;col<W;col++) {
            switch(maze[row][col]) {
                case 0:
                    line[col]=' ';
                    break;
                case 1:
                    line[col]=row%2?'-':'|';
                    break;
                case 8:
                    line[col]=(row==y*2+1&&col==x*2+1)?'@':'?';
                    break;
                case 9:
                    line[col]=(row==y*2+1&&col==x*2+1)?'@':'*';
                    break;
            }
        }
        line[W]='\n';
        printf("%s",line);
    }
    printf("%d %d\n",y,x);
}

int main(){
    srand (time(NULL));
    long long total_turns = 0;
    for(int round=0;round<ROUNDS;round++) {
        for (int r=0;r<H;r++) {
            for (int c=0;c<W;c++) {
                maze[r][c]=0;
            }
        }
        maze[1][1]=9;
        maze[1][2]=1;
        maze[2][1]=1;
        maze[1][3]=8;
        maze[3][1]=8;
        int progress_l = 0;
        int progress_r = 0;
        int side = 0;
        int closed_exit = 0;
        x=0;
        y=0;
        if (DEBUG) print_maze();
        long long turn = 0;
        int in = 0;
        while (x!=X-1||y!=Y-1) {
            turn++;
            int r = y*2+1;
            int c = x*2+1;
            int dx=0, dy=0;
            if (DEBUG) {
                std::cin>>in;
                switch(in) {
                    case 0:
                        dy=-1; dx=0; break;
                    case 1:
                        dy=0; dx=1; break;
                    case 2:
                        dy=1; dx=0; break;
                    case 3:
                        dy=0; dx=-1; break;
                    default:
                        dy=0; dx=0; break;
                }
            } else {
                int exits = maze[r-1][c] + maze[r][c+1] + maze[r+1][c] + maze[r][c-1];
                int exit_choice = -1;
                do {
                    if (rand()%exits == 0) {
                        exit_choice = exits;
                        break;
                    } else {
                        exits--;
                    }
                }while(exits);

                --exits;

                if (maze[r-1][c]&&!dx&&!dy) {
                    if (exits) {
                        --exits;
                    } else {
                        dy = -1;
                        dx = 0;
                    }
                }
                if (maze[r][c+1]&&!dx&&!dy) {
                    if (exits) {
                        --exits;
                    } else {
                        dy = 0;
                        dx = 1;
                    }
                }
                if (maze[r+1][c]&&!dx&&!dy) {
                    if (exits) {
                        --exits;
                    } else {
                        dy = 1;
                        dx = 0;
                    }
                }
                if (maze[r][c-1]&&!dx&&!dy) {
                    if (exits) {
                        --exits;
                    } else {
                        dy = 0;
                        dx = -1;
                    }
                }
            }

            x+=dx;
            y+=dy;

            if(x==X-1 && y==Y-1) continue;

            if (x==0&&y==1) side=-1;
            if (x==1&&y==0) side=1;
            if (maze[y*2+1][x*2+1]==8) { // room needs another exit, maybe
                if (side==-1) { // left half of maze
                    if (y==1) { // top of a column
                        if (x%2) { // going up, turn right
                            maze[y*2+1][x*2+2]=1;
                            maze[y*2+1][x*2+3]=8;
                        } else { // going right, turn down
                            maze[y*2+2][x*2+1]=1;
                            maze[y*2+3][x*2+1]=8;
                        }
                    } else if (y==Y-1) { // bottom of a column
                        if (x%2 && x<(X-progress_r-3)) { // going right, turn up if there's room
                            maze[y*2+0][x*2+1]=1;
                            maze[y*2-1][x*2+1]=8;
                            progress_l=x+1;
                        } else { // going down or exiting, go right
                            if (x!=X-2 or closed_exit==1) {
                                maze[y*2+1][x*2+2]=1;
                                maze[y*2+1][x*2+3]=8;
                            } else {
                                closed_exit = -1;
                            }
                        }
                    } else { // in a column
                        if (maze[y*2+0][x*2+1]) { // going down
                            maze[y*2+2][x*2+1]=1;
                            maze[y*2+3][x*2+1]=8;
                        } else { // going up
                            maze[y*2+0][x*2+1]=1;
                            maze[y*2-1][x*2+1]=8;
                        }
                    }
                } else { // right half of maze
                    if (y==0) { // top row
                        if (x<X-1) { // go right
                            maze[y*2+1][x*2+2]=1;
                            maze[y*2+1][x*2+3]=8;
                        } else { // go down
                            maze[y*2+2][x*2+1]=1;
                            maze[y*2+3][x*2+1]=8;
                        }
                    } else if (y==Y-2) { // heading right to the exit
                        if (x<X-1) { // go right
                            maze[y*2+1][x*2+2]=1;
                            maze[y*2+1][x*2+3]=8;
                        } else { // go down
                            if (x!=X-1 or closed_exit==-1) {
                                maze[y*2+2][x*2+1]=1;
                                maze[y*2+3][x*2+1]=8;
                            } else {
                                closed_exit = 1;
                            }
                        }
                    } else if (y==Y-3) { // bottom of a column
                        if (x>progress_l+1) { // do we have room for another column?
                            if (!(x%2)&&y>1) { // going left, turn up
                                maze[y*2+0][x*2+1]=1;
                                maze[y*2-1][x*2+1]=8;
                            } else { // going down, turn left
                                maze[y*2+1][x*2+0]=1;
                                maze[y*2+1][x*2-1]=8;
                                progress_r=X-x-1;
                            }
                        } else { // abort, move down to escape row
                            maze[y*2+2][x*2+1]=1;
                            maze[y*2+3][x*2+1]=8;
                        }
                    } else if (y==1) { // top of a column
                        if (!(x%2)) { // going up, turn left
                            maze[y*2+1][x*2+0]=1;
                            maze[y*2+1][x*2-1]=8;
                        } else { // going left, turn down
                            maze[y*2+2][x*2+1]=1;
                            maze[y*2+3][x*2+1]=8;
                        }
                    } else { // in a column
                        if (maze[y*2+0][x*2+1]) { // going down
                            maze[y*2+2][x*2+1]=1;
                            maze[y*2+3][x*2+1]=8;
                        } else { // going up
                            maze[y*2+0][x*2+1]=1;
                            maze[y*2-1][x*2+1]=8;
                        }
                    }

                }
                maze[y*2+1][x*2+1]=9;
            }

            if (DEBUG) print_maze();
        }
        // print_maze();
        printf("turns:%lld\n",turn);
        scores[round] = turn;
        total_turns += turn;
    }
    printf("%d rounds in a %d*%d maze\n",ROUNDS,X,Y);
    long long avg = total_turns/ROUNDS;
    printf("average: % 10lld\n",avg);
    long long var = 0;
    for(int r=0;r<ROUNDS;r++){
        var += (scores[r]-avg)*(scores[r]-avg);
    }
    var/=ROUNDS;
    // printf("variance: %lld\n",var);
    int stddev=sqrt(var);
    printf("stddev:  % 10d\n",stddev);

}

उत्पादन (समय के साथ):

...
turns:194750
turns:506468
turns:129684
turns:200712
turns:158664
turns:156550
turns:311440
turns:137900
turns:86948
turns:107134
turns:81806
turns:310274
100000 rounds in a 20*20 maze
average:     227934
stddev:      138349
real    10m54.797s
...

मेरे चक्रव्यूह का उदाहरण, पथ के लगभग बराबर लंबाई के साथ, बाहर निकलने (बाएं दाएँ) से कटे हुए / निचले रास्ते को दिखाते हुए:

  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
 |  _   _   _   _   _   _   _   _   _  |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | | | | | | | | | | |
 | | | | | | | | | | |_| |_| |_| |_| |_|
 | | | | | | | | | |_ _ _ _ _ _ _ _ _ _
 |_| |_| |_| |_| |_ _ _ _ _ _ _ _ _ _  !

पुनश्च: मैं इस एल्गोरिथ्म के लिए एक बहुत ही मामूली सुधार के बारे में जानता हूं जिसमें दो रास्तों के लिए एक अलग आकार बनाने के लिए अधिक चतुर कोड की आवश्यकता होती है, लगातार ऊंचाई zig zags के बजाय सीढ़ियां।


रंग मुझे प्रभावित करता है। आपके पास मेरा वोट है सर!
स्टोकैस्टिक

1
यह बहुत प्रभावशाली है। याद है जब हम सिर्फ ड्रंक के चेहरे पर आकर्षित होते हैं?
डेनिस

अपने ग्राफ को समझ पाना काफी कठिन है, शायद आप अपने ग्राफ प्रिंटिंग को खान के समान बदल सकते हैं?
बजे

1
@ अन्याय आपकी इच्छा मेरी आज्ञा है
Sparr

1
@ अन्याय मुझे मिल गया है यह कागज पर निकाला गया है। बस तर्क लिखने की जरूरत है। अगर मैं इसे एक जोड़े में और अधिक दिनों में नहीं करवाता हूं, तो मैं आपको स्केच दूंगा? :)
१arr

6

98x98 के लिए 135,488,307.9

20x20 के लिए 199094.3

मैंने एक समाधान लागू किया है जो खत्म करने के लिए दो रास्ते बनाता है, और शराबी के पहुंचने के बाद उनमें से एक को बिल्कुल बंद कर देता है। यह एक पथ की लम्बाई का अनुकरण करता है जो शुरू से अंत तक किसी एक पथ की लंबाई 1.5x होगी। 27 रन के बाद मैंने लगभग 135 मिलियन की औसत से रन बनाए। दुर्भाग्य से प्रति मिनट कई मिनट लगते हैं, इसलिए मुझे इसे अगले कुछ घंटों तक चलाना होगा। एक कैविएट - मेरा डबल पाथ जनरेटर केवल तभी काम करता है जब ग्राफ का आकार 4 * n + 2 के रूप में हो, जिसका अर्थ है कि निकटतम 100 मैं 102 या 98 प्राप्त कर सकता हूं। मैं 98 का ​​उपयोग करके परिणाम पोस्ट करने जा रहा हूं, जिसकी मुझे उम्मीद है अभी भी ज़िगज़ैग पथ विधि को पार करने के लिए। मैं बाद में एक बेहतर पाथिंग सिस्टम पर काम करूंगा। वर्तमान में आउटपुट प्रत्येक चलने के बाद (numSteps, currentApret) के रूप में परिणाम देता है।

संपादित करें: अब तय किया गया कोड अब 4 * n + 2 के बजाय ग्राफ़ आकार पर काम करता है जो कि 2 से अधिक हैं।

कोड: (ग्राफ के कछुए ड्राइंग के लिए लाइन 187 पर वॉकर निर्माणकर्ता के लिए 'सही' तर्क जोड़ें)।

import random
import turtle

WIDTH  = 20
HEIGHT = 20
L, U, R, D = 1, 2, 4, 8

def delEdge(grid, x1, y1, x2, y2):

    # check that coordinates are in-bounds
    if not (0 <= x1 < WIDTH):  return False
    if not (0 <= y1 < HEIGHT): return False
    if not (0 <= x2 < WIDTH):  return False
    if not (0 <= y2 < HEIGHT): return False

    # swap order such that x1 <= x2 and y1 <= y2
    if x2 < x1:
        x2 ^= x1
        x1 ^= x2
        x2 ^= x1
    if x2 < x1: print "Swap failure: {}, {}".format(x1, x2)

    if y2 < y1:
        y2 ^= y1
        y1 ^= y2
        y2 ^= y1
    if y2 < y1: print "Swap failure: {}, {}".format(y1, y2)

    # check that only one of the deltas is = 1
    dx = x2 - x1
    dy = y2 - y1

    if dx and dy:       return False
    if not (dx or dy):  return False
    if dx > 1:          return False
    if dy > 1:          return False

    #print "<{}, {}>, <{}, {}>".format(x1, y1, x2, y2)

    if dx > 0:
        try: grid[x1][y1].remove(R)
        except: pass
        try: grid[x2][y2].remove(L)
        except: pass
    if dy > 0:
        try: grid[x1][y1].remove(D)
        except: pass
        try: grid[x2][y2].remove(U)
        except: pass

    return True

def newGrid():

    grid = [[[] for y in xrange(HEIGHT)] for x in xrange(WIDTH)]

    for x in xrange(WIDTH):
        for y in xrange(HEIGHT):
            if x > 0:
                grid[x][y].append(L)
            if x < WIDTH-1:
                grid[x][y].append(R)
            if y > 0:
                grid[x][y].append(U)
            if y < HEIGHT-1:
                grid[x][y].append(D)

    return grid

class walker:

    def __init__(self, grid, mode, draw=False):
        self.x  = 0
        self.y  = 0
        self.dx = WIDTH-1
        self.dy = HEIGHT-1

        self.grid     = grid
        self.mode     = mode
        self.draw     = draw
        self.numSteps = 0

        self.initGrid()

    def initGrid(self):
        if self.mode == 0:
            #pass
            if self.draw: drawGrid(grid)

        elif self.mode == 1:

            for y in xrange(HEIGHT-1):
                if y % 2 == 0:
                    for x in xrange(WIDTH - 1):
                        delEdge(grid, x, y, x, y+1)
                else:
                    for x in xrange(1, WIDTH):
                        delEdge(grid, x, y, x, y+1)
            if self.draw: drawGrid(grid)

        elif self.mode == 2:
            for y in xrange(HEIGHT/2):
                if y % 2 == 0:
                    for x in xrange(1, WIDTH-1):
                        delEdge(grid, x, y, x, y+1)
                else:
                    for x in xrange(2, WIDTH):
                        delEdge(grid, x, y, x, y+1)
            for y in xrange(HEIGHT/2, HEIGHT-1):
                if y%2 == 0:
                    for x in xrange(1, WIDTH-1):
                        delEdge(grid, x, y, x, y+1)
                else:
                    for x in xrange(0, WIDTH-2):
                        delEdge(grid, x, y, x, y+1)
            for y in xrange(1, HEIGHT-1):
                midpoint = HEIGHT/2
                if HEIGHT % 4 == 0: 
                    midpoint = HEIGHT/2 + 1
                if y < midpoint:
                    delEdge(grid, 0, y, 1, y)
                else:
                    delEdge(grid, WIDTH-1, y, WIDTH-2, y)
            if self.draw: drawGrid(grid)

    def walk(self):
        self.numSteps += 1
        choices = grid[self.x][self.y]
        direction = random.choice(choices)
        #print (self.x, self.y), grid[self.x][self.y], direction
        if direction   == L: self.x -= 1
        elif direction == U: self.y -= 1
        elif direction == R: self.x += 1
        elif direction == D: self.y += 1

    def main(self):
        hasBlocked = False
        while (self.x, self.y) != (self.dx, self.dy):
            #print (self.x, self.y), (self.dx, self.dy)
            self.walk()
            if self.mode == 2:
                if not hasBlocked:
                    if (self.x, self.y) == (WIDTH-2, HEIGHT-1):
                        delEdge(self.grid, WIDTH-2, HEIGHT-1, WIDTH-1, HEIGHT-1)
                        hasBlocked = True
                    elif (self.x, self.y) == (WIDTH-1, HEIGHT-2):
                        delEdge(self.grid, WIDTH-1, HEIGHT-1, WIDTH-1, HEIGHT-2)
                        hasBlocked = True

        return self.numSteps

def drawGrid(grid):
    size = 3
    turtle.speed(0)
    turtle.delay(0)
    turtle.ht()
    for x in xrange(WIDTH):
        for y in xrange(HEIGHT):
            dirs = grid[x][y]
            for dir in dirs:
                if dir == L:
                    turtle.pu()
                    turtle.setpos((x*4, y*4))
                    turtle.pd()
                    turtle.setpos(((x-1)*4, y*4))
                elif dir == R:
                    turtle.pu()
                    turtle.setpos((x*4, y*4))
                    turtle.pd()
                    turtle.setpos(((x+1)*4, y*4))
                elif dir == U:
                    turtle.pu()
                    turtle.setpos((x*4, y*4))
                    turtle.pd()
                    turtle.setpos((x*4, (y-1)*4))
                elif dir == D:
                    turtle.pu()
                    turtle.setpos((x*4, y*4))
                    turtle.pd()
                    turtle.setpos((x*4, (y+1)*4))
    turtle.mainloop()

numTrials  = 100
totalSteps = 0.0
i = 0
try:
    while i < numTrials:
        grid = newGrid()

        w = walker(grid, 2)
        steps = w.main()
        totalSteps += steps
        print steps, totalSteps/(i+1)
        i += 1

    print totalSteps / numTrials

except KeyboardInterrupt:
    print totalSteps / i

कच्चा डेटा: (वर्तमान संख्या में, औसत चल रहा है)

358796490 358796490.0
49310430 204053460.0
106969130 171692016.667
71781702 146714438.0
49349086 127241367.6
40874636 112846912.333
487607888 166384194.571
56423642 152639125.5
71077302 143576700.667
101885368 139407567.4
74423642 133499937.818
265170542 144472488.167
59524778 137938048.923
86919630 134293876.143
122462528 133505119.6
69262650 129489965.25
85525556 126903823.529
161165512 128807250.667
263965384 135920836.632
128907594 135570174.5
89535930 133378067.619
97344576 131740181.636
98772132 130306788.174
140769524 130742735.5
198274280 133443997.28
95417374 131981434.846
226667006 135488307.852

मैंने रन समय को तेज बनाने के लिए ग्राफ का आकार 20 से घटाकर 20 कर दिया। मुझे उम्मीद है यह मदद करेगा।

आप वर्तमान में जीत रहे हैं :)

क्या 1000 रन से अधिक आपका 20 स्कोर है?

@ लिम्बिक हाँ यह है।
स्टोकैस्टिक

1
@ डेनिस औ गर्भनिरोधक :)
23

6

4-पथ दृष्टिकोण, 213k

एक-पथ दृष्टिकोण है

S से E तक सीधी रेखा

और औसत का स्कोर करता है N^2

दो-पथ दृष्टिकोण है

एक दूसरे के विपरीत एस और ई के साथ लूप

लेकिन फिर शराबी पहली बार अंत बिंदु की पहुंच के भीतर हो जाता है, यह कट जाता है:

लूप को S से E तक एक घुमावदार रेखा देने के लिए काटा जाता है

यह औसत स्कोर करता है (N/2)^2 + N^2

चार-पथ दृष्टिकोण दो कटौती का उपयोग करता है:

नेस्टेड छोरों, दो कांटों में शामिल हो गए, ई के दोनों ओर ई में से एक कांटे को काटें दूसरी तरफ, गैर-ई की तरफ कांटा काट लें।  यह एक मार्ग को छोड़ देता है

मान लें कि बाहरी लूप लंबाई का है xNऔर लंबाई का आंतरिक लूप (1-x)N। सरलता के लिए, मैं सामान्य करूँगा N=1

शुरू से लेकर पहले कट स्कोर तक औसतन (x/2)^2। पहली कट से दूसरी कट तक लंबाई के दो विकल्प हैं xऔर 1-x; यह औसत देता है (1-x)x^2 + x(1-x)^2 = x-x^2। अंत में शेष मार्ग देता है 1। तो कुल स्कोर हैN^2 (1 + x - 3/4 x^2)

मैंने शुरू में यह मान लिया था कि प्रत्येक चरण पर समान लंबाई के उपलब्ध पथों को रखना इष्टतम होगा, इसलिए मेरे प्रारंभिक दृष्टिकोण ने x = 1/2स्कोर दिया 1.3125 N^2। लेकिन उपरोक्त विश्लेषण करने के बाद यह पता चला कि x = 2/3स्कोर के साथ इष्टतम विभाजन दिया गया है 1.3333 N^2

1000 walks with average 210505.738 in 202753ms

1000 walks with average 212704.626 in 205191ms

कोड के साथ

import java.awt.Point;
import java.util.*;

// http://codegolf.stackexchange.com/q/37484/194
public class RandomWalker {
    private static final int SIZE = 19;
    private static final Point dest = new Point(SIZE, SIZE);

    private final Random rnd = new Random();
    private Point p = new Point(0, 0);
    private int step = 0;
    private Set<Set<Point>> edges;
    private Map<Set<Point>, String> cuttableEdgeNames;
    private Set<String> cutSequences;
    private String cutSequence = "";

    public static void main(String[] args) {
        long start = System.nanoTime();
        long total = 0;
        int walks = 0;
        while (walks < 1000 && total < 1L << 40) {
            RandomWalker rw = new RandomWalker();
            total += rw.walk();
            walks++;
        }

        long timeTaken = System.nanoTime() - start;
        System.out.println(walks + " walks with average " + total / (double)walks + " in " + (timeTaken / 1000000) + "ms");
    }

    RandomWalker() {
        loadMaze(
            "+-+ +-+ +-+ +-+ +-+ +-+ +-+-+-+-+-+-+-+",
            "| | | | | | | | | | | | |             |",
            "+ + + + + + + + + + + + + +-+ +-+ +-+ +",
            "| | | | | | | | | | | | | | | | | | | |",
            "+ + + + + + + + + + + + + + + + + + + +",
            "| | | | | | | | | | | | | | | | | | | |",
            "+ + + + + + + + + + + +-+ + + + + + + +",
            "| | | | | | | | | | |     | | | | | | |",
            "+ + + + + + + + + + + +-+-+ + + + + + +",
            "| | | | | | | | | | | |     | | | | | |",
            "+ + + + + + + + + + + + +-+ + + + + + +",
            "| | | | | | | | | | | | | | | | | | | |",
            "+ + + + + + + + + + + + + + + + + + + +",
            "| | | | | | | | | | | | | | | | | | | |",
            "+ + + + + + + + + + + + + + + + + + + +",
            "| | | | | | | | | | | | | | | | | | | |",
            "+ + + + + + + + + + + + + + + + + + + +",
            "| | | | | | | | | | | | | | | | | | | |",
            "+ +-+ +-+ +-+ +-+ +-+ + + + + + + + + +",
            "|                     | | | | | | | | |",
            "+ +-+ +-+ +-+ +-+ +-+ + + + + + + + + +",
            "| | | | | | | | | | | | | | | | | | | |",
            "+ + + + + + + + + + + + + + + + + + + +",
            "| | | | | | | | | | | | | | | | | | | |",
            "+ + + + + + + + + + + + + + + + + + + +",
            "| | | | | | | | | | | | | | | | | | | |",
            "+ + + + + + + + + + + + + + + + + + + +",
            "| | | | | | | | | | | | | | | | | | | |",
            "+ + + + + + + + + + + + + + + + + + + +",
            "| | | | | | | | | | | | | | | | | | | |",
            "+ + + + + + + + + + + +-+ + + + + + + +",
            "| | | | | | | | | | |     | | | | | | |",
            "+ + + + + + + + + + + +-+ + + + + + + +",
            "| | | | | | | | | | | | | | | | | | | d",
            "+ + + + + + + + + + + + + + +-+ +-+ +c+",
            "| | | | | | | | | | | | | |           |",
            "+ + + + + + + + + + + + + +-+-+-+-+-+ +",
            "| | | | | | | | | | | | |           f b",
            "+-+ +-+ +-+ +-+ +-+ +-+ +-+-+-+-+-+e+a+"
        );
        cutSequences = new HashSet<String>();
        cutSequences.add("ac");
        cutSequences.add("ad");
        cutSequences.add("be");
        cutSequences.add("bf");
    }

    private void loadMaze(String... row) {
        edges = new HashSet<Set<Point>>();
        cuttableEdgeNames = new HashMap<Set<Point>, String>();

        // Horizontal edges
        for (int y = 0; y <= SIZE; y++) {
            for (int x0 = 0; x0 < SIZE; x0++) {
                char ch = row[y * 2].charAt(x0 * 2 + 1);
                if (ch == ' ') continue;
                Set<Point> edge = new HashSet<Point>();
                edge.add(new Point(x0, y));
                edge.add(new Point(x0 + 1, y));
                edges.add(edge);
                if (ch != '-') cuttableEdgeNames.put(edge, "" + ch);
            }
        }

        // Vertical edges
        for (int y0 = 0; y0 < SIZE; y0++) {
            for (int x = 0; x <= SIZE; x++) {
                char ch = row[y0 * 2 + 1].charAt(x * 2);
                if (ch == ' ') continue;
                Set<Point> edge = new HashSet<Point>();
                edge.add(new Point(x, y0));
                edge.add(new Point(x, y0 + 1));
                edges.add(edge);
                if (ch != '|') cuttableEdgeNames.put(edge, "" + ch);
            }
        }
    }

    int walk() {
        while (!p.equals(dest)) {
            List<Point> neighbours = neighbours(p);
            int idx = rnd.nextInt(neighbours.size());
            p = neighbours.get(idx);
            step++;
        }

        return step;
    }

    List<Point> neighbours(Point p) {
        List<Point> rv = new ArrayList<Point>();
        if (p.x > 0) handlePossibleNeighbour(rv, p, new Point(p.x - 1, p.y));
        if (p.x < SIZE) handlePossibleNeighbour(rv, p, new Point(p.x + 1, p.y));
        if (p.y > 0) handlePossibleNeighbour(rv, p, new Point(p.x, p.y - 1));
        if (p.y < SIZE) handlePossibleNeighbour(rv, p, new Point(p.x, p.y + 1));
        return rv;
    }

    private void handlePossibleNeighbour(List<Point> neighbours, Point p1, Point p2) {
        if (edgeExists(p1, p2)) neighbours.add(p2);
    }

    private boolean edgeExists(Point p1, Point p2) {
        Set<Point> edge = new HashSet<Point>();
        edge.add(p1);
        edge.add(p2);

        // Is it cuttable?
        String id = cuttableEdgeNames.get(edge);
        if (id != null) {
            String prefix = cutSequence + id;
            for (String seq : cutSequences) {
                if (seq.startsWith(prefix)) {
                    // Cut it
                    cutSequence = prefix;
                    edges.remove(edge);
                    return false;
                }
            }
        }

        return edges.contains(edge);
    }
}

आह, मैं देख रहा हूं, इसीलिए मेरा द्वीप दृष्टिकोण काम नहीं करता है, मैंने पथ की लंबाई को संतुलित नहीं किया है। बस मेरी समझ को स्पष्ट करने के fलिए c, आपके कोड में से लंबाई के बारे में है N/2, इसके माध्यम से e(और d) या नहीं, है ना?
justhalf

लंबाई N / 2 के बजाय y पथ की लंबाई N कैसे है?
स्पर

@ अन्याय, हाँ। 400 कोने हैं, इसलिए 401 किनारे हैं (एक कट के बाद ग्राफ एक हैमिल्टन चक्र है); दो बाहरी पथ प्रत्येक के 100 किनारे हैं, और आंतरिक लूप इसलिए 101 किनारे हैं।
पीटर टेलर

समझ गया। दो अवलोकन: ए) बड़े mazes अधिक से अधिक 2 ^ n पथ से लाभ होगा। b) यदि आप अपने पथ की लंबाई को गतिशील बनाते हैं, तो आप वर्तमान नेताओं को गतिशील दो-पथ समाधानों से हरा देंगे (स्वयं और @ अन्याय)
20

@ शेपर: यह N^2 , नहीं है 2^N। और हाँ, इस गतिशील बनाने से यह सबसे अच्छा होगा, चुनौती यह है कि चार-पथ की संपत्ति रखते हुए इसे गतिशील कैसे बनाया जाए। @PeterTaylor: अच्छी छवियां!
जस्टफुल

5

मैंने लगभग हर kपंक्तियों में ग्रिड को पूरी तरह से स्लाइड करने के साथ प्रयोग किया । यह प्रभावी रूप से इसे kबाय N * N/kग्रिड पर एक यादृच्छिक चलने के समान कुछ में परिवर्तित करता है । सबसे प्रभावी विकल्प हर पंक्ति को टुकड़ा करना है ताकि हम शराबी को ज़िगज़ैग के लिए मजबूर कर सकें।

20x20 केस के लिए ( SIZE=19) मेरे पास है

time java RandomWalker 
1000 walks with average 148577.604

real    0m14.076s
user    0m13.713s
sys     0m0.360s

कोड के साथ

import java.awt.Point;
import java.util.*;

// http://codegolf.stackexchange.com/q/37484/194
// This handles a simpler problem where the grid is mutilated before the drunkard starts to walk.
public class RandomWalker {
    private static final int SIZE = 19;
    private final Random rnd = new Random();

    public static void main(String[] args) {
        RandomWalker rw = new RandomWalker();
        long total = 0;
        int walks = 0;
        while (walks < 1000 && total < 1L << 40) {
            total += rw.walk();
            walks++;
        }

        System.out.println(walks + " walks with average " + total / (double)walks);
    }

    int walk() {
        Point dest = new Point(SIZE, SIZE);
        Point p = new Point(0, 0);
        int step = 0;

        while (!p.equals(dest)) {
            List<Point> neighbours = neighbours(p);
            int idx = rnd.nextInt(neighbours.size());
            p = neighbours.get(idx);
            step++;
        }

        return step;
    }

    List<Point> neighbours(Point p) {
        List<Point> rv = new ArrayList<Point>();
        if (p.x > 0) handlePossibleNeighbour(rv, p, new Point(p.x - 1, p.y));
        if (p.x < SIZE) handlePossibleNeighbour(rv, p, new Point(p.x + 1, p.y));
        if (p.y > 0) handlePossibleNeighbour(rv, p, new Point(p.x, p.y - 1));
        if (p.y < SIZE) handlePossibleNeighbour(rv, p, new Point(p.x, p.y + 1));
        return rv;
    }

    private void handlePossibleNeighbour(List<Point> neighbours, Point p1, Point p2) {
        if (edgeExists(p1, p2)) neighbours.add(p2);
    }

    private boolean edgeExists(Point p1, Point p2) {
        return p1.x != p2.x || p1.x == SIZE * (Math.max(p1.y, p2.y) & 1);
    }
}

क्या मैं यह सोचने में सही हूं कि आपके समाधान में चलने से पहले सभी एज डिलीट हो जाते हैं?

@ लिम्बिक, हाँ। मुझे लगा कि शीर्ष पर टिप्पणी से यह स्पष्ट हो जाएगा।
पीटर टेलर

यह करता है, धन्यवाद। मुझे आश्चर्य है कि टहलने के दौरान किनारों को हटाकर आप कितना अंतर कर सकते हैं।

जिज्ञासा से बाहर, इसे चलाने में कितना समय लगता है (पूरी तरह से और प्रति रन)?
स्टोकैस्टिक

@stokastic, रन के बारे में 3 सेकंड।
पीटर टेलर

3

उन लोगों के लिए जो पहिया को सुदृढ़ नहीं करना चाहते हैं

चिंता मत करो! मैं इसे तुम्हारे लिए प्रबल कर दूँगा :)

यह जावा में है।

मैंने एक वॉकर वर्ग बनाया जो बेतरतीब ढंग से चलने से संबंधित है। इसमें यह निर्धारित करने के लिए एक सहायक विधि भी शामिल है कि क्या कोई चाल वैध है (यदि यह पहले ही चल चुका है)।

मैं मान रहा हूं कि आप सभी लोग स्मार्ट लोगों को पता लगा सकते हैं कि कंस्ट्रक्टर के लिए रैंडम नंबर डालने के लिए, मैंने इसे आपके ऊपर छोड़ दिया ताकि आप कुछ मामलों का परीक्षण कर सकें। इसके अलावा, बस कॉल वॉक () फ़ंक्शन टू (आपने अनुमान लगाया!) ड्रंकर्ड वॉक (बेतरतीब ढंग से) करें।

मैं canComeHome () कुछ अन्य समय पर कार्य करूंगा। अधिमानतः मैं ऐसा करने का सबसे अच्छा तरीका देखता हूं।

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.TreeSet;

public class Walker {
    int width,height;
    int x,y; //walker's position (does anyone else keep thinking about zombies?!?)
    int dX,dY; //destination
    TreeSet<Edge> pathsNoLongerAvailable = new TreeSet<Edge>();
    TreeSet<Edge> previouslyTraveled = new TreeSet<Edge>();
    int stepCount = 0;

    public static void main(String[]args){
        int side = 10;
        Walker walker = null;
        int total = 0;
        double count = 1000;
        for(int i=0; i<count; i++){
            walker = new Walker(0,0,side,side,side-1,side-1);
            total += walker.stepCount;
            System.out.println("Iteration "+i+": "+walker.stepCount);
        }
        System.out.printf("Average: %.3f\n", total/count);
        walker.printPath();
    }

    public Walker(int startingX,int startingY, int Width, int Height, int destinationX, int destinationY){
        width = Width;
        height = Height;
        dX = destinationX;
        dY = destinationY;
        x=startingX;
        y=startingY;
        while(!walk()){
            // Do something
        }
    }

    public void printPath(){
        for(int i=0; i<width-1; i++){
            if(!pathsNoLongerAvailable.contains(new Edge(i,height-1,i+1,height-1))){
                System.out.print(" _");
            } else {
                System.out.print("  ");
            }
        }
        System.out.println();
        for(int i=height-2; i>=0; i--){
            for(int j=0; j<2*width-1; j++){
                if(j%2==0){
                    if(!pathsNoLongerAvailable.contains(new Edge(j/2,i,j/2,i+1))){
                        System.out.print("|");
                    } else {
                        System.out.print(" ");
                    }
                } else {
                    if(!pathsNoLongerAvailable.contains(new Edge(j/2,i,j/2+1,i))){
                        System.out.print("_");
                    } else {
                        System.out.print(" ");
                    }
                }
            }
            System.out.println();
        }
    }

    public boolean walk(){
        ArrayList<int[]> possibleMoves = new ArrayList<int[]>();
        if(x!=0 && !pathsNoLongerAvailable.contains(new Edge(x,y,x-1,y))){
            possibleMoves.add(new int[]{-1,0});
        }
        if(x!=width-1 && !pathsNoLongerAvailable.contains(new Edge(x,y,x+1,y))){
            possibleMoves.add(new int[]{1,0});
        }
        if(y!=0 && !pathsNoLongerAvailable.contains(new Edge(x,y,x,y-1))){
            possibleMoves.add(new int[]{0,-1});
        }
        if(y!=height-1 && !pathsNoLongerAvailable.contains(new Edge(x,y,x,y+1))){
            possibleMoves.add(new int[]{0,1});
        }
        int random = (int)(Math.random()*possibleMoves.size());
        int[] move = possibleMoves.get(random);
        previouslyTraveled.add(new Edge(x,y,x+move[0],y+move[1]));
        x+=move[0];
        y+=move[1];
        stepCount++;
        if(x==dX && y == dY){
            return true;
        } else {
            return false;
        }
    }

    public boolean isSolvable(){
        TreeSet<Point> reachable = new TreeSet<Point>();
        Queue<Point> next = new LinkedList<Point>();
        next.offer(new Point(x,y));
        reachable.add(new Point(x,y));
        while(next.size()>0){
            Point cur = next.poll();
            int x = cur.x;
            int y = cur.y;
            ArrayList<Point> neighbors = new ArrayList<Point>();
            if(x!=0 && !pathsNoLongerAvailable.contains(new Edge(x,y,x-1,y))){
                neighbors.add(new Point(x-1, y));
            }
            if(x!=width-1 && !pathsNoLongerAvailable.contains(new Edge(x,y,x+1,y))){
                neighbors.add(new Point(x+1, y));
            }
            if(y!=0 && !pathsNoLongerAvailable.contains(new Edge(x,y,x,y-1))){
                neighbors.add(new Point(x, y-1));
            }
            if(y!=height-1 && !pathsNoLongerAvailable.contains(new Edge(x,y,x,y+1))){
                neighbors.add(new Point(x, y+1));
            }
            for(Point neighbor: neighbors){
                if(!reachable.contains(neighbor)){
                    if(neighbor.compareTo(new Point(dX, dY))==0){
                        return true;
                    }
                    reachable.add(neighbor);
                    next.offer(neighbor);
                }
            }
        }
        return false;
    }

    public boolean hasBeenWalked(int x1, int y1, int x2, int y2){
        return previouslyTraveled.contains(new Edge(x1, y1, x2, y2));
    }

    public boolean hasBeenWalked(Edge edge){
        return previouslyTraveled.contains(edge);
    }

    public void deletePath(int startX, int startY, int endX, int endY){
        Edge toAdd = new Edge(startX,startY,endX,endY);
        if(hasBeenWalked(toAdd)){
            System.out.println("Edge already travelled!");
            return;
        }
        pathsNoLongerAvailable.add(toAdd);
        if(!isSolvable()){
            pathsNoLongerAvailable.remove(toAdd);
            System.out.println("Invalid deletion!");
        }
    }

    static class Edge implements Comparable<Edge>{
        Point start, end;

        public Edge(int x1, int y1, int x2, int y2){
            start = new Point(x1, y1);
            end = new Point(x2, y2);
            if(start.compareTo(end)>0){
                Point tmp = end;
                end = start;
                start = tmp;
            }
        }

        @Override
        public int compareTo(Edge o) {
            int result = start.compareTo(o.start);
            if(result!=0) return result;
            return end.compareTo(o.end);
        }
    }

    static class Point implements Comparable<Point>{
        int x,y;
        public Point(int x, int y){
            this.x = x;
            this.y = y;
        }
        public int compareTo(Point o){
            int result = Integer.compare(x, o.x);
            if(result!=0) return result;
            result = Integer.compare(y, o.y);
            if(result!=0) return result;
            return 0;
        }
    }
}

इसमें कुछ बग और विसंगतियां शामिल हैं। previouslyTraveled.add(new int[]{x,y,move[0],move[1]})होना चाहिए x+move[0]और y+move[1]Width-1और Height-1नष्ट कर दिया रास्तों जाँच में, और अक्षमता। मैंने आपका कोड (अतिरिक्त फ़ंक्शन के साथ भूलभुलैया को प्रिंट करने के लिए) संपादित किया है। यदि आपको लगता है कि यह अनुचित है, तो रोलबैक करने के लिए स्वतंत्र महसूस करें।
जस्टफुल

आपका Edgeसही ढंग से लागू नहीं होता है Comparable<Edge>। यदि आप किनारों की तुलना करना चाहते हैं, भले ही आप उन्हें उल्टा करते हैं, तो आपको उलटे और गैर-बराबर मामले में भी ध्यान रखना होगा। ऐसा करने का सबसे आसान तरीका यह होगा कि निर्माणकर्ता को आदेशों को रखने के लिए बदल दिया जाए।
पीटर टेलर

@PeterTaylor: सिर के लिए धन्यवाद। मैंने गैर-बराबर मामले के बारे में थोड़ा सोचा, लेकिन यह समझने के लिए खुद को नहीं समझा कि यह क्यों मायने रखता है। क्या आप जानते हैं कि मैं कार्यान्वयन की आवश्यकता के लिए Comparableकहां देख सकता हूं ?
जस्टफुल

1
docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html कुंजी यह है कि इसे कुल ऑर्डर परिभाषित करने की आवश्यकता है। लेकिन अगर Aऔर Bएक ही किनारे उलट हैं और Cअलग है, तो आप प्राप्त कर सकते हैं A.compareTo(B) == B.compareTo(A) == 0लेकिन A.compareTo(C) < 0और B.compareTo(C) > 0
पीटर टेलर

अभी के बारे में कैसे? मैंने एक और क्लास जोड़ी। और मैंने फ़ंक्शन को यह जांचने के लिए जोड़ा है कि क्या यह canComeHome()
सॉल्वेबल

3

64,281

अपडेट के बाद से ग्रिड को 100x100 से 20x20 (1000 परीक्षण) में बदल दिया गया था। 100x100 (100 परीक्षण) पर स्कोर लगभग 36M था।

हालांकि यह 1D वॉक को हरा नहीं सकता है, मैं एक विचार के साथ खेलना चाहता था जो मेरे पास था।

मूल विचार यह है कि ग्रिड को चौकोर कमरे में विभाजित किया गया है, जिसमें से प्रत्येक के लिए केवल एक ही मार्ग है, जिसमें 'होमवार्ड' है। खुले रास्ते में जो भी नशे में रहता है वह आखिरी पास है , जिसका अर्थ है कि उसे हर संभव निकास का पता लगाना है, केवल सभी के लिए है लेकिन उनमें से एक ने उसके चेहरे पर पटक दिया।

कमरे के आकार के साथ खेलने के बाद, मैं पीटर के समान निष्कर्ष पर आया, इसे छोटा करना बेहतर है। सर्वश्रेष्ठ स्कोर 2 के कमरे के आकार के साथ आते हैं।

Average score over 100 trials: 36051265

कोड मैला है, गड़बड़ मत करो। आप SHOWस्विच पर फ्लिप कर सकते हैं और यह हर SHOW_INTकदम पर पथों की एक छवि दिखाएगा ताकि आप इसे कार्रवाई में देख सकें। एक पूरा रन कुछ इस तरह दिखता है:

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

(यह पिछले 100x100 ग्रिड से छवि है। 20x20 ऐसा ही है, लेकिन, ठीक है, छोटा। नीचे दिए गए कोड को नए आकार / रन के लिए अद्यतन किया गया है।)

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.image.*;
import java.util.*;
import javax.swing.*;

public class DrunkWalk {

    boolean SHOW = false;
    int SHOW_INT = 10;
    int SIZE = 20;
    Random rand = new Random();
    Point pos;
    int[][] edges;
    int[][] wally;
    int[] wallx;
    int roomSize = 2;
    JFrame frame;
    final BufferedImage img;

    public static void main(String[] args){
        long total=0,runs=1000;
        for(int i=0;i<runs;i++){
            int steps = new DrunkWalk().run();
            total += steps;
            System.out.println("("+i+") "+steps);
        }
        System.out.println("\n Average " + (total/runs) + " over " + runs + " trials.");
    }

    DrunkWalk(){
        edges = new int[SIZE][SIZE];
        for(int x=0;x<SIZE;x++){
            for(int y=0;y<SIZE;y++){
                if(x>0) edges[x][y] |= WEST;
                if(x+1<SIZE) edges[x][y] |= EAST;
                if(y>0) edges[x][y] |= NORTH;
                if(y+1<SIZE) edges[x][y] |= SOUTH;
            }
        }
        wallx = new int[SIZE/roomSize+1];
        wally = new int[SIZE/roomSize+1][SIZE/roomSize+1];
        pos = new Point(SIZE-1,SIZE-1);
        img = new BufferedImage(SIZE*6+1,SIZE*6+1, BufferedImage.TYPE_INT_RGB);
        frame = new JFrame(){
            public void paint(Graphics g) {
                g.drawImage(img, 50, 50, null);
            }
        };
        frame.setSize(700,700);
        if(SHOW)
            frame.show();
    }

    void draw(){
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        Graphics g = img.getGraphics();
        g.setColor(Color.WHITE);
        g.clearRect(0, 0, img.getWidth(), img.getHeight());
        for(int x=0;x<SIZE;x++){
            for(int y=0;y<SIZE;y++){
                if((edges[x][y]&EAST)==EAST)
                    g.drawLine(x*6, y*6, x*6+5, y*6);
                if((edges[x][y]&SOUTH)==SOUTH)
                    g.drawLine(x*6, y*6, x*6, y*6+5);
            }
        }
        g.setColor(Color.RED);
        g.drawOval(pos.x*6-2, pos.y*6-2, 5, 5);
        g.drawOval(pos.x*6-1, pos.y*6-1, 3, 3);
        frame.repaint();
    }

    int run(){
        int steps = 0;
        Point home = new Point(0,0);
        while(!pos.equals(home)){
            if(SHOW&&steps%SHOW_INT==0){
                System.out.println(steps);
                draw();
            }
            step();
            adversary();
            steps++;
        }
        if(SHOW)
            draw();
        return steps;
    }

    void adversary(){
        int rx = pos.x / roomSize;
        int ry = pos.y / roomSize;
        int maxWalls = roomSize - 1;
        if(wally[rx][ry] < maxWalls){
            if(pos.y%roomSize==0)
                if(delete(pos.x,pos.y,NORTH))
                    wally[rx][ry]++;
        }
        maxWalls = SIZE-1;
        if(pos.x%roomSize==0){
            if(wallx[rx] < maxWalls)
                if(delete(pos.x, pos.y,WEST))
                    wallx[rx]++;


        }       
    }

    void step(){
        List<Integer> choices = getNeighbors(pos);
        Collections.shuffle(choices);
        int dir = choices.get(0);
        pos.x += dir==WEST?-1:dir==EAST?1:0;
        pos.y += dir==NORTH?-1:dir==SOUTH?1:0;
    }

    boolean delete(int x, int y, int dir){
        if((edges[x][y] & dir) != dir)
            return false;
        edges[x][y] -= dir;
        if(dir == NORTH)
            if(y>0) edges[x][y-1] -= SOUTH;
        if(dir == SOUTH)
            if(y+1<SIZE) edges[x][y+1] -= NORTH;
        if(dir == EAST)
            if(x+1<SIZE) edges[x+1][y] -= WEST;
        if(dir == WEST)
            if(x>0) edges[x-1][y] -= EAST;
        return true;
    }

    List<Integer> getNeighbors(Point p){
        if(p.x==SIZE || p.y==SIZE){
            System.out.println("wtf");
            System.exit(0);
        }
        List<Integer> choices = new ArrayList<Integer>();
        if((edges[p.x][p.y] & NORTH) == NORTH)
            choices.add(NORTH);
        if((edges[p.x][p.y] & SOUTH) == SOUTH)
            choices.add(SOUTH);
        if((edges[p.x][p.y] & EAST) == EAST)
            choices.add(EAST);
        if((edges[p.x][p.y] & WEST) == WEST)
            choices.add(WEST);
        return choices;
    }

    final static int NORTH=1,EAST=2,SOUTH=4,WEST=8;
}

मैंने अभी देखा कि वह बॉट / लेफ्ट-> टॉप / राइट से जा रहा है, जबकि मेरा बॉट / राइट-> टॉप / लेफ्ट हो रहा है। मैं इसे बदल सकता हूं अगर यह वास्तव में मायने रखता है, लेकिन ...
16

यह बहुत अच्छा है और मुझे लगता है कि पहला गतिशील समाधान है। मुझे दिलचस्पी है कि आपका मार्ग तब तक स्थिर नहीं है, जब तक स्थिर लोग नहीं हैं।

यदि "काफी लंबे समय तक नहीं" से आपका मतलब है ~ 1/3 जब तक एक और ~ 36x दूसरे के रूप में? : पी
16

3

188k, 2 रास्तों के साथ

सबसे अच्छी प्रविष्टियां सभी को 2 रास्तों के निर्माण के दृष्टिकोण को लेती हुई प्रतीत होती हैं, और फिर जब रास्ते के अंत में नशे के पास एक को काटते हैं। मुझे नहीं लगता कि मैं जस्टफेल की प्रविष्टि को हरा सकता हूं, लेकिन मैं मदद नहीं कर सकता, लेकिन आश्चर्य: 2 रास्ते क्यों? 3, या 5 या 20 क्यों नहीं?

टीएल; डीआर : 2 पथ इष्टतम प्रतीत होते हैं

इसलिए मैंने एक प्रयोग किया। स्ट्रेच मनिक के ढांचे के आधार पर, मैंने विभिन्न रास्तों की जांच करने के लिए एक प्रविष्टि लिखी। आप featureSizeपथों की संख्या भिन्न करने के लिए पैरामीटर को ट्विक कर सकते हैं। एक featureSize20 दे 1 पथ के, 10 2 रास्तों देता है, 7 देता है 3, 5 4 देता है, और इतने पर।

import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Objects;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;

public class Walker {
    final int width,height;
    int x,y; //walker's position (does anyone else keep thinking about zombies?!?)
    final int dX,dY; //destination
    final int featureSize;
    Set<Edge> pathsNoLongerAvailable = new HashSet<>();
    Set<Edge> previouslyTraveled = new HashSet<>();
    int stepCount = 0;
    private final BitSet remainingExits;

    public static void main(String[]args){
        int side = 20;
        Walker walker = null;
        int total = 0;
        int featureSize = 10;
        double count = 1000;
        for(int i=0; i<count; i++){
            walker = new Walker(0,0,side,side,side-1,side-1, featureSize);
            total += walker.stepCount;
            System.out.println("Iteration "+i+": "+walker.stepCount);
        }
        System.out.printf("Average: %.3f\n", total/count);
        walker.printPath();
    }

    public Walker(int startingX,int startingY, int Width, int Height, int destinationX, int destinationY, int featureSize){
        width = Width;
        height = Height;
        dX = destinationX;
        dY = destinationY;
        x=startingX;
        y=startingY;
        this.featureSize = featureSize;

        deleteBars();

        remainingExits = new BitSet();
        for (int yy = 0; yy < height; yy++) {
            if (!pathsNoLongerAvailable.contains(new Edge(width - 2, yy, width - 1, yy))) {
                remainingExits.set(yy);
            }
        }

        while(!walk()){
            if (x == width - 2
                    && remainingExits.get(y)
                    && remainingExits.cardinality() > 1) {
                deletePath(x, y, x + 1, y);
                remainingExits.set(y, false);
            }
        }
    }

    private void deleteBars() {
        for (int xx = 0; xx < width - 1; xx++) {
            for (int yy = 0; yy < height / featureSize + 1; yy++) {
                if (xx != 0) deletePath(xx, featureSize * yy + featureSize - 1, xx, featureSize * yy + featureSize);
                boolean parity = xx % 2 == 0;
                if (yy == 0) parity ^= true; // First path should be inverted
                for (int i = 0; i < featureSize && featureSize * yy + i < height; i++) {
                    if (i == 0 && !parity) continue;
                    if ((i == featureSize - 1 || featureSize * yy + i == height - 1) && parity) continue;
                        deletePath(xx, featureSize * yy + i, xx + 1, featureSize * yy + i);
                }
            }
        }
    }

    public void printPath(){
        for(int i=0; i<width-1; i++){
            if(!pathsNoLongerAvailable.contains(new Edge(i,height-1,i+1,height-1))){
                System.out.print(" _");
            } else {
                System.out.print("  ");
            }
        }
        System.out.println();
        for(int i=height-2; i>=0; i--){
            for(int j=0; j<2*width-1; j++){
                if(j%2==0){
                    if(!pathsNoLongerAvailable.contains(new Edge(j/2,i,j/2,i+1))){
                        System.out.print("|");
                    } else {
                        System.out.print(" ");
                    }
                } else {
                    if(!pathsNoLongerAvailable.contains(new Edge(j/2,i,j/2+1,i))){
                        System.out.print("_");
                    } else {
                        System.out.print(" ");
                    }
                }
            }
            System.out.println();
        }
    }

    public boolean walk(){
        ArrayList<int[]> possibleMoves = new ArrayList<int[]>();
        if(x!=0 && !pathsNoLongerAvailable.contains(new Edge(x,y,x-1,y))){
            possibleMoves.add(new int[]{-1,0});
        }
        if(x!=width-1 && !pathsNoLongerAvailable.contains(new Edge(x,y,x+1,y))){
            possibleMoves.add(new int[]{1,0});
        }
        if(y!=0 && !pathsNoLongerAvailable.contains(new Edge(x,y,x,y-1))){
            possibleMoves.add(new int[]{0,-1});
        }
        if(y!=height-1 && !pathsNoLongerAvailable.contains(new Edge(x,y,x,y+1))){
            possibleMoves.add(new int[]{0,1});
        }
        int random = ThreadLocalRandom.current().nextInt(possibleMoves.size());
        int[] move = possibleMoves.get(random);
        previouslyTraveled.add(new Edge(x,y,x+move[0],y+move[1]));
        x+=move[0];
        y+=move[1];
        stepCount++;
        if(x==dX && y == dY){
            return true;
        } else {
            return false;
        }
    }

    public boolean isSolvable(){
        Set<Point> reachable = new HashSet<>();
        Queue<Point> next = new LinkedList<>();
        next.offer(new Point(x,y));
        reachable.add(new Point(x,y));
        while(next.size()>0){
            Point cur = next.poll();
            int x = cur.x;
            int y = cur.y;
            ArrayList<Point> neighbors = new ArrayList<>();
            if(x!=0 && !pathsNoLongerAvailable.contains(new Edge(x,y,x-1,y))){
                neighbors.add(new Point(x-1, y));
            }
            if(x!=width-1 && !pathsNoLongerAvailable.contains(new Edge(x,y,x+1,y))){
                neighbors.add(new Point(x+1, y));
            }
            if(y!=0 && !pathsNoLongerAvailable.contains(new Edge(x,y,x,y-1))){
                neighbors.add(new Point(x, y-1));
            }
            if(y!=height-1 && !pathsNoLongerAvailable.contains(new Edge(x,y,x,y+1))){
                neighbors.add(new Point(x, y+1));
            }
            for(Point neighbor: neighbors){
                if(!reachable.contains(neighbor)){
                    if(neighbor.compareTo(new Point(dX, dY))==0){
                        return true;
                    }
                    reachable.add(neighbor);
                    next.offer(neighbor);
                }
            }
        }
        return false;
    }

    public boolean hasBeenWalked(int x1, int y1, int x2, int y2){
        return previouslyTraveled.contains(new Edge(x1, y1, x2, y2));
    }

    public boolean hasBeenWalked(Edge edge) {
        return previouslyTraveled.contains(edge);
    }

    public void deletePath(int startX, int startY, int endX, int endY){
        Edge toAdd = new Edge(startX,startY,endX,endY);
        if(hasBeenWalked(toAdd)){
            System.out.println("Edge already travelled!");
            return;
        }
        pathsNoLongerAvailable.add(toAdd);
        if(!isSolvable()){
            pathsNoLongerAvailable.remove(toAdd);
            System.out.println("Invalid deletion!");
        }
    }

    public static class Edge implements Comparable<Edge>{
        Point start, end;

        public Edge(int x1, int y1, int x2, int y2){
            start = new Point(x1, y1);
            end = new Point(x2, y2);
            if(start.compareTo(end)>0){
                Point tmp = end;
                end = start;
                start = tmp;
            }
        }

        @Override
        public int compareTo(Edge o) {
            int result = start.compareTo(o.start);
            if(result!=0) return result;
            return end.compareTo(o.end);
        }

        @Override
        public String toString() {
            return start.toString() + "-" + end.toString();
        }

        @Override
        public int hashCode() {
            int hash = 7;
            hash = 83 * hash + Objects.hashCode(this.start);
            hash = 83 * hash + Objects.hashCode(this.end);
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final Edge other = (Edge) obj;
            if (!Objects.equals(this.start, other.start)) {
                return false;
            }
            if (!Objects.equals(this.end, other.end)) {
                return false;
            }
            return true;
        }


    }

    static class Point implements Comparable<Point>{
        int x,y;
        public Point(int x, int y){
            this.x = x;
            this.y = y;
        }
        public int compareTo(Point o){
            int result = Integer.compare(x, o.x);
            if(result!=0) return result;
            result = Integer.compare(y, o.y);
            if(result!=0) return result;
            return 0;
        }
        @Override
        public String toString() {
            return "(" + x + "," + y + ")";
        }

        @Override
        public int hashCode() {
            int hash = 7;
            hash = 23 * hash + this.x;
            hash = 23 * hash + this.y;
            return hash;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final Point other = (Point) obj;
            if (this.x != other.x) {
                return false;
            }
            if (this.y != other.y) {
                return false;
            }
            return true;
        }


    }
}

कुछ अनुकूलन हैं जो मैं कर सकता था लेकिन नहीं किया है, और यह किसी भी अनुकूली प्रवंचना का समर्थन नहीं करता है जो जस्टफुल उपयोग करता है।

वैसे भी, यहाँ विभिन्न featureSizeमूल्यों के लिए परिणाम हैं:

20 (1 path):  156284 
10 (2 paths): 188553
7 (3 paths):  162279
5 (4 paths):  152574
4 (5 paths):  134287
3 (7 paths):  118843
2 (10 paths): 94171
1 (20 paths): 64515

और यहाँ 3 रास्तों के साथ एक नक्शा है:

 _   _   _   _   _   _   _   _   _    
| | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |
| |_| |_| |_| |_| |_| |_| |_| |_| |_| |
|_   _   _   _   _   _   _   _   _   _|
| | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |
| |_| |_| |_| |_| |_| |_| |_| |_| |_| |
|  _   _   _   _   _   _   _   _   _  |
| | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | |
|_| |_| |_| |_| |_| |_| |_| |_| |_| | |

इसके लिए धन्यवाद। ऐसा लगता है कि सारा पैसा अब अनुकूली प्रवंचना में है :)

आप सबसे नीचे का रास्ता क्यों काटते हैं? मुझे लगता है कि बेहतर स्कोर के लिए आप निचले रास्ते और मध्य मार्ग के बीच का रास्ता काट सकते हैं।
justhalf

@ अन्याय, हाँ, मुझे उम्मीद है कि यह होगा। मैंने फैसला नहीं किया, क्योंकि इसने कोड को अधिक जटिल बना दिया होगा, और यह किसी भी तरह से एक विजेता प्रविष्टि नहीं होगी।
जेम्स_पिक

1
तीन रास्ते (इष्टतम 3-पथ को मानते हुए) औसतन एकल पथ के समान होंगे: Nपथ की लंबाई (जो है n^2-1), एकल पथ की औसत N^2चालों की आवश्यकता होगी , जबकि तीन रास्तों में (N/3)^2 + (2N/3)^2 + (2N/3)^2 = N^2कुछ अपेक्षाकृत छोटे मूल्य हैं, इसलिए तीन रास्तों का एकल मार्ग पर कोई महत्वपूर्ण लाभ नहीं है, अकेले दुगुने रास्ते पर चलने दें। (गणना संभाव्यता परिणाम पर आधारित है जो बताता है कि लंबाई के 1-डी पथ पर यादृच्छिक आंदोलन को एक से दूसरे तक Nऔसत N^2आंदोलन की आवश्यकता होती है ।)
जस्टफुल

@ अन्याय अच्छा लगा। मैं क्यों 2 सबसे अच्छा था के लिए एक अच्छा पहला-सिद्धांतों तर्क के साथ आने के लिए संघर्ष कर रहा था, लेकिन यह इसे नाखून।
जेम्स_पिक

2

131k (20x20)

मेरा पहला प्रयास था कि ऊपर और नीचे की पंक्ति को छोड़कर सभी क्षैतिज किनारों को हटा दिया जाए, फिर हर बार वॉकर एक कॉलम के नीचे तक पहुँच जाता है, मैं उसके आगे के किनारे को हटा देता हूँ, जब तक कि वह हर कॉलम के निचले हिस्से पर नहीं गया था और आखिरकार बाहर निकलने में सक्षम हो। इसके परिणामस्वरूप @ पीटरटयलर के 1d वॉक अप्रोच के रूप में 1/8 का औसत निकला।

इसके बाद मैंने कुछ अधिक सर्किट बनाने की कोशिश की। मैंने भूलभुलैया को नेस्टेड खोखले शेवरॉन की एक श्रृंखला में विभाजित किया है, और उसे कम से कम 1.5 बार प्रत्येक शेवरॉन की परिधि को पार करने की आवश्यकता है। इसके पास औसतन 131k कदम है।

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <math.h>

#define DEBUG 0
#define ROUNDS 10000

#define Y 20
#define X 20
#define H (Y*2+1)
#define W (X*2+1)

int maze[H][W];
int scores[ROUNDS];

int x, y;

void print_maze(){
    char line[W+2];
    line[W+1]=0;
    for(int row=0;row<H;row++) {
        for(int col=0;col<W;col++) {
            switch(maze[row][col]) {
                case 0:
                    line[col]=' ';
                    break;
                case 1:
                    line[col]=row%2?'-':'|';
                    break;
                case 9:
                    line[col]=(row==y*2+1&&col==x*2+1)?'@':' ';
                    break;
            }
        }
        line[W]='\n';
        printf("%s",line);
    }
    printf("%d %d\n",y,x);
}

int main(){
    srand (time(NULL));
    long long total_turns = 0;
    for(int round=0;round<ROUNDS;round++) {
        for (int r=0;r<H;r++) {
            for (int c=0;c<W;c++) {
                if (r==0 || r==H-1 || c==0 || c==W-1) maze[r][c]=0; // edges
                else if (r%2) { // rows with cells and E/W paths
                    if (c%2) maze[r][c] = 9; // col with cells
                    else if (r==1 || r==H-2) maze[r][c]=1; // E/W path on N/Smost row
                    else if (c>r) maze[r][c]=1; // E/W path on chevron perimeter
                    else maze[r][c]=0; // cut path between cols
                } else { // rows with N/S paths
                    if (c%2==0) maze[r][c] = 0; // empty space
                    else if (c==1 || c==W-2) maze[r][c]=1; // N/S path on E/Wmost row
                    else if (r>c) maze[r][c]=1; // N/S path on chevron perimeter
                    else maze[r][c]=0;
                }
            }
        }
        int progress = 0;
        int first_cut = 0;
        x=0;
        y=0;
        if(DEBUG) print_maze();
        long long turn = 0;
        while (x!=X-1||y!=Y-1) {
            if(DEBUG) std::cin.ignore();
            turn++;
            int r = y*2+1;
            int c = x*2+1;
            int exits = maze[r-1][c] + maze[r][c+1] + maze[r+1][c] + maze[r][c-1];
            int exit_choice = -1;
            do {
                if (rand()%exits == 0) {
                    exit_choice = exits;
                    break;
                } else {
                    exits--;
                }
            }while(exits);
            int dx=0, dy=0;
            --exits;
            if (maze[r-1][c]&&!dx&&!dy) {
                if (exits) {
                    --exits;
                } else {
                    dy = -1;
                    dx = 0;
                }
            }
            if (maze[r][c+1]&&!dx&&!dy) {
                if (exits) {
                    --exits;
                } else {
                    dy = 0;
                    dx = 1;
                }
            }
            if (maze[r+1][c]&&!dx&&!dy) {
                if (exits) {
                    --exits;
                } else {
                    dy = 1;
                    dx = 0;
                }
            }
            if (maze[r][c-1]&&!dx&&!dy) {
                if (exits) {
                    --exits;
                } else {
                    dy = 0;
                    dx = -1;
                }
            }
            x+=dx;
            y+=dy;
            if (first_cut==0) {
                if(x==X-1 && y==progress*2+1) {
                    first_cut = 1;
                    maze[y*2+2][x*2+1]=0;
                }
                if(y==Y-1 && x==progress*2+1) {
                    first_cut = 2;
                    maze[y*2+1][x*2+2]=0;
                }
            }
            else if (first_cut==1) {
                if (y==Y-1 && x==progress*2) {
                    maze[y*2+1][x*2+2]=0;
                    progress++;
                    first_cut=0;
                }
                else if (y==Y-2 && x==progress*2+1) {
                    maze[y*2+2][x*2+1]=0;
                    progress++;
                    first_cut=0;
                }
            }
            else if (first_cut==2) {
                if (x==X-1 && y==progress*2) {
                    maze[y*2+2][x*2+1]=0;
                    progress++;
                    first_cut=0;
                }
                else if (x==X-2 && y==progress*2+1) {
                    maze[y*2+1][x*2+2]=0;
                    progress++;
                    first_cut=0;
                }
            }
            if(DEBUG) print_maze();
        }
        // printf("turns:%lld\n",turn);
        scores[round] = turn;
        total_turns += turn;
    }
    long long avg = total_turns/ROUNDS;
    printf("average: % 10lld\n",avg);
    long long var = 0;
    for(int r=0;r<ROUNDS;r++){
        var += (scores[r]-avg)*(scores[r]-avg);
    }
    var/=ROUNDS;
    // printf("variance: %lld\n",var);
    int stddev=sqrt(var);
    printf("stddev:  % 10d\n",stddev);

}

0

कुछ मत करो

चूंकि आदमी बेतरतीब ढंग से आगे बढ़ता है, इसलिए कोई सोच सकता है कि किसी भी नोड को हटाने से लंबे समय में घर मिलने की संभावना बढ़ जाएगी।

सबसे पहले, एक-आयामी मामले पर एक नज़र डालते हैं, यह तब तक नोड्स को हटाकर प्राप्त किया जा सकता है जब तक कि आप डेडली या साइकिल के बिना समाप्त नहीं हो जाते हैं, बिना डेड या साइकिल के, हर ग्रिड पॉइंट पर जाते हैं। N x Nग्रिड पर इस तरह के पथ की अधिकतम लंबाई L = N*N - 2 + N%2 (10x10 ग्रिड के लिए 98) है। पथ के साथ चलना एक संक्रमण मैट्रिक्स द्वारा उत्पन्न के रूप में वर्णित किया जा सकता है T1dसंक्रमण मैट्रिक्स

(मामूली विषमता बहुत छोटे या अनंत मैट्रिक्स को छोड़कर, एक विश्लेषणात्मक समाधान खोजने के लिए कठिन बनाता है, लेकिन हम तेजी से संख्यात्मक समाधान प्राप्त करते हैं, क्योंकि यह मैट्रिक्स को विकर्ण करने के लिए ले जाएगा)।
राज्य वेक्टर 1प्रारंभिक स्थिति में एक है और Kचरणों के बाद (T1d**K) * stateहमें शुरुआत से एक निश्चित दूरी पर होने की संभावना वितरण देता है (जो कि औसत से अधिक के बराबर है2**K पथ के साथ संभावित चलता !)

10*L**2चरणों के लिए सिमुलेशन चलाना और प्रत्येक चरण के बाद राज्य वेक्टर के अंतिम तत्व को सहेजना जो हमें निश्चित चरणों की कुल संख्या के बाद लक्ष्य तक पहुंचने की संभावना देता है - संचयी संभाव्यता वितरण cd(t)। इसे अलग करने से हमें संभावना मिलती हैp निश्चित समय पर लक्ष्य तक पहुंचने । हम t*p(t) dt
जिस औसत समय को एकीकृत करते हैं उसे खोजने के लिए लक्ष्य तक पहुंचने का औसत समय L**2एक कारक के साथ आनुपातिक है जो बहुत जल्दी 1 हो जाता है। मानक विचलन औसत समय के लगभग 79% पर लगभग स्थिर है।
यह ग्राफ विभिन्न पथ लंबाई के लिए लक्ष्य तक पहुंचने के लिए औसत समय दिखाता है (5x5 से 15x15 के ग्रिड आकार के अनुसार) यहां छवि विवरण दर्ज करें

यहां बताया गया है कि लक्ष्य तक पहुंचने की संभावना कैसी है। दूसरा वक्र भरा हुआ दिखता है क्योंकि प्रत्येक विषम समय में स्थिति विषम होती है और इसलिए लक्ष्य पर नहीं हो सकता। यहां छवि विवरण दर्ज करें

उससे हम देख सकते हैं कि संतुलित दोहरे पथ की रणनीति यहां सबसे अच्छा काम करती है। बड़े ग्रिडों के लिए, जहाँ अधिक पथ बनाने का ओवरहेड उनके आकार की तुलना में नगण्य है, हम पथों की संख्या बढ़ाने से बेहतर हो सकते हैं, पीटर टेलर ने इसका वर्णन कैसे किया, लेकिन लंबाई को संतुलित रखते हुए

क्या होगा अगर हम किसी भी नोड्स को बिल्कुल नहीं हटाते हैं?

तब हमारे पास दो चलने योग्य नोड्स के साथ-साथ दो के बजाय चार संभव दिशाएं होंगी। ऐसा लगता है कि यह कभी भी कहीं भी होने की संभावना को बहुत कम कर देता है। हालांकि, सिमुलेशन, अन्यथा दिखाने के एक 10x10 ग्रिड पर सिर्फ 100 चरणों के बाद आदमी है एक व्यर्थ प्रयास बहुत अपने लक्ष्य तक पहुंचने की संभावना है, इसलिए उसे द्वीपों में trappin है जब से तुम एक संभावित व्यापार कर रहे हैं N**2लंबे समय के एक औसत पूरा होने के समय के साथ पथ घुमावदार N**4के लिए एक द्वीप जो N**2चरणों में पार किया जाता है

2 डी ग्रिड पर चलने की संभावना

from numpy import *
import matplotlib.pyplot as plt

def L(N): # maximal length of a path on an NxN grid
    return N*N - 2 + N%2

def T1d(N): # transition along 1d path
    m = ( diag(ones(N-1),1) + diag(ones(N-1),-1) )/2.
    m[1,0] = 1
    m[-2,-1] = 0
    m[-1,-1] = 1
    return m

def walk(stepmatrix, state, N):
    data = zeros(N)
    for i in xrange(N):
        data[i] = state[-1]
        state = dot(stepmatrix, state)
    return data

def evaluate(data):
    rho = diff(data)/data[-1]
    t = arange(len(rho))
    av = sum(rho*t)
    stdev = sum((t-av)**2 * rho)**.5
    print 'average: %f\nstd: %f'%(av, stdev)
    return rho, av, stdev

gridsize = 10
M = T1d(L(gridsize))
initpos = zeros(L(gridsize))
initpos[0] = 1
cd = walk(M, initpos, L(gridsize)**2*5)

plt.subplot(2,1,1)
plt.plot(cd)
plt.title('p of reaching the goal after N steps')
plt.subplot(2,1,2)
plt.plot(evaluate(cd)[0])
plt.title('p of reaching the goal at step N')
plt.show()


''' 
# uncomment to run the 2D simulation
# /!\ WARNING /!\ generates a bunch of images, dont run on your desktop

def links(k,n):
    x = [k-n, k+n]
    if k%n != 0: x.append(k-1)
    if k%n != n-1: x.append(k+1)
    x = [i for i in x if 0<= i <n*n]
    return x

N = 10 # gridsize    

MM = zeros((N*N, N*N)) # build transition matrix
for i in range(N*N):
    temp = links(i,N)
    for j in temp: MM[i,j] = 1./len(temp)
MM[:,-1] = zeros(N*N)
MM[-1,-1] = 1

pos = zeros(N*N)
pos[0] = 1
for i in range(N*N):
    plt.imsave('grid_%.2d'%i, kron(pos.reshape((N,N)), ones((10,10))), cmap='gray')
    pos = dot(MM, pos)
'''

प्रयास और अच्छे रेखांकन के लिए +1। लेकिन यह सवाल का जवाब नहीं देता है, और पहले दो शब्द आपके विश्लेषण के निष्कर्ष के साथ विरोधाभासी हैं। और, आपको वास्तव में अपने ग्राफ़ के अक्षों को लेबल करना चाहिए। आपकी संभावना का ग्राफ किस ग्रिड आकार के लिए लागू है?
26

प्यारी तस्वीरें लेकिन मुझे यकीन नहीं है कि आपके पास सवाल सही है। उदाहरण के लिए "चूंकि आदमी बेतरतीब ढंग से आगे बढ़ता है, इसलिए कोई सोच सकता है कि किसी भी नोड को हटाने से लंबे समय में घर मिलने की संभावना बढ़ जाएगी।" 1) आदमी हमेशा नियमों के तहत घर लेगा जो कि सेट हैं इसलिए यह प्रासंगिक नहीं लगता है और 2) हम किनारों को हटा रहे हैं नोड्स नहीं।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.