বাড়ি যাওয়ার পথে কোনও মাতালকে কীভাবে কম করবেন


15

এন গ্রিড গ্রাফের মতো দেখতে বর্গাকার এন বিবেচনা করুন।

গ্রিড গ্রাফ

এই গ্রাফটি 11 বাই 11 এর মতো লক্ষ্য করা গুরুত্বপূর্ণ

যে কোনও বিন্দুতে একটি মানুষ একটি চৌরাস্তাতে দাঁড়িয়ে থাকে এবং সে কেবল একবারে এক ধাপে উল্লম্ব বা অনুভূমিকভাবে পরবর্তী চৌরাস্তার দিকে চলে যায়। দুঃখজনকভাবে তিনি খানিকটা মাতাল হয়েছেন তাই তিনি 4 টি সম্ভাব্য দিক (উপরে, নীচে, বাম, ডান) থেকে এলোমেলোভাবে যে দিকনির্দেশনা চালিয়েছেন তা চয়ন করেন। এটি 4 অবধি যদি কোনও দেয়ালে দাঁড়িয়ে থাকে তবে তার কাছে অবশ্যই 3 টি বিকল্প রয়েছে এবং একটি কোণে তার কাছে কেবল 2 আছে।

তিনি নীচের বাম হাতের কোণে শুরু করেন এবং তার লক্ষ্য বাড়ি পৌঁছানো যা উপরের ডান হাতের কোণে। সময়টি কেবল তাকে গ্রহণের পদক্ষেপের সংখ্যা।

তবে, আপনি একজন দূষিত শত্রু যিনি তাকে যতটা সম্ভব আস্তে আস্তে বাড়ি ফেলাতে চান। আপনি তার হাঁটার সময় গ্রাফ থেকে যে কোনও সংখ্যক প্রান্ত মুছে ফেলতে পারেন । একমাত্র সীমাবদ্ধতা হ'ল আপনাকে অবশ্যই তার বাড়ির জন্য কিছুটা পথ ছেড়ে দিতে হবে এবং তিনি ইতিমধ্যে ব্যবহার করা কোনও কিনারা মুছতে পারবেন না।

চ্যালেঞ্জটি হ'ল সম্ভব প্রতিপক্ষ হিসাবে ক্ষতিকারক হিসাবে পরিকল্পনা করা এবং তারপরে এলোমেলো মাতাল ওয়াটারের সাথে এটি একটি 100 বাই 100 20 বাই 20 গ্রাফে পরীক্ষা করা। আপনার স্কোরটি কেবলমাত্র গড় সময় যা এলোমেলো ওয়াকারকে 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 রাউন্ড চালাচ্ছি এবং আমি ফলাফলগুলি তুলনা-যোগ্য বিবেচনা করব না।
স্পার

উত্তর:


10

23x20 এ 230,794.38, 100k রান

সর্বশেষ আপডেট: অবশেষে আমি নিখুঁত গতিশীল 2-পাথ সমাধান তৈরি করেছি। আমি বললাম নিখুঁত যেহেতু পূর্ববর্তী সংস্করণটি আসলে প্রতিসম নয়, মাতাল যদি অন্য পথ ধরে একটি পথ নেয় তবে আরও দীর্ঘ পথ পাওয়াই সহজ ছিল। বর্তমানেরটি একটি প্রতিসম, তাই এটি উচ্চতর প্রত্যাশিত পদক্ষেপ পেতে পারে। কয়েকটি পরীক্ষার পরে, এটি প্রায় 230k এর কাছাকাছি বলে মনে হচ্ছে, এটি আগেরটির তুলনায় একটি উন্নতি যা প্রায় 228k। তবে পরিসংখ্যানগতভাবে বলতে গেলে এই সংখ্যাগুলি এখনও তাদের বিশাল বিচ্যুতির মধ্যে রয়েছে, তাই আমি দাবি করি না যে এটি উল্লেখযোগ্যভাবে ভাল, তবে আমি বিশ্বাস করি এটি আগের সংস্করণের চেয়ে ভাল হওয়া উচিত।

কোডটি এই পোস্টের নীচে রয়েছে। এটি আপডেট করা হয়েছে যাতে এটি পূর্ববর্তী সংস্করণের তুলনায় অনেক দ্রুত, 23 এর মধ্যে 1000 রান পূর্ণ করে।

নীচে নমুনা চালানো এবং নমুনা গোলকধাঁধা:

