পেট্রি ডিশের জন্য যুদ্ধ


32

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

.....x....
...x...o..
...x.c..o.
.......o..

আরোপ করা

প্রতিটি ঘরে তিনটি বৈশিষ্ট্য রয়েছে। গেমের শুরুতে আপনার সেল প্রজাতিগুলি নির্দিষ্ট করার সময়, আপনি এই বৈশিষ্ট্যের মধ্যে 12 পয়েন্ট বরাদ্দ করেন।

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

ক্রিয়াকলাপ

প্রতিটি পালা, প্রতিটি ঘর একটি পদক্ষেপ নিতে পারে:

  • সরান: ঘরটি 1 শক্তি ব্যয়ে যে কোনও দিকে (N / S / E / W / NE / NW / SE / SW) এক স্থান স্থানান্তরিত করে।

    • একটি ঘর অন্য একটি জীবন্ত কক্ষ দ্বারা দখল করা স্থানের উপরে স্থানান্তর করতে পারে না।
    • একটি ঘর গ্রিড থেকে সরানো যায় না।
    • একটি কক্ষের দেহে চলে যাওয়া শবকে ধ্বংস করে।
  • আক্রমণ: 1 থেকে 3 এনার্জি পয়েন্ট ব্যয় করে 1 থেকে 3 টি ক্ষতি করে, একটি সেল একটি সংলগ্ন কক্ষে আক্রমণ করে।

    • একটি ঘর যে কোনও দিকে আক্রমণ করতে পারে (এন / এস / ই / ডাব্লু / এনই / এনডাব্লু / এসই / এসডাব্লু)
    • বন্ধুত্বপূর্ণ কোষগুলিতে আক্রমণ করা আইনী।
  • ভাগ করুন: ঘরটি 5 শক্তির ব্যয়ে সংলগ্ন স্থানে একটি নতুন ঘর তৈরি করে এবং তৈরি করে।

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

    • একটি ঘর যে কোনও দিকে খেতে পারে (এন / এস / ই / ডাব্লু / এনই / এনডাব্লু / এসই / এসডাব্লু)
  • বিশ্রাম: একটি ঘরের জন্য একটি ঘরের কিছুই করা হয় না, আবার 2 শক্তি ফিরে আসে।

  • বিস্ফোরণ: যখন কোনও কোষে 3 বা তার চেয়ে কম এইচপি এবং এইচপির চেয়ে বেশি শক্তি থাকে, তখন এটি বিস্ফোরিত হতে পারে এবং আটটি সংলগ্ন কোষের ক্ষতির কারণ হতে পারে।

    • প্রতিটি সংলগ্ন কক্ষের ক্ষয়ক্ষতি (exploding cell HP) + (explodng cell acidity)
    • বিস্ফোরণে নিহত যে কোনও কোষের মতোই একটি বিস্ফোরিত সেল মারা যায় এবং মৃতদেহের পিছনে ছেড়ে যায়।

প্রোটোকল

সেটআপ

আপনার প্রোগ্রাম BEGINস্টিডিনে সরবরাহিত স্ট্রিংয়ের সাথে চলবে । আপনার প্রোগ্রামটি অবশ্যই আপনার কোষের প্রজাতির জন্য এইচপি, শক্তি এবং অ্যাসিডিটির প্রতিনিধিত্ব করে 3 অ-নেতিবাচক পূর্ণসংখ্যার স্পেস-বিভাজিত তালিকাটিকে স্টাডাউট করতে হবে: যেমন 5 6 1,। সংখ্যাগুলি অবশ্যই 12 এর সমষ্টি হতে হবে 0, আপনি যদি চান তবে অম্লতা হতে পারে । (অন্যান্য বৈশিষ্ট্যগুলিও শূন্য হতে পারে তবে কার্যত এমনটি করা গেমটি হারায়!)

আপনি উত্তর-পশ্চিম বা দক্ষিণ-পূর্ব কোণে, একটি প্রান্ত দিয়ে উভয় প্রান্ত থেকে এক স্থান দূরে একটি কক্ষ দিয়ে শুরু করুন। প্রারম্ভিকণে পূর্ণ এইচপি এবং শক্তি রয়েছে।

প্রতিটি কোষ কাজ করে

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

10 4
..........
..xx.c....
...c...o..
......o...

6 3 5 7

প্রথম দুটি সংখ্যা অঙ্গনের প্রস্থ এবং উচ্চতা নির্দেশ করে: এখানে একটি 10-বাই -4 আখড়া রয়েছে।

  • oকোষ তোমার; xকোষ তোমার শত্রুদের হয়। (এটি সর্বদা সত্য; প্রতিটি প্লেয়ার সর্বদা তাদের নিজস্ব কোষ হিসাবে দেখায় o))
  • .শূণ্যস্থান খালি আছে।
  • cশূণ্যস্থান ভোজ্য সেল ওই মৃতদেহগুলিকে প্রতিনিধিত্ব করে।

খালি লাইনের পরে সংখ্যাগুলি এই সেল সম্পর্কে তথ্য উপস্থাপন করে:

  • প্রথম দুটি সংখ্যা x,yস্থানাঙ্কগুলি হয়, 0,0উপরের বাম দিক থেকে সূচিকৃত (সুতরাং 6 3এখানে দক্ষিণ-সর্বাধিক oকক্ষকে বোঝানো হয় )।
  • তৃতীয় নম্বরটি হ'ল কোষের এইচপি; চতুর্থ নম্বরটি হ'ল কোষের শক্তি।

আপনার প্রোগ্রামটি একটি ক্রিয়াকলাপ (স্টাডাউট) করা উচিত। নীচের উদাহরণগুলিতে, আমরা Nউদাহরণের দিকনির্দেশ হিসাবে ব্যবহার করব , তবে এটি সেই ক্রিয়া ( N/ S/ E/ W/ NE/ NW/ SE/ SW) এর জন্য কোনও দিকনির্দেশ আইনী হতে পারে । সমস্ত প্রোগ্রাম আউটপুট কেস-সংবেদনশীল, তবে উদাহরণগুলি বড় হাতের অক্ষর ব্যবহার করবে। অবৈধ যে কোনও আউটপুট ক্রিয়াকলাপ (এটির মধ্যে অবৈধ সিনট্যাক্স রয়েছে বা অবৈধ ক্রিয়াকলাপের চেষ্টা করার কারণে) উপেক্ষা করা হয় এবং এর ফলে সেল RESTইনিংয়ের ফলাফল হয় (এবং এভাবে 2 শক্তি অর্জন)।

  • MOVE N
  • DIVIDE N
  • EAT N
  • ATTACK N 2 - সংখ্যাটি আক্রমণটির শক্তি উপস্থাপন করে (1 - 3)
  • REST
  • EXPLODE

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

উদাহরণ

একটি প্রোগ্রাম কীভাবে আচরণ করে তা এখানে রয়েছে। স্টিডিনের ইনপুটটি এখানে নেতৃস্থানীয় >তীরগুলির সাথে বোঝানো হয় (স্পষ্ট করে স্পেস দিয়ে প্রকৃত ইনপুট থেকে পৃথক করা হয়) এবং স্টডআউটে আউটপুটটিতে <তীর থাকে।

> BEGIN
< 5 6 1

তারপরে, প্রোগ্রামটি আবার শুরু করা হয়েছে:

> 10 4
> ..........
> .o........
> ........x.
> ..........
>
> 1 1 5 6
< DIVIDE SE

আপনার প্রতিপক্ষের পালা (যিনি DIVIDE Wএকক প্রারম্ভিক কক্ষটি নিয়ে সিদ্ধান্ত নিয়েছিলেন ) পরে, প্রতিটি প্রোগ্রামের জন্য একবার আপনার প্রোগ্রামটি দু'বার চাওয়া হয়েছে:

> 10 4
> ..........
> .o........
> ..o....xx.
> ..........
>
> 1 1 5 1
< MOVE E

আপনার পালা দ্বিতীয় অনুরোধ জন্য:

> 10 4
> ..........
> ..o.......
> ..o....xx.
> ..........
>
> 2 2 5 1
< MOVE SE

নোট করুন এই দ্বিতীয় কক্ষটি আপনার পালা শুরুর আগে অন্য কোষের চলাচলের ভিত্তিতে আপডেট হওয়া বোর্ডের অবস্থাটি দেখে sees এছাড়াও লক্ষ করুন যে এই কক্ষটি 1 শক্তি দিয়ে তৈরি করা হয়েছে, কারণ পিতামৃত কোষটিতে 6 টি শক্তি ছিল যখন এটি বিভাগে শেষ পালা করেছিল (সুতরাং মূল 6, বিয়োগের 5-শক্তি ব্যয়কে 1 শক্তি দিয়ে একটি শিশু কোষ তৈরি করেছিল)।

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

জিত

আপনি উভয় দ্বারা জিততে পারেন:

  • সমস্ত বিরোধী কোষ ধ্বংস করে দেওয়া, বা
  • প্রতি খেলোয়াড়ের 150 টি মোড় শেষ হওয়ার পরে আপনার প্রতিপক্ষের চেয়ে বেশি কক্ষ থাকা

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

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

অন্যান্য তথ্য

  • আপনার প্রোগ্রামের রাজ্য বজায় রাখার চেষ্টা করা উচিত নয় (পেট্রি থালা ব্যবহারের বাইরে): এককোষী জীবের খুব ভাল স্মৃতি থাকে না এবং মুহুর্তে বিশ্ববাসীর প্রতিক্রিয়া হয়। বিশেষত কোনও ফাইলের (বা অন্যান্য ডেটা স্টোর) লিখিতভাবে, একটি রিমোট সার্ভারের সাথে যোগাযোগ করা, বা পরিবেশের ভেরিয়েবলগুলি সুস্পষ্টভাবে অনুমোদিত নয়।
  • উবুন্টু 12.04.4 এ জমা দেওয়া / সংকলন করা হবে।
  • ১০০ স্কোরিং গেমের স্পেসিফিকেশনগুলি এখনও নিশ্চিত হওয়া যায়নি তবে তারা সম্ভবত একাধিক রঙ্গিন মাপের সাথে জড়িত থাকবে (উদাহরণস্বরূপ, একটি ছোট অঙ্গনে 50 রান এবং বৃহত্তর অঙ্গনে 50 রান)। বৃহত্তর অঙ্গনের জন্য, উপযুক্ত যুদ্ধ সংঘটিত হতে পারে তা নিশ্চিত করার জন্য আমি সর্বোচ্চ টার্নের গণনা বাড়িয়ে তুলতে পারি।

