폴리 니모를 찾아라!


11

아뇨! 우리의 작은 광대 물고기 인 Nemo는이 ASCII 바다에서 길을 잃었고 그의 아버지 Marlin이 그를 찾으려고합니다.

당신의 임무는 Marlin을 Nemo에 안전하게 가져 오는 것입니다. 그러나 우리는 느슨한에 먹이 열풍 브루스가 있으므로 모든 비용으로 그를 피하는 것이 좋습니다!

세부

소문자 알파벳 만 포함 된 직사각형 ASCII 해상 그리드가 제공됩니다 a-z. 이 바다는 것 nemo, marlin그리고 bruce그 안에 연속 폴리오 미노의 형태로, 항상 폴리오 미노의 첫 번째 열에서 상위 대부분의 세포에서 시작. 예를 들어, 가능한 모든 테트로 미노 중에서 유효한 것들은 아래 스 니펫에 나열되어 있습니다.

그러나 다음과 같은 형식은 유효하지 않으며 입력에 표시되지 않습니다.

omen

ne
mo

nem
o

o
m
en

nem
 o

n
eo
m

마지막으로, 작업은 marlinpolyomino tile 에서 polyomino tile 까지의 경로를 찾아 경로의 nemo모든 셀이 brucepolyomino tile에 인접하지 않도록하는 것 입니다. 출력은 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, marlinbruce.
  • 경로는 타일 bruce에있는 셀의 인접한 4 개 (위, 아래, 왼쪽 및 오른쪽) 셀을 통과하지 않아야합니다 bruce.
  • 에서 marlin까지 유효한 경로가 하나 이상 있어야 합니다 nemo.
  • 여기서 가장 짧은 경로는 필요하지 않습니다.
  • 최단 경로를 찾을 필요는 없지만 경로에있는 셀 (말린 또는 니모를 포함하지 않는 경로)은 경로에있는 두 개 이상의 다른 셀에 인접 할 수 없습니다.
  • 길은 marlin또는 nemo타일을 통과해서는 안됩니다. 그러면 작은 물고기가 방향을 선택하는 데 혼란을 줄 수 있습니다.
  • 일반적으로 STDIN (또는 가장 가까운 해당 항목), 명령 줄 인수 또는 함수 매개 변수를 통해 입력을 받고 STDOUT (또는 가장 가까운 해당), 반환 값 또는 함수 (out) 매개 변수를 통해 출력을 생성하는 프로그램이나 함수를 작성할 수 있습니다.
  • 여러 줄을 입력 할 수없는 경우 표 |대신에 문자로 표를 연결했다고 가정 할 수 있습니다 \n. 입력을 그리드 행의 배열로 가져올 수도 있습니다.

이것은 코드 골프이므로 바이트 단위의 가장 짧은 항목이 이깁니다.


경로가 말린 (또는 니모)을 통과 할 수 있습니까? k위의 l청새치가 보이는 경우 위의 해결책이 여전히 유효 합니까? (
Marlin

@KSab 나는 말린을 혼동하기 때문에 아니오라고 말하고 싶습니다 :)
Optimizer

답변:


4

MATLAB 560

모든 불필요한 공백, 모든 세미콜론 및 모든 주석을 제거 할 때 560 바이트 훨씬 더 골프를 칠 수는 있지만 지금 당장 피곤할 것입니다.

추신 : 나는 경로에 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이고 경로를 찾는 함수는 기본적으로 끔찍하게 비효율적 인 A * 구현 인 C입니다.

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))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.