সেই জীবাণু কোথায় গেল?


21

ভূমিকা

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

ইনপুট

আপনার ইনপুটগুলি কোনও যুক্তিসঙ্গত বিন্যাসে অক্ষরের দুটি 2 ডি অ্যারে, পেট্রি থালাটির একটানা ছবি উপস্থাপন করে। উভয় অ্যারেতে, অক্ষরটি .শূন্য স্থান Oউপস্থাপন করে এবং একটি জীবাণু উপস্থাপন করে (আপনি চাইলে যে কোনও দুটি স্বতন্ত্র অক্ষর চয়ন করতে পারেন)। এছাড়াও, চারটি কার্ডিনাল দিকের মধ্যে একটি ধাপে কিছু জীবাণু সরিয়ে "পূর্বে" অ্যারে থেকে "পরে" অ্যারে পাওয়া যায়; বিশেষত, অ্যারেগুলির একই আকার রয়েছে। জীবাণুগুলি একই সাথে চলাফেরা করে, তাই তাদের মধ্যে একটি এমন একটি জায়গায় চলে যেতে পারে যেখানে ইতিমধ্যে অন্য জীবাণু রয়েছে, যদি এটি পথ থেকে সরে যায়। এটি নিশ্চিত যে "" আগে "অ্যারের সীমানায় কেবল ফাঁকা জায়গা থাকে এবং কমপক্ষে একটি জীবাণু থাকে। সুতরাং, নিম্নলিখিত ইনপুটগুলির একটি বৈধ জোড়:

Before  After
......  ......
.O..O.  ....O.
.OO.O.  .OO.O.
......  ..O...

আউটপুট

আপনার আউটপুট ইনপুটগুলির একই আকারে অক্ষরের একক 2D অ্যারে। এটি "পূর্বে" অ্যারে থেকে যে সমস্ত জীবাণুগুলির মধ্যে একটির সাথে স্থানান্তরিত হয়েছিল তাদের প্রতিস্থাপনের মাধ্যমে প্রাপ্ত >^<vহয়, যা গতিপথের দিকের উপর নির্ভর করে (আপনি এখানে 4 টি স্বতন্ত্র অক্ষরও ব্যবহার করতে পারেন)। বেশ কয়েকটি সম্ভাব্য আউটপুট হতে পারে, তবে আপনি কেবল তার মধ্যে একটি দিতে পারেন। উপরের উদাহরণে, একটি সম্ভাব্য সঠিক আউটপুট

......
.v..O.
.>v.O.
......

আউটপুটে অহেতুক চলাচলের অনুমতি রয়েছে এবং জীবাণুগুলি স্থানগুলি অদল-বদল করতে পারে, সুতরাং নিম্নলিখিতটিও বৈধ:

......
.v..v.
.>v.^.
......

বিধি এবং স্কোরিং

আপনি একটি সম্পূর্ণ প্রোগ্রাম বা একটি ফাংশন লিখতে পারেন। সর্বনিম্ন বাইট গণনা জয়, এবং মান লুফোলগুলি অনুমোদিত নয়।

আমি তুলনামূলকভাবে দক্ষ অ্যালগরিদমগুলিতে আগ্রহী, তবে আমি সম্পূর্ণ জোর করে জোর করে নিষিদ্ধ করতে চাই না। এই কারণে, একটি আধুনিক সিপিইউতে 10 মিনিটের মধ্যে শেষ পরীক্ষার কেস সমাধান করার জন্য -75% এর বোনাস রয়েছে (আমি বেশিরভাগ সমাধান পরীক্ষা করতে পারছি না, তাই আমি আপনাকে এখানে বিশ্বাস করব)। দাবি অস্বীকার: আমি জানি যে একটি দ্রুত অ্যালগরিদম বিদ্যমান ("বিচ্ছিন্ন পথগুলির সমস্যার জন্য অনুসন্ধান করুন"), তবে আমি নিজে এটি প্রয়োগ করি নি।

