당신의 임무는 RoboZZle 통역사를 작성하는 것입니다. 게임에 익숙하지 않은 경우 robozzle.com 의 비디오를 보거나 아래 설명을 읽으십시오.
로봇은 빨간색, 녹색, 파란색 또는 검은 색의 사각형 사각형 격자에 있습니다. 검은 색 사각형에 액세스 할 수 없습니다. 다른 사람들은 접근 할 수 있고 그들 중 일부는 별을 포함합니다. 목표는 검은 사각형을 밟거나지도에서 떨어지지 않고 모든 별을 모으는 것입니다. 로봇은 하나의 사각형을 차지하고 왼쪽, 오른쪽, 위 또는 아래로 특정 방향을 향합니다. 서브 루틴 F1, F2, …, F5로 그룹화 된 어셈블리와 같은 명령어를 따릅니다. 명령은 한 쌍의 술어 ( “없음”, “적색 인 경우”, “녹색 인 경우”, “파란색 인 경우”)와 조치 ( “앞으로 이동”, “왼쪽으로 돌림”, “오른쪽으로 돌리기”, “현재 사각 빨간색 페인트”, “녹색 페인트”, “파란색 페인트”, “아무것도하지 않음”, “call F1”, …, “call F5”). 서브 루틴 호출은 스택을 사용하며 재귀적일 수 있습니다. 기존 프로그래밍과 마찬가지로 서브 루틴의 마지막 명령이 완료된 후 서브 루틴이 호출 된 지점부터 실행이 계속됩니다. 실행은 F1의 첫 번째 명령에서 시작하여 로봇이 별이있는 모든 사각형을 방문하거나 로봇이 검은 사각형 또는지도 외부에 닿을 때까지 또는 1000 개의 명령이 실행될 때 (조건 자 실패 및 “아무것도하지 않음”동작)까지 계속됩니다. 계산하지 않거나) 실행할 명령이 더 이상 없습니다 (스택 언더 플로).
입력 :
-
a
-지도를 인코딩하는 12×16 문자 매트릭스 (일반적으로 언어로 표시되는 문자열 배열)-'#'
액세스 할 수없는 (검은 색) 사각형,'*'
별이있는 사각형,'.'
나머지 -
c
-액세스 가능한 사각형의 색상을 설명하는 12×16 문자 매트릭스-'R'
(빨간색),'G'
(녹색) 또는'B'
(파란색). 액세스 할 수없는 사각형은 3 개의 임의의 문자로 표시됩니다. -
y
그리고x
-로봇의 0 기반 행과 열;a[y][x]
~로 보장된다'.'
-
d
– 방향이 로봇이 직면 :0 1 2 3
권리, 아래로, 즉쪽으로, 위, 왼쪽(y,x+1)
,(y+1,x)
,(y,x-1)
,(y-1,x)
-
f
-단일 문자열, 연결된 F1 … F5 구현. 각 구현은 술어 조치 쌍 (서브 루틴 당 최대 10 쌍)의 시퀀스 (비어있을 수 있음)'|'
입니다.-
술어 :
'_'
없음,'r'
빨강,'g'
초록,'b'
파랑 -
행동 :
'F'
앞으로 이동,'L'
좌회전,'R'
우회전,'r'
빨간색'g'
페인트, 녹색'b'
페인트, 파란색 페인트,'1'
F1 호출, …,'5'
F5 호출,'_'
아무것도하지 마십시오
-
위와 같이 입력 이름을 지정할 필요는 없지만 해당 값은 지정해야합니다.
출력 : 1
(또는 true
) 로봇이 규칙에 따라 모든 별을 수집하는 경우 0
( false
) 그렇지 않은 경우
예 :
a=["################","################","##*....*...*#.##","##.####.#####.##","##.####.#####.##","##.####*...*#.##","##.########.####","##*........*#.##","################","################","################","################"]
c=["RRRRRRRRRRRRRRRR","RRRRRRRRRRRRRRRR","RRRBBBBRGGGGRRRR","RRBRRRRGRRRRRRRR","RRBRRRRGRRRRRRRR","RRBRRRRRGGGBRRRR","RRBRRRRRRRRGRRRR","RRRBBBBGGGGBRBRR","RRRRRRRRRRRRRRRR","RRRRRRRRRRRRRRRR","RRRRRRRRRRRRRRRR","RRRRRRRRRRRRRRRR"]
y=2; x=6; d=2
// and then depending on "f":
f="_FrLg2_1|_FbLrR_2||||" // result:1
f="_FrRg2_1|_FbLrR_2||||" // result:0 (stepped on a black square)
f="_FrLrL_1|_FbLrR_2||||" // result:0 (1000-step limit exceeded)
f="_FrLg2__|________||||" // result:0 (stack underflow)
“페인트”명령과 관련된 또 다른 예 :
a=["#***************","#*###*###*###*##","#*###*###*###*##","***#***#***#***#","***#***#***#***#","*###*###*###*###","***#***#***#***#","***#***#***#***#","***#***#***#***#","*###*###*###*###","*.*#***#***#***#","***#***#***#***#"]
c=["RGGGGGGGGGGGGGGG","RBRRRGRRRGRRRGRR","RBRRRGRRRGRRRGRR","RBRRGGGRGGGRGGGR","BRRRGGGRGGGRGGGR","BRRRGRRRGRRRGRRR","BRRRGGGRGGGRGGGR","RBRRGGGRGGGRGGGR","BRRRGGGRGGGRGGGR","BRRRGRRRGRRRGRRR","BGRRGGGRGGGRGGGR","RBRRGGGRGGGRGGGR"]
y=10; x=1; d=0
f="_2_R_R_1|_FgRgFgFg3rRr4b2_Fgb|_F_F_R|_2_L_r||"
// result:1
자체 테스트를 생성하려면 robozzle.com의 목록에서 퍼즐로 이동하여 문제를 해결하거나 시도하지 마십시오. 브라우저에서 F12를 누르고 JS 콘솔에 입력하십시오.
r=robozzle;s=JSON.stringify;with(r.level)console.log('a='+s(Items)+'\nc='+s(Colors)+'\ny='+RobotRow+'\nx='+RobotCol+'\nd='+RobotDir+'\nf='+s(r.encodeSolution()))
언어의 결과를 다시 포맷하십시오.
최단 승리. 허점이 없습니다.
답변
프롤로그 (SWI) 574 바이트
Z*A:-findall(X^Y-D,(nth0(Y,Z,O),nth0(X,O,C),plus(32,C,D)),L),list_to_assoc(L,A).
N^C^G^[P,I|R]^F^X^Y^D:-map_assoc(\=(74),G);N<1e3,get_assoc(X^Y,G,J),J>67,put_assoc(X^Y,G,78,H),T=N+1,((I\=95,(P=95;get_assoc(X^Y,C,P)))->(between(49,53,I),plus(48,M,I),nth1(M,F,Q),append(Q,R,S),T^C^H^S^F^X^Y^D;member(I,`RL`),E is(D-I//3)mod 4,T^C^H^R^F^X^Y^E;I=70,(D=0,U is X+1;D=1,V is Y+1;D=2,U is X-1;D=3,V is Y-1),(U=X;V=Y),T^C^H^R^F^U^V^D;I>97,put_assoc(X^Y,C,I,W),T^W^H^R^F^X^Y^D);N^C^H^R^F^X^Y^D).
A+C+F+L:-A*G,C*B,split_string(F,"|","",P),maplist(string_codes,P,[M|N]),0^B^G^M^[M|N]^L.
이것은 모든 별들이 성공적으로 수집되고 그렇지 않으면 실패하면 호출 될 때 성공하는 술어를 정의합니다. 술어는 다음과 같은 인수를 취합니다 a+c+f+x^y^d.
. a
과 c
동시에, 역 따옴표 인용 문자열의 목록이어야 f
이중 인용 문자열이어야합니다.
설명
이 프로그램은 세 가지 술어를 포함, */2
, ^/2
,와 +/2
. */2
첫 줄에 정의 된 조건 입력 처리의 일부분에 대응한다. ^/2
술어는 재귀 적 로봇 이동 단계별로 어떻게 계산하고 로봇이 법적으로 모든 별을 수집하고, 그렇지 않으면 실패 할 경우 성공합니다. +/2
술어는 프로그램의 기본 조건이며, 대한 입력을 준비 ^/2
로부터 약간의 도움으로 술어 */2
술어. 이 술어 각각은 기술적으로 두 개의 인수 만 취하지 만 연산자와 패턴 일치를 사용하면 더 많은 인수가있는 것처럼 동작 할 수 있습니다 (여기서이 현상에 대해 자세히 설명 합니다 ).
*/2
Z*A:-findall(X^Y-D,(nth0(Y,Z,O),nth0(X,O,C),plus(32,C,D)),L),list_to_assoc(L,A).
이 술어는 두 가지 주장을 취합니다. 첫 번째는 문자 코드 목록의 목록입니다 (이는 Prolog가 백틱 인용 문자열을 구문 분석하는 방법입니다). 두 번째는 12×16 맵 (으로 표시 X^Y
)의 포인트에서 32까지의 문자 맵 과 해당 포인트에 저장된 문자 코드 목록의 연관 코드입니다. 32는 각 문자 코드에 추가되어 색상 매트릭스의 경우 대문자 문자를 소문자 문자로 바꿉니다.
이를 수행하는 방법은을 사용하여 점 쌍과 해당 지점의 문자 코드 목록을 생성하는 것 findall/3
입니다. 그런 다음 list_to_assoc/2
점에서 해당 지점의 문자 코드까지 해당 연관 맵을 작성하는 데 사용 됩니다.
findall/3
술어는 기본적 으로 “템플릿”을 첫 번째 인수로, 목표를 두 번째 인수로, 목록을 세 번째 인수로 취합니다. 술어는 목표가 성공하게하는 가능한 모든 템플리트 값으로 목록을 채 웁니다. 연산자 우선 순위에 전달되는 템플릿으로 인해 findall/3
에 */2
로 분석된다 (X^Y)-D
. -
템플릿 점의 위치 (대표되도록 오퍼레이터 프롤로그 두 값의 쌍을 나타내고, X^Y
(32)를 더한 지점의 문자 코드와 쌍을 () D
). (가) 있습니다 ^
지점을 나타내는에서 사용이에 연결된 방식에 ^/2
술어.
findall/3
술어에 전달되는 목표를 고려해 봅시다 .
nth0(Y,Z,O),nth0(X,O,C),plus(32,C,D) % Note that the O (oh) is not a 0 (zero)
목표에는 목표를 달성하기 위해 각각 성공해야하는 세 가지 술어가 포함됩니다. nth0/3
두 번 사용하는 술어 목록의 특정 인덱스에서 값을 가져 오는 데 사용합니다 (이 0
이름에 인덱싱 제로 표시). 첫 번째 호출 Y
은 문자 행렬 의 세 번째 행을 O
저장하고 두 번째 호출은 X
해당 행 의 세 번째 문자를에 저장합니다 C
. plus/3
첫 번째 두 인수가 세 번째 인수와 합치면 최종 술어 가 성공합니다. 이것은 쌍의 문자 코드가 문자 행렬의 문자 코드보다 32 더 크게 만드는 데 사용되며 위에서 언급 한 것처럼 모든 대문자를 소문자로 바꿉니다.
마지막으로 연관 맵이 작성된 목록에 목표가 성공하도록하는 findall/3
모든 X^Y-D
조합을 저장합니다 L
.
더 곧 올 …
답변
자바 스크립트 (ES6), 298 276 264 바이트
@ngn 덕분에 8 바이트 절약
입력을로 (a,c,x,y,d,f)
, 위치 a
및 c
문자 배열 로 취 합니다. 반환 0
또는 1
.
(a,c,x,y,d,f,k=1e3)=>(g=(F,p=0,s=f.split`|`[F],r=a[y])=>!k|!r|x&16||r[x]<'$'?2:/\*/.test(a)?(r[x]=o=0,(I=s[p+1],P=s[p])&&(P<'b'|P==c[y][x].toLowerCase()&&I!='_'&&k--?+I?o=g(I-1):I=='L'?d--:I=='R'?d++:I<'b'?y+=(d&=3,x-=~-d%2,2-d)%2:c[y][x]=I:0,o||g(F,p+2))):1)(0)&1
테스트 사례
let f =
(a,c,x,y,d,f,k=1e3)=>(g=(F,p=0,s=f.split`|`[F],r=a[y])=>!k|!r|x&16||r[x]<'$'?2:/\*/.test(a)?(r[x]=o=0,(I=s[p+1],P=s[p])&&(P<'b'|P==c[y][x].toLowerCase()&&I!='_'&&k--?+I?o=g(I-1):I=='L'?d--:I=='R'?d++:I<'b'?y+=(d&=3,x-=~-d%2,2-d)%2:c[y][x]=I:0,o||g(F,p+2))):1)(0)&1
getA = _ => [
"################",
"################",
"##*....*...*#.##",
"##.####.#####.##",
"##.####.#####.##",
"##.####*...*#.##",
"##.########.####",
"##*........*#.##",
"################",
"################",
"################",
"################"
].map(s => [...s]);
getC = _ => [
"RRRRRRRRRRRRRRRR",
"RRRRRRRRRRRRRRRR",
"RRRBBBBRGGGGRRRR",
"RRBRRRRGRRRRRRRR",
"RRBRRRRGRRRRRRRR",
"RRBRRRRRGGGBRRRR",
"RRBRRRRRRRRGRRRR",
"RRRBBBBGGGGBRBRR",
"RRRRRRRRRRRRRRRR",
"RRRRRRRRRRRRRRRR",
"RRRRRRRRRRRRRRRR",
"RRRRRRRRRRRRRRRR"
].map(s => [...s]);
y=2; x=6; d=2;
[
"_FrLg2_1|_FbLrR_2||||", // result:1
"_FrRg2_1|_FbLrR_2||||", // result:0 (stepped on a black square)
"_FrLrL_1|_FbLrR_2||||", // result:0 (1000-step limit exceeded)
"_FrLg2__|________||||" // result:0 (stack underflow)
]
.forEach(code => console.log('Example #1', code, '-->', f(getA(), getC(), x, y, d, code)));
getA = _ => [
"#***************",
"#*###*###*###*##",
"#*###*###*###*##",
"***#***#***#***#",
"***#***#***#***#",
"*###*###*###*###",
"***#***#***#***#",
"***#***#***#***#",
"***#***#***#***#",
"*###*###*###*###",
"*.*#***#***#***#",
"***#***#***#***#"
].map(s => [...s]);
getC = _ => [
"RGGGGGGGGGGGGGGG",
"RBRRRGRRRGRRRGRR",
"RBRRRGRRRGRRRGRR",
"RBRRGGGRGGGRGGGR",
"BRRRGGGRGGGRGGGR",
"BRRRGRRRGRRRGRRR",
"BRRRGGGRGGGRGGGR",
"RBRRGGGRGGGRGGGR",
"BRRRGGGRGGGRGGGR",
"BRRRGRRRGRRRGRRR",
"BGRRGGGRGGGRGGGR",
"RBRRGGGRGGGRGGGR"
].map(s => [...s]);
y=10; x=1; d=0;
[
"_2_R_R_1|_FgRgFgFg3rRr4b2_Fgb|_F_F_R|_2_L_r||" // result:1
]
.forEach(code => console.log('Example #2', code, '-->', f(getA(), getC(), x, y, d, code)));
댓글
( // main function taking:
a, c, x, y, d, f, // - input variables
k = 1e3 // - k = instruction counter
) => ( //
g = ( // g = recursive execution function, taking:
F, // - F = subroutine id
p = 0, // - p = instruction pointer
s = f.split`|`[F], // - s = instruction string
r = a[y] // - r = current row in a[]
) => //
!k | // if we've executed 1000 instructions
!r | x & 16 || // or we've felt out of the map
r[x] < '$' ? // or we've reached a black square:
2 // exit with error code 2
: // else:
/\*/.test(a) ? ( // if there are still some stars:
r[x] = o = 0, // mark the current cell as visited
(I = s[p + 1], P = s[p]) && // I = instruction, P = predicate
( // if P is defined:
P < 'b' | // if the predicate is '_'
P == c[y][x].toLowerCase() // or it matches the color of the cell
&& I != '_' // and the instruction is not '_',
&& k-- ? // then decrement k and:
+I ? // if I is '1' ... '5':
o = g(I - 1) // process call to subroutine
: // else:
I == 'L' ? // if I is 'L':
d-- // turn left
: // else:
I == 'R' ? // if I is 'R':
d++ // turn right
: // else:
I < 'b' ? ( // if I is not a color:
y += ( // I must be 'F',
d &= 3, // so make the bot advance
x -= ~-d % 2, // by updating x
2 - d // and y
) % 2 //
) : // else:
c[y][x] = I // paint the current cell
: // else:
0, // do nothing
o || // provided that o is equal to 0,
g(F, p + 2) // go on with the next instruction
) // end of instruction execution
) : // else:
1 // success: return 1
)(0) & 1 // initial call to the subroutine F1
답변
APL (Dyalog 기본) , 236 (233) 바이트
Outgolfer Erik 덕분에 -3
이제 보너스를 주었으므로 샘플 솔루션을 내 도전에 게시하고 있습니다. 여기에는 개선의 여지가 있습니다-더 자유롭게 복사하고 골프를 즐기십시오.
a c r d f←⎕⋄c←819⌶c⋄F←0,('|'=¯1⌽f)/⍳≢f⋄t←n←0
{~(⊂r)∊⍳⍴a:0⋄'#'=r⌷a:0⋄p q←2↑f↓⍨⊃⌽t⋄(_←p≡'|')∧×≢t:0⋄_:∇t↓←¯1⋄(⊃⌽t)+←2⋄~p∊'_',r⌷c:∇0⋄n+←1⋄n>999:0⋄(r⌷a)←'.'⋄~'*'∊a:1⋄r+←(q≡'F')×11 9○0j1*d⋄d+←4|'.R.L'⍳q⋄q∊'rgb':∇(r⌷c)←q⋄q∊⎕d:∇t,←F[⍎q]⋄∇0}0
위와 동일하며 주석으로 확장되었습니다.
⎕io←0 ⍝ 0-based indices (not counted in the score)
a c r d f←⎕ ⍝ decompose eval'ed input (⎕) into variables
c←819⌶c ⍝ make c lowercase
F←0,('|'=¯1⌽f)/⍳≢f ⍝ split f at the '|'-s
t←n←0 ⍝ t:stack, n:step counter
{ ⍝ lambda
~(⊂r)∊⍳⍴a:0 ⍝ if the robot is off the map, return 0
'#'=r⌷a:0 ⍝ if the robot is on a wall, return 0
p q←2↑f↓⍨⊃⌽t ⍝ current instruction - p:predicate, q:action
(_←p≡'|')∧1≥≢t:0 ⍝ if at end of func and stack is empty, return 0
_:∇t↓←¯1 ⍝ if at end of func, pop from stack and recurse
(⊃⌽t)+←2 ⍝ increment program counter (top of stack)
~p∊'_',r⌷c:∇0 ⍝ if predicate doesn't match cell colour, recurse
n+←1⋄n>999:0 ⍝ if too meany steps, return 0
(r⌷a)←'.' ⍝ consume star
~'*'∊a:1 ⍝ if no more stars left, return 1
r+←(q≡'F')×11 9○0j1*d ⍝ if action is F, move forward
d+←4|'.R.L'⍳q ⍝ if action is L or R, turn left or right
q∊'rgb':∇(r⌷c)←q ⍝ if action is paint (r,g,b), do it
q∊⎕d:∇t,←F[⍎q] ⍝ if action is F1...F5, push on stack and recurse
∇0 ⍝ action is nop (_), recurse
}0 ⍝ call the lambda (argument will be ignored)