C #, 604 바이트
완전한 프로그램, STDIN에서 입력 (라인으로 구분 된 레이아웃, 치수 없음)을 수락하고 STDOUT으로 출력합니다.
using C=System.Console;class P{static void Main(){int w=0,W,i,j,t,k,l,c;string D="",L;for(;(L=C.ReadLine())!=null;D+=L)w=L.Length;var R=new[]{-1,0,1,w,-w};L="X";for(W=i=D.Length;i-->0;){var M=new int[W];for(k=j=i;i>0;){M[j]=++k;t=j+R[c=D[j]%5];if(t<0|t>=W|c<3&t/w!=j/w|c>2&t%w!=j%w)break;j=t;if((l=M[j])>0){var J=new int[W+1];System.Func<int,int>B=null,A=s=>J[s]<0?0:J[k=B(s)]=k==W?k:i;B=x=>J[x]==x?x:B(J[x]);for(i=J[W]=W;i>0;)J[--i]=M[i]<l?i%w<1|i%w>w-2|i<w|i>W-w?W:i:-1;for(;i<W;)if(J[++i]<0)l=D[i]%5/2-1;else{A(i-1);if(i>w)A(i-w);}for(c=W;i-->0;L=""+(c>2?c:0)*l)c-=J[i]<0?0:B(i)/W;}}}C.WriteLine(L);}}
이 프로그램은 먼저 레이아웃을 읽고 말할 필요가 없으며 모든 셀을 반복하여 작동합니다. 그런 다음 각 셀에서 '뱀'을 실행합니다. 화살표는 가장자리에서 벗어날 때까지 화살표를 따라 가거나 자체적으로 나옵니다. 그것이 저절로 빠지면, 우리는 우리가 고리 (또는 그 "> <"것들 중 하나)를 발견했다는 것을 알고, 또한 그 고리에 뱀이 얼마나 있는지 알고 있습니다.
루프가 있음을 알면 루프에있는 셀을 알고 각 셀 (이유로 +1)에서 자체로 -1
(루프에 있음을 의미) 또는 W
(전체 너비)에 대한 맵을 만듭니다. 가장자리에 있거나 W
더 많은 것을 단순화하기 위해 +1 (색인 인 경우 ).
이 작업을 수행하는 동안 루프의 '마지막'요소가 갖는 방향 (즉, 루프의 요소가있는 마지막 행의 루프의 마지막 요소)도 찾습니다. 이 요소는 "<"또는 "^"이어야하며, 루프의 클럭 (CW / CCW)을 알려줍니다 (-1 / + 1로 변환).
그런 다음 분리 세트 패스를 수행하여 루프 외부에있는 모든 요소를 세트에 할당합니다 W
. 그런 다음 W
루프에 포함 된 숫자를 얻기 위해이 중 몇 개를 뺍니다 . 이 숫자가 3보다 작 으면 0으로 대체합니다.이 값에 클럭을 곱하고 결과로 설정 한 다음 결과가 출력되는 for 루프에서 벗어날 수 있습니다.
그러나 뱀이 발견되지 않기 때문에 위의 대부분이 발생하지 않으면 결과는 "X"로 유지되고 출력됩니다.
using C=System.Console;
class P
{
static void Main()
{
int w=0, // width
W, // full length
i, // used for iterating over all the cells
j, // keeps track of where the snake as got to
t, // t is next j
k, // how far along the snake we are, kind of
// later on, k is used as temp for A
l, // stores a threshold for how far along the snake the loop starts
// later on, l stores the last seen pointer - this tells us the clockness
c; // the translated direction
// later on, c is a backwards-count
string D="", // D is the map
L; // used for reading lines, and then storing the result
// might not be the best yay of doing this
for(;(L=C.ReadLine())!=null; // read a line, while we can
D+=L) // add the line to the map
w=L.Length; // record the width
var R=new[]{-1,0,1,w,-w}; // direction table (char%5) - might be able to replace this array with some bit bashing/ternary
L="X"; // can't seem to fit this in anywhere... (don't strictly need to re-use L)
for(W=i=D.Length;i-->0;) // for each cell, we send a 'snake' to try to find the loop from that cell
{
var M=new int[W]; // stores how far along the snake this point is
for(k=j=i; // k's value doesn't really matter, as long as it's not stupidly big
i>0;) // the i>0 check is just for when we return (see comment at the end of the code)
{
M[j]=++k; // store snake point and advance distance
t=j+R[c=D[j]%5]; // t is position after move (translate <>v^ to 0234 (c is direction))
//c=D[j]%5; // translate <>v^ to 0234 (c is direction)
//t=j+R[c]; // t is position after move
if(t<0|t>=W|c<3&t/w!=j/w|c>2&t%w!=j%w)
break; // hit an edge - will always happen if we don't find a loop - give up on this snake
j=t; // move to new position
if((l=M[j])>0) // we've been here before...
{
// disjoint sets (assign all the edges to one set, assign all the ones on the line to another set, do adjacent disjoint, return size-outteredge (minus if necessary)
var J=new int[W+1]; // looks like we can reuse M for this
System.Func<int,int>B=null,
// whatever s points at should point to i, unless s points to W, in which case it should keep point to W
A=s=>J[s]<0?0:J[k=B(s)]=k==W?k:i;
// read the value this points to
B=x=>J[x]==x?x:B(J[x]);
for(i=J[W]=W;i>0;)
J[--i]=M[i]<l? // if we are not part of the loop
i%w<1|i%w>w-2|i<w|i>W-w? // if we are on the edge
W: // on the edge
i: // not on the edge
-1; // this is on the loop
// now fill in
// we don't have to worry about wrapping, the important bit being an un-wrapping closed loop
// i = 0
for(;i<W;)
if(J[++i]<0) // we are on the loop
l=D[i]%5/2-1; // last one must be ^(4) or <(0)
else{ // can probably crush this into an l returning l assigning term (with if above)
A(i-1);
if(i>w)
A(i-w);
}
// now count the number of non-edges
for(c=W; // assume everything is a non-edge
i-->0;
L=""+(c>2?c:0)*l) // set output to be number of non-edges * clockness (or 0 if too few)
c-=J[i]<0?0:B(i)/W; // subtract 1 if an edge (B(i) is W), othewise 0
// at this point, i is 0, so we will fall out of all the loops
}
}
}
C.WriteLine(L); // output result
}
}