অতিরিক্ত পরীক্ষার মামলা

Before
......
.O..O.
..OO..
......
After
......
..O...
...OO.
..O...
Possible output
......
.>..v.
..vO..
......

Before
.......
.OOOOO.
.O..OO.
.OO..O.
.OOOOO.
.......
After
.......
..OOOOO
.O...O.
.O...O.
.OOOOOO
....O..
Possible output
.......
.>>>>>.
.O..>v.
.Ov..v.
.O>>v>.
.......

Before
..........
.OOO..OOO.
.OOOOOOOO.
.OOO..OOO.
..........
After
..O.......
.OOO..O.O.
..OOOOOOOO
.O.O..OOO.
.......O..
Possible output
..........
.>^O..O>v.
.^O>>>vO>.
.O>^..>vO.
..........

Before
............
.OO..OOOOOO.
.OO......OO.
...OOOOOO...
.O.OOOOOO.O.
...OOOOOO...
.OOOOOOOOOO.
............
After
..........O.
.OO..OOOOO..
.O...O...O..
.O.OOOOOOO..
.O.OOOOOO..O
...OO..OO...
....OOOOOOOO
.OOO........
Possible output
............
.OO..v<<<<^.
.v<......^<.
...OOO>>>...
.O.OOO^OO.>.
...OOv^OO...
.vvvO>>>>>>.
............

Before
................
.OOOOOO.OOOOOOO.
..OO..OOOOOOOOO.
.OOO..OOOO..OOO.
..OOOOOOOO..OOO.
.OOOOOOOOOOOOOO.
................
After
................
..OOOOO.OOOOOOOO
..OO..OOOOOOOOO.
..OO..OOOO..OOOO
..OOOOOOOO..OOO.
..OOOOOOOOOOOOOO
................
Possible output
................
.>>>>>v.>>>>>>>.
..OO..>>^>>>>>v.
.>>v..OOO^..OO>.
..O>>>>>>^..OOO.
.>>>>>>>>>>>>>>.
................

Before
..............................
.OOO.O.O.....O.....O.O.O..O...
..OOO.O...O..OO..O..O.O.......
.....O......O..O.....O....O...
.O.OOOOO......O...O..O....O...
.OO..O..OO.O..OO..O..O....O...
..O.O.O......OO.OO..O..OO.....
..O....O..O.OO...OOO.OOO...O..
.....O..OO......O..O...OO.OO..
........O..O........OO.O.O....
..O.....OO.....OO.OO.......O..
.O.....O.O..OO.OO....O......O.
..O..OOOO..O....OO..........O.
.O..O...O.O....O..O....O...OO.
....O...OO..O.......O.O..OO...
........O.O....O.O....O.......
.OO.......O.OO..O.......O..O..
....O....O.O.O...OOO..O.O.OO..
.OO..OO...O.O.O.O.O...OO...O..
..............................
After
..............................
.OOOOO.......OO.....O..O......
...OO..O...O...O....OO....O...
....O.O......O..OO...OO...O...
.OO.OOOO......OO..O..O........
O.O.OO..O..O..O..OO...O...OO..
.OO.....O....OO.O..O.OO.O.....
......O.....O.....OOO.OO...O..
....O..OOOO..O..O..O.O.O.OO...
..O......O.O........O...O.O...
.O.....OOO.....OO.OO...O...O..
.......OOO..O.O.O...........O.
.O...O.....O...OOOO..O.O....O.
.O..O.O..O.....O......O....OO.
....O..O..O.O......O.....O....
........OOO....O......O..O....
.OO......O..OO..OOO.....O..O..
..O.O....OO..O...OO...O...OO..
.O..OO....O..O...O.O.O.OO.....
..............O............O..
Possible output
..............................
.OOO.O.v.....>.....>.v.O..v...
..>>^.v...>..^>..v..O.v.......
.....<......>..>.....O....O...
.O.<O><O......O...O..O....v...
.<O..O..v<.O..O^..O..>....>...
..<.^.v......OO.O^..>..<O.....
..^....v..v.Ov...>>^.<OO...O..
.....<..OO......O..O...Ov.v<..
........>..O........O^.v.^....
..^.....Ov.....OO.OO.......O..
.^.....^.^..O>.vO....v......O.
..<..Ov^^..O....><..........O.
.O..O...>.v....O..^....^...OO.
....O...<v..O.......<.^..v<...
........O.O....O.v....O.......
.OO.......<.Ov..O.......O..O..
....O....O.<.^...O^v..O.v.OO..
.O^..<<...O.>.v.>.^...<O...v..
..............................