পারফেক্ট ওয়াকার
গড়: 230794.384
সর্বাধিক: 1514506
ন্যুনতম: 25860
2317.374 এ সম্পন্ন হয়েছে
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
| | | | | | | | | | | | | | | _ _ _ _ _  
| | | | | | | | | | | | | | | | _ _ _ _ _  
| | | | | | | | | | | | | | | _ _ _ _ | |
| | | | | | | | | | | | | | | | _ _ _ _ _  
| | | | | | | | | | | | | | | _ _ _ _ | |
| | | | | | | | | | | | | | | | _ _ _ _ _  
| | | | | | | | | | | | | | | _ _ _ _ | |
| | | | | | | | | | | | | |: _ | | _ _ _ _ _  
| | | | | | | | | | | | | _ _ _ _ _ _ _ |
| | | | | | | | | | | | | | _ _ _ _ _ _ _  
| | | | | | | | | | | | | _ _ _ _ _ _ _ |
| | | | | | | | | | | | | | _ _ _ _ _ _ _  
| | | | | | | | | | | | | _ _ _ _ _ _ _ |
| | | | | |: _ | |: _ | |: _ | |: _ | | _ _ _ _ _ _ _  
| | | | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | | | | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _  
| | | | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| |: _ | |: _ | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _  
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | 


পূর্ববর্তী জমাগুলি

পরিশেষে আমি স্পার এর ফলাফল মেলে করতে পারি! = D:

আমার আগের পরীক্ষাগুলির উপর ভিত্তি করে (এই পোস্টের নীচের অংশটি দেখুন) সর্বোত্তম কৌশলটি হ'ল মাতালটি যে কোনওটির কাছে পৌঁছানোর সাথে সাথে দ্বিগুণ পথ রয়েছে এবং একটিটিকে বন্ধ করে দেওয়া হবে এবং মাতালটি কোথায় যাবে সে সম্পর্কে আমরা পরিবর্তনশীলভাবে ভবিষ্যদ্বাণী করতে পারি যে পরিবর্তনটি এসেছে from তার দীর্ঘতর পথে যাওয়ার সম্ভাবনা বাড়িয়ে দিন।

সুতরাং আমার DOUBLE_PATHকৌশলটির ভিত্তিতে , আমি আর একটি তৈরি করেছি, যা DOUBLE_PATHমাতালদের গতিবিধির উপর নির্ভর করে গোলকধাঁধা পরিবর্তন করে (আমার ধাঁধাঁটি সহজেই পরিবর্তনযোগ্য হয়েছিল)। যেহেতু তিনি একাধিক উপলভ্য বিকল্প সহ একটি পথ অবলম্বন করেন, আমি কেবল দুটি সম্ভাব্য বিকল্প (যেটি থেকে সে এসেছিল, অন্যটি অবিকৃত নয়) ছেড়ে দিতে আমি পথগুলি বন্ধ করব।

এটি স্পার যা অর্জন করেছে তার সমান মনে হচ্ছে, ফলাফলটি দেখায়। এটিকে আরও ভাল হিসাবে বিবেচনা করার জন্য তার সাথে পার্থক্যটি খুব সামান্য, তবে আমি বলব যে আমার পদ্ধতির তার চেয়ে বেশি গতিশীল, যেহেতু আমার গোলকধাঁধাঁটি স্পার এর = এর চেয়ে বেশি পরিবর্তনযোগ্য)

একটি নমুনা চূড়ান্ত গোলকধাঁধা সহ ফলাফল:

EXTREME_DOUBLE_PATH
গড়: 228034.89
সর্বাধিক: 1050816
ন্যুনতম: 34170
396.728 এর মধ্যে সম্পন্ন হয়েছে
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
 _ _ _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
 _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |


পরীক্ষা বিভাগ

সেরা কৌশলটি স্টোকাস্টিকের মতো একই কৌশল হিসাবে দেখা যায়, আমি বিভিন্ন কৌশল ব্যবহার করে এবং দুর্দান্ত ফলাফলগুলি মুদ্রণের জন্য গর্ব করি take

মাতাল ঘরে পৌঁছে যাওয়ার পরে নীচের প্রতিটি মুদ্রিত গোলকধাঁধাটি হ'ল শেষ গোলকধাঁধা , তাই তারা মাতাল হয়ে যাওয়া আন্দোলনের এলোমেলো এবং প্রতিকূলতার গতিবেগের কারণে রান থেকে চালানো থেকে কিছুটা আলাদা হতে পারে।

আমি প্রতিটি কৌশল বর্ণনা করব:

একক পথ

এটি সহজতম পদ্ধতির, যা প্রবেশ থেকে প্রস্থান করার জন্য একটি একক পথ তৈরি করবে।

