Poly Nemo finden!

11

Ach nein! Nemo, unser kleiner Clownfisch ist in diesem ASCII-Ozean verloren und sein Vater Marlin versucht ihn zu finden.

Ihre Aufgabe ist es, Marlin sicher nach Nemo zu bringen. Aber Vorsicht, wir haben einen Fütterungsrausch Bruce auf freiem Fuß, also meide ihn besser um jeden Preis!

Einzelheiten

Sie erhalten ein rechteckiges ASCII-Ozeangitter, das nur Kleinbuchstaben enthält a-z. Dieser Ozean wird nemo, marlinund im bruceInnern in Form eines kontinuierlichen polyomino, beginnend immer von der obersten Zelle in der ersten Spalte der polyomino. So sind beispielsweise von allen möglichen Tetrominos die gültigen im folgenden Snippet aufgeführt

Formulare wie diese sind jedoch ungültig und in der Eingabe nicht vorhanden:

omen

ne
mo

nem
o

o
m
en

nem
 o

n
eo
m

Schließlich besteht Ihre Aufgabe darin, einen Pfad von der marlinPolyomino-Kachel zur nemoPolyomino-Kachel zu finden, um sicherzustellen, dass sich keine Zelle in Ihrem Pfad neben der brucePolyomino-Kachel befindet. Ihre Ausgabe sollte alle Alphabete ersetzen, die nicht Teil der marlinKachel, der nemoKachel und des Pfads sind, die beide durch ein Zeichen aus dem druckbaren ASCII-Bereich (einschließlich Leerzeichen) mit Ausnahme des Kleinbuchstabens verbinden a-z.

Beispiel

Wenn der Eingangsozean wie folgt ist:

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

(mit den 3 Polyominos sind:

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

)

Dann könnte eine gültige Lösung folgendermaßen aussehen:

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

Das folgende Snippet enthält einige weitere Beispiele:

Anmerkungen

  • Das Gitter wird immer ein perfektes Rechteck sein und nur eine polyomino Kachel enthält nemo, marlinund bruce.
  • Ihr Pfad sollte nicht durch bruceoder eine der 4 benachbarten (nach oben, unten, links und rechts) Zellen einer Zelle in der bruceKachel verlaufen.
  • Es ist immer garantiert, dass es mindestens einen gültigen Pfad von marlinbis gibt nemo.
  • Hier ist kein kürzester Weg erforderlich, also verrückt!
  • Auch wenn Sie nicht den kürzesten Pfad finden müssen, kann eine Zelle im Pfad (Pfad ohne Marlin oder Nemo) nicht an mehr als zwei andere Zellen im Pfad angrenzen.
  • Der Weg sollte nicht durch die marlinoder nemoKacheln führen, da dies die kleinen Fische bei der Wahl der Richtung verwirren würde.
  • Wie üblich können Sie ein Programm oder eine Funktion schreiben, indem Sie Eingaben über STDIN (oder das nächstgelegene Äquivalent), ein Befehlszeilenargument oder einen Funktionsparameter vornehmen und die Ausgabe über STDOUT (oder das nächstgelegene Äquivalent), den Rückgabewert oder den Funktionsparameter (out) erzeugen.
  • Wenn eine mehrzeilige Eingabe nicht möglich ist, können Sie davon ausgehen, dass das Raster durch das |Zeichen anstelle von verbunden wird \n. Sie können die Eingabe auch als Array von Rasterzeilen verwenden.

Dies ist Code Golf, so dass der kürzeste Eintrag in Bytes gewinnt.

Optimierer
quelle
Kann der Weg durch Marlin (oder Nemo) gehen? Wäre die obige Lösung noch gültig, wenn die koben genannte lin Marlin sichtbar wäre? (macht den Weg vom n in Marlin nach Nemo)
KSab
@KSab Ich würde nein sagen, da es dann Marlin verwirren würde :)
Optimizer

Antworten:

4

Matlab 560

560 Bytes beim Entfernen aller unnötigen Leerzeichen, aller Semikolons und aller Kommentare. Könnte viel mehr Golf spielen, aber ich bin jetzt zu müde (vielleicht morgen ...) Gute Nacht allerseits.

PS: Ich habe angenommen, dass der Pfad eine 4-Nachbarschafts-Verbindung ('+') haben muss.

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

Aufruffunktion: (Zeilenumbrüche nicht erforderlich)

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

Ausgabe:

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

Wie es funktioniert

Namen extrahieren

Der erste Teil ist das Extrahieren der Namen, z. B. nemovon der Funktion q(). Die Funktion markiert zuerst alles als 0, dann den ersten Buchstaben des Namens als 1, dann den zweiten Buchstaben, als 2ob sich ein 1in der Nachbarschaft befindet, dann den dritten und so weiter. Danach sollte nemoes nur noch einen geben 4. Von da an gehen wir rückwärts, bis wir das 1wieder gefunden haben, und löschen dann alle anderen Zahlen, die größer waren, so dass wir eine schöne Maske zurückbekommen, in der die Buchstaben nemomaskiert sind. Wir tun dies für alle drei Namen und können dann einen Pfad finden.

Den Weg finden

Wir beginnen an Marlins Positionen und senden Schritt für Schritt eine Schockwelle durch das Loch 'Bild'. In jedem Schritt erhöhen wir den Abstandszähler und markieren die 'Pixel' unter der Wellenfront mit der aktuellen Entfernung. (Wie es normalerweise mit Algorithmen für kürzeste Wege gemacht wird.) Diese Wellenfront wird offensichtlich durch den Bereich von Bruce blockiert, daher fließt sie um ihn herum. Dieser Schritt wird wiederholt, bis eine Obergrenze erreicht ist. Diese (zugegebenermaßen sehr lockere) Obergrenze ist nun der Umfang des 'Bildes' (die kürzesten Wege sind auf jeden Fall viel kürzer). Im Testfall sieht es ungefähr so ​​aus:

 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

Beginnen Sie nun bei nemoPixeln und verringern Sie den Entfernungszähler in jedem Schritt und fügen Sie unserem Pfad einen Nachbarn mit der nächst niedrigeren Entfernung (gemäß der zuvor berechneten Entfernungskarte) hinzu.

fehlerhaft
quelle
3

Python 2 - 658

Sehr sehr ineffizient in Zeit und Gedächtnis. Die Funktion zum Identifizieren der Muster ist die rekursive Funktion S, und die Funktion zum Finden der Pfade ist das C, was im Grunde eine schrecklich ineffiziente A * -Implementierung ist.

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

Verwenden Sie zum Testen dieses (sehr geringfügig) weniger Golfspiel (das den Pfad stattdessen einmal für jedes Plättchen berechnet).

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))
KSab
quelle