ঠিক নিশ্চিত করার জন্য, জীবাণু কেবল একটি বা শূন্য কোষ দ্বারা চালিত হতে পারে, তাই না?
ডোমিনো

@ জ্যাকগৌপিল হ্যাঁ, এটি সঠিক। প্রতিটি >^<vস্ব স্ব দিকের ঠিক এক ধাপের একটি আন্দোলনের সাথে সামঞ্জস্য করে।
Zgarb

আমি এটি সমাধান করার চেষ্টা করি নি, তবে আরও পরীক্ষার কেসগুলি তৈরি করার জন্য এখানে একটি সরঞ্জাম রয়েছে :) jsfiddle.net/xd2xns64/ebded/result
ডমিনো

ওহ, সাবধান, এই সুযোগটি রয়েছে যে স্ক্রিপ্টটি চিরতরে লুপ হয়ে যাবে যদি এটি সমস্ত কক্ষ একটি প্রান্তের বিরুদ্ধে সরানোর চেষ্টা করে তবে প্রান্তের ঘরগুলি কোথাও যেতে পারে না।
ডোমিনো

উত্তর:


3

অক্টাভা, 494 496 বাইট - 372 বাইট বোনাস = 124 বাইট

function o=G(b,a)
y='.O<^v>';s=(b>46)+0;t=a>46;v=t;f=s;t(:,2:end,2)=t(:,1:end-1);t(2:end,:,3)=t(1:end-1,:,1);t(1:end-1,:,4)=t(2:end,:,1);t(:,1:end-1,5)=t(:,2:end,1);t=reshape(t,[],5);m=size(s,1);p=[0 -m -1 1 m];
function z(n)
f(n+p(s(n)))--;q=find(t(n,:));w=n+p(q);d=min(f(w));q=q(f(w)==d);j=randi(numel(q));s(n)=q(j);f(n+p(q(j)))++;end
for g=find(s)' z(g);end
while any((f~=v)(:)) L=find(s);k=zeros(size(s));for h=L' k(h)=f(h+p(s(h)));end;c=find(k>1);g=c(randi(numel(c)));z(g);end
o = y(s+1);end

এই উত্তরে এখনও প্রচুর গল্ফ করা উচিত, তবে আমি অবারিত ব্যাখ্যাটি পেতে চাই।

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

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

কোডটি এখানে:

function output = germs(before, after)

%before = ['......';'.O..O.';'.OO.O.';'......'];
%after = ['......';'....O.';'.OO.O.';'..O...'];

symbs = '.O<^v>';
start = (before > 46) + 0;                   %should be called current_board
target = after > 46;                         %destinations on current cell == O
goal = target;
conflicts = start;
target(:, 2:end,2) = target(:, 1:end-1);     %destinations on cell to left
target(2:end, :,3) = target(1:end-1, :,1);   %destinations on cell above
target(1:end-1, :,4) = target(2:end, :,1);   %destinations on cell below
target(:, 1:end-1,5) = target(:, 2:end,1);   %destinations on cell to right
target=reshape(target,[],5);
m = size(start,1);                           %number of rows = offset to previous/next column
offsets = [0 -m -1 1 m];                     %offsets of neighbors from current index