SINGLE_PATH
গড়: 162621.612
সর্বাধিক: 956694
ন্যুনতম: 14838
149.430 এর মধ্যে সম্পন্ন হয়েছে
 _ _ _ _ _ _ _ _ _ _ _ _
| |: _ | |: _ | |: _ | |: _ | |: _ | |: _ | |: _ | |: _ | |: _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |

দ্বীপ (স্তর 0)

এটি এমন একটি পন্থা যা মাতালকে প্রায় বিচ্ছিন্ন একটি দ্বীপে আটকাতে চেষ্টা করে। আমি যেমনটি প্রত্যাশা করেছিলাম তেমন ভাল কাজ করে না তবে এটি আমার প্রথম ধারণাগুলির মধ্যে একটি, তাই আমি এটি অন্তর্ভুক্ত করছি।

প্রস্থান করার পথে দুটি পথ রয়েছে, এবং মাতাল যখন তাদের কোনওটির কাছে পৌঁছে, তখন শত্রুরা এটি বন্ধ করে দেয় এবং তাকে অন্য প্রস্থানটি খুঁজে বের করতে বাধ্য করে (এবং সম্ভবত দ্বীপে আবার আটকা পড়ে)

আইল্যান্ড
গড়: 74626.070
সর্বাধিক: 428560
ন্যুনতম: 1528
122.512 এর মধ্যে সম্পন্ন হয়েছে
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _   
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
|: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ |: _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |

ডাবল পাথ

এটিই সর্বাধিক আলোচিত কৌশল, যা প্রস্থান করার জন্য দুটি সমান দৈর্ঘ্যের পাথ থাকতে হবে এবং মাতাল তাদের কোনওটির কাছে যাওয়ার সাথে সাথে তার একটিকে বন্ধ করে দেয়।

DOUBLE_PATH
গড়: 197743.472
সর্বাধিক: 1443406
ন্যুনতম: 21516
308.177 এ সম্পন্ন হয়েছে
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
 _ _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
 _ _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
 _ _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
 _ _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
 _ _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
 _ _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
 _ _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
 _ _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
 _ _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |

দ্বীপ (স্তর 1)

একক পথের দ্বীপের একাধিক পাথ এবং উচ্চ পথের গণনা দ্বারা অনুপ্রাণিত হয়ে আমরা দ্বীপটিকে প্রস্থান করার সাথে সংযুক্ত করি এবং দ্বীপে একক পথের ধাঁধা তৈরি করি, প্রস্থান করার জন্য মোট তিনটি পথ তৈরি করে এবং পূর্ববর্তী কেসের মতোই, যেকোনটি বন্ধ করে দিন মাতাল কাছাকাছি হিসাবে প্রস্থান করুন।

এটি খাঁটি একক পাথের চেয়ে কিছুটা ভাল কাজ করে তবে তবুও দ্বিগুণ পথকে পরাভূত করে না।

আইল্যান্ড
গড়: 166265.132
সর্বাধিক: 1162966
ন্যুনতম: 19544
471.982 এর মধ্যে সম্পন্ন হয়েছে
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ | _ _
| | |: _ | |: _ | |: _ | |: _ | |: _ | |: _ | |: _ | |: _ | |  
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |

দ্বীপ (স্তর 2)

পূর্ববর্তী ধারণাটি প্রসারিত করার চেষ্টা করে, আমি মোট পাঁচটি পথ তৈরি করে নেস্টেড দ্বীপ তৈরি করেছি, তবে এটি তেমন কার্যকর হবে বলে মনে হয় না।

আইল্যান্ড
গড়: 164222.712
সর্বাধিক: 927608
ন্যুনতম: 22024
793.591 এ সমাপ্ত
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | _
| | _ _ _ _ _ _ _ _ _ | _ | |  
| | | |: _ | |: _ | |: _ | |: _ | |: _ | |: _ | |: _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| _ | _ | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |

দ্বীপ (স্তর 3)

ডাবল পাথটি আসলে একক পথের চেয়ে আরও ভাল কাজ করে লক্ষ্য করে, আসুন দ্বীপটিকে দ্বৈত পথে পরিণত করুন!

ফলাফলটি দ্বীপের উপরে উন্নতি (স্তর 1), তবে এটি এখনও খাঁটি দ্বিগুণ পথকে হারাতে পারে না।

তুলনার জন্য, দ্বীপের আকারের দ্বিগুণ পথের ফলাফলটি গড়ে 131,134.42 মুভ। সুতরাং এটি বেশ কয়েকটি উল্লেখযোগ্য সংখ্যক চাল (প্রায় 40 কিলোমিটার) যুক্ত করে, তবে ডাবল পাথের জন্য যথেষ্ট নয় not