সম্পদ

এখানে ড্রাইভার কোড যা সিমুলেশনটি চালায়, নোড.জেএস এর জন্য লিখিত, দ্বারা ডাকা হয়েছিল node petri.js 'first program' 'second program'। উদাহরণস্বরূপ, জাভা-লিখিত কক্ষের বিরুদ্ধে পাইথন-লিখিত কক্ষটি আঁকানো যেমন দেখায় node petri.js 'python some_cell.py' 'java SomeCellClass'

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

অবশ্যই আপনি আলাদা ভাষায় একটি সেল লিখতে মুক্ত; এগুলি কেবল তিনটি ভাষা যা আমি সময় সাশ্রয় সহায়তা হিসাবে বয়লারপ্লেট কোড লেখার সিদ্ধান্ত নিয়েছি।

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


1
@ রায়ান আপনাকে জাভা কোডের জন্য 'node c:/cell/cell_template.js'যেমন নির্দিষ্ট করতে হবে ঠিক তেমন প্রতিটি যুক্তির জন্য একটি সম্পূর্ণ চালিতযোগ্য কমান্ড নির্দিষ্ট করতে হবে 'java CellTemplate'। আমি চ্যালেঞ্জ পাঠ্যে আরও পরিষ্কার করব। আপনার যদি সমস্যা হতে থাকে তবে আমরা (এবং প্রযুক্তিগত সমস্যাযুক্ত অন্য কেউ) আমার সবেমাত্র তৈরি একটি চ্যাটরুমে এই আলোচনা চালিয়ে যেতে পারি
অ্যাপসিলাররা

1
@ মুগি প্রতি খেলায় মাত্র 2 জন প্রতিপক্ষ
এপিসিলার

3
মানুষ, উদাহরণগুলি দুর্দান্ত!
কমনগ্যুই

3
@ অ্যাপসিলাররা আমরা আপনাকে আড্ডায় জিজ্ঞাসা করেছি কিন্তু আপনাকে পিং করতে ভুলে গিয়েছি যাতে আপনি খেয়াল নাও করতে পারেন: আমরা ভাবছিলাম কখন আপনি গেমটি চালানোর পরিকল্পনা করছেন?
প্ল্যানাপাস

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

উত্তর:


3

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

def surroundingCells(x, y)
  result = Hash.new
  if x >= 1
    if y >= 1
      # northwest
      result["NW"] = $petriDish[x - 1][y - 1]
    end
    if y < ($sizeY - 1) # $sizeY - 1 is the farthest south square
      # southwest
      result["SW"] = $petriDish[x - 1][y + 1]
    end
      # west
      result["W"] = $petriDish[x - 1][y]
  end
  if x < ($sizeX - 1)
    if y >= 1
      # northeast
      result["NE"] = $petriDish[x + 1][y - 1]
    end
    if y < ($sizeY - 1)
      # southeast
      result["SE"] = $petriDish[x + 1][y + 1]
    end
    # east
    result["E"] = $petriDish[x + 1][y]
  end
  # north
  result["N"] = $petriDish[x][y - 1] if y >= 1
  # south
  result["S"] = $petriDish[x][y + 1] if y < ($sizeY - 1)
  return result
end

def directionTowardsEnemies(locX, locY)
  totalXDirections = 0
  totalYDirections = 0
  totalTargetsFound = 0 # enemies or corpses
  optimalDirections = []
  for x in 0..($petriDish.length - 1)
    for y in 0..($petriDish[0].length - 1)
      if $petriDish[x][y] == 'c' or $petriDish[x][y] == 'x'
        totalXDirections += (x - locX)
        totalYDirections += (y - locY)
        totalTargetsFound += 1
      end
    end
  end
  if totalXDirections == 0
    if totalYDirections > 0
      optimalDirections << "S" << "SE" << "SW"
    else
      optimalDirections << "N" << "NE" << "NW"
    end
    return optimalDirections
  end
  if totalYDirections == 0
    if totalXDirections > 0
      optimalDirections << "E" << "NE" << "SE"
    else
      optimalDirections << "W" << "NW" << "SW"
    end
    return optimalDirections
  end
  if totalXDirections > 0
    if totalYDirections > 0
      optimalDirections << "SE"
      if totalYDirections > totalXDirections
        optimalDirections << "S" << "E"
      else
        optimalDirections << "E" << "S"
      end
    else
      optimalDirections << "NE"
      if -totalYDirections > totalXDirections
        optimalDirections << "N" << "E"
      else
        optimalDirections << "E" << "N"
      end
    end
    return optimalDirections
  end
  if totalXDirections < 0
    if totalYDirections > 0
      optimalDirections << "SW"
      if totalYDirections > -totalXDirections
        optimalDirections << "S" << "W"
      else
        optimalDirections << "W" << "S"
      end
    else
      optimalDirections << "NW"
      if -totalYDirections > -totalXDirections
        optimalDirections << "N" << "W"
      else
        optimalDirections << "W" << "N"
      end
    end
  end
  return optimalDirections
end

firstLine = gets
if firstLine == "BEGIN"
  puts "5 7 0"
  exit 0
end
$sizeX, $sizeY = firstLine.split(' ')[0].to_i, firstLine.split(' ')[1].to_i
$petriDish = Array.new($sizeX) { Array.new($sizeY) }
for y in 0..($sizeY - 1)
  line = gets
  chars = line.split('').reverse.drop(1).reverse # this gets every character but     the last
  for x in 0..(chars.length - 1)
    $petriDish[x][y] = chars[x]
  end
end
gets # blank line
info = gets
locX = info.split(' ')[0].to_i
locY = info.split(' ')[1].to_i
hp = info.split(' ')[2].to_i
energy = info.split(' ')[3].to_i

# dividing is our first priority
if(energy >= 5)
  # try to divide towards enemies
  dirs = directionTowardsEnemies(locX, locY)
  directions = { "N" => [0, -1], "NE" => [1, -1], "E" => [1, 0],
    "SE" => [1, 1], "S" => [0, 1], "SW" => [-1, 1],
    "W" => [-1, 0], "NW" => [-1, -1] }
  for dir in dirs
    potentialNewX = locX + directions[dir][0]
    potentialNewY = locY + directions[dir][1]
    if $petriDish[potentialNewX][potentialNewY] == '.'
      puts "DIVIDE #{dir}"
      exit 0
    end
  end
  # otherwise, just divide somewhere.
  surroundingCells(locX, locY).each do |k, v|
    if v == '.'
      puts "DIVIDE #{k}"
      exit 0
    end
  end
end

# next, eating
surroundingCells(locX, locY).each do |k, v|
  if v == 'c'
    puts "EAT #{k}"
    exit 0
  end
end

# next, attacking
surroundingCells(locX, locY).each do |k, v|
  attackStrength = 0
  if (energy > 5) then # we want to save energy for dividing
    attackStrength = [(energy - 5), 3].min
  else
    attackStrength = [energy, 3].min
  end
  if v == 'x'
    puts "ATTACK #{k} #{attackStrength}"
    exit 0
  end
end

# otherwise, rest
puts "REST"

আমি কোনও রুবি প্রোগ্রামার নই, তাই আমি ভাবছি কেন কিছু ভেরিয়েবলগুলি সাধারণ এবং কিছু একটি দিয়ে শুরু হয় $
seequ

$একটি বৈশ্বিক চলক নির্দেশ করতে ব্যবহৃত হয়। হ্যাঁ, তারা মন্দ, কিন্তু এই ছোট প্রোগ্রামে, এটি খুব বেশি গুরুত্বপূর্ণ নয়।
অ্যালেক্স

গ্লোবাল ভেরিয়েবলগুলি কেবলমাত্র উত্পাদন কোডেই খারাপ in এগুলি স্ক্রিপ্টগুলিতে কে মনে রাখে?
seequ

আমার ঘর কি সত্যই একমাত্র যার দক্ষতা 4-8-0 নয়?
অ্যালেক্স

এটি এখন পর্যন্ত আমার সমন্বিত ব্যাকটিরিয়ার সেরা প্রতিযোগী! আমি আপনার একক সেল-জীবের উপর পরীক্ষার ফলাফলের ভিত্তিতে আমার কৌশল তৈরি করেছি। =)

3

জীবাণুবিশেষ

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

যদি কোনও শত্রু সংলগ্ন হয় বা এক স্থান দূরে থাকে তবে সর্বদা আক্রমণ করে বা তার দিকে অগ্রসর হয়, কোনও শূন্যস্থান পূরণ না করে পেছনের সারিটিকে কিছু করার অনুমতি দেয়।

আমি অন্য কোনও জমা দেওয়ার বিপরীতে এটি পরীক্ষা করি নি তাই এটি কতটা ভাল করবে তা সম্পর্কে ধারণা নেই।

var MAX_HP = 2;
var MAX_ENERGY = 10;
var ACIDITY = 0;

function PathfindingNode(_x, _y, _prevNode, _distance, _adjacentEnemies) {
    this.x = _x;
    this.y = _y;
    this.prevNode = _prevNode;
    this.distance = _distance;
    this.adjacentEnemies = _adjacentEnemies;
}

PathfindingNode.prototype.GetDistance = function()
{
    return this.distance;
}

var evaluatedNodes = {};
var initialNode = {};
var firstEval = true;