function moveGerm(n)
   conflicts(n+offsets(start(n)))--;         %take germ off board
   move = find(target(n, :));                %get valid moves for this germ
   neighbors = n + offsets(move);            %valid neighbors = current position + offsets
   minVal = min(conflicts(neighbors));       %minimum number of conflicts for valid moves
   move = move(conflicts(neighbors)==minVal);
   mi = randi(numel(move));                  %choose a random move with minimum conflicts
   start(n) = move(mi);                      %add move type to board
   conflicts(n + offsets(move(mi)))++;       %add a conflict on the cell we move to
end

% Generate an initial placement
for g = find(start)'
   moveGerm(g);                              %make sure all germs are moved to valid cells
end

% Repeat until board matches goal
while any((conflicts ~= goal)(:))
   germList = find(start);                   %list of all our germs
   cost = zeros(size(start));                %calculate conflicts for each germ
   for h = germList'
      cost(h) = conflicts(h + offsets(start(h)));
   end
   conflicted = find(cost > 1);              %find those germs that occupy the same cell as another
   g = conflicted(randi(numel(conflicted))); %choose a random germ to move
   moveGerm(g);
end

output = symbs(start+1);                     %use moves as indices into symbol array for output

end

শেষ পরীক্ষার ক্ষেত্রে আউটপুট:

>> gtest
ans =

..............................
.OO>.O.v.....>.....>.v.O..v...
..>^O.v...>..^>..v..O.v.......
.....v......>..>.....O....O...
.O.<^<OO......>...O..O....v...
.<O..O..v<.O..^<..O..>....>...
..<.^.v......OO.O^..<..<O.....
..^....v..v.Ov...>>>.^OO...O..
.....<..OO......O..O...Ov.<<..
........>..O........O^.v.>....
..^.....OO.....OO.OO.......O..
.^.....^.O..O>.vO....v......O.
..<..Ov^^..O....OO..........O.
.O..O...>.v....O..^....^...OO.
....O...<v..O.......<.^..v<...
........O.O....O.v....O.......
.OO.......<.OO..O.......O..O..
....O....O.<.O...O^<..O.v.OO..
.O^..<<...O.>.v.>.>...<O...v..
..............................

Elapsed time is 0.681691 seconds.

5 বছর বয়সী কোর আই 5-তে গড় সময় অতিবাহিত সময় 9 সেকেন্ড 1 সেকেন্ডেরও কম ছিল , বোনাসের জন্য যোগ্যতা অর্জন করেছিল।