আইল্যান্ড
গড়: 171730.090
সর্বাধিক: 769080
ন্যুনতম: 29760
587.646 এ শেষ হয়েছে
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | _ _
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |  
| _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ _ | |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | |
| _ | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |

দ্বীপ (স্তর 4)

আবার, নেস্টেড দ্বীপ নিয়ে পরীক্ষা-নিরীক্ষা করা, এবং আবার এটি এত ভাল কাজ করে না।

আইল্যান্ড
গড়: 149723.068
সর্বাধিক: 622106
ন্যুনতম: 25752
830.889 এর মধ্যে সম্পন্ন হয়েছে
 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _    
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |  
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
| | _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ | | |
| | | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| | _ _ _ _ _ _ _ _ | | _ _ _ _ _ _ _ _ | | |
| | _ | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| _ | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | | |
| _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |

উপসংহার

সর্বোপরি, এটি প্রমাণ করে যে মাতাল বর্তমান অবস্থান থেকে প্রস্থান পর্যন্ত একক দীর্ঘ পথ পাওয়াই সবচেয়ে ভাল কাজ করে, যা দ্বিগুণ পথের কৌশল দ্বারা অর্জন করা হয়, যেহেতু একটি প্রস্থান বন্ধ করার পরে, মাতালকে সর্বোচ্চতম দূরত্বে ভ্রমণ করতে হবে বাহির.

এটি আরও ইঙ্গিত দেয় যে মৌলিক কৌশলটি এখনও দ্বৈত পথ হওয়া উচিত, এবং আমরা কেবলমাত্র পরিবর্তন করতে পারি যে কতগুলি গতিশীল পথ তৈরি হয়, যা স্পার দ্বারা সম্পন্ন হয়েছে। সুতরাং আমি বিশ্বাস করি তার কৌশলটিই চলার পথ!

কোড

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 এর কাছাকাছি। এটি প্রতিটি পাথ মোছার ক্ষেত্রে সমাধানযোগ্যতা পরীক্ষা সহ including আমি এটি 1000 রানের জন্য প্রায় 170s থাকা সরাতে পারি। সুতরাং আমি প্রায় এক ঘন্টার মধ্যে 20k রান করতে পারি।
justhalf

প্রকৃতপক্ষে আরও অনুকূলিতকরণ আমি 3.5 ঘন্টা মধ্যে 100k চালাতে সক্ষম হতে পারে।
justhalf

আমার স্কোরটি 100k রান নিয়ে 10 মিনিট সময় নিয়েছে। আরও নমনীয় ডাবল পাথ ধাঁধাতে @ অ্যাডহাজল্ফটি খুব সুন্দর। কীভাবে আরও উন্নততর করা যায় তা আমি জানি তবে এখনই এটি প্রয়োগ করার ধৈর্য আমার নেই।
স্পার

2
প্রতিসম সমাধান প্রয়োগ করা দেখে খুশি। এই সমাধানটির উন্নতি করার জন্য আমার কাছে আরও একটি ধারণা পেয়েছে, এবং এবার আমি মনে করি এটি নিজেই প্রয়োগ করতে পারি :)
স্পার

10

227934 (20x20)

আমার তৃতীয় প্রচেষ্টা। প্রস্থান করার জন্য দুটি পথ সহ @ স্টকাস্টিকের মতো একই সাধারণ পদ্ধতির ব্যবহার করে। ওয়াকার যখন একটি পাথের শেষে পৌঁছে যায়, তখন এটি বন্ধ হয়ে যায় এবং প্রস্থান করার জন্য তাকে অন্য পথের শেষে ফিরে আসতে হবে। আমার উন্নতি হ'ল পথ চলার সাথে সাথে পথগুলি উত্পন্ন করা, যাতে প্রক্রিয়াটির প্রথমার্ধে তিনি যে যেদিকেই এগিয়ে চলেছেন অন্য পথের চেয়ে দীর্ঘস্থায়ী হয়।

#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
...

আমার গোলকধাঁধার উদাহরণ, পথের সমান দৈর্ঘ্যের অর্ধেক সহ, প্রস্থান (নীচের ডানদিকে) থেকে বিচ্ছিন্নভাবে বাম / নীচের পথটি দেখানো হয়েছে:

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

পিএস: আমি এই অ্যালগরিদমের খুব সামান্য উন্নতির বিষয়ে অবগত আছি যার জন্য দু'টি পথের জন্য একটি পৃথক আকার তৈরি করার জন্য আরও চৌকস কোডের প্রয়োজন, নিয়মিত উচ্চতা জিগ জিগের পরিবর্তে সিঁড়ি।