function evaluateNode(x, y, arena)
{
    //get surrounding reachable nodes that havent already been checked
    var adjacentEmpties = arena.getAdjacentMatches(arena.get(x, y), [".", "c"]);

    //if this node is adjacent to the start node - special case because the start node isnt an empty
    if (firstEval)
        adjacentEmpties.push({ 'x': initialNode.x, 'y': initialNode.y });

    //find the optimal node to reach this one
    var prevNode = null;
    for (var i in adjacentEmpties)
    {
        if(evaluatedNodes[adjacentEmpties[i].x + "," + adjacentEmpties[i].y])
        {
            var currentNode = evaluatedNodes[adjacentEmpties[i].x + "," + adjacentEmpties[i].y];

            if (!prevNode) {
                prevNode = currentNode;
            }
            else {
                if(currentNode.GetDistance() < prevNode.GetDistance())
                {
                    prevNode = currentNode;
                }
            }
        }
    }

    var adjacentEnemies = arena.getAdjacentMatches(arena.get(x, y), ["x"]);
    var newNode = new PathfindingNode(x, y, prevNode, prevNode.GetDistance() + 1, adjacentEnemies.length);
    evaluatedNodes[x + "," + y] = newNode;
}

function evaluateNeighbours(arena) {
    //breadth first search all reachable cells
    var nodesToEvaluate = [];
    for (var i in evaluatedNodes) {
        var emptyNodes = arena.getAdjacentMatches(arena.get(evaluatedNodes[i].x, evaluatedNodes[i].y), [".", "c"]);
        //only ones that havent already been eval'd
        for (var j in emptyNodes)
            if (!evaluatedNodes[emptyNodes[j].x + "," + emptyNodes[j].y])
                nodesToEvaluate.push(emptyNodes[j])
    }

    //have all available nodes been evaluated
    if (nodesToEvaluate.length === 0)
        return false;

    for (var i in nodesToEvaluate)
    {
        evaluateNode(parseInt(nodesToEvaluate[i].x), parseInt(nodesToEvaluate[i].y), arena)
    }

    firstEval = false;
    return true;
}

function getAllReachableNodes(arena, cell) {
    //return a list of all reachable cells, with distance and optimal path
    evaluatedNodes = {};

    //add the first node to get started
    var adjacentEnemies = arena.getAdjacentMatches(arena.get(cell.x, cell.y), ["x"]);
    var newNode = new PathfindingNode(parseInt(cell.x), parseInt(cell.y), null, 0, adjacentEnemies.length);
    evaluatedNodes[cell.x + "," + cell.y] = newNode;
    initialNode.x = parseInt(cell.x);
    initialNode.y = parseInt(cell.y);
    firstEval = true;

    while (evaluateNeighbours(arena))
        ;

    return evaluatedNodes;
}

function passedMiddleGround(arena)
{
    for (var i = (parseInt(arena.width) / 2) - 1; i < parseInt(arena.width); i++)
    {
        for(var j = 0; j < parseInt(arena.height); j++)
        {
            if (arena.get(i, j).symbol == "o")
                return true;
        }
    }
    return false;
}

function decide(arena, cell, outputCallback) {

    var nearbyEmpties = arena.getAdjacentMatches(cell.point, [".", "c"]);
    var nearbyEnemies = arena.getAdjacentMatches(cell.point, ["x"]);
    var nearbyCorpses = arena.getAdjacentMatches(cell.point, ["c"]);

    if (nearbyEnemies.length > 4 && cell.energy >= cell.hp && cell.hp <= 3) {
        outputCallback("EXPLODE");
        return;
    }

    //attack whenever we get the chance. leave the replication to the cells doing nothing
    if (cell.energy > 0 && nearbyEnemies.length > 0){
        outputCallback("ATTACK " + arena.getDirection(cell, nearbyEnemies[(nearbyEnemies.length * Math.random()) | 0]) + " " + Math.min(cell.energy, 3));
        return;
    }

    //if we are close to an enemy, move towards it. let the back line fill the new space
    if (cell.energy > 2) {
        for (var i = 0; i < nearbyEmpties.length; ++i) {
            var space = nearbyEmpties[i];
            if (arena.getAdjacentMatches(space, ["x"]).length) {
                outputCallback("MOVE " + arena.getDirection(cell, space));
                return;
            }
        }
    }

    //yum
    if (nearbyCorpses.length > 0) {
        outputCallback("EAT " + arena.getDirection(cell, nearbyCorpses[(nearbyCorpses.length * Math.random()) | 0]));
        return;
    }

    //until we pass the middle ground, just keep moving into tactical position. afterwards we can start replication
    if (passedMiddleGround(arena) && cell.energy < 5 && nearbyEmpties.length > 0)
    {
        outputCallback("REST");
        return;
    }

    //try to block the opponent cells - interrupt their replication
    //if we have enough energy to move, choose the best spot
    if (nearbyEmpties.length > 0 && ((cell.energy >= 2 && nearbyEnemies.length == 0) || cell.energy >= 5)) {

        var nextMove = null;

        if (nearbyEmpties.length === 1) {
            nextMove = nearbyEmpties[0];
        }
        else {
            var reachableNodes = getAllReachableNodes(arena, cell);

            //select nodes that have an adjacent enemy
            var enemyAdjacentNodes = {};
            var enemyNodesReachable = false;
            for (var node in reachableNodes) {
                if (reachableNodes.hasOwnProperty(node) && reachableNodes[node].adjacentEnemies > 0) {
                    enemyAdjacentNodes[node] = reachableNodes[node];
                    enemyNodesReachable = true;
                }
            }

            if (enemyNodesReachable)
            {
                //if there are any then select the closest one
                var closest = null;
                for (var node in enemyAdjacentNodes) {
                    if(!closest)
                    {
                        closest = enemyAdjacentNodes[node];
                    }
                    else{
                        if(enemyAdjacentNodes[node].GetDistance() < closest.GetDistance())
                        {
                            closest = enemyAdjacentNodes[node];
                        }
                    }

                }

                //select the first move of the nodes path
                //trace the selected node back to the first node to select the first move towards the cell.
                while (closest.prevNode != null && closest.prevNode.prevNode != null)
                {
                    closest = closest.prevNode;
                }
                nextMove = arena.get(closest.x, closest.y);
            }
        }

        //a path to the enemy was found
        if(nextMove)
        {
            //do this until we get half way across the board, then we just replicate
            if (!passedMiddleGround(arena)) {
                if (cell.energy >= 5) {
                    outputCallback("DIVIDE " + arena.getDirection(cell, nextMove));
                    return;
                }

                outputCallback("MOVE " + arena.getDirection(cell, nextMove));
                return;
            }
            else {
                outputCallback("DIVIDE " + arena.getDirection(cell, nextMove));
                return;
            }

        }

    }

    //if theres no path to an enemy available, just divide anywhere
    if (cell.energy >= 5 && nearbyEmpties.length > 0) {
        outputCallback("DIVIDE " + arena.getDirection(cell, nearbyEmpties[(nearbyEmpties.length * Math.random()) | 0]));
        return;
    }

    outputCallback("REST");
    return;
}

var input = "";
// quiet stdin EPIPE errors
process.stdin.on("error", function(err) {
    log("slight error: " + err);
});
process.stdin.on("data", function(data) {
    input += data;
});
process.stdin.on("end", function() {
    if(input == "BEGIN") {
        // output space-separated attributes
        process.stdout.write([MAX_HP, MAX_ENERGY, ACIDITY].join(" "));
        clearLog();
    } else {
        // read in arena and decide on an action
        var arena = new Arena();
        var lines = input.split("\n");
        var dimensions = lines[0].split(" ").map(function(d) { return parseInt(d); });
        arena.width = dimensions[0];
        arena.height = dimensions[1];
        for(var y=1; y<=dimensions[1]; ++y) {
            for(var x=0; x<lines[y].length; ++x) {
                arena.set(x, y-1, lines[y][x]);
            }
        }

        var stats = lines[dimensions[1]+2].split(" ");
        var cell = { x: stats[0], y: stats[1], hp: stats[2], energy: stats[3], point: arena.get(stats[0], stats[1]) };

        // decide on an action and write the action to stdout
        decide(arena, cell, function(output) { process.stdout.write(output); })
    }
});

var Arena = function() {
    this.dict = {};
};
Arena.prototype = {
    // get Point object
    get: function(x,y) {
        if(!this.dict[x+","+y])
            return 'w';
        return this.dict[x+","+y];
    },

    // store Point object
    set: function(x,y,d) {
        this.dict[x+","+y] = new Point(x,y,d);
    },

    // get an array of all Points adjacent to this one whose symbol is contained in matchList
    // if matchList is omitted, return all Points
    getAdjacentMatches: function(point, matchList) {
        var result = [];
        for(var i=-1; i<=1; ++i) {
            for(var j=-1; j<=1; ++j) {
                var inspectedPoint = this.get(point.x+i, point.y+j);
                if(inspectedPoint && 
                   (i!=0 || j!=0) &&
                   (!matchList || matchList.indexOf(inspectedPoint.symbol) != -1)) {
                    result.push(inspectedPoint);
                }
            }
        }
        return result;
    },

    // return the direction from point1 to point2
    getDirection: function(point1, point2) {
        var dx = point2.x - point1.x;
        var dy = point2.y - point1.y;
        dx = Math.abs(dx) / (dx || 1);
        dy = Math.abs(dy) / (dy || 1);

        c2d = { "0,0":"-",
                "0,-1":"N", "0,1":"S", "1,0":"E", "-1,0":"W",
                "-1,-1":"NW", "1,-1":"NE", "1,1":"SE", "-1,1":"SW" };

        return c2d[dx + "," + dy];
    }
}

var Point = function(x,y,d) {
    this.x = x;
    this.y = y;
    this.symbol = d;
}
Point.prototype.toString = function() {
    return "(" + this.x + ", " + this.y + ")";
}

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

বিটিডব্লিউ, এটি খেলোয়াড় 2 হিসাবে লক্ষ্য হিসাবে কাজ করবে বলে মনে হচ্ছে না
জাস্টহাল্ফ

3

সরল কোষ মধ্যে সম্পন্ন node.js। এটি পরীক্ষা করে আবার উদাহরণ নোড সেল এবং কোস্টরনারের বিরুদ্ধে এটি তাদের মারধর করে।

হালনাগাদ

এখনও মোটামুটি সহজ, শত্রু বা বিভাজনের দিকে এগিয়ে যাওয়ার চেষ্টা করুন।

// used in defining cell spec
var MAX_HP = 4;
var MAX_ENERGY = 8;
var ACIDITY = 0;

