ভেক্টরিতে! - ভেক্টর রেসিং গ্র্যান্ড প্রিক্স


39

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

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

ট্র্যাক

  • মানচিত্রটি একটি দ্বিমাত্রিক গ্রিড, যেখানে প্রতিটি ঘরের পূর্ণসংখ্যার স্থানাঙ্ক থাকে।
  • আপনি গ্রিড কোষে সরান।
  • প্রতিটি গ্রিড সেলটি হয় ট্র্যাকের অংশ বা এটি প্রাচীর।
  • ঠিক একটি ট্র্যাক সেল হ'ল সূচনা সমন্বয়।
  • কমপক্ষে একটি ট্র্যাক সেল লক্ষ্য হিসাবে মনোনীত করা হয়। এগুলির যে কোনওটিতে অবতরণ রেসটি সম্পূর্ণ করে। একাধিক গোল কক্ষগুলি অগত্যা সংযুক্ত নয়।

গাড়ী চালনা

আপনার গাড়ী একটি নির্দিষ্ট স্থানাঙ্কে এবং বেগ ভেক্টর দিয়ে শুরু হয় (0, 0)। প্রতিটি ঘুরে আপনি বেগের প্রতিটি উপাদানকে সামঞ্জস্য করতে পারেন ±1বা এটি যেমন রেখে দিতে পারেন। তারপরে, ফলস্বরূপ বেগ ভেক্টরটি আপনার গাড়ির অবস্থানটিতে যুক্ত করা হবে।

একটি ছবি সাহায্য করতে পারে! লাল বৃত্তটি আপনার অবস্থানটি শেষ বার ছিল। নীল বৃত্তটি আপনার বর্তমান অবস্থান। আপনার বেগটি লাল থেকে নীল বৃত্তের ভেক্টর। এই ঘুরে আপনি কীভাবে আপনার বেগকে সামঞ্জস্য করবেন তার উপর নির্ভর করে আপনি যে কোনও সবুজ চেনাশোনাতে যেতে পারেন move

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

আপনি যদি কোনও দেয়ালে অবতরণ করেন, আপনি অবিলম্বে হারাবেন।

তোমার কাজ

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

ইনপুট

আপনার প্রোগ্রামটি শুরু করা হলে, স্টিডিন থেকে পড়ুন :

target
n m
[ASCII representation of an n x m racetrack]
time

targetট্র্যাকটি সম্পূর্ণ করতে আপনি সর্বাধিক সংখ্যক টার্ন নেবেন এবং ট্র্যাকের timeজন্য আপনার মোট সময় বাজেট হ'ল সেকেন্ডে (অগত্যা পূর্ণসংখ্যার নয়) not সময় সম্পর্কে বিস্তারিত জানার জন্য নীচে দেখুন।

নতুন লাইন-বিস্মৃত ট্র্যাকের জন্য, নিম্নলিখিত অক্ষরগুলি ব্যবহৃত হয়:

  • # - প্রাচীর
  • S- শুরু
  • *- একটি লক্ষ্য
  • . - অন্যান্য সমস্ত ট্র্যাক সেল (যেমন রাস্তা)

n x mগ্রিডের বাইরের সমস্ত কক্ষ দেয়াল হিসাবে আবদ্ধ।

সমন্বিত উত্স উপরের বাম কোণে is

এখানে একটি সহজ উদাহরণ:

8
4.0
9 6
###...***
###...***
###...***
......###
S.....###
......###

0-ভিত্তিক সূচক ব্যবহার করে, সূচনা সমন্বয় হবে (0,4)

প্রতিটি পদক্ষেপের পরে আপনি আরও ইনপুট পাবেন:

x y
u v
time

কোথায় x, y, u, vসব 0 ভিত্তিক পূর্ণসংখ্যা। (x,y)আপনার বর্তমান অবস্থান এবং (u,v)আপনার বর্তমান বেগ। নোট করুন x+uএবং / অথবা y+vসীমা ছাড়িয়ে যেতে পারে।

timeআপনার সময় বাজেটের যা কিছু অবশিষ্ট রয়েছে তা সেকেন্ডে। নির্দ্বিধায় এটিকে অবহেলা করুন। এটি কেবলমাত্র তাদের অংশগ্রহণকারীদের জন্য যারা তাদের বাস্তবায়নকে সময়সীমাতে নিতে চান।

গেমটি শেষ হয়ে গেলে (কারণ আপনি কোনও দেয়ালে অবতরণ করেছেন, সীমা ছাড়িয়ে targetগেছেন, পালা ছাড়িয়েছেন , সময় পেরিয়েছেন বা লক্ষ্যে পৌঁছেছেন), আপনি খালি লাইন পাবেন।

আউটপুট

প্রতিটি পরিবর্তনের জন্য, stdout লিখুন :

Δu Δv

যেখানে Δuএবং Δvপ্রতিটি এক -1, 0, 1। এটি (u,v)আপনার নতুন অবস্থান নির্ধারণ করতে যুক্ত করা হবে । কেবল পরিষ্কার করার জন্য, দিকনির্দেশগুলি নীচে রয়েছে

(-1,-1) ( 0,-1) ( 1,-1)
(-1, 0) ( 0, 0) ( 1, 0)
(-1, 1) ( 0, 1) ( 1, 1)

উপরের উদাহরণের জন্য একটি অনুকূল সমাধান হবে

1 0
1 -1
1 0

নোট করুন যে কন্ট্রোলার স্টডারারের সাথে নিজেকে সংযুক্ত করে না , সুতরাং আপনার বট বিকাশের সময় আপনার যে ধরণের ডিবাগ আউটপুট প্রয়োজন হতে পারে তার জন্য আপনি এটি ব্যবহার করতে মুক্ত। যদিও আপনার জমা দেওয়া কোডে এই জাতীয় কোনও আউটপুট সরান / মন্তব্য করুন।

আপনার বট প্রতিটি একক পালাতে সাড়া দিতে আধ সেকেন্ড সময় নিতে পারে। যে সময়গুলির জন্য বেশি সময় নেয়, আপনার target/2সেকেন্ডের একটি সময় বাজেট (প্রতি ট্র্যাক) হবে । প্রতিবার কোনও পালা আধ সেকেন্ডের বেশি সময় নেয়, অতিরিক্ত সময় আপনার সময় বাজেট থেকে বিয়োগ করা হবে। যখন আপনার সময়ের বাজেট শূন্য হিট হয় তখন বর্তমান রেসটি বাতিল করা হবে।

নতুন: ব্যবহারিক কারণে, আমাকে একটি স্মৃতি সীমা নির্ধারণ করতে হবে (যেহেতু মেমরিটি যুক্তিসঙ্গত ট্র্যাক আকারের জন্য সময়ের চেয়ে সীমাবদ্ধ বলে মনে হয়)। অতএব, আমি কোনো পরীক্ষার রান যেখানে নৌকো চেয়ে বেশি ব্যবহার বাতিল করতে হবে 1GB মেমরি হিসাবে দ্বারা পরিমাপ প্রক্রিয়া এক্সপ্লোরার হিসাবে ব্যক্তিগত বাইট

স্কোরিং

20 টি ট্র্যাকের একটি মাপদণ্ড রয়েছে। প্রতিটি ট্র্যাকের জন্য:

  • আপনি যদি ট্র্যাকটি সম্পূর্ণ করেন তবে আপনার স্কোরটি এমন একটি চলকের সংখ্যা যা আপনার দ্বারা বিভক্তtarget কোনও লক্ষ্য কক্ষে পৌঁছতে হবে ।
  • সময় / মেমরি ফুরিয়ে গেলে বা লক্ষ্য পৌঁছাতে না সামনে targetপালাক্রমে অতিবাহিত হয়েছে বা আপনি যে কোনো সময়ে একটি প্রাচীর অবতরণের / সীমার বাইরে, আপনার স্কোর হল 2
  • যদি আপনার প্রোগ্রামটি নিয়ন্ত্রক না হয় তবে আপনার স্কোরটি সেই ট্র্যাকটিতে গড়ে 10 টিরও বেশি রান (দয়া করে আপনার উত্তরে এটি বর্ণনা করুন)।

আপনার সামগ্রিক স্কোরটি পৃথক ট্র্যাক স্কোরের যোগফল। সর্বনিম্ন স্কোর জয়!

তদুপরি, প্রতিটি অংশগ্রহণকারী একটি অতিরিক্ত বেঞ্চমার্ক ট্র্যাক সরবরাহ করতে (এবং দৃ strongly়ভাবে উত্সাহিত) হতে পারে, যা অফিসিয়াল তালিকায় যুক্ত হবে। এই নতুন ট্র্যাক সহ পূর্ববর্তী উত্তরগুলি পুনরায় মূল্যায়ন করা হবে। এটি নিশ্চিত করার জন্য যে কোনও সমাধানের সাথে বিদ্যমান পরীক্ষার কেসগুলি খুব কাছাকাছিভাবে তৈরি করা হয়নি এবং আকর্ষণীয় প্রান্তের কেসগুলি আমি মিস করেছি (তবে যা আপনি দেখতে পাচ্ছেন) এর জন্য অ্যাকাউন্ট করতে হবে।

টাই ব্রেকিং

এখন থেকে যেহেতু ইতিমধ্যে একটি সর্বোত্তম সমাধান রয়েছে, এটি সম্ভবত অংশগ্রহণকারীদের স্কোরের প্রধান কারণ factor

যদি কোনও টাই থাকে (বেশ কয়েকটি জবাবের কারণে সমস্ত ট্র্যাকগুলি নিখুঁতভাবে বা অন্যথায় সমাধান করা হয়), আমি টাইটি ভাঙ্গতে অতিরিক্ত (বৃহত্তর) পরীক্ষার কেস যুক্ত করব। এই টাই-ব্রেকার তৈরি করার সময় কোনও মানব পক্ষপাত এড়ানোর জন্য এগুলি একটি নির্দিষ্ট পদ্ধতিতে তৈরি করা হবে :

  • আমি পাশ দৈর্ঘ্য বৃদ্ধি হবে nদ্বারা 10এই ভাবে উত্পন্ন গত ট্র্যাক তুলনায়। (তারা টাই না ভাঙ্গলে আমি আকারগুলি এড়িয়ে যেতে পারি))
  • ভিত্তি হ'ল এই ভেক্টর-গ্রাফিক
  • এই গাণিতিক স্নিপেট ব্যবহার করে কাঙ্ক্ষিত রেজোলিউশনে এটি উত্সাহিত করা হবে ।
  • শুরুটি উপরের বাম কোণে। বিশেষত, এটি ট্র্যাকের প্রান্তের শীর্ষ-সারিটির বাম-সর্বাধিক ঘর হবে।
  • লক্ষ্যটি নীচে ডানদিকে রয়েছে। বিশেষত, এটি ট্র্যাকের প্রান্তের নীচে-সারিটির ডান-সর্বাধিক ঘর হবে।
  • targetইচ্ছা 4*n

প্রাথমিক বেঞ্চমার্কের চূড়ান্ত ট্র্যাকটি ইতিমধ্যে এর সাথে তৈরি হয়েছিল n = 50