রঙিন আমাকে মুগ্ধ। আপনি আমার ভোট স্যার আছে!
স্টকাস্টিক

1
এটা বেশ চিত্তাকর্ষক। মনে আছে আমরা কখন মাতালদের মুখের দিকে টানলাম?
ডেনিস

আপনার গ্রাফটি বোঝা বেশ কঠিন, সম্ভবত আপনি আমার গ্রাফের মুদ্রণ আমার মতো কিছুতে পরিবর্তন করতে পারেন?
justhalf

1
@ ঠিকঠাক আপনার ইচ্ছা আমার আদেশ
স্পার

1
@ চাপহালফ আমি এটি কাগজে আঁকতে পেরেছি। শুধু যুক্তি লেখার দরকার আছে। আমি যদি আরও কয়েকদিনের মধ্যে এটি না করি, আমি আপনাকে স্কেচ দেব? :)
স্পার

6

98x98 এর জন্য 135,488,307.9

1990x4.3 20x20 এর জন্য

আমি একটি সমাধান কার্যকর করেছি যা সমাপ্তির জন্য দুটি পথ তৈরি করে, এবং মাতালটি এটি পৌঁছানোর পরে ঠিক সেগুলির মধ্যে একটি বন্ধ করে দেয়। এটি একটি পাথের দৈর্ঘ্য সিমুলেট করে যা খুব কমপক্ষে শুরু থেকে শেষ অবধি একক পাথের দৈর্ঘ্য 1.5x হবে। ২ runs রানের পরে আমি গড়ে প্রায় ১৩৫ মিলিয়ন রান করেছি। দুর্ভাগ্যক্রমে এটি হাঁটাতে কয়েক মিনিট সময় নেয়, সুতরাং আমাকে এটি পরবর্তী কয়েক ঘন্টা চালাতে হবে। একটি সতর্কতামূলক - আমার ডাবল পাথ জেনারেটর কেবল তখনই কাজ করে যদি গ্রাফের আকার 4 4 n + 2 ফর্মের হয় তবে আমি 100 এর নিকটতমতম অর্থ 102 বা 98 হতে পারি 98 আমি 98 ব্যবহার করে ফলাফল পোস্ট করতে যাচ্ছি, যা আমি আশা করি এখনও জিগজ্যাগ পাথ পদ্ধতিকে ছাড়িয়ে যেতে। আমি পরে আরও ভাল পাথিং সিস্টেমে কাজ করব। বর্তমানে প্রতিটি হাঁটার পরে ফলাফলগুলি (নামস্টেপস, কারেন্টএভারেজ) আকারে আউটপুট দেয়।

সম্পাদনা: ফিক্সড তাই কোডটি এখন গ্রাফের আকারগুলিতে কাজ করে যা 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

কাঁচা তথ্য: (বর্তমান numSteps, চলমান গড়)

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 এ কমিয়েছি। আমি আসা করি এটা সাহায্য করবে.

আপনি বর্তমানে জিতে আছেন :)

আপনার 20 বাই 20 স্কোর 1000 রান বেশি?

@ ল্যাম্বিক হ্যাঁ
দৃok়তম

1
@ ডেনিস অ বিপরীতে :)
স্পার

6

4-পন্থা পদ্ধতির, 213 কে

ওয়ান-পাথ অ্যাপ্রোচ

এস থেকে ই পর্যন্ত সোজা লাইন

এবং স্কোর গড়ে N^2

দ্বি-পথ পদ্ধতির হয়

একে অপরের বিপরীতে এস এবং ই এর সাথে লুপ

তবে তারপরেই প্রথম মাতালটি শেষ পয়েন্টের কাছে পৌঁছায়, এটি কেটে গেছে:

এস থেকে ই পর্যন্ত একটি বাঁকা লাইন দিতে লুপটি কেটে দেওয়া হয়

এটি গড়ে স্কোর করে (N/2)^2 + N^2

চার-পথ পদ্ধতির দুটি কাট ব্যবহার করা হয়:

নেস্টেড লুপস, দুটি কাঁটাচামচ, ই এর উভয় পাশে যোগদান করেছে E পাশের একটি কাঁটাচামচ কাটা অন্যদিকে, নন-ই পাশের কাঁটাটি কেটে নিন।  এটি একটি বিভক্ত পথ ছেড়ে দেয়

ধরুন বাইরের লুপটি দৈর্ঘ্যের 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 এর পরিবর্তে YE পাথের দৈর্ঘ্য N কীভাবে হবে?
স্পার