function decide(arena, cell, outputCallback) {

    var nearbyEmpties = arena.getAdjacentMatches(cell.point, [".", "c"]);
    var nearbyEnemies = arena.getAdjacentMatches(cell.point, ["x"]);
    var nearbyCorpses = arena.getAdjacentMatches(cell.point, ["c"]);
    var nearbyFriends = arena.getAdjacentMatches(cell.point, ["o"]);

    if (nearbyFriends.length >= 8) {
        outputCallback("REST");
        return;
    }

    if (nearbyFriends.length >= 7 && nearbyEnemies.length < 0 && nearbyCorpses.length > 0 && energy < MAX_ENERGY) {
        outputCallback("EAT " + arena.getDirection(cell, nearbyCorpses[(nearbyCorpses.length*Math.random())|0]));
        return;
    }

    // if you have two or more nearby enemies, explode if possible
    if(nearbyEnemies.length >= 1
        && cell.energy >= cell.hp 
        && cell.hp <= 1 
        && nearbyEnemies.length > nearbyFriends.length) {
        outputCallback("EXPLODE");
        return;
    }

    // if you have two or more nearby enemies, explode if possible
    if(nearbyEnemies.length >= 3 && cell.energy >= cell.hp && nearbyEnemies.length > nearbyFriends.length) {
        outputCallback("EXPLODE");
        return;
    }

    // if you have the energy and space to divide, do it
    if(cell.energy >= 5 && nearbyEmpties.length > 0) {
        var ed = arena.getEnemyDirection(cell);
        if (nearbyEmpties.indexOf(ed) >= 0 && Math.random() < 0.5){
            outputCallback("DIVIDE " + ed);
        } else{
            outputCallback("DIVIDE " + arena.getDirection(cell, nearbyEmpties[(nearbyEmpties.length*Math.random())|0]));
        }
        return;
    }

    // if at least one adjacent enemy, attack if possible
    if(cell.energy > 0 && nearbyEnemies.length > 0) {
        outputCallback("ATTACK " + arena.getDirection(cell, nearbyEnemies[(nearbyEnemies.length*Math.random())|0]) + " " + Math.min(cell.energy, 3));
        return;
    }

    if (Math.random() < 0.5) {
        for(var i=0; i<nearbyEmpties.length; ++i) {
            outputCallback("MOVE " + arena.getEnemyDirection(cell));
            return;
        }
    } 

    if (nearbyEmpties.length > 0 && nearbyEnemies.length <= 6) {
        outputCallback("REST"); // because next turn is divide time
        return;
    }

    // if there's a nearby corpse, eat it if your energy is below max
    if(nearbyCorpses.length > 0) {
        outputCallback("EAT " + arena.getDirection(cell, nearbyCorpses[(nearbyCorpses.length*Math.random())|0]));
        return;
    }

    outputCallback("REST");
    return;
}

var input = "";
// quiet stdin EPIPE errors
process.stdin.on("error", function(err) {
    console.log("slight error: " + err);
});
process.stdin.on("data", function(data) {
    input += data;
});
process.stdin.on("end", function() {
    if(input == "BEGIN") {
        // output space-separated attributes
        process.stdout.write([MAX_HP, MAX_ENERGY, ACIDITY].join(" "));
    } else {
        // read in arena and decide on an action
        var arena = new Arena();
        var lines = input.split("\n");
        var dimensions = lines[0].split(" ").map(function(d) { return parseInt(d); });
        arena.width = dimensions[0];
        arena.height = dimensions[1];
        for(var y=1; y<=dimensions[1]; ++y) {
            for(var x=0; x<lines[y].length; ++x) {
                arena.set(x, y-1, lines[y][x]);
            }
        }

        var stats = lines[dimensions[1]+2].split(" ");
        var cell = { x: stats[0], y: stats[1], hp: stats[2], energy: stats[3], point: arena.get(stats[0], stats[1]) };

        // decide on an action and write the action to stdout
        decide(arena, cell, function(output) { process.stdout.write(output); })
    }
});

var Arena = function() {
    this.dict = {};
};
Arena.prototype = {
    // get Point object
    get: function(x,y) {
        return this.dict[x+","+y];
    },

    // store Point object
    set: function(x,y,d) {
        this.dict[x+","+y] = new Point(x,y,d);
    },

    // get an array of all Points adjacent to this one whose symbol is contained in matchList
    // if matchList is omitted, return all Points
    getAdjacentMatches: function(point, matchList) {
        var result = [];
        for(var i=-1; i<=1; ++i) {
            for(var j=-1; j<=1; ++j) {
                var inspectedPoint = this.get(point.x+i, point.y+j);
                if(inspectedPoint && 
                   (i!=0 || j!=0) &&
                   (!matchList || matchList.indexOf(inspectedPoint.symbol) != -1)) {
                    result.push(inspectedPoint);
                }
            }
        }
        return result;
    },

    // return the direction from point1 to point2
    getDirection: function(point1, point2) {
        var dx = point2.x - point1.x;
        var dy = point2.y - point1.y;
        dx = Math.abs(dx) / (dx || 1);
        dy = Math.abs(dy) / (dy || 1);

        c2d = { "0,0":"-",
                "0,-1":"N", "0,1":"S", "1,0":"E", "-1,0":"W",
                "-1,-1":"NW", "1,-1":"NE", "1,1":"SE", "-1,1":"SW" };

        return c2d[dx + "," + dy];
    },

    getEnemyDirection: function(p) {
        for (var i = 0; i < this.width; i++) {
            for (var j = 0; j < this.height; j++) {
                var found = this.get(i,j);
                if (found != null && found.symbol == "x") {
                    return this.getDirection(p, found);
                }
            }
        }
        return "N"; //should never happen
    }
}

var Point = function(x,y,d) {
    this.x = x;
    this.y = y;
    this.symbol = d;
}
Point.prototype.toString = function() {
    return "(" + this.x + ", " + this.y + ")";
}

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

2

বিবর্তন

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

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;

public class Evolution {
    public static final int MAX_HP = 4;
    public static final int MAX_ENERGY = 8;
    public static final int ACIDITY = 0;

    // given arena state and cell stats, return an action string (e.g., "ATTACK NW 2", "DIVIDE S")
    public static String decide(Arena arena, Point cell, int hp, int energy) {
        ArrayList<Point> nearbyEmpty = arena.getAdjacentMatches(cell, ".");
        ArrayList<Point> nearbyEnemies = arena.getAdjacentMatches(cell, "x");
        ArrayList<Point> nearbyCorpses = arena.getAdjacentMatches(cell, "c");
        ArrayList<Point> nearbyFriends = arena.getAdjacentMatches(cell, "o");

        // more than 1 enemy around => explode if possible and worth it
        if(nearbyEnemies.size() > 1 && energy > hp && hp <= 3 && nearbyEnemies.size() > nearbyFriends.size()) {
            return "EXPLODE";
        }

        // enemies around => always attack with max strength
        if(energy > 0 && nearbyEnemies.size() > 0) {
            int attackStrength = Math.min(energy, 3);
            Point enemy = nearbyEnemies.get(0);
            return "ATTACK " + arena.getDirection(cell, enemy) + " " + attackStrength;
        }       

        // safe spot => divide if possible
        if(energy >= 5 && nearbyEmpty.size() > 0) {
            Point randomEmpty = nearbyEmpty.get((int)Math.floor(nearbyEmpty.size()*Math.random()));
            return "DIVIDE " + arena.getDirection(cell, randomEmpty);
        }

        // nearby corpse and missing energy => eat
        if(nearbyCorpses.size() > 0 && energy < MAX_ENERGY) {
            Point corpse = nearbyCorpses.get(0);
            return "EAT " + arena.getDirection(cell, corpse);
        }

        // move towards enemy => constant flow of attacks
        if(energy == 4) {
            return "MOVE " + arena.getEnemyDirection(cell);
        }

        return "REST";
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br =
            new BufferedReader(new InputStreamReader(System.in));

        String firstLine;

        firstLine = br.readLine();
        if(firstLine.equals("BEGIN")) {
            System.out.println(MAX_HP + " " + MAX_ENERGY + " " + ACIDITY);
        } else {
            String[] dimensions = firstLine.split(" ");
            int width = Integer.parseInt(dimensions[0]);
            int height = Integer.parseInt(dimensions[1]);
            Point[][] arena = new Point[height][];
            String input;
            int lineno = 0;

            while(!(input=br.readLine()).equals("")) {
                String[] charList = input.substring(1).split("");
                arena[lineno] = new Point[width];
                for(int i=0; i<charList.length; ++i) {
                    arena[lineno][i] = new Point(i, lineno, charList[i]);
                }
                lineno++;
            }

            String[] stats = br.readLine().split(" ");
            int x = Integer.parseInt(stats[0]);
            int y = Integer.parseInt(stats[1]);
            int hp = Integer.parseInt(stats[2]);
            int energy = Integer.parseInt(stats[3]);

            Arena arenaObj = new Arena(arena, width, height);
            System.out.print(decide(arenaObj, arenaObj.get(x,y), hp, energy));
        }
    }

    public static class Arena {
        public Point[][] array;
        public HashMap<String, String> c2d;
        public int height;
        public int width;

        public Arena(Point[][] array, int width, int height) {
            this.array = array;
            this.width = width;
            this.height = height;

            this.c2d = new HashMap<String, String>();
            this.c2d.put("0,0", "-");
            this.c2d.put("0,-1", "N");
            this.c2d.put("0,1", "S");
            this.c2d.put("1,0", "E");
            this.c2d.put("-1,0", "W");
            this.c2d.put("-1,-1", "NW");
            this.c2d.put("1,-1", "NE");
            this.c2d.put("-1,1", "SW");
            this.c2d.put("1,1", "SE");
        }

        // get the character at x,y
        // or return empty string if out of bounds
        public Point get(int x, int y) {
            if(y < 0 || y >= this.array.length){
                return null;
            }

            Point[] row = this.array[y];

            if(x < 0 || x >= row.length) {
                return null;
            }

            return row[x];
        }

        // get arraylist of Points for each adjacent space that matches the target string
        public ArrayList<Point> getAdjacentMatches(Point p, String match) {
            ArrayList<Point> result = new ArrayList<Point>();
            for(int i=-1; i<=1; ++i) {
                for(int j=-1; j<=1; ++j) {
                    Point found = this.get(p.x+i, p.y+j);
                    if((i!=0 || j!=0) && found != null && found.symbol.equals(match)) {
                        result.add(found);
                    }
                }
            }
            return result;
        }