নিয়ামক

প্রোগ্রামগুলি যা জমা দেওয়ার পরীক্ষা করে তা রুবিতে লেখা হয় এবং আমি ব্যবহার করব এমন মাপদণ্ডের ফাইলের সাথে গিটহাবের উপরও পাওয়া যাবে। সেখানে একটি উদাহরণ বটও বলা randomracer.rbহয় যা কেবল এলোমেলো পদক্ষেপ গ্রহণ করে। যোগাযোগটি কীভাবে কাজ করে তা দেখতে আপনি আপনার বটের প্রাথমিক বিন্যাস হিসাবে এটির প্রাথমিক কাঠামোটি ব্যবহার করতে পারেন।

আপনি নিজের পছন্দের ট্র্যাক ফাইলের বিরুদ্ধে নিজের বট চালাতে পারেন:

ruby controller.rb track_file_name command to run your racer

যেমন

ruby controller.rb benchmark.txt ruby randomracer.rb

ভান্ডারে দুটি শ্রেণিও রয়েছে Point2Dএবং Track। যদি আপনার জমাটি রুবিতে লেখা থাকে তবে আপনার সুবিধার জন্য সেগুলি বিনা দ্বিধায় ব্যবহার করুন।

কমান্ড-লাইন সুইচ

আপনি কম্যান্ড-লাইন সুইচ যোগ করতে পারেন -v, -s, -tবেঞ্চমার্ক ফাইল নাম আগে। আপনি যদি একাধিক স্যুইচ ব্যবহার করতে চান তবে উদাহরণস্বরূপ, আপনি এটিও করতে পারেন -vs। তারা এটাই করে:

-v (ভার্বোস): কন্ট্রোলার থেকে আরও কিছুটা ডিবাগ আউটপুট উত্পাদন করতে এটি ব্যবহার করুন।

-s (নিঃশব্দ): আপনি যদি নিজের অবস্থান এবং গতিবেগ নিজেকে ট্র্যাক করে রাখতে পছন্দ করেন এবং সময়ের বাজেটের বিষয়ে চিন্তা না করেন তবে আপনি এই পতাকাটি দিয়ে প্রতিটি পালা (আপনার জমা দেওয়ার জন্য প্রেরিত) তিনটি লাইন আউটপুট বন্ধ করতে পারেন।

-t(ট্র্যাকস): আপনাকে পরীক্ষার জন্য পৃথক ট্র্যাকগুলি নির্বাচন করতে দেয়। যেমন -t "1,2,5..8,15"1, 2, 5, 6, 7, 8 এবং 15 কেবল ট্র্যাক পরীক্ষা করে। এই বৈশিষ্ট্য এবং বিকল্পগুলি পার্সার করার জন্য ভেন্তেরোকে অনেক ধন্যবাদ ।

আপনার জমা

সংক্ষেপে, দয়া করে আপনার উত্তরে নিম্নলিখিতটি অন্তর্ভুক্ত করুন:

  • তোমার ফলাফল.
  • আপনি যদি এলোমেলো ব্যবহার করে থাকেন তবে দয়া করে এটি জানিয়ে দিন, তাই আমি একাধিক রানের তুলনায় আপনার স্কোরকে গড় করতে পারি।
  • আপনার জমা দেওয়ার জন্য কোড।
  • উইন্ডোজ 8 মেশিনে চলিত আপনার পছন্দের ভাষার জন্য একটি বিনামূল্যে সংকলক বা দোভাষীর অবস্থান।
  • প্রয়োজনে সংকলনের নির্দেশাবলী।
  • আপনার জমাটি চালানোর জন্য একটি উইন্ডোজ কমান্ড-লাইন স্ট্রিং।
  • আপনার জমা দেওয়ার -sপতাকাটি দরকার কিনা ।
  • ( allyচ্ছিকভাবে ) একটি নতুন, দ্রবণযোগ্য ট্র্যাক যা মানদণ্ডে যুক্ত করা হবে। আমি targetনিজেই আপনার ট্র্যাকের জন্য একটি যুক্তিসঙ্গত নির্ধারণ করব । ট্র্যাকটি যখন বেঞ্চমার্কে যুক্ত হবে, আমি আপনার উত্তরের বাইরে এটি সম্পাদনা করব। আমি আপনাকে আলাদা ট্র্যাকের জন্য জিজ্ঞাসা করার অধিকার সংরক্ষণ করি (কেবলমাত্র আপনি যদি অস্বাভাবিকভাবে বড় ট্র্যাক যোগ করেন তবে ট্র্যাকটিতে অশ্লীল ASCII শিল্প অন্তর্ভুক্ত করুন ইত্যাদি)। আমি যখন পরীক্ষার কেসটি বেঞ্চমার্ক সেটে যুক্ত করব, তখন আমি এই পোস্টের বিশৃঙ্খলা হ্রাস করার জন্য আপনার উত্তরের ট্র্যাকটি বেঞ্চমার্ক ফাইলে ট্র্যাকের লিঙ্কের সাথে প্রতিস্থাপন করব।

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

সেরা ড্রাইভারটি ভেক্টরিয়াস হয়ে উঠুক!

তবে আমি খেলতে চাই!

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

লিডারবোর্ড

সর্বশেষ আপডেট হয়েছে: 01/09/2014, 21:29 ইউটিসি
বেঞ্চমার্কের ট্র্যাকগুলি: 25
টাই-ব্রেকার আকার: 290, 440

  1. 6,86688 - Kuroi Neko
  2. 8.73108 - ব্যবহারকারী 2357112 - দ্বিতীয় জমা
  3. 9.86627 - নিনেনিও
  4. 10.66109 - ব্যবহারকারী 2357112 - 1 ম জমা
  5. 12.49643 - রায়
  6. 40.0759 - ছদ্মনাম 117 (সম্ভাব্য)

বিস্তারিত পরীক্ষার ফলাফল । (সম্ভাব্য জমা দেওয়ার স্কোরগুলি পৃথকভাবে নির্ধারণ করা হয়েছে।)

উত্তর:


5

সি ++ 11 - 6.66109

তবুও আরেকটি প্রস্থের প্রথম অনুসন্ধান বাস্তবায়ন, কেবলমাত্র অনুকূলিত।

এটি অবশ্যই -s বিকল্প দিয়ে চালানো উচিত ।
এর ইনপুটটি একেবারেই স্যানিটাইজ করা হয় না, তাই ভুল ট্র্যাকগুলি এটিকে কুমড়োতে পরিণত করতে পারে।

আমি এটি মাইক্রোসফ্ট ভিজ্যুয়াল সি ++ 2013 দিয়ে পরীক্ষা করেছি, ডিফল্ট / ও 2 পতাকা দিয়ে বিল্ডটি প্রকাশ করেছি (গতির জন্য অনুকূলিতকরণ)।
জি ++ এবং মাইক্রোসফ্ট আইডিই দিয়ে ঠিক আছে।
আমার ব্রেডবোন মেমরি বরাদ্দকারী একটি খাঁজকাটা টুকরো, সুতরাং এটির অন্যান্য এসটিএল বাস্তবায়নের সাথে কাজ করার আশা করবেন না unordered_set!

#include <cstdint>
#include <iostream>
#include <fstream>
#include <sstream>
#include <queue>
#include <unordered_set>

#define MAP_START 'S'
#define MAP_WALL  '#'
#define MAP_GOAL  '*'

#define NODE_CHUNK_SIZE   100 // increasing this will not improve performances
#define VISIT_CHUNK_SIZE 1024 // increasing this will slightly reduce mem consumption at the (slight) cost of speed

#define HASH_POS_BITS 8 // number of bits for one coordinate
#define HASH_SPD_BITS (sizeof(size_t)*8/2-HASH_POS_BITS)

typedef int32_t tCoord; // 32 bits required to overcome the 100.000 cells (insanely) long challenge

// basic vector arithmetics
struct tPoint {
    tCoord x, y;
    tPoint(tCoord x = 0, tCoord y = 0) : x(x), y(y) {}
    tPoint operator+ (const tPoint & p) { return tPoint(x + p.x, y + p.y); }
    tPoint operator- (const tPoint & p) { return tPoint(x - p.x, y - p.y); }
    bool operator== (const tPoint & p) const { return p.x == x && p.y == y;  }
};

// a barebone block allocator. Improves speed by about 30%
template <class T, size_t SIZE> class tAllocator
{
    T * chunk;
    size_t i_alloc;
    size_t m_alloc;
public:
    typedef T                 value_type;
    typedef value_type*       pointer;
    typedef const value_type* const_pointer;
    typedef std::size_t       size_type;
    typedef value_type&       reference;
    typedef const value_type& const_reference;
    tAllocator()                                              { m_alloc = i_alloc = SIZE; }
    template <class U> tAllocator(const tAllocator<U, SIZE>&) { m_alloc = i_alloc = SIZE; }
    template <class U> struct rebind { typedef tAllocator<U, SIZE> other; };
    pointer allocate(size_type n, const_pointer = 0)
    {
        if (n > m_alloc) { i_alloc = m_alloc = n; }      // grow max size if request exceeds capacity
        if ((i_alloc + n) > m_alloc) i_alloc = m_alloc;  // dump current chunk if not enough room available
        if (i_alloc == m_alloc) { chunk = new T[m_alloc]; i_alloc = 0; } // allocate new chunk when needed
        T * mem = &chunk[i_alloc];
        i_alloc += n;
        return mem;
    }
    void deallocate(pointer, size_type) { /* memory is NOT released until process exits */ }
    void construct(pointer p, const value_type& x) { new(p)value_type(x); }
    void destroy(pointer p) { p->~value_type(); }
};

// a node in our search graph
class tNode {
    static tAllocator<tNode, NODE_CHUNK_SIZE> mem; // about 10% speed gain over a basic allocation
    tNode * parent;
public:
    tPoint pos;
    tPoint speed;
    static tNode * alloc (tPoint pos, tPoint speed, tNode * parent) { return new (mem.allocate(1)) tNode(pos, speed, parent); }
    tNode (tPoint pos = tPoint(), tPoint speed = tPoint(), tNode * parent = nullptr) : parent(parent), pos(pos), speed(speed) {}
    bool operator== (const tNode& n) const { return n.pos == pos && n.speed == speed; }
    void output(void)
    {
        std::string output;
        tPoint v = this->speed;
        for (tNode * n = this->parent ; n != nullptr ; n = n->parent)
        {
            tPoint a = v - n->speed;
            v = n->speed;
            std::ostringstream ss;  // a bit of shitty c++ text I/O to print elements in reverse order
            ss << a.x << ' ' << a.y << '\n';
            output = ss.str() + output;
        }
        std::cout << output;
    }
};
tAllocator<tNode, NODE_CHUNK_SIZE> tNode::mem;