@ সরফাল্ফ, হ্যাঁ এখানে 400 টির শীর্ষগুলি রয়েছে, সুতরাং 401 প্রান্ত রয়েছে (এক কাটার পরে গ্রাফটি হ্যামিলটনিয়ান চক্র); দুটি বাইরের পাথ প্রতিটি 100 টি প্রান্ত এবং অভ্যন্তরীণ লুপটি তাই 101 টি প্রান্ত।
পিটার টেলর

বুঝেছি. দুটি পর্যবেক্ষণ: ক) বৃহত্তর ম্যাজগুলি বৃহত্তর 2 ^ n পথ থেকে উপকৃত হবে। খ) আপনি যদি আপনার পথের দৈর্ঘ্যকে গতিশীল করে তোলেন তবে আপনি বর্তমান নেতাদের গতিশীল দ্বি-পথের সমাধানগুলি (আমার এবং @ অ্যাডেজাল্ফ) দিয়ে পরাজিত করবেন
স্পার

@ স্পার: না N^2, তা নয় 2^N। এবং হ্যাঁ, এই গতিশীলটি তৈরি করা এটিকে সেরা করে তুলবে, চ্যালেঞ্জ হ'ল চার-পথের সম্পত্তি রেখে কীভাবে এটি গতিশীল করা যায়। @ পিটারটেলর: চমৎকার ছবি!
justhalf

5

আমি প্রায় প্রতিটি kসারি জুড়ে গ্রিডটি পুরোপুরি টুকরো টুকরো করে পরীক্ষা করে দেখলাম । এই কার্যকরভাবে একটি উপর একটি র্যান্ডম হাঁটার অনুরূপ কিছু মধ্যে এটি পরিবর্তন করে kদ্বারা N * N/kগ্রিড। সর্বাধিক কার্যকর বিকল্পটি হ'ল প্রতিটি সারিতে টুকরো টুকরো করা যাতে আমরা মাতালকে জিগজিগ করতে বাধ্য করি।

SIZE=19আমার কাছে 20x20 কেস ( ) রয়েছে

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);
    }
}

আপনার সমাধানে হাঁটাচলা শুরু হওয়ার আগেই আমি কি সমস্ত প্রান্ত মুছে ফেলার কথা ভাবছি?

@ লাম্বিক, হ্যাঁ আমি ভেবেছিলাম শীর্ষে মন্তব্যটি এটি পরিষ্কার করে দেবে।
পিটার টেলর

এটা, আপনাকে ধন্যবাদ। হাঁটতে চলতে প্রান্তগুলি মুছে ফেলে আপনি কতটা পার্থক্য তৈরি করতে পারেন তা অবাক করি।

কৌতূহলের বাইরে, এটি চালাতে কত সময় নেয় (পুরো এবং প্রতি রান)?
স্টকাস্টিক

@ স্টোকাস্টিক, প্রতি রান প্রায় 3 সেকেন্ড।
পিটার টেলর

3

যারা চাকা পুনরায় উদ্ভাবন করতে চান না তাদের জন্য

চিন্তা করবেন না! আমি আপনার জন্য এটি পুনরায় উদ্ভাবন করব :)

এটি জাভাতে, যাই হোক।

আমি একটি ওয়াকার ক্লাস তৈরি করেছি যা এলোমেলোভাবে চলার সাথে সম্পর্কিত হয়। এটি কোনও পদক্ষেপ বৈধ কিনা তা নির্ধারণের জন্য একটি সহায়ক পদ্ধতিও অন্তর্ভুক্ত রয়েছে (যদি এটি ইতিমধ্যে চলে গেছে)।

আমি ধরে নিচ্ছি যে আপনারা সবাই স্মার্ট লোকেরা নির্মাতার জন্য এলোমেলো সংখ্যার সংখ্যা নির্ধারণ করতে পারে, আমি এটি আপনার কাছে রেখে দিয়েছি যাতে আপনি নির্দিষ্ট কিছু ক্ষেত্রে পরীক্ষা করতে পারেন। এছাড়াও, মাতালকে হাঁটা (এলোমেলোভাবে) করতে কেবল ওয়াক () ফাংশনটিতে কল করুন (আপনি এটি অনুমান করেছেন!)

আমি অন্য কিছু সময় ক্যানকোম () ফাংশন বাস্তবায়ন করব। আমি এটি করার সর্বোত্তম উপায়টি সন্ধান করার পরে পছন্দ করি।

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মোছা পাথ পরীক্ষণ, এবং অদক্ষতা। আমি আপনার কোড সম্পাদনা করেছি (ধাঁধাটি মুদ্রণের জন্য অতিরিক্ত ফাংশন সহ)। যদি আপনি এটি অনুচিত বলে মনে করেন তবে নির্দ্বিধায় রোলব্যাক করুন।
justhalf