        // get the direction string from point 1 to point 2
        public String getDirection(Point p1, Point p2) {
            int dx = p2.x - p1.x;
            int dy = p2.y - p1.y;
            dx = Math.abs(dx) / (dx==0?1:dx);
            dy = Math.abs(dy) / (dy==0?1:dy);

            return this.c2d.get(dx + "," + dy);
        }

        public String getEnemyDirection(Point p) {
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    Point found = this.get(x,y);
                    if (found != null && found.symbol.equals("x")) {
                        return getDirection(p, found);
                    }
                }
            }
            return "N"; //should never happen
        }
    }

    public static class Point {
        int x, y;
        String symbol;

        public Point(int x, int y, String sym) {
            this.x=x;
            this.y=y;
            this.symbol=sym;
        }
    }
}

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

2

নরত্তএদেশীয় রণোন্মাদ যোদ্ধা

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

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

আমি উত্পন্ন জার-ফাইলটি আমার ড্রপবক্সে আপলোড করেছি । সাথে চালাওjava -jar petridish-clojure.jar

শুধু নির্মল:

> BEGIN
< 4 6 2 LOOP
> 10 4
> ..........
> ..xx.c....
> ...c...O..
> ......o...
> 
> 3 4 6
< DIVIDE NW
> 10 4
> ..........
> ..xx.c....
> ...c.o.o..
> ......o...
>
> 5 2 4 1
< EAT N
> END
(ns petridish.core
  (:require [clojure.string :as s])
  (:gen-class))

(def ^:const maxhp     4)
(def ^:const maxenergy 6)
(def ^:const acidity   2)