// node queueing and storing
static int num_nodes = 0;
class tNodeJanitor {
    // set of already visited nodes. Block allocator improves speed by about 20%
    struct Hasher { size_t operator() (tNode * const n) const 
    {
        int64_t hash = // efficient hashing is the key of performances
            ((int64_t)n->pos.x   << (0 * HASH_POS_BITS))
          ^ ((int64_t)n->pos.y   << (1 * HASH_POS_BITS))
          ^ ((int64_t)n->speed.x << (2 * HASH_POS_BITS + 0 * HASH_SPD_BITS))
          ^ ((int64_t)n->speed.y << (2 * HASH_POS_BITS + 1 * HASH_SPD_BITS));
        return (size_t)((hash >> 32) ^ hash);
        //return (size_t)(hash);
    }
    };
    struct Equalizer { bool operator() (tNode * const n1, tNode * const n2) const
        { return *n1 == *n2; }};
    std::unordered_set<tNode *, Hasher, Equalizer, tAllocator<tNode *, VISIT_CHUNK_SIZE>> visited;
    std::queue<tNode *> queue; // currently explored nodes queue
public:
    bool empty(void) { return queue.empty();  }
    tNode * dequeue() { tNode * n = queue.front(); queue.pop(); return n; }
    tNode * enqueue_if_new (tPoint pos, tPoint speed = tPoint(0,0), tNode * parent = nullptr)
    {
        tNode signature (pos, speed);
        tNode * n = nullptr;
        if (visited.find (&signature) == visited.end()) // the classy way to check if an element is in a set
        {
            n = tNode::alloc(pos, speed, parent);
            queue.push(n);
            visited.insert (n);
num_nodes++;
        }
        return n;
    }
};

// map representation
class tMap {
    std::vector<char> cell;
    tPoint dim; // dimensions
public:
    void set_size(tCoord x, tCoord y) { dim = tPoint(x, y); cell.resize(x*y); }
    void set(tCoord x, tCoord y, char c) { cell[y*dim.x + x] = c; }
    char get(tPoint pos)
    {
        if (pos.x < 0 || pos.x >= dim.x || pos.y < 0 || pos.y >= dim.y) return MAP_WALL;
        return cell[pos.y*dim.x + pos.x];
    }
    void dump(void)
    {
        for (int y = 0; y != dim.y; y++)
        {
            for (int x = 0; x != dim.x; x++) fprintf(stderr, "%c", cell[y*dim.x + x]);
            fprintf(stderr, "\n");
        }
    }
};

// race manager
class tRace {
    tPoint start;
    tNodeJanitor border;
    static tPoint acceleration[9];
public:
    tMap map;
    tRace ()
    {
        int target;
        tCoord sx, sy;
        std::cin >> target >> sx >> sy;
        std::cin.ignore();
        map.set_size (sx, sy);
        std::string row;
        for (int y = 0; y != sy; y++)
        {
            std::getline(std::cin, row);
            for (int x = 0; x != sx; x++)
            {
                char c = row[x];
                if (c == MAP_START) start = tPoint(x, y);
                map.set(x, y, c);
            }
        }
    }

    // all the C++ crap above makes for a nice and compact solver
    tNode * solve(void)
    {
        tNode * initial = border.enqueue_if_new (start);
        while (!border.empty())
        {
            tNode * node = border.dequeue();
            tPoint p = node->pos;
            tPoint v = node->speed;
            for (tPoint a : acceleration)
            {
                tPoint nv = v + a;
                tPoint np = p + nv;
                char c = map.get(np);
                if (c == MAP_WALL) continue;
                if (c == MAP_GOAL) return new tNode (np, nv, node);
                border.enqueue_if_new (np, nv, node);
            }
        }
        return initial; // no solution found, will output nothing
    }
};
tPoint tRace::acceleration[] = {
    tPoint(-1,-1), tPoint(-1, 0), tPoint(-1, 1),
    tPoint( 0,-1), tPoint( 0, 0), tPoint( 0, 1),
    tPoint( 1,-1), tPoint( 1, 0), tPoint( 1, 1)};

#include <ctime>
int main(void)
{
    tRace race;
    clock_t start = clock();
    tNode * solution = race.solve();
    std::cerr << "time: " << (clock()-start)/(CLOCKS_PER_SEC/1000) << "ms nodes: " << num_nodes << std::endl;
    solution->output();
    return 0;
}

ফলাফল

 No.       Size     Target   Score     Details
-------------------------------------------------------------------------------------
  1       37 x 1        36   0.22222   Racer reached goal at ( 36, 0) in 8 turns.
  2       38 x 1        37   0.24324   Racer reached goal at ( 37, 0) in 9 turns.
  3       33 x 1        32   0.25000   Racer reached goal at ( 32, 0) in 8 turns.
  4       10 x 10       10   0.40000   Racer reached goal at ( 7, 7) in 4 turns.
  5        9 x 6         8   0.37500   Racer reached goal at ( 6, 0) in 3 turns.
  6       15 x 7        16   0.37500   Racer reached goal at ( 12, 4) in 6 turns.
  7       17 x 8        16   0.31250   Racer reached goal at ( 14, 0) in 5 turns.
  8       19 x 13       18   0.27778   Racer reached goal at ( 0, 11) in 5 turns.
  9       60 x 10      107   0.14953   Racer reached goal at ( 0, 6) in 16 turns.
 10       31 x 31      106   0.23585   Racer reached goal at ( 27, 0) in 25 turns.
 11       31 x 31      106   0.24528   Racer reached goal at ( 15, 15) in 26 turns.
 12       50 x 20       50   0.24000   Racer reached goal at ( 49, 10) in 12 turns.
 13      100 x 100    2600   0.01385   Racer reached goal at ( 50, 0) in 36 turns.
 14       79 x 63      242   0.24380   Racer reached goal at ( 3, 42) in 59 turns.
 15       26 x 1        25   0.32000   Racer reached goal at ( 25, 0) in 8 turns.
 16       17 x 1        19   0.52632   Racer reached goal at ( 16, 0) in 10 turns.
 17       50 x 1        55   0.34545   Racer reached goal at ( 23, 0) in 19 turns.
 18       10 x 7        23   0.34783   Racer reached goal at ( 1, 3) in 8 turns.
 19       55 x 55       45   0.17778   Racer reached goal at ( 50, 26) in 8 turns.
 20      101 x 100     100   0.14000   Racer reached goal at ( 99, 99) in 14 turns.
 21   100000 x 1         1   1.00000   Racer reached goal at ( 0, 0) in 1 turns.
 22       50 x 50      200   0.05500   Racer reached goal at ( 47, 46) in 11 turns.
 23      290 x 290    1160   0.16466   Racer reached goal at ( 269, 265) in 191 turns.
-------------------------------------------------------------------------------------
TOTAL SCORE:                 6.66109

ক্রিয়াকাণ্ড

সেই কৃপণ সি ++ টি ভাষার একটি ছদ্মবেশ রয়েছে যা আপনাকে কেবল একটি ম্যাচস্টিক সরানোর জন্য হুপসের মধ্য দিয়ে ঝাঁপিয়ে পড়ে। তবে, আপনি তুলনামূলকভাবে দ্রুত এবং মেমরি-দক্ষ কোড উত্পাদন করতে এটি চাবুক করতে পারেন।

হ্যাশ

এখানে কীগুলি নোডগুলির জন্য একটি ভাল হ্যাশ টেবিল সরবরাহ করা। এটি কার্যকর করার গতির জন্য এখন পর্যন্ত প্রভাবশালী গুণক। (জিএনইউ এবং মাইক্রোসফ্ট)
এর দুটি বাস্তবায়ন unordered_set30% কার্যকর করার গতি পার্থক্য পেয়েছে (জিএনইউর পক্ষে, হ্যাঁ!)।

পার্থক্যটি সত্যিই অবাক করার মতো নয়, ট্রাকের বোঝা কোডের পিছনে কী লুকানো আছে unordered_set

কৌতূহলের বাইরে আমি হ্যাশ টেবিলের চূড়ান্ত অবস্থার বিষয়ে কিছু পরিসংখ্যান করেছি।
উভয় অ্যালগরিদম প্রায় একই বালতি / উপাদান অনুপাতের সাথে শেষ হয়, তবে পুনরায় ভাগ আলাদা হয়:
290x290 টাই ব্রেকারটির জন্য, জিএনইউ নন খালি বালতিতে গড়ে 1.5 টি উপাদান পায়, যখন মাইক্রোসফ্ট 5.8 (!) এ থাকে।

মনে হচ্ছে আমার হ্যাশিংয়ের কাজটি মাইক্রোসফ্ট দ্বারা খুব ভালভাবে এলোমেলোভাবে করা যায় না ... আমি অবাক হই যে রেডমন্ডের ছেলেরা সত্যিই তাদের এসটিএলকে বেঞ্চমার্ক করেছে, অথবা আমার ব্যবহারের ক্ষেত্রে কেবল জিএনইউ বাস্তবায়নের পক্ষে রয়েছে ...

অবশ্যই, আমার হ্যাশিং ফাংশন অনুকূলের কাছাকাছি কোথাও নেই। আমি একাধিক শিফট / মুলসের উপর ভিত্তি করে সাধারণ পূর্ণসংখ্যার মিশ্রণটি ব্যবহার করতে পারতাম তবে একটি হ্যাশ-দক্ষ ফাংশন গণনা করতে সময় নেয়।

এটি উপস্থিত রয়েছে যে সংখ্যার তুলনায় হ্যাশ টেবিল প্রশ্নের সংখ্যা খুব বেশি appears উদাহরণস্বরূপ, 290x290 টাই ব্রেকারে, আপনার 22.7 মিলিয়ন প্রশ্নের জন্য প্রায় 3.6 মিলিয়ন সন্নিবেশ রয়েছে।
এই প্রসঙ্গে, একটি সাবঅপটিমাল কিন্তু দ্রুত হ্যাশিং আরও ভাল পারফরম্যান্স দেয়।

মেমরি বরাদ্দ

একটি দক্ষ মেমরি বরাদ্দ সরবরাহকারী দ্বিতীয় আসে। এটি প্রায় 30% দ্বারা পারফরম্যান্স উন্নত করেছে। এটি যুক্ত ক্রেপ কোডের জন্য মূল্যবান কিনা তা বিতর্কযোগ্য :)।

বর্তমান সংস্করণটি নোডে 40 থেকে 55 বাইটের মধ্যে ব্যবহার করে।
ক্রিয়ামূলক তথ্য নোডের জন্য 24 বাইট প্রয়োজন (4 স্থানাঙ্ক এবং 2 পয়েন্টার)।
পাগল 100.000 লাইন পরীক্ষার ক্ষেত্রে, স্থানাঙ্কগুলি 4 বাইট শব্দের মধ্যে সংরক্ষণ করতে হবে, অন্যথায় আপনি শর্টস ব্যবহার করে 8 বাইট অর্জন করতে পারবেন (সর্বাধিক 32767 এর স্থানাঙ্কের মান সহ)। বাকী বাইটগুলি বেশিরভাগই আনর্ডারড সেটগুলির হ্যাশ টেবিল দ্বারা গ্রাস করা হয়। এর অর্থ হ'ল ডেটা হ্যান্ডলিংটি "দরকারী" পেডলোডের চেয়ে কিছুটা বেশি খরচ করে।