আপনার Edgeসঠিকভাবে প্রয়োগ হয় না Comparable<Edge>। আপনি যদি প্রান্তগুলি বিপরীত করেও সমান হিসাবে তুলনা করতে চান তবে আপনাকে সমতুল্য ক্ষেত্রেও বিপরীতটিকে বিবেচনা করা উচিত। এটি করার সহজতম উপায় হ'ল পয়েন্টগুলি অর্ডার করার জন্য কনস্ট্রাক্টর পরিবর্তন করা।
পিটার টেলর

@ পিটারটেলর: মাথা উঁচু করার জন্য ধন্যবাদ। আমি অ-সমতুল্য কেসটি সম্পর্কে কিছুটা ভাবলাম, তবে কেন এটি গুরুত্বপূর্ণ তা বুঝতে পেলাম না। আপনি কি জানেন যেখানে আমি বাস্তবায়নের প্রয়োজনীয়তাটি সন্ধান করতে পারি Comparable?
justhalf

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।

যদিও এটি 1 ডি হাঁটা পরাজিত করতে যাচ্ছে না, আমি আমার ধারণার সাথে খেলতে চেয়েছিলাম।

মূল ধারণাটি হ'ল গ্রিডটি বর্গাকার কক্ষগুলিতে বিভক্ত, প্রতিটি থেকে কেবল 'বাড়ির দিকে' যাওয়ার একটি পথ রয়েছে। খোলা পথটি মাতাল যেভাবে শেষের কাছাকাছি যায় is , তার অর্থ তাকে প্রতিটি সম্ভাব্য প্রস্থানটি অন্বেষণ করতে হবে, কেবলমাত্র তার মধ্যে একটির মুখের উপরে চটকা দেওয়া হয়েছে।

ঘরের আকারগুলি নিয়ে খেলার পরে, আমি পিটারের মতো একই সিদ্ধান্তে পৌঁছেছি, এটি আরও ছোট করে কেটে ফেলা ভাল। সেরা স্কোরগুলি 2 রুমের আকারের সাথে আসে।

Average score over 100 trials: 36051265

কোডটি ম্লান, গণ্ডগোলের কিছু মনে করবেন না। আপনি SHOWস্যুইচটিতে ফ্লিপ করতে পারেন এবং এটি প্রতিটি SHOW_INTপদক্ষেপে একটি চিত্র প্রদর্শন করবে যাতে আপনি এটিকে কার্যক্রমে দেখতে পারেন। একটি সম্পূর্ণ রান কিছু দেখতে:

এখানে চিত্র বর্ণনা লিখুন

(এটি পূর্ববর্তী 100x100 গ্রিডের চিত্র 20

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;
}

আমি কেবল লক্ষ্য করেছি যে তার বট / বাম থেকে> উপরের / ডানদিকে যাওয়া উচিত, যখন আমার বট / ডান-> উপরে / বামে যায়। এটি যদি সত্যিই গুরুত্বপূর্ণ হয় তবে আমি এটি পরিবর্তন করতে পারি, তবে ...
Geobits

এটি খুব সুন্দর এবং আমি মনে করি এটি প্রথম গতিশীল সমাধান। আমি আগ্রহী যে আপনার পথটি এখনও স্থায়ী রাস্তাগুলির মতো দীর্ঘ নয়।

যদি "বেশিক্ষণ দীর্ঘ না হয়" তবে আপনি যদি এক হিসাবে দীর্ঘ হিসাবে? 1/3 এবং অন্য হিসাবে দীর্ঘ 36x ডলার বলতে চান? : পি
জিওবিটস

3

188 কে, 2 টি পথ সহ

সর্বোত্তম এন্ট্রিগুলি 2 টি পাথ তৈরির পদ্ধতিকে গ্রহণ করে এবং মাতাল যখন পথের শেষের কাছাকাছি আসে তখন তার একটি কেটে ফেলা বলে মনে হয়। আমি মনে করি না যে আমি জাস্টহল্ফের প্রবেশকে মারতে পারি, কিন্তু আমি সাহায্য করতে পারিনি কিন্তু আশ্চর্য হয়েছি: 2 টি পথ কেন? 3, বা 5, বা 20 কেন নয়?

টিএল; ডিআর : 2 টি পথটি সর্বোত্তম বলে মনে হচ্ছে

