Пошук Полі Немо!


11

О ні! Немо, наша маленька риба-клоун загинула в цьому океані ASCII, і його тато Марлін намагається його знайти.

Ваше завдання - безпечно дістати Марліна до Немо. Але будьте обережні, у нас годувальний шалений Брюс на свободі, тому краще уникайте його будь-якою ціною!

Деталі

Вам надається прямокутна океанічна сітка ASCII, що містить лише малі алфавіти a-z. Цей океан матиме nemo, marlinа bruceвсередині нього у вигляді суцільного полиомино, завжди починаючи від самої верхньої клітини в першій колоні поліоміно. Так, наприклад, з усіх можливих тетроміносів, валідні з них наведені у фрагменті нижче

Але такі форми як недійсні і не будуть присутні у введенні:

omen

ne
mo

nem
o

o
m
en

nem
 o

n
eo
m

Нарешті, ваше завдання - знайти шлях від marlinплитки polyomino до плитки nemopolyomino, переконавшись, що будь-яка клітина на вашому шляху не прилягає до bruceплитки polyomino. Вихід повинен замінити всі алфавіти, які не входять до складу marlinплитки, nemoплитки та шляху, що з'єднує їх обидва символи з діапазону ASCII для друку (включаючи пробіл), окрім малих літер a-z.

Приклад

Якщо вхідний океан такий:

oxknvvolacycxg
xmliuzsxpdzkpw
warukpyhcldlgu
tucpzymenmoyhk
qnvtbsalyfrlyn
cicjrucejhiaeb
bzqfnfwqtrzqbp
ywvjanjdtzcoyh
xsjeyemojwtyhi
mcefvugvqabqtt
oihfadeihvzakk
pjuicqduvnwscv

(3 поліомінос:

...n..........
.mli..........
.ar...........
..............
....b.........
....ruce......
..............
.....n........
.....emo......
..............
..............
..............

)

Тоді дійсне рішення може виглядати так:

...n..........
.mli..........
.ar...........
.u............
.n............
.i............
.z............
.wvjan........
.....emo......
..............
..............
..............

Нижче фрагмент містить ще кілька прикладів:

Примітки

  • Сітка завжди буде ідеальним прямокутником і буде містити тільки один Полімін плитки nemo, marlinі bruce.
  • Ваш шлях не повинен проходити через bruceбудь-яку з 4 сусідніх (вгору, вниз, вліво та вправо) комірок будь-якої комірки в bruceплитці.
  • Завжди гарантується, що буде щонайменше один дійсний шлях від marlinдо nemo.
  • Тут немає вимоги найкоротшого шляху, тож підемо!
  • Незважаючи на те, що вам не потрібно знайти найкоротший шлях, жодна комірка на шляху (шлях, що не включає marlin або nemo), не може сусідати з більш ніж двома іншими клітинками шляху.
  • Шлях не повинен проходити через плитки marlinчи nemoплитки, оскільки це потім заплутає рибок у виборі напрямку.
  • Як завжди, ви можете написати програму або функцію, взявши введення через STDIN (або найближчий еквівалент), аргумент командного рядка або параметр функції та виробляючи вихід через STDOUT (або найближчий еквівалент), значення повернення або функцію (out).
  • Якщо багаторядковий ввід неможливий, ви можете припустити, що сітку приєднав |символ замість \n. Ви також можете приймати дані як масив рядків сітки.

Це кодовий гольф, тому найкоротший запис у байтах виграє.


Чи може шлях пройти через Марлін (або немо)? Чи було б вищезазначене рішення все-таки справедливим, якби було видно kвищезазначене lв marlin? (пройшовши шлях від n в marlin to nemo)
KSab

@KSab Я б сказав, що ні, це б тоді заплутало Марлін :)
Оптимізатор

Відповіді:


4

Матлаб 560

560 байт при видаленні всіх зайвих пробілів, крапки з комою та всіх коментарів. Можна було б пограти в гольф набагато більше, але я втомився прямо зараз (можливо, завтра ...) Доброї ночі всім.

PS: Я припускав, що шлях повинен мати 4 сусідства ('+').

function c(A)
Z = [0,1,0;1,1,1;0,1,0];
Br = q('bruce');
Bn = conv2(Br,ones(3),'s')>0;
Ne = q('nemo');
Ma = q('marlin');
%construct path marlin to nemo
U=Ma>0;M=A*Inf;
M(U)=0;
for k=1:2*sum(size(A))%upper bound for path length
    %expand
    V=imdilate(U,Z);
    V(Bn)=0;
    M(V-U==1)=k;
    U=V;
    %disp(M)
end
%go back from nemo to marlin
Pr=reshape(1:numel(A),size(A));
[i,j]=find(Ne);
m=M(i(1),j(1));%value
P=A*0;%path image
P(i(1),j(1))=1;
for k=m:-1:1
    %find neighbour of (i(1),j(1)) with value m-1
    U=imdilate(P,Z);
    F = M==k;
    G = F&U;
    mask = Pr == min(Pr(F & U));
    P(mask)=1; 
end
A(~P & ~Ma & ~Ne)='.';
disp(A)



    function M = q(s)%find string in matrix, A ascii, M mask
        M = A*0;
        m=numel(s);
        N = M+1;%all neighbours
        for k=1:m;
            M(A==s(k) & N)=k;%only set the ones that were in the neighbourhood of last
            L=M==k;
            N=imdilate(L,Z);
        end
        for k=m:-1:2
            %set all that are not neighbour to next higher highest to zero
            L=M==k;
            N=imdilate(L,Z);
            M(M==k-1 & ~N)=0;
        end
    end


end

Функція виклику: (нові лінії не потрібні)