এবং বিজয়ী...

উইন under এর অধীনে আমার পিসিতে টাই ব্রেকার (কেস 23, 290x290) প্রায় ২.২ সেকেন্ডের মধ্যে সবচেয়ে খারাপ সংস্করণ (অর্থাত্ মাইক্রোসফ্ট সংকলিত) দ্বারা প্রায় 185 এমবি স্মৃতি খরচ করে সমাধান করা হয়েছে।
তুলনার জন্য, বর্তমান নেতা (ব্যবহারকারী 2357112 দ্বারা অজগর কোড) 30 সেকেন্ডের চেয়ে কিছুটা বেশি সময় নেয় এবং প্রায় 780 এমবি গ্রাস করে।

নিয়ামক সমস্যা

আমি নিশ্চিত না যে আমার জীবন বাঁচাতে আমি রুবিতে কোড করতে সক্ষম হব।
যাইহোক, আমি নিয়ন্ত্রণকারী কোডের বাইরে দুটি সমস্যা চিহ্নিত এবং হ্যাক করেছি:

1) মানচিত্র পড়া track.rb

রুবি ১.৯.৩ ইনস্টল করার সাথে সাথে ট্র্যাক রিডারটি shift.to_iউপলব্ধ না হওয়ায় ক্রোক করবে string.lines
অনলাইন রুবি ডকুমেন্টেশনের মাধ্যমে দীর্ঘক্ষণ বিচূর্ণ হওয়ার পরে আমি স্ট্রিংস ছেড়ে দিয়েছিলাম এবং এর পরিবর্তে একটি মধ্যবর্তী অ্যারে ব্যবহার করেছি (ঠিক ততক্ষণে ফাইলের সূচনাতে):

def initialize(string)
    @track = Array.new;
    string.lines.each do |line|
        @track.push (line.chomp)
    end

2) ভূত হত্যা controller.rb

অন্যান্য পোস্টারগুলি ইতিমধ্যে উল্লেখ করেছে যে নিয়ামক কখনও কখনও ইতিমধ্যে উপস্থিত প্রসেসগুলি মেরে ফেলার চেষ্টা করে। এই অসম্মানজনক ত্রুটির আউটপুটগুলি এড়াতে আমি কেবল ব্যতিক্রমগুলি সামলিয়েছি (লাইনের ১৩৪ টি)

if silent
    begin # ;!;
        Process.kill('KILL', racer.pid)
    rescue Exception => e
    end

পরীক্ষা ক্ষেত্রে

বিএফএস সলভারদের বর্বর বলের পদ্ধতির কাছে পরাস্ত করার জন্য, সবচেয়ে খারাপ ট্র্যাকটি 100.000 কোষের মানচিত্রের বিপরীত: শুরু থেকে যতদূর সম্ভব লক্ষ্য সহ একটি সম্পূর্ণ মুক্ত অঞ্চল।

এই উদাহরণস্বরূপ, উপরের বাম কোণে লক্ষ্য এবং নীচের ডানদিকে শুরু সহ একটি 100x400 মানচিত্র।

এই মানচিত্রটির ২৮ টি পরিবর্তনে সমাধান রয়েছে, তবে এটি একটি বিএফএস দ্রাবক মিলিয়ন মিলিয়ন রাজ্যের সন্ধান করতে পারবে এটি খুঁজে পেতে (আমার গণনা করা হয়েছে 10.022.658 রাজ্যগুলি পরিদর্শন করেছে, প্রায় 12 সেকেন্ড সময় নিয়েছে এবং 600 এমবিতে পৌঁছেছে!)।

290x290 টাই ব্রেকারের অর্ধেকেরও কম পৃষ্ঠের সাথে এটির জন্য প্রায় 3 গুণ বেশি নোড ভিজিট প্রয়োজন। অন্যদিকে, একজন হিউরিস্টিক / এ * ভিত্তিক সমাধানকারীকে এটিকে সহজেই পরাজিত করা উচিত।

30
100 400
*...................................................................................................
....................................................................................................
                          < 400 lines in all >
....................................................................................................
....................................................................................................
...................................................................................................S

বোনাস: একটি সমতুল্য (তবে কিছুটা কম দক্ষ) পিএইচপি সংস্করণ

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

<?php

class Trace {
    static $file;
    public static $state_member;
    public static $state_target;
    static function msg ($msg)
    {
        fputs (self::$file, "$msg\n");
    }

    static function dump ($var, $msg=null)
    {
        ob_start();
        if ($msg) echo "$msg ";
        var_dump($var);
        $dump=ob_get_contents();
        ob_end_clean();
        fputs (self::$file, "$dump\n");
    }

    function init ($fname)
    {
        self::$file = fopen ($fname, "w");
    }
}
Trace::init ("racer.txt");

class Point {
    public $x;
    public $y;

    function __construct ($x=0, $y=0)
    {
        $this->x = (float)$x;
        $this->y = (float)$y;
    }

    function __toString ()
    {
        return "[$this->x $this->y]";
    }

    function add ($v)
    {
        return new Point ($this->x + $v->x, $this->y + $v->y);
    }

    function vector_to ($goal)
    {
        return new Point ($goal->x - $this->x, $goal->y - $this->y);
    }
}

class Node {
    public $posx  , $posy  ;
    public $speedx, $speedy;
    private $parent;

    public function __construct ($posx, $posy, $speedx, $speedy, $parent)
    {
        $this->posx = $posx;
        $this->posy = $posy;
        $this->speedx = $speedx;
        $this->speedy = $speedy;
        $this->parent = $parent;
    }

    public function path ()
    {
        $res = array();
        $v = new Point ($this->speedx, $this->speedy);
        for ($node = $this->parent ; $node != null ; $node = $node->parent)
        {
            $nv = new Point ($node->speedx, $node->speedy);
            $a = $nv->vector_to ($v);
            $v = new Point ($node->speedx, $node->speedy);
            array_unshift ($res, $a);
        }
        return $res;
    }
}

class Map {

    private static $target;       // maximal number of turns
    private static $time;         // time available to solve
    private static $sx, $sy;      // map dimensions
    private static $cell;         // cells of the map
    private static $start;        // starting point
    private static $acceleration; // possible acceleration values

    public static function init ()
    {
        // read map definition
        self::$target = trim(fgets(STDIN));
        list (self::$sx, self::$sy) = explode (" ", trim(fgets(STDIN)));
        self::$cell = array();
        for ($y = 0 ; $y != self::$sy ; $y++) self::$cell[] = str_split (trim(fgets(STDIN)));
        self::$time = trim(fgets(STDIN));

        // get starting point
        foreach (self::$cell as $y=>$row)
        {
            $x = array_search ("S", $row);
            if ($x !== false)
            {
                self::$start = new Point ($x, $y);
Trace::msg ("start ".self::$start);
                break;
            }
        }

        // compute possible acceleration values
        self::$acceleration = array();
        for ($x = -1 ; $x <= 1 ; $x++)
        for ($y = -1 ; $y <= 1 ; $y++)
        {
            self::$acceleration[] = new Point ($x, $y);
        }
    }

    public static function solve ()
    {
        $now = microtime(true);
        $res = array();
        $border = array (new Node (self::$start->x, self::$start->y, 0, 0, null));
        $present = array (self::$start->x." ".self::$start->y." 0 0" => 1);
        while (count ($border))
        {
if ((microtime(true) - $now) > 1)
{
Trace::msg (count($present)." nodes, ".round(memory_get_usage(true)/1024)."K");
$now = microtime(true);
}
            $node = array_shift ($border);
//Trace::msg ("node $node->pos $node->speed");
            $px = $node->posx;
            $py = $node->posy;
            $vx = $node->speedx;
            $vy = $node->speedy;
            foreach (self::$acceleration as $a)
            {
                $nvx = $vx + $a->x;
                $nvy = $vy + $a->y;
                $npx = $px + $nvx;
                $npy = $py + $nvy;
                if ($npx < 0 || $npx >= self::$sx || $npy < 0 || $npy >= self::$sy || self::$cell[$npy][$npx] == "#")
                {
//Trace::msg ("invalid position $px,$py $vx,$vy -> $npx,$npy");
                    continue;
                }
                if (self::$cell[$npy][$npx] == "*")
                {
Trace::msg ("winning position $px,$py $vx,$vy -> $npx,$npy");
                    $end = new Node ($npx, $npy, $nvx, $nvy, $node);
                    $res = $end->path ();
                    break 2;
                }
//Trace::msg ("checking $np $nv");
                $signature = "$npx $npy $nvx $nvy";
                if (isset ($present[$signature])) continue;
//Trace::msg ("*** adding $np $nv");
                $border[] = new Node ($npx, $npy, $nvx, $nvy, $node);
                $present[$signature] = 1;
            }
        }
        return $res;
    }
}

ini_set("memory_limit","1000M");
Map::init ();
$res = Map::solve();
//Trace::dump ($res);
foreach ($res as $a) echo "$a->x $a->y\n";
?>

আরএফ ... আমার নগ্ন হাড় বরাদ্দকারী কিছুটা খালি খালি। আমি তখন এটি g ++ দিয়ে কাজ করতে প্রয়োজনীয় বকাবালী যুক্ত করব। এর জন্যে দুঃখিত.

ঠিক আছে, ঠিক আছে। জি ++ সংস্করণ এমনকি প্রায় 30% দ্রুত কাজ করে। এটি এখন স্ট্যাডারের কিছু পরিসংখ্যানকে আউটপুট করে। এটি বিনা দ্বিধায় মন্তব্য করুন (উত্সের শেষ লাইন থেকে)। ভুলের জন্য আবার দুঃখিত।

ঠিক আছে, এটি এখন কাজ করে এবং আমি আপনার স্কোর পুনরুত্পাদন। এটা খুব দ্রুত! :) আমি আপনার পরীক্ষার কেসটি বেঞ্চমার্কে যুক্ত করব, তবে আমি লক্ষ্যটি পরিবর্তন করব 400, যেভাবে আমি অন্যান্য সমস্ত লক্ষ্য নির্ধারণ করেছি (টাই ব্রেকার ব্যতীত) line আমি অন্যান্য পোস্টগুলি একবারে পুনরায় চালু করার পরে আমি মূল পোস্টটি আপডেট করব।
মার্টিন এন্ডার

ফলাফল আপডেট। টাই ব্রেকার দরকার ছিল না, কারণ অন্যান্য পরীক্ষার সমস্ত পরীক্ষাগুলি আপনার পরীক্ষার ট্র্যাকের মেমরির সীমা অতিক্রম করে। অভিনন্দন! :)
মার্টিন ইন্ডার

ধন্যবাদ। আসলে এই চ্যালেঞ্জটি আমাকে এই এসটিএল হ্যাশ টেবিলগুলি খনন করার জন্য একটি সময় দিয়েছে। যদিও আমি সি ++ সাহসকে ঘৃণা করি, আমি সাহায্য করতে পারি না তবে আমার কৌতূহল দ্বারা নিহত। মিউ! :)।

10

সি ++, 5.4 (নিরস্তক, সর্বোত্তম)