আমি এই আইডিয়োনে কাজ করার চেষ্টা করছি, তবে আমি যা বিশ্বাস করি তা যেভাবে নেস্ট ফাংশন পরিচালনা করে তাতে সমস্যা সমাধানের বিষয়টি আমার মনে হয়। : (এখানে উল্লেখের জন্য অ পরিশ্রমী ideone লিঙ্ক http://ideone.com/mQSwgZ )
কোডটি ideone এখন কাজ করছে। আমাকে সমস্ত পরিবর্তনশীলকে বিশ্বব্যাপী বাধ্য করতে হয়েছিল, যা স্থানীয়ভাবে এটি চালানো অপ্রয়োজনীয় ছিল।

* আমার অজস্র সংস্করণে আমার একটি নোট ছিল যে এই পদক্ষেপের একটি অকার্যকর ছিল, তাই আমি চেষ্টা করেছিলাম যে আমি মৃত্যুদন্ড কার্যকর করতে পারব কিনা এবং ২ টি বাইটের জন্য ফাঁসির সময়টি এখন এক সেকেন্ডের নিচে চলেছে। কোড এবং নমুনা আউটপুট আপডেট করা হয়েছে এবং আদর্শের ইনপুটটি শেষ পরীক্ষার ক্ষেত্রে পরিবর্তন করা হয়েছে।


3

পাইথন, 1171 বাইট - 878.25 বাইট বোনাস = 292.75 বাইট

from itertools import *;from random import *;R=range;L=len;O=choice;G='O'
def A(a,b):a.append(b)
def D(y,z):
 a=[];b=[];c=[]
 for i in R(L(y)):
  A(c,[])
  for j in R(L(y[0])):
   k=[(i,j),y[i][j]==G,z[i][j]==G,[],0];A(c[i],k)
   for l,m in [(0,1),(1,0)]:
    try:
     n=c[i-l][j-m]
     if k[2]&n[1]:A(n[3],k)
     if k[1]&n[2]:A(k[3],n)
    except:pass
   if k[1]&~k[2]:A(a,k)
   elif k[2]&~k[1]:A(b,k)
 d={}
 for i in a:
  j=[[i]]
  while j:
   k=j.pop();l=[e[0] for e in k]
   while True:
    m=k[-1];n=[o for o in m[3] if o[0] not in l]
    if not n:
     if m in b:A(d.setdefault(i[0],[]),k)
     break
    for o in n[1:]:p=k[:];A(p,o);A(j,p)
    A(k,n[0]);A(l,n[0][0])
 e={}
 for i in a:e[i[0]]=O(d[i[0]])
 def E():return sum(any(k in j for k in i) for i,j in combinations(e.values(),2))
 f=E()
 for i in count():
  t=3**-i/L(a);j=O(a);k=e[j[0]];e[j[0]]=O(d[j[0]]);l=E()
  if not l:break
  else:
   if l>f and random()>t:e[j[0]]=k
   else:f=l
 for i in e.values():
  for j in R(L(i)-1):i[j][4]=i[j+1]
 for i in c:
  for j in R(L(i)):
   k=i[j]
   if 1&~k[1]:i[j]='.'
   elif not k[4]:i[j]=G
   else:l,m=k[0];n,o=k[4][0];i[j]='v>^<'[abs((l-n+1)+2*(m-o))]
 return c

আদর্শ লিঙ্ক: http://ideone.com/0Ylmwq

বোনাসের জন্য যোগ্যতা অর্জন করে গড়ে সর্বশেষ পরীক্ষার ক্ষেত্রে 1 - 8 সেকেন্ড থেকে যে কোনও জায়গায় নিয়ে যায়।

এটি আমার প্রথম কোড-গল্ফ জমা, সুতরাং এটি সম্ভবত সেরা গল্ফযুক্ত প্রোগ্রাম নয়। তবুও, এটি একটি আকর্ষণীয় চ্যালেঞ্জ ছিল এবং আমি এটি বেশ উপভোগ করেছি। @ বেকার আমাকে স্মরণ করিয়ে দেওয়ার জন্য একটি উল্লেখের দাবিদার যা হিউরিস্টিক ভিত্তিক অনুসন্ধানগুলি একটি জিনিস। তিনি তার সমাধান পোস্ট করার আগে এবং আমার পুনরায় কাজ করার জন্য আমাকে অনুপ্রাণিত করার আগে, আমার ব্রুট ফোর্স অনুসন্ধান শেষ পরীক্ষার ক্ষেত্রে বোনাসের জন্য যোগ্যতা অর্জনের জন্য অনেক দীর্ঘ ছিল (এটি 69৯-এর পুনরাবৃত্তির ক্রম অনুসারে, যা একটি 99-সংখ্যার নম্বর ..) ।)।

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

ব্যাখ্যা

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

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

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

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

টীকায়িত সংস্করণ

from itertools import *;from random import *;

# redefine some built-in functions to be shorter
R=range;L=len;O=choice;G='O'
def A(a,b):a.append(b)