তাই আমি একটি পরীক্ষা করেছি। স্ট্রেচ পাগলের কাঠামোর ভিত্তিতে, আমি বিভিন্ন সংখ্যক পথ পরীক্ষা করার জন্য একটি এন্ট্রি লিখেছিলাম। featureSizeপাথের সংখ্যা পরিবর্তনের জন্য আপনি প্যারামিটারটি টুইঙ্ক করতে পারেন । A featureSizeএর 20 টি 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

131 কে (20x20)

আমার প্রথম প্রয়াসটি ছিল উপরের এবং নীচের সারি বাদে সমস্ত অনুভূমিক প্রান্তগুলি সরিয়ে ফেলতে, তারপরে প্রতিটি বার ওয়াকার একটি কলামের নীচে পৌঁছালে আমি তার সামনে প্রান্তটি সরিয়ে ফেলতাম, যতক্ষণ না সে প্রতিটি কলামের নীচে পরিদর্শন করে এবং শেষ পর্যন্ত প্রস্থান করতে সক্ষম হতে। এর ফলে @ পিটারটেলারের 1 ডি ওয়াক অ্যাপ্রোচ যতটা পদক্ষেপ গড়ে গড়ে 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নির্দিষ্ট সময়ে ঠিক লক্ষ্যে পৌঁছানোর সম্ভাবনা দেয় gives আমরা একীভূত t*p(t) dt
হওয়া গড় সময়টি সন্ধানের জন্য লক্ষ্যটিতে পৌঁছানোর গড় সময়টি L**2একটি কারণের সাথে সমানুপাতিক হয় যা খুব দ্রুত 1 এ চলে যায় মানক বিচ্যুতি গড় সময়ের প্রায় 79% প্রায় স্থির থাকে।
এই গ্রাফটি বিভিন্ন পাথ দৈর্ঘ্যের লক্ষ্যে পৌঁছানোর গড় সময় দেখায় (5x5 থেকে 15x15 গ্রিড আকারের সাথে মিলিয়ে) এখানে চিত্র বর্ণনা লিখুন

এখানে লক্ষ্যে পৌঁছানোর সম্ভাবনাটি কেমন দেখাচ্ছে। দ্বিতীয় কার্ভটি ভরাট দেখায় কারণ প্রতিটি বিজোড় টাইমস্টেপে অবস্থানটি বিজোড় এবং তাই লক্ষ্যটিতে থাকতে পারে না। এখানে চিত্র বর্ণনা লিখুন

সেখান থেকে আমরা দেখতে পাচ্ছি যে ভারসাম্যপূর্ণ দ্বৈতপথ কৌশলটি এখানে সর্বোত্তমভাবে কাজ করে। বৃহত্তর গ্রিডগুলির জন্য, যেখানে আরও পাথ তৈরির ওভারহেড তাদের আকারের তুলনায় নগণ্য, আমরা পিটার টেলর যেভাবে বর্ণনা করেছেন তার অনুরূপ, তবে দৈর্ঘ্যের ভারসাম্য বজায় রেখে পাথের সংখ্যা বৃদ্ধি করা আরও ভাল might

যদি আমরা কোনও নোড একেবারেই অপসারণ না করি?

তারপরে আমাদের দ্বিগুণ হাঁটার যোগ্য নোড থাকবে, আরও দুটি পরিবর্তে চারটি সম্ভাব্য দিকনির্দেশ। দেখে মনে হবে এটি কোথাও পাওয়ার সম্ভাবনা খুব কম করে দেয়। যাইহোক, সিমিউলেশন, অন্যথায় দেন একটি 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। তবে এটি প্রশ্নের উত্তর দেয় না এবং প্রথম দুটি শব্দ আপনার বিশ্লেষণের উপসংহারের সাথে বিরোধী। এবং, আপনার সত্যিই আপনার গ্রাফগুলির অক্ষগুলি লেবেল করা উচিত। গ্রিড আকারের জন্য আপনার সম্ভাব্যতা গ্রাফটি প্রযোজ্য?
justhalf

সুন্দর ছবি তবে আমি নিশ্চিত না যে আপনার প্রশ্নটি ঠিক আছে। উদাহরণস্বরূপ "যেহেতু লোকটি এলোমেলোভাবে পদক্ষেপ নেয়, তাই কেউ মনে করতে পারে যে কোনও নোড অপসারণ করলে তার দীর্ঘমেয়াদে বাড়িতে যাওয়ার সম্ভাবনা বাড়বে" " 1) লোকটি সর্বদা নির্ধারিত নিয়মের অধীনে বাড়ি ফিরে আসবে যাতে এটি প্রাসঙ্গিক বলে মনে হয় না এবং 2) আমরা নোড নয় প্রান্তগুলি সরিয়ে দিচ্ছি।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.