ডায়নামিক প্রোগ্রামিং সলিউশন। সম্ভবত অনুকূল। খুব দ্রুত: সমস্ত 20 টি টেস্টকেস 0.2 এর মধ্যে সমাধান করে। 64৪-বিট মেশিনে বিশেষত দ্রুত হওয়া উচিত। ধরে নিলেন বোর্ডটি প্রতিটি দিকে 32,000 টিরও কম জায়গার (যা আশাবাদী সত্য হওয়া উচিত)।

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

সংকলন g++ -O3। সি ++ 11 (এর জন্য <unordered_map>) প্রয়োজন হতে পারে। চালানোর জন্য, কেবল কম্পাইলড এক্সিকিউটেবল চালিত করুন (কোনও পতাকা বা বিকল্প সমর্থনযোগ্য নয়; সমস্ত ইনপুট স্টিডিনে নেওয়া হয়)।

#include <unordered_map>
#include <iostream>
#include <string>
#include <vector>
#include <sstream>

#include <cstdint>

#define MOVES_INF (1<<30)

union state {
    struct {
        short px, py, vx, vy;
    };
    uint64_t val;
};

struct result {
    int nmoves;
    short dvx, dvy;
};

typedef std::unordered_map<uint64_t, result> cache_t;
int target, n, m;
std::vector<std::string> track;
cache_t cache;

static int solve(uint64_t val) {
    cache_t::iterator it = cache.find(val);
    if(it != cache.end())
        return it->second.nmoves;

    // prevent recursion
    result res;
    res.nmoves = MOVES_INF;
    cache[val] = res;

    state cur;
    cur.val = val;
    for(int dvx = -1; dvx <= 1; dvx++) for(int dvy = -1; dvy <= 1; dvy++) {
        state next;
        next.vx = cur.vx + dvx;
        next.vy = cur.vy + dvy;
        next.px = cur.px + next.vx;
        next.py = cur.py + next.vy;
        if(next.px < 0 || next.px >= n || next.py < 0 || next.py >= m)
            continue;
        char c = track[next.py][next.px];
        if(c == '*') {
            res.nmoves = 1;
            res.dvx = dvx;
            res.dvy = dvy;
            break;
        } else if(c == '#') {
            continue;
        } else {
            int score = solve(next.val) + 1;
            if(score < res.nmoves) {
                res.nmoves = score;
                res.dvx = dvx;
                res.dvy = dvy;
            }
        }
    }

    cache[val] = res;
    return res.nmoves;
}

bool solve_one() {
    std::string line;
    float time;

    std::cin >> target;
    // std::cin >> time; // uncomment to use "time" control
    std::cin >> n >> m;
    if(!std::cin)
        return false;
    std::cin.ignore(); // skip newline at end of "n m" line

    track.clear();
    track.reserve(m);

    for(int i=0; i<m; i++) {
        std::getline(std::cin, line);
        track.push_back(line);
    }

    cache.clear();

    state cur;
    cur.vx = cur.vy = 0;
    for(int y=0; y<m; y++) for(int x=0; x<n; x++) {
        if(track[y][x] == 'S') {
            cur.px = x;
            cur.py = y;
            break;
        }
    }

    solve(cur.val);

    int sol_len = 0;
    while(track[cur.py][cur.px] != '*') {
        cache_t::iterator it = cache.find(cur.val);
        if(it == cache.end() || it->second.nmoves >= MOVES_INF) {
            std::cerr << "Failed to solve at p=" << cur.px << "," << cur.py << " v=" << cur.vx << "," << cur.vy << std::endl;
            return true;
        }

        int dvx = it->second.dvx;
        int dvy = it->second.dvy;
        cur.vx += dvx;
        cur.vy += dvy;
        cur.px += cur.vx;
        cur.py += cur.vy;
        std::cout << dvx << " " << dvy << std::endl;
        sol_len++;
    }

    //std::cerr << "Score: " << ((float)sol_len) / target << std::endl;

    return true;
}

int main() {
    /* benchmarking: */
    //while(solve_one())
    //    ;

    /* regular running */
    solve_one();
    std::string line;
    while(std::cin) std::getline(std::cin, line);

    return 0;
}

ফলাফল

 No.    Size     Target   Score     Details
-------------------------------------------------------------------------------------
  1    37 x 1        36   0.22222   Racer reached goal at ( 36, 0) in 8 turns.
  2    38 x 1        37   0.24324   Racer reached goal at ( 37, 0) in 9 turns.
  3    33 x 1        32   0.25000   Racer reached goal at ( 32, 0) in 8 turns.
  4    10 x 10       10   0.40000   Racer reached goal at ( 7, 7) in 4 turns.
  5     9 x 6         8   0.37500   Racer reached goal at ( 6, 0) in 3 turns.
  6    15 x 7        16   0.37500   Racer reached goal at ( 12, 4) in 6 turns.
  7    17 x 8        16   0.31250   Racer reached goal at ( 15, 0) in 5 turns.
  8    19 x 13       18   0.27778   Racer reached goal at ( 1, 11) in 5 turns.
  9    60 x 10      107   0.14953   Racer reached goal at ( 2, 6) in 16 turns.
 10    31 x 31      106   0.25472   Racer reached goal at ( 28, 0) in 27 turns.
 11    31 x 31      106   0.24528   Racer reached goal at ( 15, 15) in 26 turns.
 12    50 x 20       50   0.24000   Racer reached goal at ( 49, 10) in 12 turns.
 13   100 x 100    2600   0.01385   Racer reached goal at ( 50, 0) in 36 turns.
 14    79 x 63      242   0.26860   Racer reached goal at ( 3, 42) in 65 turns.
 15    26 x 1        25   0.32000   Racer reached goal at ( 25, 0) in 8 turns.
 16    17 x 1        19   0.52632   Racer reached goal at ( 16, 0) in 10 turns.
 17    50 x 1        55   0.34545   Racer reached goal at ( 23, 0) in 19 turns.
 18    10 x 7        23   0.34783   Racer reached goal at ( 1, 3) in 8 turns.
 19    55 x 55       45   0.17778   Racer reached goal at ( 52, 26) in 8 turns.
 20    50 x 50      200   0.05500   Racer reached goal at ( 47, 46) in 11 turns.
-------------------------------------------------------------------------------------
TOTAL SCORE:              5.40009

নতুন টেস্টকেস


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

আপনার রেসার আপনার পরীক্ষার ক্ষেত্রে কীভাবে সম্পাদন করে?
ব্যবহারকারী 2357112

0.14 (14 চাল)
ন্নেনিও

সেই সময় কি নেওয়া বা চাল / লক্ষ্য? যদি এটি চাল / লক্ষ্য হয় তবে এটি সময়ের সাথে কীভাবে সম্পাদন করে?
ব্যবহারকারী 2357112

1
আমি মনে করি চক্র প্রতিরোধের কোডটিতে আমি একটি বাগ পেয়েছি। এটা তোলে অনুমান এটা যে মনে হতে পারে প্রতিটি রাষ্ট্রের জন্য একটি রাষ্ট্র এস থেকে অনুসন্ধান প্রান্তে, একটি অনুকূল পথ এস ফিরে যাওয়ার হতে পারে না যে যদি একটি অনুকূল পথ নেই এস ফিরে, তারপর রাষ্ট্র না একটি অনুকূল পথে হতে পারে (আমরা পারা যেহেতু এটির লুপটি কেবল সরিয়ে ফেলুন এবং আরও একটি ছোটো পথ পান) এবং তাই আমরা সেই রাষ্ট্রের জন্য আমরা খুব বেশি উচ্চমানের ফলাফল পাব কিনা তা আমাদের খেয়াল নেই। যাইহোক, যদি একটি অনুকূল পথটি ক্রম A এবং B এর মধ্য দিয়ে যায় তবে অনুসন্ধানটি প্রথমে A টি সন্ধান করে যখন বি এখনও স্ট্যাকের উপরে রয়েছে, তবে ল এর প্রতিরোধের ফলে এ এর ​​ফলাফলগুলিকে বিষাক্ত করা হয়।
ব্যবহারকারী 2357112

6

পাইথন 2 , নির্মাতারা, সর্বোত্তম

এই আমার রেসার। আমি এটি মানদণ্ডে পরীক্ষা করে দেখিনি (রুবির কী সংস্করণ এবং ইনস্টলার ইনস্টল করতে হবে তা নিয়ে এখনও বিচলিত), তবে এটি সর্বোত্তমভাবে এবং সময়সীমার অধীনে সবকিছু সমাধান করা উচিত। কমান্ড এটি চালানোর জন্য python whateveryoucallthefile.py। প্রয়োজন -sনিয়ামক পতাকা।

# Breadth-first search.
# Future directions: bidirectional search and/or A*.

import operator
import time

acceleration_options = [(dvx, dvy) for dvx in [-1, 0, 1] for dvy in [-1, 0, 1]]

class ImpossibleRaceError(Exception): pass

def read_input(line_source=raw_input):
    # We don't use the target.
    target = int(line_source())

    width, height = map(int, line_source().split())
    input_grid = [line_source() for _ in xrange(height)]

    start = None
    for i in xrange(height):
        for j in xrange(width):
            if input_grid[i][j] == 'S':
                start = i, j
                break
        if start is not None:
            break

    walls = [[cell == '#' for cell in row] for row in input_grid]
    goals = [[cell == '*' for cell in row] for row in input_grid]

    return start, walls, goals

def default_bfs_stop_threshold(walls, goals):
    num_not_wall = sum(sum(map(operator.not_, row)) for row in walls)
    num_goals = sum(sum(row) for row in goals)
    return num_goals * num_not_wall

def bfs(start, walls, goals, stop_threshold=None):
    if stop_threshold is None:
        stop_threshold = default_bfs_stop_threshold(walls, goals)

    # State representation is (x, y, vx, vy)
    x, y = start
    initial_state = (x, y, 0, 0)
    frontier = {initial_state}
    # Visited set is tracked by a map from each state to the last move taken
    # before reaching that state.
    visited = {initial_state: None}

    while len(frontier) < stop_threshold:
        if not frontier:
            raise ImpossibleRaceError

        new_frontier = set()
        for x, y, vx, vy in frontier:
            for dvx, dvy in acceleration_options:
                new_vx, new_vy = vx+dvx, vy+dvy
                new_x, new_y = x+new_vx, y+new_vy
                new_state = (new_x, new_y, new_vx, new_vy)

                if not (0 <= new_x < len(walls) and 0 <= new_y < len(walls[0])):
                    continue
                if walls[new_x][new_y]:
                    continue
                if new_state in visited:
                    continue

                new_frontier.add(new_state)
                visited[new_state] = dvx, dvy

                if goals[new_x][new_y]:
                    return construct_path_from_bfs(new_state, visited)
        frontier = new_frontier

def construct_path_from_bfs(goal_state, best_moves):
    reversed_path = []
    current_state = goal_state
    while best_moves[current_state] is not None:
        move = best_moves[current_state]
        reversed_path.append(move)

        x, y, vx, vy = current_state
        dvx, dvy = move
        old_x, old_y = x-vx, y-vy # not old_vx or old_vy
        old_vx, old_vy = vx-dvx, vy-dvy
        current_state = (old_x, old_y, old_vx, old_vy)
    return reversed_path[::-1]

