뱀은 다음과 같습니다
>>>v
@ ^ v
^ >>>^ v
^ v
^<<<<<<<<<
뱀은이 경우와 같이 스스로 넘어갈 수 있습니다.
@
^
>^>v
^<<
크로스 오버가 유효하려면 양쪽의 문자가 같은 방향으로 움직여야합니다. 의 경우에
@
>^v
^<
불분명하고 유효하지 않은 것으로 간주 될 수 있습니다.
출력은 WASD
머리에서 꼬리 ( @
) 로가는 것을 나타내는 문자열입니다 .
역 추적이지 않고 모호하지 않은 뱀이 주어지면 뱀이 취하는 일련의 움직임을 출력하는 프로그램을 작성할 수 있습니까?
이것은 코드 골프이므로 최단 답변이 승리합니다!
테스트 사례 :
(참고 :은에 @
없는 문자로 대체 가능 v^<>
)
입력:
>>>>v
v
v<< @
v ^
>>>>>^
산출: ddddssaassdddddww
입력:
@>>v
^ v
^ v
^<<<
산출: dddsssaaawww
입력:
>>>v
v @
v ^
>>>>v ^
>>>>^
산출: dddsssddddsddddwww
입력:
@<< v
^ v
v<^<<
v ^
>>^
산출: ssaaaassddwwwwaa
입력:
@v<v
^v^v
^v^<
^<
산출: ssawwasssawww
답변
자바, 626 539 536 529 바이트
많은 장소에 몇을 저장하여 -87 바이트. 일부를 지적 해 준 Public 씨에게 감사드립니다.
먼저 시도하는 모든 공간을 제거 할 수 없기 때문에 -3 바이트 (감사 mbomb007)
이 경우 수정하려면 +8 바이트 :
@v<v
^v^v
^v^<
^<
프론트 로딩 변수 선언으로 -15 바이트
s->{String o="",t;String[]p=s.split("\n");int h=p.length,w=p[0].length(),y=0,x,b=0,a,n,m;char[][]d=new char[h][w];for(;y<h;y++)for(x=0;x<w;x++){d[y][x]=p[y].charAt(x);if(d[y][x]=='@')d[y][x]=' ';}for(;b<h;b++)for(a=0;a<w;a++){t="";x=a;y=b;n=0;m=0;while(!(y<0|y>h|x<0|x>w||d[y][x]==' ')){if(y+m>=0&y+m<h&x+n>=0&x+n<w&&d[y+m][x+n]==d[y-m][x-n])d[y][x]=d[y-m][x-n];n=m=0;switch(d[y][x]){case'^':t+="W";m--;break;case'<':t+="A";n--;break;case'v':t+="S";m++;break;case'>':t+="D";n++;}x+=n;y+=m;}o=t.length()>o.length()?t:o;}return o;}
읽을 수있는 버전 :
static Function<String,String> parser = snake -> {
// declare all variables in one place to minimize declaration overhead
String output = "", path;
String[] split = snake.split("\n");
int h=split.length, w=split[0].length(), y=0, x, startY=0, startX, dx, dy;
char[][] board = new char[h][w];
// setup char[][] board
for (; y<h; y++)
for (x=0; x<w; x++) {
board[y][x]=split[y].charAt(x);
if(board[y][x]=='@')board[y][x]=' ';
}
// find the longest possible path
for (; startY<h; startY++)
for (startX=0; startX<w; startX++) {
path = "";
x=startX; y=startY; dx=0; dy=0;
while (!(y<0 | y>h | x<0 | x>w || board[y][x] == ' ')) {
if (y + dy >= 0 & y + dy < h & x + dx >= 0 & x + dx < w
&& board[y + dy][x + dx] == board[y - dy][x - dx]) {
board[y][x] = board[y - dy][x - dx];
} dx = dy = 0;
switch(board[y][x]) {
case '^':path+="W";dy--;break;
case '<':path+="A";dx--;break;
case 'v':path+="S";dy++;break;
case '>':path+="D";dx++;break;
}
x+=dx; y+=dy;
}
output = path.length()>output.length()?path:output;
}
return output;
};
같은 문자열을 사용 v @\n>>>^
합니다. 각 좌표에서 시작하여 경로를 만든 다음 가장 긴 경로를 반환합니다. 겹치는 경로에 필요한 예측은 가장 어려운 부분이었습니다.
답변
루비, 217
->a{r=''
z=a.index ?@
a.tr!('<^>v',b='awds').scan(/\w/){c=0
e,n=[a[z,c+=1][?\n]?p: c,d=c*a[/.*
/].size,a[z-c,c][?\n]?p: -c,-d].zip(b.chars).reject{|i,k|!i||a[v=i+z]!=k||0>v}.max_by{|q|q&[a[z]]}until n
z+=e
r=n*c+r}
r}
이 위치에서 시작하여 @
뒤로 이동하여 현재 위치 ( z
) 를 가리키는 이웃을 찾습니다 . 4 방향 교차로에서 올바른 방법을 선택하려면 동일한 방향 ( max_by{...}
)을 가리키는 이웃을 선호 합니다. 즉각적인 이웃이 발견되지 않으면 크로스 오버가 있어야하고 한 번에 한 레벨 씩 ( until n
및 c+=1
)을 찾을 때까지 도달한다고 가정합니다 . 이 과정은 바디 세그먼트 수 (헤드 제외) ( .scan(/\w/){...}
)에 대해 반복됩니다 .
퍼즐에 추가 한 테스트 케이스는 계속 저를 넘어 뜨리기 때문에 182 문자에서 218로갔습니다. 추가 캐릭터는 모두 수평 이동이 다음 / 이전 줄로 들어 가지 않았 음을 확인했습니다. 더 나은 방법으로 처리 할 수 있을지 궁금합니다.
언 골프 드 :
f=->a{
result=''
position=a.index ?@ # start at the @
a.tr!('<^>v',b='awds') # translate arrows to letters
a.scan(/\w/){ # for each letter found...
search_distance=0
until distance
search_distance+=1
neighbors = [
a[position,search_distance][?\n]?p: search_distance, # look right by search_distance unless there's a newline
width=search_distance*a[/.*\n/].size, # look down (+width)
a[position-search_distance,search_distance][?\n]?p: -search_distance, # look left unless there's a newline
-width # look up (-width)
]
distance,letter = neighbors.zip(b.chars).reject{ |distance, letter_to_find|
!distance || # eliminate nulls
a[new_position=distance+position]!=letter_to_find || # only look for the letter that "points" at me
0>new_position # and make sure we're not going into negative indices
}.max_by{ |q|
# if there are two valid neighbors, we're at a 4-way intersection
# this will make sure we prefer the neighbor who points in the same
# direction we're pointing in. E.g., when position is in the middle of
# the below, the non-rejected array includes both the top and left.
# v
# >>>
# v
# We want to prefer left.
q & [a[position]]
# ['>',x] & ['>'] == ['>']
# ['v',x] & ['>'] == []
# ['>'] > [], so we select '>'.
}
end
position+=distance
result=(letter*search_distance)+result # prepend result
}
result # if anyone has a better way of returning result, I'm all ears
}