Sua tarefa é escrever um intérprete RoboZZle. Se você não conhece o jogo, assista ao vídeo em robozzle.com ou leia minha descrição abaixo.
Um robô vive em uma grade retangular de quadrados coloridos de vermelho, verde, azul ou preto. Quadrados pretos são inacessíveis. Os outros são acessíveis e alguns deles contêm uma estrela. O objetivo é coletar todas as estrelas sem pisar nos quadrados pretos ou cair no mapa. O robô ocupa um quadrado e enfrenta uma direção específica - esquerda, direita, cima ou baixo. Segue instruções de montagem agrupadas nas sub-rotinas F1, F2, ..., F5. Uma instrução é um par de predicado ("nenhum", "se estiver em vermelho", "se estiver em verde", "se estiver em azul") e uma ação ("vá em frente", "vire à esquerda", "vire à direita", "pinte o quadrado atual de vermelho", "pinte de verde", "pinte de azul", "não faça nada", "chame F1", ..., "chame F5"). As chamadas para sub-rotinas usam uma pilha e podem ser recursivas. Assim como na programação convencional, após a conclusão da última instrução de uma sub-rotina, a execução continua a partir do ponto em que a sub-rotina foi chamada. A execução começa na primeira instrução da F1 e continua até que o robô tenha visitado todos os quadrados com estrelas, ou quando o robô pisa em um quadrado preto ou fora do mapa, ou 1000 instruções foram executadas (falhas de predicados e ações "não fazer nada") não conte) ou não há mais instruções para executar (pilha insuficiente).
Entradas:
a
- uma matriz de caracteres de 12x16 (como normalmente representada no seu idioma, por exemplo, conjunto de seqüências de caracteres) que codifica um mapa -'#'
para quadrados inacessíveis (pretos),'*'
para quadrados com uma estrela,'.'
para o restoc
- uma matriz de caracteres de 12x16 que descreve as cores dos quadrados acessíveis -'R'
(vermelho),'G'
(verde) ou'B'
(azul). Quadrados inacessíveis serão representados por uma carta arbitrária dos três.y
ex
- a linha e coluna com base em 0 do robô;a[y][x]
é garantido para ser'.'
d
- a direção que o robô está enfrentando:0 1 2 3
para a direita, para baixo, esquerda, para cima, ou seja, para(y,x+1)
,(y+1,x)
,(y,x-1)
,(y-1,x)
f
- uma única sequência, as implementações concatenadas de F1 ... F5. Cada implementação é uma sequência (possivelmente vazia) de pares de ação de predicado (no máximo 10 pares por sub-rotina), finalizada com a'|'
.predicados:
'_'
nenhum,'r'
vermelho,'g'
verde,'b'
azulações:
'F'
vá em frente,'L'
vire à esquerda,'R'
vire à direita,'r'
pinte de vermelho,'g'
pinte de verde,'b'
pinte de azul,'1'
ligue para F1, ...,'5'
ligue para F5,'_'
não faça nada
Você não precisa nomear suas entradas como acima, mas seus valores devem ser os especificados.
Saída: 1
(ou true
) se o robô coletar todas as estrelas de acordo com as regras, 0
( false
) caso contrário.
Exemplo :
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)
Outro exemplo , envolvendo instruções de "pintura":
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
Para gerar seu próprio teste, vá para um quebra-cabeça da lista em robozzle.com , tente resolvê-lo (ou não), pressione F12 no seu navegador, digite o console 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()))
e reformate o resultado para o seu idioma.
Vitórias mais curtas. Sem brechas.
Respostas:
Prolog (SWI) , 574 bytes
Experimente online!
Isso define um predicado que, quando chamado, terá êxito se todas as estrelas forem coletadas com êxito e falharem de outra forma. O predicado leva os argumentos como tal:
a+c+f+x^y^d.
.a
ec
deve ser uma lista de strings entre aspas de backtick, enquantof
deve ser uma string de aspas duplas.Explicação
Este programa contém três predicados,
*/2
,^/2
, e+/2
. Os*/2
predicados definidos na primeira linha são responsáveis por parte do processamento de entrada. O^/2
predicado calcula recursivamente como o robô se move passo a passo e obtém êxito se o robô coletar legalmente todas as estrelas e falhar de outra forma. O+/2
predicado é o principal predicado do programa e prepara a entrada para o^/2
predicado com alguma ajuda do*/2
predicado. Observe que tecnicamente cada um desses predicados leva apenas dois argumentos, mas usando operadores e correspondência de padrões, eles podem se comportar como se tivessem mais argumentos (discuto esse fenômeno mais detalhadamente aqui ).*/2
Esse predicado recebe dois argumentos. A primeira é uma lista de listas de códigos de caracteres (é assim que o Prolog analisa as strings citadas pelo backtick). O segundo é um mapa associativo de pontos no mapa 12x16 (representado como
X^Y
) a 32, mais o código de caractere armazenado naquele ponto na lista de listas de códigos de caractere. O 32 é adicionado a cada um dos códigos de caracteres para que, para a matriz de cores, ele transforme os caracteres maiúsculos em caracteres minúsculos.A maneira como isso é feito gera uma lista de pares de pontos e os códigos de caracteres nesse ponto usando
findall/3
. Em seguida, ele é usadolist_to_assoc/2
para criar o mapa associativo correspondente de pontos para o código de caractere naquele ponto.O
findall/3
predicado é que um interno usa um "modelo" como seu primeiro argumento, um objetivo como seu segundo argumento e uma lista como seu terceiro argumento. O predicado preenche a lista com todos os valores possíveis do modelo que fazem com que o objetivo seja bem-sucedido. Devido à precedência do operador, o modelo que é passado parafindall/3
dentro*/2
é analisado como(X^Y)-D
. O-
operador representa um par de dois valores no Prolog, de modo que o modelo representa a localização do ponto (X^Y
) emparelhado com 32 mais o código de caractere do ponto (D
). Observe que o^
usado para representar o ponto não está de forma alguma conectado ao^/2
predicado.Vamos considerar a meta que é passada para o
findall/3
predicado.O objetivo contém três predicados, cada um dos quais precisa ter sucesso para que o objetivo seja bem-sucedido. O
nth0/3
predicado usado duas vezes é usado para obter o valor em um índice específico da lista (o0
nome indica que é zero indexado). A primeira chamada para ele armazena aY
th linha da matriz de caracteresO
enquanto a segunda chamada armazena oX
th caractere nessa linhaC
. O predicado final seráplus/3
bem-sucedido se seus dois primeiros argumentos somarem seu terceiro argumento. Isso é usado para fazer com que o código de caractere no par seja 32 maior que o código de caractere na matriz de caracteres que, como mencionado acima, transformará todas as letras maiúsculas em minúsculas.Finalmente,
findall/3
armazena todas asX^Y-D
combinações que fazem com que seu objetivo seja bem-sucedido na lista daL
qual o mapa associativo é construído.Mais em breve...
fonte
JavaScript (ES6),
298276264 bytesGuardado 8 bytes graças a @ngn
Recebe entrada como
(a,c,x,y,d,f)
, ondea
ec
são matrizes de matrizes de caracteres. Retorna0
ou1
.Casos de teste
Mostrar snippet de código
Comentado
fonte
x+='2101'[d&3]-1,y+='1210'[d&3]-1
->d&=3,x+=(1-d)%2,y+=(2-d)%2
x
muda por no máximo 1, então eu acho que você pode substituirx&~15
porx&16
APL (Dyalog Classic) ,
236233 bytes-3 graças a Erik, o Outgolfer
Agora que dei o bônus, estou postando uma solução de amostra para meu próprio desafio. Há espaço para melhorias aqui - fique à vontade para copiar e jogar mais.
Experimente online!
Igual ao anterior, expandido com comentários:
fonte