def main():
    t = time.time()

    start, walls, goals = read_input()
    path = bfs(start, walls, goals, float('inf'))
    for dvx, dvy in path:
        # I wrote the whole program with x pointing down and y pointing right.
        # Whoops. Gotta flip things for the output.
        print dvy, dvx

if __name__ == '__main__':
    main()

নিনেনিওর রেসার পরিদর্শন করার পরে (তবে আসলে এটি পরীক্ষা করা হচ্ছে না, যেহেতু আমার কাছে সি ++ সংকলকও নেই) আমি লক্ষ্য করেছি যে লক্ষ্যটি যতই নিকটবর্তী বা সংক্ষিপ্ত হোক না কেন, এটি রাষ্ট্রের জায়গার সর্বাধিক বিস্তৃত অনুসন্ধান সম্পাদন করে seems ইতিমধ্যে একটি পথ খুঁজে পাওয়া গেছে। আমি আরও জানতে পেরেছি যে সময়ের বিধি মানে দীর্ঘ, জটিল সমাধান সহ একটি মানচিত্র তৈরি করা দীর্ঘ, বিরক্তিকর সময়সীমা দরকার। সুতরাং, আমার মানচিত্র জমা খুব সহজ:

নতুন টেস্টকেস

(গিটহাব দীর্ঘ লাইনটি প্রদর্শন করতে পারে না The ট্র্যাকটি হ'ল *S.......[and so on].....)


অতিরিক্ত জমা: পাইথন 2, দ্বি নির্দেশমূলক অনুসন্ধান

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

# Bidirectional search.
# Future directions: A*.

import operator
import time

acceleration_options = [(dvx, dvy) for dvx in [-1, 0, 1] for dvy in [-1, 0, 1]]

class ImpossibleRaceError(Exception): pass

def read_input(line_source=raw_input):
    # We don't use the target.
    target = int(line_source())

    width, height = map(int, line_source().split())
    input_grid = [line_source() for _ in xrange(height)]

    start = None
    for i in xrange(height):
        for j in xrange(width):
            if input_grid[i][j] == 'S':
                start = i, j
                break
        if start is not None:
            break

    walls = [[cell == '#' for cell in row] for row in input_grid]
    goals = [[cell == '*' for cell in row] for row in input_grid]

    return start, walls, goals

def bfs_to_bidi_threshold(walls, goals):
    num_not_wall = sum(sum(map(operator.not_, row)) for row in walls)
    num_goals = sum(sum(row) for row in goals)
    return num_goals * (num_not_wall - num_goals)

class GridBasedGoalContainer(object):
    '''Supports testing whether a state is a goal state with `in`.

    Does not perform bounds checking.'''
    def __init__(self, goal_grid):
        self.goal_grid = goal_grid
    def __contains__(self, state):
        x, y, vx, vy = state
        return self.goal_grid[x][y]

def forward_step(state, acceleration):
    x, y, vx, vy = state
    dvx, dvy = acceleration

    new_vx, new_vy = vx+dvx, vy+dvy
    new_x, new_y = x+new_vx, y+new_vy

    return (new_x, new_y, new_vx, new_vy)

def backward_step(state, acceleration):
    x, y, vx, vy = state
    dvx, dvy = acceleration

    old_x, old_y = x-vx, y-vy
    old_vx, old_vy = vx-dvx, vy-dvy

    return (old_x, old_y, old_vx, old_vy)

def bfs(start, walls, goals):
    x, y = start
    initial_state = (x, y, 0, 0)
    initial_frontier = {initial_state}
    visited = {initial_state: None}

    goal_state, frontier, visited = general_bfs(
        frontier=initial_frontier,
        visited=visited,
        walls=walls,
        goalcontainer=GridBasedGoalContainer(goals),
        stop_threshold=float('inf'),
        step_function=forward_step
    )

    return construct_path_from_bfs(goal_state, visited)

def general_bfs(
        frontier,
        visited,
        walls,
        goalcontainer,
        stop_threshold,
        step_function):

    while len(frontier) <= stop_threshold:
        if not frontier:
            raise ImpossibleRaceError

        new_frontier = set()
        for state in frontier:
            for accel in acceleration_options:
                new_state = new_x, new_y, new_vx, new_vy = \
                        step_function(state, accel)

                if not (0 <= new_x < len(walls) and 0 <= new_y < len(walls[0])):
                    continue
                if walls[new_x][new_y]:
                    continue
                if new_state in visited:
                    continue

                new_frontier.add(new_state)
                visited[new_state] = accel

                if new_state in goalcontainer:
                    return new_state, frontier, visited
        frontier = new_frontier
    return None, frontier, visited

def max_velocity_component(n):
    # It takes a distance of at least 0.5*v*(v+1) to achieve a velocity of
    # v in the x or y direction. That means the map has to be at least
    # 1 + 0.5*v*(v+1) rows or columns long to accomodate such a velocity.
    # Solving for v, we get a velocity cap as follows.
    return int((2*n-1.75)**0.5 - 0.5)

def solver(
        start,
        walls,
        goals,
        mode='bidi'):

    x, y = start
    initial_state = (x, y, 0, 0)
    initial_frontier = {initial_state}
    visited = {initial_state: None}
    if mode == 'bidi':
        stop_threshold = bfs_to_bidi_threshold(walls, goals)
    elif mode == 'bfs':
        stop_threshold = float('inf')
    else:
        raise ValueError('Unsupported search mode: {}'.format(mode))

    goal_state, frontier, visited = general_bfs(
        frontier=initial_frontier,
        visited=visited,
        walls=walls,
        goalcontainer=GridBasedGoalContainer(goals),
        stop_threshold=stop_threshold,
        step_function=forward_step
    )

    if goal_state is not None:
        return construct_path_from_bfs(goal_state, visited)

    # Switching to bidirectional search.

    not_walls_or_goals = []
    goal_list = []
    for x in xrange(len(walls)):
        for y in xrange(len(walls[0])):
            if not walls[x][y] and not goals[x][y]:
                not_walls_or_goals.append((x, y))
            if goals[x][y]:
                goal_list.append((x, y))
    max_vx = max_velocity_component(len(walls))
    max_vy = max_velocity_component(len(walls[0]))
    reverse_visited = {(goal_x, goal_y, goal_x-prev_x, goal_y-prev_y): None
                        for goal_x, goal_y in goal_list
                        for prev_x, prev_y in not_walls_or_goals
                        if abs(goal_x-prev_x) <= max_vx
                        and abs(goal_y - prev_y) <= max_vy}
    reverse_frontier = set(reverse_visited)
    while goal_state is None:
        goal_state, reverse_frontier, reverse_visited = general_bfs(
            frontier=reverse_frontier,
            visited=reverse_visited,
            walls=walls,
            goalcontainer=frontier,
            stop_threshold=len(frontier),
            step_function=backward_step
        )
        if goal_state is not None:
            break
        goal_state, frontier, visited = general_bfs(
            frontier=frontier,
            visited=visited,
            walls=walls,
            goalcontainer=reverse_frontier,
            stop_threshold=len(reverse_frontier),
            step_function=forward_step
        )
    forward_path = construct_path_from_bfs(goal_state, visited)
    backward_path = construct_path_from_bfs(goal_state,
                                            reverse_visited,
                                            step_function=forward_step)
    return forward_path + backward_path[::-1]

def construct_path_from_bfs(goal_state,
                            best_moves,
                            step_function=backward_step):
    reversed_path = []
    current_state = goal_state
    while best_moves[current_state] is not None:
        move = best_moves[current_state]
        reversed_path.append(move)
        current_state = step_function(current_state, move)
    return reversed_path[::-1]

def main():
    start, walls, goals = read_input()
    t = time.time()
    path = solver(start, walls, goals)
    for dvx, dvy in path:
        # I wrote the whole program with x pointing down and y pointing right.
        # Whoops. Gotta flip things for the output.
        print dvy, dvx

if __name__ == '__main__':
    main()

এটি কখনও কখনও 12 এবং 13 কে ক্ষেত্রে ব্যর্থ হয় know কারণ ত্রুটি বার্তাগুলি কিছুটা বন্ধুত্বপূর্ণ কারণ কেন জানি না
রায়

@ রে আমি ত্রুটি বার্তাগুলিও পাই, তবে যাই হোক না কেন আমি সর্বদা ফলাফল পেতে পারি। আমি মনে করি এটি আমার কন্ট্রোলারের পরিবর্তে কিছু হতে পারে, কারণ দেখে মনে হচ্ছে যে নিয়ামক রেসার প্রক্রিয়াটি ইতিমধ্যে শেষ হয়ে গেলেও হত্যা করার চেষ্টা করে।
মার্টিন ইন্ডার

@ m.buettner আমি কারণটি খুঁজে পেয়েছি, অ্যাড করুন তবে ঠিক হয়ে যাবে।
রায়

@ রে ওহ, আমি এটি করছি। ফলশ্রুতি ইতিমধ্যে উপস্থিত থাকলেও কন্ট্রোলার প্রক্রিয়াটি মেরে ফেলতে চাইলে আমি 13 এবং 14 ট্র্যাকগুলিতে ত্রুটি পেয়েছি। আমার ধারণা আমি এটি খতিয়ে দেখা উচিত, তবে স্কোরিংকে প্রভাবিত করে না তাই আমি এখনও বিরক্ত করি নি।
মার্টিন ইন্ডার

দুর্ভাগ্যক্রমে, আমাকে আরও একটি বিধি যুক্ত করতে হয়েছিল। স্মরণটিকে এই চ্যালেঞ্জের সময়ের চেয়ে সীমাবদ্ধ মনে হয়, তাই মেমরির ব্যবহারকে সীমাবদ্ধ করার জন্য আমাকে একটি শক্ত সেট করতে হয়েছিল। আপনার রেসার যে কোনও রান যেখানে 1 গিগাবাইটের বেশি মেমরি ব্যবহার করে তা সময়সীমা ছাড়িয়ে গেলে একই প্রভাবতে বাতিল হয়ে যাবে। বর্তমান ট্র্যাকগুলির সেটগুলির জন্য, আপনার স্কোর এই পরিবর্তন দ্বারা প্রভাবিত হয়নি। (আমি মনে করি আপনি প্রায় টাই-ব্রেকারদের মধ্যে এই সীমাটি পৌঁছেছেন n = 400)) আপনি যদি কোন অপ্টিমাইজেশন প্রয়োগ করেন তবে দয়া করে আমাকে জানান, যাতে আমি পরীক্ষাগুলি পুনরায় চালাতে পারি।
মার্টিন ইন্ডার

3

পাইথন 3: 6.49643 (অনুকূল, বিএফএস)

পুরানো 20 কেস বেঞ্চমার্ক ফাইলের জন্য, এটি 5.35643 এর স্কোর পেয়েছে। @Nneonneo এর সমাধানটি সর্বোত্তম নয় যেহেতু এটি 5.4 পেয়েছে। কিছু বাগ সম্ভবত।