c(['oxknvvolacycxg',
'xmliuzsxpdzkpw',
'warukpyhcldlgu',
'tucpzymenmoyhk',
'qnvtbsalyfrlyn',
'cicjrucejhiaeb',
'bzqfnfwqtrzqbp',
'ywvjanjdtzcoyh',
'xsjeyemojwtyhi',
'mcefvugvqabqtt',
'oihfadeihvzakk',
'pjuicqduvnwscv']);

Вихід:

...n..........
.mli..........
.ar...........
..c...........
..v...........
..c...........
..q...........
..vjan........
.....emo......
..............
..............
..............

Як це працює

Вилучення імен

Перша частина - вилучення імен, наприклад nemo, що виконується функцією q(). Функція спочатку позначає все як 0, потім виникає перша літера імені як 1, потім друга літера 2ніби є 1сусідство, потім третя і так далі. Після цього у випадку має nemoбути лише один 4. З цього ми 1повертаємось назад, поки не знайшли знову, а потім видалимо всі інші цифри, які були більшими, тому ми отримуємо хорошу маску, де букви nemoмаскуються. Ми робимо це для всіх трьох імен, а потім можемо приступити до пошуку шляху.

Пошук шляху

Ми починаємо з позицій Марлінса і посилаємо ударну хвилю через отвір 'зображення' крок за кроком. На кожному кроці ми збільшуємо лічильник відстані і відмічаємо "пікселі" під фронтом хвилі поточною відстані. (Як це зазвичай робиться з алгоритмами найкоротшого шляху.) Цей хвильовий фронт, очевидно, блокується областю Брюса, тому він буде протікати навколо нього. Цей крок повторюється до досягнення верхньої межі. Ця (правда, дуже вільна) верхня межа зараз - це окружність «зображення» (найкоротші шляхи будуть в будь-якому випадку коротшими). У тестовому випадку це виглядає приблизно так:

 2 1 1  0  1  2  3  4  5  6  7  8  9 10
 1 0 0  0  1  2  3  4  5  6  7  8  9 10
 1 0 0  1  2  3  4  5  6  7  8  9 10 11
 2 1 1  _  _  _  5  6  7  8  9 10 11 12
 3 2 2  _  _  _  _  _  _  9 10 11 12 13
 4 3 3  _  _  _  _  _  _ 10 11 12 13 14
 5 4 4  _  _  _  _  _  _ 11 12 13 14 15
 6 5 5  6  7  8  9 10 11 12 13 14 15 16
 7 6 6  7  8  9 10 11 12 13 14 15 16 17
 8 7 7  8  9 10 11 12 13 14 15 16 17 18
 9 8 8  9 10 11 12 13 14 15 16 17 18 19
10 9 9 10 11 12 13 14 15 16 17 18 19 20

Тепер почніть з nemoпікселів і зменшуйте лічильник відстані на кожному кроці та додайте сусід з наступною нижньою відстані (відповідно до тієї карти відстаней, яку ми обчислили раніше) до нашого шляху.


3

Пітон 2 - 658

Дуже дуже неефективно як у часі, так і в пам’яті. Функція для виявлення шаблонів є рекурсивною функцією S, а функцією пошуку шляхів є C, що в основному є жахливо неефективною реалізацією A *.

G=input().split('\n')
R=range
S=lambda g,x,y,s,B:[[(x,y)]+r for a,b in[(-1,0),(0,-1),(0,1),(1,0)]for r in S(g,x+a,y+b,s[1:],B)if B(x,y)and s[0]==g[y][x]]if s else[[]]
C=lambda l,N,B:[i for i in l if i[-1]in N]or C([i+[(i[-1][0]+c,i[-1][1]+d)]for i in l for c,d in [(-1,0),(0,-1),(0,1),(1,0)]if all(1<abs(i[-1][0]+c-a)or 1<abs(i[-1][1]+d-b)for a,b in B)],N,B)
X,Y=len(G[0]),len(G)
N,M,B=[filter(list,[S(G,s,t,e,lambda a,b:0<=a<X and 0<=b<Y and Y*(a-s)+b-t>=0)for s in R(X)for t in R(Y)])[0][0]for e in["nemo","marlin","bruce"]]
print'\n'.join(''.join(G[y][x]if(x,y)in N+M+min([C([[k]],N,B)[0]for k in M],key=lambda i:len(i))else'.'for x in R(X))for y in R(Y))

Для тестування використовуйте цей (дуже трохи) менш гольф (який обчислює шлях один раз замість кожної плитки)

G=input().split('\n')
R=range
S=lambda g,x,y,s,B:[[(x,y)]+r for a,b in[(-1,0),(0,-1),(0,1),(1,0)]for r in S(g,x+a,y+b,s[1:],B)if B(x,y)and s[0]==g[y][x]]if s else[[]]
C=lambda l,N,B:[i for i in l if i[-1]in N]or C([i+[(i[-1][0]+c,i[-1][1]+d)]for i in l for c,d in [(-1,0),(0,-1),(0,1),(1,0)]if all(1<abs(i[-1][0]+c-a)or 1<abs(i[-1][1]+d-b)for a,b in B)],N,B)
X,Y=len(G[0]),len(G)
N,M,B=[filter(list,[S(G,s,t,e,lambda a,b:0<=a<X and 0<=b<Y and Y*(a-s)+b-t>=0)for s in R(X)for t in R(Y)])[0][0]for e in["nemo","marlin","bruce"]]
s=N+M+min([C([[k]],N,B)[0]for k in M],key=lambda i:len(i))
print'\n'.join(''.join(G[y][x]if(x,y)in s else'.'for x in R(X))for y in R(Y))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.