(defn str->int
  [x]
  (if (empty? x)
    0
    (Integer. (re-find #"\d+" x))))

(defn sum-vectors [vec1 vec2]
  (vec (map #(vec (map + % vec2)) vec1)))

(defn find-adjacent [[width height] board pos target]
  (let [cells (sum-vectors [[-1 -1] [0 -1] [1 -1]
                            [-1  0]        [1  0]
                            [-1  1] [0  1] [1  1]]
                           pos)
        directions ["NW" "N" "NE"
                    "W"      "E"
                    "SW" "S" "SE"]]
    (for [cell cells
          :when (and (> width  (cell 0) -1)
                     (> height (cell 1) -1)
                     (= target (get-in board (reverse cell))))]
      (directions (.indexOf cells cell)))))

(defn decide [size board [x y hp energy]]
  (let [friends (find-adjacent size board [x y] \o)
        enemies (find-adjacent size board [x y] \x)
        corpses (find-adjacent size board [x y] \c)
        empty   (find-adjacent size board [x y] \.)]
    (cond
      (and (<= hp 3) (> energy hp) (seq enemies))
        "EXPLODE"
      (and (>= energy 5) (seq empty))
        (str "DIVIDE " (first empty))
      (and (>= energy 3) (seq enemies))
        (str "ATTACK " (first enemies) " " (min 3 energy))
      (and (< energy maxenergy) (seq corpses))
        (str "EAT " (first corpses))
      (or (and (<= 5 energy maxenergy) (not (seq empty))) (< energy 5))
        "REST"
      (seq empty)
        (str "MOVE " (rand-nth empty)))))

(defn read-board [[width height]]
  (let [result (vec (for [i (range height)]
                        (read-line)))]
    (read-line) ; Skip the empty line
    result))

(defn reader []
  (loop []
    (let [firstline (read-line)]
      (when (not= firstline "END")
        (println
          (if (= firstline "BEGIN")
            (str maxhp " " maxenergy " " acidity " LOOP")
            (let [size   (map str->int (s/split firstline #"\s+"))
                  board  (read-board size)
                  status (map str->int (s/split (read-line) #"\s+"))]
              (decide size board status))))
        (recur)))))

(defn -main []
  (reader))

লগ আপডেট করুন

1. Fixed the logic a little and removed redundancies.

অ্যাসিডিটির দুর্দান্ত ব্যবহার- আসলে, আমি মনে করি এটি একমাত্র বট যা অম্লতা ব্যবহার করে।
অ্যালেক্স

@ অ্যালেক্স আমরা কীভাবে এটি কার্যকর হয় তা দেখতে পাব তবে আমি মনে করি এটি অ্যামিবা পরিষ্কার করতে সক্ষম হওয়া উচিত। আপনি কোড সম্পর্কে কি মনে করেন? আমি ক্লোজারে খুব নতুন।
seequ

আপনার উদাহরণে, সদ্য তৈরি হওয়া সেল কীভাবে স্থানান্তর করতে পারে? আমি ভেবেছিলাম আপনার আরও একবারের জন্য অপেক্ষা করা দরকার?
জাস্টহেল্ফ

@ ওসফাল্ফ এহ, সেলগুলি তাদের বয়স কত তা জানেন না।

হ্যাঁ, তবে কন্ট্রোলার জানেন, তাই না? এটি নতুন গঠিত কক্ষে ঘুরে দেখার কথা নয়।
justhalf

2

ক্ষুধার্ত, ক্ষুধার্ত বট

এখানে একটি এন্ট্রি দেওয়া আছে I আমি আশা করি আপনার প্রোগ্রামের সাথে কীভাবে যোগাযোগ করবেন তার প্রযুক্তিগত চশমাগুলি কী ছিল তা আমি সঠিকভাবে বুঝতে পেরেছি। দিয়ে ট্রিগার করা উচিত Rscript Hungryhungrybot.R
যদি এর কমপক্ষে 6 টি শক্তি থাকে তবে এটি বিভক্ত হয়, পছন্দসই শত্রুর দিকে। অন্যথায় এটি এর পাশের যা কিছু গ্রহণযোগ্য বা যা কিছু গ্রহণযোগ্য e যদি কোনও খাবার পৌঁছতে না পারে তবে বোনের কোষের চেয়ে আশেপাশে আরও শত্রু থাকলে বা কাছের শত্রুদের সাথে লড়াই করলে তা ফেটে যাবে। কেবলমাত্র শক্তি 0 হলে এবং খাওয়ার মতো কিছু না পাওয়া গেলে স্থির থাকে।

infile <- file("stdin")
open(infile)
input1 <- readLines(infile,1)
if(input1=="BEGIN"){
    out <- "4 7 1"
    }else{
        nr <- as.integer(strsplit(input1," ")[[1]][2])
        nc <- as.integer(strsplit(input1," ")[[1]][1])
        input2 <- readLines(infile, 2+as.integer(nr))
        arena <- do.call(rbind,strsplit(input2[1:nr],""))
        stats <- strsplit(input2[nr+2]," ")[[1]]
        coords <- as.integer(stats[2:1])+1
        hp <- as.integer(stats[3])
        nrj <- as.integer(stats[4])
        closest <- function(coords,arena,object){
            a <- which(arena==object,arr.ind=TRUE)
            if(length(a)){
                d <- apply(a,1,function(x)max(abs(x-coords)))
                b <- which.min(d)
                f <- a[b,]
                dir <- f-coords
                where <- ""
                if(dir[1]<0)where <- paste(where,"N",sep="")
                if(dir[1]>0)where <- paste(where,"S",sep="")
                if(dir[2]<0)where <- paste(where,"W",sep="")
                if(dir[2]>0)where <- paste(where,"E",sep="")
                dist <- d[b]
                }else{dist <- NA; where <- ""}
            list(dist,where)
            }
        near <- expand.grid((coords[1]-1):(coords[1]+1),(coords[2]-1):(coords[2]+1))
        near <- near[near[,1]<=nr&near[,2]<=nc,]
        adjacent <- t(matrix(apply(near,1,function(x)arena[x[1],x[2]]),nr=3,byrow=TRUE))
        w <- matrix(c('NW','N','NE','W','','E','SW','S','SE'),nr=3,byrow=TRUE)
        if(coords[1]==1) w <- w[-1,]
        if(coords[1]==nr) w <- w[-3,]
        if(coords[2]==1) w <- w[,-1]
        if(coords[2]==nc) w <- w[,-3]
        if(any(arena=="c")){food <- closest(coords,arena,"c")}else{food <- list(nrj+2,"")}
        enemies <- closest(coords,arena,"x")
        if(nrj>=6){
            empties <- w[adjacent=="."]
            if(!length(empties)){
                if(sum(adjacent=="x")>sum(adjacent=="o") & hp<=3 & nrj>=hp){
                    out <- "EXPLODE"
                    }else{out <- "REST"}
                }else if(enemies[[2]]%in%empties & enemies[[1]]!=1){
                out <- paste("DIVIDE", enemies[[2]])
                }else{
                out <- paste("DIVIDE", empties[1])
                }
            }else{
                if(nrj==0 & !any(adjacent=="c")){
                    out <- "REST"
                    }else{
                        if(any(adjacent=="c")){
                            out <- paste("EAT",w[adjacent=="c"][1])
                            }else if(any(arena=="c") & food[[1]]<=(nrj+1)){
                                    out <- paste("MOVE",food[[2]])
                            }else if(sum(adjacent=="x")>sum(adjacent=="o") & hp<=3 & nrj>=hp){
                                out <- "EXPLODE"
                            }else if(any(adjacent=="x")){
                                out <- paste("ATTACK",w[adjacent=="x"][1],max(nrj,3))
                            }else{
                                out <- paste("MOVE", enemies[[2]])
                            }
                    }
            }
        }
cat(out)
flush(stdout())

আমি (অবশেষে) চ্যালেঞ্জটি চালানোর চেষ্টা করছি এবং আমি Error: unexpected 'else' in "else"আপনার কোডটি পেয়ে যাচ্ছি । আমি ভয় করি যে আমি আর কিছু জানি না, তাই আমি এই ত্রুটিটি সমাধান করতে শুরু করতে পারি না। রেফারেন্সের জন্য, আমি ড্রাইভারটি চালানোর সময় এবং যখন আমি কেবল প্রোগ্রামটি চালিত করি এবং ম্যানুয়ালি টাইপ করি তখনই আমি এই ত্রুটিটি পেয়েছি BEGIN
অ্যাপসিলার

@ অ্যাপসিলার্স আরএফ আমি একটি নতুন লাইন যুক্ত করেছি যেখানে আমার উচিত ছিল না: এটি এখন কাজ করা উচিত।
প্ল্যানাপাস

এটি সেই ত্রুটিটি ঠিক করেছে যাতে আমরা সেলটি ডিমে যেতে পারি; গেমটি আসলে শুরু হওয়ার সাথে সাথে আমি এখন আর একটি পেয়ে যাচ্ছি:Error in if (dir[1] < 0) where <- paste(where, "N", sep = "") : missing value where TRUE/FALSE needed
অ্যাপসিলাররা

এখন প্রথম Error: object 'food' not found
পালাটি ঠিকঠাক

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

2

সমন্বিত ব্যাকটিরিয়া

আমি আশা করি আমি বেশি দেরী করি না

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

আপনি যখন এককোষী হয়ে থাকেন, আপনি পূর্বের অবস্থাটি মুখস্থ করতে পারেন, তবে অন্যরকম আচরণ করার জন্য আপনি নিজের অবস্থানটি কাজে লাগাতে পারেন! =)

এটি ব্যাকটিরিয়াকে বিভাজক এবং মুভারে বিভক্ত করবে এবং এর ফলে প্রতিরক্ষা রেখাটি ঠিক রেখে, কেবল সামনের লাইনের পরিবর্তে আরও ব্যাকটিরিয়া দরকারী রাখে।

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

মিড-গেমটিতে, যা বোর্ডের কক্ষের সংখ্যা দ্বারা সনাক্ত করা হয়, তারা শত্রু অঞ্চলগুলিতে আটকানো চেষ্টা করবে them এটিই মূল বিজয়ী কৌশল।

বর্তমানে অন্যান্য সমস্ত বিরোধীদের তুলনায় এটির সর্বোচ্চ বৃদ্ধির হার রয়েছে তবে এটির ধীরে ধীরে সূচনা হয়েছে, সুতরাং এটি বৃহত অঙ্গনে আরও ভাল কাজ করে।

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

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

public class CoordinatedBacteria {
    public static final int MAX_HP = 6;
    public static final int MAX_ENERGY = 6;
    public static final int ACIDITY = 0;

    // given arena state and cell stats, return an action string (e.g., "ATTACK NW 2", "DIVIDE S")
    public static String decide(final Arena arena, Point cell, int hp, int energy) {
        // empty and corpses are free for movement and division
        final Point2D enemyCenter = arena.getCenterOf("x");
        final Point2D ourCenter = arena.getCenterOf("o");
        final int moverPos = (enemyCenter.x <= ourCenter.x || enemyCenter.y <= ourCenter.y) ? (arena.width+arena.height+1)%2 : 1;
        final int attackPos = (enemyCenter.x <= ourCenter.x || enemyCenter.y <= ourCenter.y) ? (arena.width+arena.height)%2 : 1;

        int selfCount = arena.count("o");
        boolean isMidWay = selfCount > (arena.width*arena.height/2-1);

        if(!isMidWay){
            if(enemyCenter.x < ourCenter.x){
                enemyCenter.x = 0;
                enemyCenter.y = 0;
                ourCenter.x = arena.width;
                ourCenter.y = arena.height;
            } else {
                enemyCenter.x = arena.width;
                enemyCenter.y = arena.height;
                ourCenter.x = 0;
                ourCenter.y = 0;
            }
        }
        ArrayList<Point> nearbyEmpty = arena.getAdjacentMatches(cell, ".");
        Collections.sort(nearbyEmpty, new Comparator<Point>(){
            @Override
            public int compare(Point o1, Point o2) {
                Double score1 = arena.getAdjacentMatches(o1, ".").size()
                        + arena.getAdjacentMatches(o1, "c").size()
                        + arena.getAdjacentMatches(o1, "x").size()
                        - arena.getAdjacentMatches(o1, "o").size()
                        + distance(o1.x, o1.y, enemyCenter.x, enemyCenter.y)*100;
                Double score2 = arena.getAdjacentMatches(o2, ".").size()
                        + arena.getAdjacentMatches(o2, "c").size()
                        + arena.getAdjacentMatches(o2, "x").size()
                        - arena.getAdjacentMatches(o2, "o").size()
                        + distance(o1.x, o1.y, enemyCenter.x, enemyCenter.y)*100;
                return Double.compare(score2, score1);
            }
        });
        ArrayList<Point> nearbyEnemies = arena.getAdjacentMatches(cell, "x");
        Collections.sort(nearbyEnemies, new Comparator<Point>(){
            @Override
            public int compare(Point o1, Point o2) {
                Integer score1 = (arena.getAdjacentMatches(o1, ".").size()
                        + arena.getAdjacentMatches(o1, "c").size()
                        - arena.getAdjacentMatches(o1, "x").size()
                        + arena.getAdjacentMatches(o1, "o").size())
                        *10
                        + (isAtBoundary(o1, arena)?1000:0)
                        + (o1.x + o1.y + attackPos + 1)%2;
                Integer score2 = (arena.getAdjacentMatches(o2, ".").size()
                        + arena.getAdjacentMatches(o2, "c").size()
                        - arena.getAdjacentMatches(o2, "x").size()
                        + arena.getAdjacentMatches(o2, "o").size())
                        *10
                        + (isAtBoundary(o2, arena)?1000:0)
                        + (o2.x + o2.y + attackPos + 1)%2;
                return Integer.compare(score2, score1);
            }
        });
        ArrayList<Point> nearbyCorpses = arena.getAdjacentMatches(cell, "c");
        Collections.sort(nearbyCorpses, new Comparator<Point>(){
            @Override
            public int compare(Point o1, Point o2) {
                Integer score1 = arena.getAdjacentMatches(o1, "x").size()
                        - arena.getAdjacentMatches(o1, "o").size();
                Integer score2 = arena.getAdjacentMatches(o2, "x").size()
                        - arena.getAdjacentMatches(o2, "o").size();
                return Integer.compare(score1, score2);
            }
        });
        ArrayList<Point> nearbyFriends = arena.getAdjacentMatches(cell, "o");

        for(Point empty: nearbyEmpty){
            if(nearbyFriends.size()>=2 && energy >= 1 && arena.getAdjacentMatches(empty, "x").size()==3 && isAtBoundary(empty, arena)){
                return "MOVE "+arena.getDirection(cell, empty);
            }
        }

        for(Point empty: nearbyCorpses){
            if(nearbyFriends.size()>=2 && energy >= 1 && arena.getAdjacentMatches(empty, "x").size()==3 && isAtBoundary(empty, arena)){
                return "MOVE "+arena.getDirection(cell, empty);
            }
        }

        if ((cell.x+cell.y)%2 == moverPos && energy >= 1 && energy <= 5){
            if(nearbyEmpty.size()>0){
                Point foremost = nearbyEmpty.get(0);
                if(nearbyFriends.size() >= 4){
                    return "MOVE "+arena.getDirection(cell, foremost);
                }
            }
            if(nearbyCorpses.size() > 0) {
                Point corpse = nearbyCorpses.get(0);
                return "EAT " + arena.getDirection(cell, corpse);
            }

            if(energy > 0 && nearbyEnemies.size() > 0) {
                int attackStrength = Math.min(energy, 3);
                Point enemy = nearbyEnemies.get(0);
                return "ATTACK " + arena.getDirection(cell, enemy) + " " + attackStrength;
            }

            if(nearbyFriends.size() >= 4 && nearbyEmpty.size() > 0){
                Point movePoint = getBestPointToDivide(arena, nearbyEmpty);
                return "MOVE " + arena.getDirection(cell, movePoint);
            }
        }

        if(energy >= 5 && nearbyEmpty.size() > 0) {
            Point divisionPoint = getBestPointToDivide(arena, nearbyEmpty);
            if(energy == MAX_ENERGY && nearbyFriends.size() >= 5
                    && distance(enemyCenter.x, enemyCenter.y, cell.x, cell.y) > distance(enemyCenter.x, enemyCenter.y, divisionPoint.x, divisionPoint.y)){
                return "MOVE " + arena.getDirection(cell, divisionPoint);
            }
            return "DIVIDE " + arena.getDirection(cell, divisionPoint);
        }

        if(nearbyCorpses.size() > 0) {
            Point corpse = nearbyCorpses.get(0);
            if (energy < MAX_ENERGY){
                return "EAT " + arena.getDirection(cell, corpse);
            } else {
                return "DIVIDE " + arena.getDirection(cell, corpse);
            }
        }

        if(energy >= 5 && nearbyCorpses.size() > 0) {
            Point divisionPoint = getBestPointToDivide(arena, nearbyCorpses);
            if(energy == MAX_ENERGY && nearbyFriends.size() >= 5
                    && distance(enemyCenter.x, enemyCenter.y, cell.x, cell.y) < distance(enemyCenter.x, enemyCenter.y, divisionPoint.x, divisionPoint.y)){
                return "MOVE " + arena.getDirection(cell, divisionPoint);
            }
            return "DIVIDE " + arena.getDirection(cell, divisionPoint);
        }

        // if at least one adjacent enemy, attack if possible
        if(energy > 0 && nearbyEnemies.size() > 0) {
            int attackStrength = Math.min(energy, 3);
            Point enemy = nearbyEnemies.get(0);
            return "ATTACK " + arena.getDirection(cell, enemy) + " " + attackStrength;
        }

        return "REST";

    }

    public static boolean isAtBoundary(Point point, Arena arena){
        return point.x==0 || point.x==arena.width-1 || point.y==0 || point.y==arena.height-1;
    }

    public static double distance(double x1, double y1, double x2, double y2){
        return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
    }

    public static Point getBestPointToDivide(Arena arena, List<Point> nearbyEmpty){
        Point result = null;
        double minDist = 100000;
        List<Point> mostEmpty = new ArrayList<Point>();
        int max = -1000;
        List<Point> neighbor = nearbyEmpty;
        for(Point point: neighbor){
            int emptyNeighborScore = arena.getAdjacentMatches(point, ".").size()
                    + arena.getAdjacentMatches(point, "c").size()
                    + arena.getAdjacentMatches(point, "x").size()
                    - arena.getAdjacentMatches(point, "o").size();
            if(emptyNeighborScore > max){
                mostEmpty = new ArrayList<Point>();
                mostEmpty.add(point);
                max = emptyNeighborScore;
            } else if(emptyNeighborScore == max){
                mostEmpty.add(point);
            }
        }
        for(Point point: mostEmpty){
            Point2D enemyCenter = arena.getCenterOf("x");
            double dist = Math.pow(point.x-enemyCenter.x, 2) + Math.pow(point.y-enemyCenter.y, 2);
            if(dist < minDist){
                minDist = dist;
                result = point;
            }
        }
        return result;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br =
                new BufferedReader(new InputStreamReader(System.in));

        String firstLine;

        firstLine = br.readLine();
        if(firstLine.equals("BEGIN")) {
            System.out.println(MAX_HP + " " + MAX_ENERGY + " " + ACIDITY);
        } else {
            String[] dimensions = firstLine.split(" ");
            int width = Integer.parseInt(dimensions[0]);
            int height = Integer.parseInt(dimensions[1]);
            Point[][] arena = new Point[height][];
            String input;
            int lineno = 0;

            while(!(input=br.readLine()).equals("")) {
                char[] charList = input.toCharArray();
                arena[lineno] = new Point[width];
                for(int i=0; i<charList.length; ++i) {
                    arena[lineno][i] = new Point(i, lineno, charList[i]);
                }
                lineno++;
            }

            String[] stats = br.readLine().split(" ");
            int x = Integer.parseInt(stats[0]);
            int y = Integer.parseInt(stats[1]);
            int hp = Integer.parseInt(stats[2]);
            int energy = Integer.parseInt(stats[3]);

            Arena arenaObj = new Arena(arena, width, height);
            System.out.print(decide(arenaObj, arenaObj.get(x,y), hp, energy));
        }
    }

    public static class Arena {
        public Point[][] array;
        public HashMap<String, String> c2d;
        public int height;
        public int width;

        public Arena(Point[][] array, int width, int height) {
            this.array = array;
            this.width = width;
            this.height = height;


            this.c2d = new HashMap<String, String>();
            this.c2d.put("0,0", "-");
            this.c2d.put("0,-1", "N");
            this.c2d.put("0,1", "S");
            this.c2d.put("1,0", "E");
            this.c2d.put("-1,0", "W");
            this.c2d.put("-1,-1", "NW");
            this.c2d.put("1,-1", "NE");
            this.c2d.put("-1,1", "SW");
            this.c2d.put("1,1", "SE");
        }

        // get the character at x,y
        // or return empty string if out of bounds
        public Point get(int x, int y) {
            if(y < 0 || y >= this.array.length){
                return null;
            }

            Point[] row = this.array[y];

            if(x < 0 || x >= row.length) {
                return null;
            }

            return row[x];
        }

        // get arraylist of Points for each adjacent space that matches the target string
        public ArrayList<Point> getAdjacentMatches(Point p, String match) {
            ArrayList<Point> result = new ArrayList<Point>();
            for(int i=-1; i<=1; ++i) {
                for(int j=-1; j<=1; ++j) {
                    Point found = this.get(p.x+i, p.y+j);
                    if((i!=0 || j!=0) && found != null && found.symbol.equals(match)) {
                        result.add(found);
                    }
                }
            }
            return result;
        }

        public ArrayList<Point> getAdjacents(Point p){
            ArrayList<Point> result = new ArrayList<Point>();
            for(int i=-1; i<=1; ++i) {
                for(int j=-1; j<=1; ++j) {
                    Point found = this.get(p.x+i, p.y+j);
                    if((i!=0 || j!=0) && found != null) {
                        result.add(found);
                    }
                }
            }
            return result;
        }

        public int count(String sym){
            int result = 0;
            for(int y=0; y<array.length; y++){
                for(int x=0; x<array[y].length; x++){
                    Point cur = this.get(x, y);
                    if(cur!=null && cur.symbol.equals(sym)){
                        result++;
                    }
                }
            }
            return result;
        }

        // get the direction string from point 1 to point 2
        public String getDirection(Point p1, Point p2) {
            int dx = p2.x - p1.x;
            int dy = p2.y - p1.y;
            dx = Math.abs(dx) / (dx==0?1:dx);
            dy = Math.abs(dy) / (dy==0?1:dy);

            return this.c2d.get(dx + "," + dy);
        }

        public Point2D getCenterOf(String sym){
            Point2D result = new Point2D(0,0);
            int count = 0;
            for(int y=0; y<array.length; y++){
                for(int x=0; x<array[y].length; x++){
                    if(this.get(x,y).symbol.equals(sym)){
                        result.x += x;
                        result.y += y;
                        count++;
                    }
                }
            }
            result.x /= count;
            result.y /= count;
            return result;
        }

    }

    public static class Point {
        int x, y;
        String symbol;

        public Point(int x, int y, String sym) {
            this.x=x;
            this.y=y;
            this.symbol=sym;
        }

        public Point(int x, int y, char sym){
            this(x, y, ""+sym);
        }
    }

    public static class Point2D{
        double x,y;
        public Point2D(double x, double y){
            this.x = x;
            this.y = y;
        }
    }
}

1

আমি মনে করি আমি আমার জমা পোস্ট করব, যেহেতু আপনি বয়লারপ্লেট যুক্তি যুক্ত করতে এত উদার ...

আপনার যুক্তিতে একটি সমস্যা ছিল, যেখানে খাওয়ার-ক্রিয়া একটি EAT এর পরিবর্তে একটি ATTACK জারি করবে এবং মৃতদেহটি নষ্ট করবে।

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

অ্যাসিডটি আমার কাছে পয়েন্টের অপচয় হিসাবে মনে হচ্ছে তাই আমি এটি রেখে দিয়েছি ...

আমি জমাটি পরীক্ষা করিনি, কারণ এটি 2 মিনিটের জিনিস;)

এখানে আমার কোড:

/*
 Sample code for a "Battle for the Petri Dish" cell

 Released under the terms of the WTF Public License
 No warranty express or implied is granted, etc, etc.

 I just hacked this together very quickly; improvements are welcome, so please fork the Gist if you like.

 used this code for a submission @kostronor

 */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;

public class SlimeCell {
    public static final int MAX_HP = 4;
    public static final int MAX_ENERGY = 8;
    public static final int ACIDITY = 0;

    // given arena state and cell stats, return an action string (e.g., "ATTACK NW 2", "DIVIDE S")
    public static String decide(final Arena arena, final Point cell, final int hp, final int energy) {
        // empty and corpses are free for movement and division
        ArrayList<Point> nearbyEmpty = arena.getAdjacentMatches(cell, ".");
        nearbyEmpty.addAll(arena.getAdjacentMatches(cell, "c"));

        ArrayList<Point> nearbyEnemies = arena.getAdjacentMatches(cell, "x");
        ArrayList<Point> nearbyCorpses = arena.getAdjacentMatches(cell, "c");
        ArrayList<Point> nearbyFriends = arena.getAdjacentMatches(cell, "o");

        // if you have energy and space to divide, divide into a random space
        if((energy >= 5) && (nearbyEmpty.size() > 0)) {
            Point randomEmpty = nearbyEmpty.get((int)Math.floor(nearbyEmpty.size()*Math.random()));
            return "DIVIDE " + arena.getDirection(cell, randomEmpty);
        }

        // if at least one adjacent enemy, attack if possible
        if((energy > 0) && (nearbyEnemies.size() > 1)) {
            int attackStrength = Math.min(energy, 3);
            Point enemy = nearbyEnemies.get((int)Math.floor(nearbyEnemies.size()*Math.random()));
            return "ATTACK " + arena.getDirection(cell, enemy) + " " + attackStrength;
        }

        // if there's a nearby corpse, eat it if your energy is below max
        if(nearbyCorpses.size() > 0) {
            Point corpse = nearbyCorpses.get((int)Math.floor(nearbyCorpses.size()*Math.random()));
            return "EAT " + arena.getDirection(cell, corpse);
        }

        return "REST";

    }

    public static void main(final String[] args) throws IOException {
        BufferedReader br =
                new BufferedReader(new InputStreamReader(System.in));

        String firstLine;

        firstLine = br.readLine();
        if(firstLine.equals("BEGIN")) {
            System.out.println(MAX_HP + " " + MAX_ENERGY + " " + ACIDITY);
        } else {
            String[] dimensions = firstLine.split(" ");
            int width = Integer.parseInt(dimensions[0]);
            int height = Integer.parseInt(dimensions[1]);
            Point[][] arena = new Point[height][];
            String input;
            int lineno = 0;

            while(!(input=br.readLine()).equals("")) {
                String[] charList = input.substring(1).split("");
                arena[lineno] = new Point[width];
                for(int i=0; i<charList.length; ++i) {
                    arena[lineno][i] = new Point(i, lineno, charList[i]);
                }
                lineno++;
            }

            String[] stats = br.readLine().split(" ");
            int x = Integer.parseInt(stats[0]);
            int y = Integer.parseInt(stats[1]);
            int hp = Integer.parseInt(stats[2]);
            int energy = Integer.parseInt(stats[3]);

            Arena arenaObj = new Arena(arena, width, height);
            System.out.print(decide(arenaObj, arenaObj.get(x,y), hp, energy));
        }
    }

    public static class Arena {
        public Point[][] array;
        public HashMap<String, String> c2d;
        public int height;
        public int width;

        public Arena(final Point[][] array, final int width, final int height) {
            this.array = array;
            this.width = width;
            this.height = height;

            this.c2d = new HashMap<String, String>();
            this.c2d.put("0,0", "-");
            this.c2d.put("0,-1", "N");
            this.c2d.put("0,1", "S");
            this.c2d.put("1,0", "E");
            this.c2d.put("-1,0", "W");
            this.c2d.put("-1,-1", "NW");
            this.c2d.put("1,-1", "NE");
            this.c2d.put("-1,1", "SW");
            this.c2d.put("1,1", "SE");
        }

        // get the character at x,y
        // or return empty string if out of bounds
        public Point get(final int x, final int y) {
            if((y < 0) || (y >= this.array.length)){
                return null;
            }

            Point[] row = this.array[y];

            if((x < 0) || (x >= row.length)) {
                return null;
            }

            return row[x];
        }

        // get arraylist of Points for each adjacent space that matches the target string
        public ArrayList<Point> getAdjacentMatches(final Point p, final String match) {
            ArrayList<Point> result = new ArrayList<Point>();
            for(int i=-1; i<=1; ++i) {
                for(int j=-1; j<=1; ++j) {
                    Point found = this.get(p.x+i, p.y+j);
                    if(((i!=0) || (j!=0)) && (found != null) && found.symbol.equals(match)) {
                        result.add(found);
                    }
                }
            }
            return result;
        }

        // get the direction string from point 1 to point 2
        public String getDirection(final Point p1, final Point p2) {
            int dx = p2.x - p1.x;
            int dy = p2.y - p1.y;
            dx = Math.abs(dx) / (dx==0?1:dx);
            dy = Math.abs(dy) / (dy==0?1:dy);

            return this.c2d.get(dx + "," + dy);
        }

    }

    public static class Point {
        int x, y;
        String symbol;

        public Point(final int x, final int y, final String sym) {
            this.x=x;
            this.y=y;
            this.symbol=sym;
        }
    }
}

1

পাতলা ছড়িয়ে পড়ে বোম্বার

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

এটি একটি দুর্দান্ত বলসি কৌশল এবং সম্ভবত খারাপভাবে সম্পাদন করবে, তবে এটি কী করে তা দেখার জন্য আমি আগ্রহী। আমি এটি পরীক্ষা করব এবং আজকে পরে এটি উন্নত করব, সম্ভবত।

/*
 Sample code for a "Battle for the Petri Dish" cell

 Released under the terms of the WTF Public License,
 No warranty express or implied is granted, etc, etc.

 I just hacked this together very quickly; improvements are welcome, so please fork the Gist if you like.
*/

// used in defining cell spec
var MAX_HP = 1;
var MAX_ENERGY = 7;
var ACIDITY = 4;

/*
   The decide function takes an Arena object (see below for prototype methods), a cell object,
   and an outputCallback, which accepts a command string to output
*/
function decide(arena, cell, outputCallback) {
    var nearbyEmpties = arena.getAdjacentMatches(cell.point, [".", "c"]);
    var nearbyEnemies = arena.getAdjacentMatches(cell.point, ["x"]);
    var nearbyCorpses = arena.getAdjacentMatches(cell.point, ["c"]);
    var nearbyFriendlies = arena.getAdjacentMatches(cell.point, ["o"]);

    //attempt to move away from friendlies if possible
    if(nearbyFriendlies.length>1 && cell.energy>0)
    {
        for(var i=0; i<nearbyEmpties.length; ++i)
        {
            var space = nearbyEmpties[i];
            if(arena.getAdjacentMatches(space, ["o"]).length == 1)
            {
                outputCallback("MOVE " + arena.getDirection(cell,space));
                return;
            }
        }
    }

    // Explode if there are two more adjacent enemies than friendlies or enemies and no friendlies.
    if((nearbyEnemies.length - nearbyFriendlies.length > 1 || (nearbyEnemies.length>0 && nearbyFriendlies.length == 0)) 
        && cell.energy >= cell.hp && cell.hp <= 3)
    {
        outputCallback("EXPLODE");
        return;
    }

    // if you have the energy and space to divide, and there's a way for the child to get away from friendlies, do it.
    if(cell.energy >= 5 && nearbyEmpties.length > 0)
    {
        for(var i=0; i<nearbyEmpties.length; ++i)
        {
            var space = nearbyEmpties[i];
            var possiblePositions = arena.getAdjacentMatches(space, ["o"]);
            for(var i=0; i<possiblePositions.length; ++i)
            {
                if(arena.getAdjacentMatches(possiblePositions[i], ["o"]).length == 0)
                {
                    outputCallback("DIVIDE " + arena.getDirection(cell,space));
                    return;
                }
            }
        }
    }

    // if at least one adjacent enemy, attack if possible
    if(cell.energy > 0 && nearbyEnemies.length > 0)
    {
        outputCallback("ATTACK " + arena.getDirection(cell, nearbyEnemies[(nearbyEnemies.length*Math.random())|0]) + " " + Math.min(cell.energy, 3));
        return;
    }

    // if there's a nearby corpse, eat it if your energy is below max
    if(nearbyCorpses.length > 0)
    {
        outputCallback("EAT " + arena.getDirection(cell, nearbyCorpses[(nearbyCorpses.length*Math.random())|0]));
        return;
    }

    outputCallback("REST");
    return;
}

var input = "";
// quiet stdin EPIPE errors
process.stdin.on("error", function(err) {
    //console.log("slight error: " + err);
});
process.stdin.on("data", function(data) {
    input += data;
});
process.stdin.on("end", function() {
    if(input == "BEGIN") {
        // output space-separated attributes
        process.stdout.write([MAX_HP, MAX_ENERGY, ACIDITY].join(" "));
    } else {
        // read in arena and decide on an action
        var arena = new Arena();
        var lines = input.split("\n");
        var dimensions = lines[0].split(" ").map(function(d) { return parseInt(d); });
        arena.width = dimensions[0];
        arena.height = dimensions[1];
        for(var y=1; y<=dimensions[1]; ++y) {
            for(var x=0; x<lines[y].length; ++x) {
                arena.set(x, y-1, lines[y][x]);
            }
        }

        var stats = lines[dimensions[1]+2].split(" ");
        var cell = { x: stats[0], y: stats[1], hp: stats[2], energy: stats[3], point: arena.get(stats[0], stats[1]) };

        // decide on an action and write the action to stdout
        decide(arena, cell, function(output) { process.stdout.write(output); })
    }
});

var Arena = function() {
    this.dict = {};
};
Arena.prototype = {
    // get Point object
    get: function(x,y) {
        return this.dict[x+","+y];
    },

    // store Point object
    set: function(x,y,d) {
        this.dict[x+","+y] = new Point(x,y,d);
    },

    // get an array of all Points adjacent to this one whose symbol is contained in matchList
    // if matchList is omitted, return all Points
    getAdjacentMatches: function(point, matchList) {
        var result = [];
        for(var i=-1; i<=1; ++i) {
            for(var j=-1; j<=1; ++j) {
                var inspectedPoint = this.get(point.x+i, point.y+j);
                if(inspectedPoint && 
                   (i!=0 || j!=0) &&
                   (!matchList || matchList.indexOf(inspectedPoint.symbol) != -1)) {
                    result.push(inspectedPoint);
                }
            }
        }
        return result;
    },

    // return the direction from point1 to point2
    getDirection: function(point1, point2) {
        var dx = point2.x - point1.x;
        var dy = point2.y - point1.y;
        dx = Math.abs(dx) / (dx || 1);
        dy = Math.abs(dy) / (dy || 1);

        c2d = { "0,0":"-",
                "0,-1":"N", "0,1":"S", "1,0":"E", "-1,0":"W",
                "-1,-1":"NW", "1,-1":"NE", "1,1":"SE", "-1,1":"SW" };

        return c2d[dx + "," + dy];
    }
}

var Point = function(x,y,d) {
    this.x = x;
    this.y = y;
    this.symbol = d;
}
Point.prototype.toString = function() {
    return "(" + this.x + ", " + this.y + ")";
}

আমি এটি পরীক্ষা করার চেষ্টা করছি কিন্তু আমি এটি চালানোর জন্য পাচ্ছি না। আমি node.js ইনস্টল করে কমান্ড লাইনটি চেষ্টা করেছি node c:/cells/petri.js 'node c:/cells/bomber.js' 'node c:/cells/sample.js। আমি যখন নোড অ্যাপ্লিকেশন কনসোলে এটি টাইপ করি তখন আমি কেবল তিনটি বিন্দু পাই, যখন আমি চেষ্টা করি এবং উইন্ডোজ সেমিডিতে চালিত করি তখন আমি পাই: 'নোড' কোনও অভ্যন্তরীণ বা বাহ্যিক কমান্ড, অপারেবল প্রোগ্রাম বা ব্যাচ ফাইল হিসাবে স্বীকৃত নয়। আমি সমস্ত ফাইলকে .js ফাইল হিসাবে সঠিক ফোল্ডারে সংরক্ষণ করেছি। কোনও নুবির জন্য কোনও সাহায্য? আমি আড্ডায় যাব বা অন্য কোথাও মন্তব্য করব, তবে আমার প্রতিনিধিত্ব খুব কম।
ওভাররেেক্টর

যেহেতু আমি পরীক্ষা করতে পারছি না, আপাতত, যদি কেউ আমাকে বলতে পারে যে আমার কোষগুলি তাদের বিরুদ্ধে কী করে। আমি আমার কৌশলটি দ্বিতীয় অনুমান করছি, বা কমপক্ষে ভাবছি এটির পরিমার্জন করা দরকার।
ওভাররেেক্টর

আপনার লাইনে কোনও প্রকার রয়েছে বলে মনে হয় if((nearbyEnemies.length - nearbyFriendlies.length > 1 ¦¦ - ¦¦এগুলি বৈধ অপারেটর বলে মনে হয় না এবং আপনার সাথে ম্যাথামেন্টের প্রথম বন্ধনী রয়েছে। আমার মনে হয় আপনি পোস্ট করার সময় কোড ফর্ম্যাটিংটি গোলযোগ পেয়ে গেছে?
অ্যাপসিলাররা

এটি আমার পরীক্ষাগুলি অনুসারে বেশ খারাপ কাজ করে। আপনার অনেক অ্যাসাইনমেন্ট রয়েছে ( =) যখন আপনি যা চান তা সমতা তুলনা ( ==)।
জাস্টহেল্ফ

ওহ অভিশাপ. আমি প্রায়শই এমন একটি ভাষায় প্রোগ্রামিং করছিলাম যেখানে (=) অ্যাসাইনমেন্টটি ফিরে আসার পরে ফিরে আসে, এটি কি এখন আরও ভাল চলে? যদিও এটি কখনও দুর্দান্ত করার আশা করিনি।
ওভাররেੈਕਟਰ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.