এই সমাধানটি গ্রাফ অনুসন্ধান করতে বিএফএস ব্যবহার করে, প্রতিটি অনুসন্ধানের অবস্থা (x, y, dx, dy) আকারে। তারপরে আমি রাজ্য থেকে দূরত্ব পর্যন্ত মানচিত্রের জন্য একটি মানচিত্র ব্যবহার করি। সবচেয়ে খারাপ ক্ষেত্রে এটির সময় এবং স্থান জটিলতা হ'ল (এন ^ 2 মি ^ 2)। এটি খুব কমই ঘটবে যেহেতু গতি খুব বেশি হবে না বা রেসার ক্রাশ হবে। প্রকৃতপক্ষে, সমস্ত 22 টি টেস্টকেস সম্পূর্ণ করতে আমার মেশিনে 3 সেকেন্ড ব্যয়।

from collections import namedtuple, deque
import itertools

Field = namedtuple('Map', 'n m grids')

class Grid:
    WALL = '#'
    EMPTY = '.'
    START = 'S'
    END = '*'

def read_nums():
    return list(map(int, input().split()))

def read_field():
    m, n = read_nums()
    return Field(n, m, [input() for i in range(n)])

def find_start_pos(field):
    return next((i, j)
        for i in range(field.n) for j in range(field.m)
        if field.grids[i][j] == Grid.START)

def can_go(field, i, j):
    return 0 <= i < field.n and 0 <= j < field.m and field.grids[i][j] != Grid.WALL

def trace_path(start, end, prev):
    if end == start:
        return
    end, step = prev[end]
    yield from trace_path(start, end, prev)
    yield step

def solve(max_turns, field, time):
    i0, j0 = find_start_pos(field)
    p0 = i0, j0, 0, 0
    prev = {}
    que = deque([p0])
    directions = list(itertools.product((-1, 0, 1), (-1, 0, 1)))

    while que:
        p = i, j, vi, vj = que.popleft()
        for dvi, dvj in directions:
            vi1, vj1 = vi + dvi, vj + dvj
            i1, j1 = i + vi1, j + vj1
            if not can_go(field, i1, j1):
                continue
            p1 = i1, j1, vi1, vj1
            if p1 in prev:
                continue
            que.append(p1)
            prev[p1] = p, (dvi, dvj)
            if field.grids[i1][j1] == Grid.END:
                return trace_path(p0, p1, prev)
    return []

def main():
    for dvy, dvx in solve(int(input()), read_field(), float(input())):
        print(dvx, dvy)

main()

। ফলাফল

± % time ruby controller.rb benchmark.txt python ../mybfs.py                                                                                                                                                                             !9349
["benchmark.txt", "python", "../mybfs.py"]

Running 'python ../mybfs.py' against benchmark.txt

 No.       Size     Target   Score     Details
-------------------------------------------------------------------------------------
  1       37 x 1        36   0.22222   Racer reached goal at ( 36, 0) in 8 turns.
  2       38 x 1        37   0.24324   Racer reached goal at ( 37, 0) in 9 turns.
  3       33 x 1        32   0.25000   Racer reached goal at ( 32, 0) in 8 turns.
  4       10 x 10       10   0.40000   Racer reached goal at ( 7, 7) in 4 turns.
  5        9 x 6         8   0.37500   Racer reached goal at ( 6, 0) in 3 turns.
  6       15 x 7        16   0.37500   Racer reached goal at ( 12, 4) in 6 turns.
  7       17 x 8        16   0.31250   Racer reached goal at ( 14, 0) in 5 turns.
  8       19 x 13       18   0.27778   Racer reached goal at ( 0, 11) in 5 turns.
  9       60 x 10      107   0.14953   Racer reached goal at ( 0, 6) in 16 turns.
 10       31 x 31      106   0.23585   Racer reached goal at ( 27, 0) in 25 turns.
 11       31 x 31      106   0.24528   Racer reached goal at ( 15, 15) in 26 turns.
 12       50 x 20       50   0.24000   Racer reached goal at ( 49, 10) in 12 turns.
 13      100 x 100    2600   0.01385   Racer reached goal at ( 50, 0) in 36 turns.
 14       79 x 63      242   0.24380   Racer reached goal at ( 3, 42) in 59 turns.
 15       26 x 1        25   0.32000   Racer reached goal at ( 25, 0) in 8 turns.
 16       17 x 1        19   0.52632   Racer reached goal at ( 16, 0) in 10 turns.
 17       50 x 1        55   0.34545   Racer reached goal at ( 23, 0) in 19 turns.
 18       10 x 7        23   0.34783   Racer reached goal at ( 1, 3) in 8 turns.
 19       55 x 55       45   0.17778   Racer reached goal at ( 50, 26) in 8 turns.
 20      101 x 100     100   0.14000   Racer reached goal at ( 99, 99) in 14 turns.
 21   100000 x 1         1   1.00000   Racer reached goal at ( 0, 0) in 1 turns.
 22       50 x 50      200   0.05500   Racer reached goal at ( 47, 46) in 11 turns.
-------------------------------------------------------------------------------------
TOTAL SCORE:                 6.49643

ruby controller.rb benchmark.txt python ../mybfs.py  3.06s user 0.06s system 99% cpu 3.146 total

হ্যাঁ, ব্যবহারকারী 2357112 এর মন্তব্য অনুসারে নিনেওর চক্র প্রতিরোধে একটি বাগ রয়েছে। আমি যতদূর জানি, গতি সীমাবদ্ধ O(√n)যার দ্বারা O(n³)স্কোর গ্রিডে আপনার প্রয়োগ করা হবে (অন্যদের মতো, আমি মনে করি)। আমি আজকের পরে232317112 এর তুলনায় আপনার জমাটি স্কোর করতে একটি টাই ব্রেকার যুক্ত করব।
মার্টিন ইন্ডার

বিটিডব্লিউ, আপনি কি আরও একটি টেস্ট কেস যুক্ত করার পরিকল্পনা করছেন?
মার্টিন ইন্ডার

@ এম.বয়েটনার না, এই গেমটির জন্য আমার যথেষ্ট ভাল বোধগম্যতা নেই। সুতরাং আমার টেস্টকেস একটি আকর্ষণীয় এক হতে হবে না।
রায়

দুর্ভাগ্যক্রমে, আমাকে আরও একটি বিধি যুক্ত করতে হয়েছিল। স্মরণটিকে এই চ্যালেঞ্জের সময়ের চেয়ে সীমাবদ্ধ মনে হয়, তাই মেমরির ব্যবহারকে সীমাবদ্ধ করার জন্য আমাকে একটি শক্ত সেট করতে হয়েছিল। আপনার রেসার যে কোনও রান যেখানে 1 গিগাবাইটের বেশি মেমরি ব্যবহার করে তা সময়সীমা ছাড়িয়ে গেলে একই প্রভাবতে বাতিল হয়ে যাবে। এই নিয়মটি সহ, আপনার জমাটি আকারের টাই-ব্রেকারের ক্ষেত্রে সীমাটি ছাড়িয়ে যাওয়ার প্রথম n=270, যার কারণে আপনি এখন অন্য দুটি "অনুকূল" সাবমিশনের পিছনে রয়েছেন। বলা হচ্ছে, আপনার জমাটি তিনটির মধ্যেও সবচেয়ে ধীরতম, তাই বৃহত্তর টাই-ব্রেকার দিয়ে তৃতীয় হওয়া উচিত।
মার্টিন ইন্ডার

আপনি যদি কোনও অপটিমাইজেশন প্রয়োগ করেন তবে দয়া করে আমাকে জানান, যাতে আমি পরীক্ষাগুলি পুনরায় চালু করতে পারি।
মার্টিন ইন্ডার

1

র‌্যান্ডমরেসার, ~ 40.0 (গড় 10 টিরও বেশি)

এটি এমন নয় যে এই বট কখনও ট্র্যাক শেষ করে না , তবে অবশ্যই 10 বারে একবারের চেয়ে অনেক কম। (আমি প্রতি 20 থেকে 30 টি সিমুলেশন বা তার মতো নন-সর্বাধিক খারাপ স্কোর পাই))

এটি বেশিরভাগই বেসলাইন কেস হিসাবে কাজ করা এবং কোনও রেসারের জন্য কোনও সম্ভাব্য (রুবি) বাস্তবায়ন প্রদর্শন করার জন্য:

# Parse initial input
target = gets.to_i
size = gets.split.map(&:to_i)
track = []
size[1].times do
    track.push gets
end
time_budget = gets.to_f

# Find start position
start_y = track.find_index { |row| row['S'] }
start_x = track[start_y].index 'S'

position = [start_x, start_y]
velocity = [0, 0]

while true
    x = rand(3) - 1
    y = rand(3) - 1
    puts [x,y].join ' '
    $stdout.flush

    first_line = gets
    break if !first_line || first_line.chomp.empty?

    position = first_line.split.map(&:to_i)
    velocity = gets.split.map(&:to_i)
    time_budget = gets.to_f
end

এটি দিয়ে চালান

ruby controller.rb benchmark.txt ruby randomracer.rb

1

র‌্যান্ডম রেসার ২.০, ~ 31

ওয়েল এটি পোস্ট করা সর্বোত্তম সমাধানকারীকে পরাস্ত করতে যাচ্ছে না, তবে এটি একটি এলোমেলো রেসারের উপর সামান্য উন্নতি। মূল পার্থক্য হ'ল এই রেसर কেবল এলোমেলোভাবে সেখানে যাওয়ার কথা বিবেচনা করবে যেখানে কোনও প্রাচীর নেই, যদি না এটি সরানোর জন্য বৈধ স্থানগুলির বাইরে চলে যায় এবং যদি এটি কোনও লক্ষ্যে চলে যেতে পারে তবে তা হয়ে যাবে। এটি একই স্থানে থাকার জন্যও সরবে না, যদি না অন্য কোনও পদক্ষেপ উপলব্ধ (সম্ভাব্য, তবে সম্ভব) না থাকে।

জাভাতে প্রয়োগ করা, জাভা 8 দিয়ে সংকলিত, তবে জাভা 6 টি ঠিক থাকতে হবে। কোনও কমান্ড লাইন প্যারামিটার নেই। শ্রেণিবিন্যাসের একটি বেশ ভাল ক্লাস্টারফাক রয়েছে, তাই আমি মনে করি আমি ঠিক জাভা করছি।

import java.util.Scanner;
import java.util.Random;
import java.util.ArrayList;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