# The function itself.  Input is in the form of two 2d arrays of characters, one each for before and after.
def D(y,z):
 # Declare the Before-but-not-after set, the After-but-not-before set, and a temp cell array
 # (the cells are temporarily stored in a 2d array because I need to be able to locate neighbors)
 a=[];b=[];c=[]

 # Build the graph
 for i in R(L(y)):
  # Append a row to the 2d temp array
  A(c,[])

  for j in R(L(y[0])):
   # Define the interesting information about the cell, then add it to the temp array
   # The cell looks like this: [position, does it have a germ before?, does it have a germ after?, list of neighbors with germs, final move]
   k=[(i,j),y[i][j]==G,z[i][j]==G,[],0];A(c[i],k)
   for l,m in [(0,1),(1,0)]:
    # Fill up the neighbors by checking the above and left cell, then mutually assigning edges
    try:
     n=c[i-l][j-m]
     if k[2]&n[1]:A(n[3],k)
     if k[1]&n[2]:A(k[3],n)
    except:pass

   # Decide if it belongs in the Before or After set
   if k[1]&~k[2]:A(a,k)
   elif k[2]&~k[1]:A(b,k)

 # For each cell in the before set, define ALL possible paths from it (this is a big number of paths if the grid is dense with germs)
 # This uses a bastard form of depth-first search where different paths can cross each other, but no path will cross itself
 d={}
 for i in a:
  j=[[i]]  # Define the initial stack of incomplete paths as the starting node.
  while j:
   # While the stack is not empty, pop an incomplete path of the stack and finish it
   k=j.pop();l=[e[0] for e in k]
   while True:
    # Set the list of next possible moves to the neighbors of the current cell,
    # ignoring any that are already in the current path.
    m=k[-1];n=[o for o in m[3] if o[0] not in l]

    # If there are no more moves, save the path if it ends in an After cell and break the loop
    if not n:
     if m in b:A(d.setdefault(i[0],[]),k)
     break

    # Otherwise, set the next move in this path to be the first move,
    # then split off new paths and add them to the stack for every other move
    for o in n[1:]:p=k[:];A(p,o);A(j,p)
    A(k,n[0]);A(l,n[0][0])

 # Perform simulated annealing to calculate the solution
 e={}
 for i in a:e[i[0]]=O(d[i[0]])  # Randomly assign paths for the first potential solution

 # Define a function for calculating the number of conflicts between all paths, then do the initial calculation for the initial potential solution
 def E():return sum(any(k in j for k in i) for i,j in combinations(e.values(),2))
 f=E()

 # Do the annealing
 for i in count():
  # The "temperature" for simulated annealing is calculated as 3^-i/len(Before set).
  # 3 was chosen as an integer approximation of e, and the function e^(-i/len) itself was chosen because
  # it exponentially decays, and does so slower for larger problem sets
  t=3**-i/L(a)

  j=O(a)              # Pick a random Before cell to change
  k=e[j[0]]           # Save it's current path
  e[j[0]]=O(d[j[0]])  # Replace the current path with a new one, randomly chosen
  l=E()               # Recalculate the number of conflicts

  if not l:break  # If there are no conflicts, we have a valid solution and can terminate
  else:           # Otherwise check the temperature to see if we keep the new move
   if l>f and random()>t:e[j[0]]=k  # Always keep the move if it's better, and undo it with probability 1 - T if it's worse
   else:f=l                         # If we don't undo, remember the new conflict count

 # Set each of the cells' final moves based on the paths
 for i in e.values():
  for j in R(L(i)-1):i[j][4]=i[j+1]

 # Build the output in the form of a 2d array of characters
 # Reuse the temp 2d array from step since its the right size
 for i in c:
  for j in R(L(i)):
   k=i[j]
   # Cells that are empty in the before array are always empty in the output
   if 1&~k[1]:i[j]='.'
   # Cells that aren't empty and don't have a move are always germs in the output
   elif not k[4]:i[j]=G
   # Otherwise draw the move
   else:l,m=k[0];n,o=k[4][0];i[j]='v>^<'[abs((l-n+1)+2*(m-o))]
 return c
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.