public class VectorRacing   {
    private static Scanner in = new Scanner(System.in);
    private static Random rand = new Random();
    private static Track track;
    private static Racer racer;
    private static int target;
    private static double time;
    public static void main(String[] args)  {
        init();
        main_loop();
    }
    private static void main_loop() {
        Scanner linescan;
        String line;
        int count = 0,
            x, y, u, v;

        while(!racer.lost() && !racer.won() && count < target)  {
            Direction d = racer.think();
            racer.move(d);
            count++;
            System.out.println(d);

            line = in.nextLine();
            if(line.equals("")) {
                break;
            }
            linescan = new Scanner(line);
            x = linescan.nextInt();
            y = linescan.nextInt();
            linescan = new Scanner(in.nextLine());
            u = linescan.nextInt();
            v = linescan.nextInt();
            time = Double.parseDouble(in.nextLine());

            assert x == racer.location.x;
            assert y == racer.location.y;
            assert u == racer.direction.x;
            assert v == racer.direction.y;
        }
    }
    private static void init()  {
        target = Integer.parseInt(in.nextLine());
        int width = in.nextInt();
        int height = Integer.parseInt(in.nextLine().trim());
        String[] ascii = new String[height];
        for(int i = 0; i < height; i++) {
            ascii[i] = in.nextLine();
        }
        time = Double.parseDouble(in.nextLine());
        track = new Track(width, height, ascii);
        for(int y = 0; y < ascii.length; y++)   {
            int x = ascii[y].indexOf("S");
            if( x != -1)    {
                racer = new RandomRacer(track, new Location(x, y));
                break;
            }
        }
    }

    public static class RandomRacer extends Racer   {
        public RandomRacer(Track t, Location l) {
            super(t, l);
        }
        public Direction think()    {
            ArrayList<Pair<Location, Direction> > possible = this.getLocationsCanMoveTo();
            if(possible.size() == 0)    {
                return Direction.NONE;
            }
            Pair<Location, Direction> ret = null;
            do  {
                ret = possible.get(rand.nextInt(possible.size()));
            }   while(possible.size() != 1 && ret.a.equals(this.location));
            return ret.b;
        }
    }

    // Base things
    public enum Direction   {
        NORTH("0 -1"), SOUTH("0 1"), EAST("1 0"), WEST("-1 0"), NONE("0 0"),
        NORTH_EAST("1 -1"), NORTH_WEST("-1 -1"), SOUTH_EAST("1 1"), SOUTH_WEST("-1 1");

        private final String d;
        private Direction(String d) {this.d = d;}
        public String toString()    {return d;}
    }
    public enum Cell    {
        WALL('#'), GOAL('*'), ROAD('.'), OUT_OF_BOUNDS('?');

        private final char c;
        private Cell(char c)    {this.c = c;}
        public String toString()    {return "" + c;}
    }

    public static class Track   {
        private Cell[][] track;
        private int target;
        private double time;
        public Track(int width, int height, String[] ascii) {
            this.track = new Cell[width][height];
            for(int y = 0; y < height; y++) {
                for(int x = 0; x < width; x++)  {
                    switch(ascii[y].charAt(x))  {
                        case '#':   this.track[x][y] = Cell.WALL; break;
                        case '*':   this.track[x][y] = Cell.GOAL; break;
                        case '.':
                        case 'S':   this.track[x][y] = Cell.ROAD; break;
                        default:    System.exit(-1);
                    }
                }
            }
        }
        public Cell atLocation(Location loc)    {
            if(loc.x < 0 || loc.x >= track.length || loc.y < 0 || loc.y >= track[0].length) return Cell.OUT_OF_BOUNDS;
            return track[loc.x][loc.y];
        }

        public String toString()    {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            PrintStream ps = new PrintStream(bos);
            for(int y = 0; y < track[0].length; y++)    {
                for(int x = 0; x < track.length; x++)   {
                    ps.append(track[x][y].toString());
                }
                ps.append('\n');
            }
            String ret = bos.toString();
            ps.close();
            return ret;
        }
    }

    public static abstract class Racer  {
        protected Velocity tdir;
        protected Location tloc;
        protected Track track;
        public Velocity direction;
        public Location location;

        public Racer(Track track, Location start)   {
            this.track = track;
            direction = new Velocity(0, 0);
            location = start;
        }
        public boolean canMove() throws GoHereDammitException {return canMove(Direction.NONE);}
        public boolean canMove(Direction d) throws GoHereDammitException    {
            tdir = new Velocity(direction);
            tloc = new Location(location);
            tdir.add(d);
            tloc.move(tdir);
            Cell at = track.atLocation(tloc);
            if(at == Cell.GOAL) {
                throw new GoHereDammitException();
            }
            return at == Cell.ROAD;
        }
        public ArrayList<Pair<Location, Direction> > getLocationsCanMoveTo()    {
            ArrayList<Pair<Location, Direction> > ret = new ArrayList<Pair<Location, Direction> >(9);
            for(Direction d: Direction.values())    {
                try {
                    if(this.canMove(d)) {
                        ret.add(new Pair<Location, Direction>(tloc, d));
                    }
                }   catch(GoHereDammitException e)  {
                    ret.clear();
                    ret.add(new Pair<Location, Direction>(tloc, d));
                    return ret;
                }
            }
            return ret;
        }
        public void move()  {move(Direction.NONE);}
        public void move(Direction d)   {
            direction.add(d);
            location.move(direction);
        }
        public boolean won()    {
            return track.atLocation(location) == Cell.GOAL;
        }
        public boolean lost()   {
            return track.atLocation(location) == Cell.WALL || track.atLocation(location) == Cell.OUT_OF_BOUNDS;
        }
        public String toString()    {
            return location + ", " + direction;
        }
        public abstract Direction think();

        public class GoHereDammitException extends Exception    {
            public GoHereDammitException()  {}
        }
    }

    public static class Location extends Point  {
        public Location(int x, int y)   {
            super(x, y);
        }
        public Location(Location l) {
            super(l);
        }
        public void move(Velocity d)    {
            this.x += d.x;
            this.y += d.y;
        }
    }

    public static class Velocity extends Point  {
        public Velocity(int x, int y)   {
            super(x, y);
        }
        public Velocity(Velocity v) {
            super(v);
        }
        public void add(Direction d)    {
            if(d == Direction.NONE) return;
            if(d == Direction.NORTH || d == Direction.NORTH_EAST || d == Direction.NORTH_WEST)  this.y--;
            if(d == Direction.SOUTH || d == Direction.SOUTH_EAST || d == Direction.SOUTH_WEST)  this.y++;
            if(d == Direction.EAST || d == Direction.NORTH_EAST || d == Direction.SOUTH_EAST)   this.x++;
            if(d == Direction.WEST || d == Direction.NORTH_WEST || d == Direction.SOUTH_WEST)   this.x--;
        }
    }

    public static class Point   {
        protected int x, y;
        protected Point(int x, int y)   {
            this.x = x;
            this.y = y;
        }
        protected Point(Point c)    {
            this.x = c.x;
            this.y = c.y;
        }
        public int getX()   {return x;}
        public int getY()   {return y;}
        public String toString()    {return "(" + x + ", " + y + ")";}
        public boolean equals(Point p)  {
            return this.x == p.x && this.y == p.y;
        }
    }

    public static class Pair<T, U>  {
        public T a;
        public U b;
        public Pair(T t, U u)   {
            a=t;b=u;
        }
    }
}

ফলাফল (আমি দেখেছি সেরা কেস)

Running 'java VectorRacing' against ruby-runner/benchmark.txt

 No.    Size     Target   Score     Details
-------------------------------------------------------------------------------------
  1    37 x 1        36   0.38889   Racer reached goal at ( 36, 0) in 14 turns.
  2    38 x 1        37   0.54054   Racer reached goal at ( 37, 0) in 20 turns.
  3    33 x 1        32   0.62500   Racer reached goal at ( 32, 0) in 20 turns.
  4    10 x 10       10   0.40000   Racer reached goal at ( 9, 8) in 4 turns.
  5     9 x 6         8   0.75000   Racer reached goal at ( 6, 2) in 6 turns.
  6    15 x 7        16   2.00000   Racer did not reach the goal within 16 turns.
  7    17 x 8        16   2.00000   Racer hit a wall at position ( 8, 2).
  8    19 x 13       18   0.44444   Racer reached goal at ( 16, 2) in 8 turns.
  9    60 x 10      107   0.65421   Racer reached goal at ( 0, 6) in 70 turns.
 10    31 x 31      106   2.00000   Racer hit a wall at position ( 25, 9).
 11    31 x 31      106   2.00000   Racer hit a wall at position ( 8, 1).
 12    50 x 20       50   2.00000   Racer hit a wall at position ( 27, 14).
 13   100 x 100    2600   2.00000   Racer went out of bounds at position ( 105, 99).
 14    79 x 63      242   2.00000   Racer went out of bounds at position (-2, 26).
 15    26 x 1        25   0.32000   Racer reached goal at ( 25, 0) in 8 turns.
 16    17 x 1        19   2.00000   Racer went out of bounds at position (-2, 0).
 17    50 x 1        55   2.00000   Racer went out of bounds at position ( 53, 0).
 18    10 x 7        23   2.00000   Racer went out of bounds at position ( 10, 2).
 19    55 x 55       45   0.33333   Racer reached goal at ( 4, 49) in 15 turns.
 20    50 x 50      200   2.00000   Racer hit a wall at position ( 14, 7).
-------------------------------------------------------------------------------------
TOTAL SCORE:             26.45641

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

আহ এটি অন্যান্য ডিরেক্টরি থেকে চালানো হয়েছে। কমান্ড লাইনে জাভার সাথে পরিচিত নয় তাদের জন্য:java -cp path/to/class/file VectorRacing
মার্টিন ইন্ডার

আহ, হ্যাঁ আমি এক টন ক্লাস করেছি (13, নির্ভুল হতে)। আমি আমার ক্লাস ডিরেক্টরি থেকে সর্বদা আপনার স্ক্রিপ্টটি চালাচ্ছিলাম, তাই আমি আসলে এটি পরীক্ষা করিনি। আমি একটি পরীক্ষার কেস করতে পারি তবে আমি মনে করি আমি এমন একটি রেসার তৈরির চেষ্টা করব যা প্রথমে এলোমেলো নয়।
ছদ্মনাম

অবশ্যই। যদি আপনি তা করেন তবে দয়া করে এটি আলাদা উত্তর হিসাবে যুক্ত করুন। (এবং তাদের প্রতিটি সঙ্গে এক পরীক্ষা ক্ষেত্রে যোগ করার জন্য বিনা দ্বিধায়।)
মার্টিন Ender

দুর্ভাগ্যক্রমে, আমাকে আরও একটি বিধি যুক্ত করতে হয়েছিল। স্মরণটিকে এই চ্যালেঞ্জের সময়ের চেয়ে সীমাবদ্ধ মনে হয়, তাই মেমরির ব্যবহারকে সীমাবদ্ধ করার জন্য আমাকে একটি শক্ত সেট করতে হয়েছিল। আপনার রেসার যে কোনও রান যেখানে 1 গিগাবাইটের বেশি মেমরি ব্যবহার করে তা সময়সীমা ছাড়িয়ে গেলে একই প্রভাবতে বাতিল হয়ে যাবে। বর্তমান ট্র্যাকগুলির সেটগুলির জন্য, আপনার স্কোর এই পরিবর্তন দ্বারা প্রভাবিত হয়নি (এবং সম্ভবত কখনও হবে না)।
মার্টিন ইন্ডার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.