Pular e correr


18

Matthew gosta de resolver quebra-cabeças. Sempre que ele consegue resolver um, ele pula alegremente. Recentemente, ele realmente precisa fazer isso, pois uma chuva de meteoros abriu crateras e buracos no chão em que ele não gostaria de cair.

Você recebe uma parte da paisagem que Mateus deseja atravessar, com sorte chegando saudável no final. O solo é dado em metros, com cada metro sendo solo normal ou um buraco. Quando ele está correndo, ele consegue atravessar um metro por passo; a alternativa é pular, que atravessa quatro metros por passo. Matthew começa na extrema esquerda no primeiro medidor de solo e quer chegar ao último (embora não além dele - imagine um buraco sem fim além do último medidor indicado na paisagem).

Entrada

A entrada é fornecida como uma única linha na entrada padrão, terminada por uma quebra de linha. A linha consiste em traços ( -) ou sublinhados ( _), representando um medidor de solo ou furo, respectivamente. Uma entrada de amostra pode ser:

----__--___---

A paisagem dada é de pelo menos um e no máximo 30 metros de comprimento e sempre começa com o solo.

Resultado

A saída é fornecida na saída padrão e representa uma série de comandos de movimento para Matthew, run ( R) ou jump ( J). Como observado acima, um comando de corrida faz com que Matthew corra um metro enquanto pula o leva adiante exatamente quatro metros. Para o exemplo acima, é possível o seguinte movimento:

RRJRJRR

que tem a seguinte aparência:

Ilustração do movimento RRJRJRR

Se não houver caminho seguro na paisagem, um único ponto de exclamação ( !) deve ser impresso.

Entradas de Amostra

--------
----__--___---
-_______
-_-_-_-_-_-
-

Saídas de amostra

JRRR
RRJRJRR
!
!

(a última saída está em branco, pois nenhum movimento é necessário, mas acho que o Markdown não pode analisar isso)

Nota

Somente um único caminho possível é necessário, portanto a saída do programa não precisa estar exatamente em conformidade com as saídas de amostra. Desde que seja fornecida uma solução, se existir, e todo comando de movimento se mover para o solo e o último medidor for atingido, o resultado será válido.

Saída adicional com erro padrão é ignorada.

Condição vencedora

O código mais curto vence, como é habitual no golfe. Em caso de empate, a solução anterior vence.

Casos de teste

Existem dois scripts de teste, contendo casos de teste idênticos:

A invocação ocorre nos dois casos:, <test script> <my program> [arguments]por exemplo, ./test ruby jumprun.rbou ./test.ps1 ./jumprun.exe.

Outra nota

Esta tarefa fez parte de um concurso de golfe realizado na minha universidade durante o período 2011-W24. As pontuações e idiomas de nossos concorrentes foram os seguintes:

  • 104 - Haskell
  • 131 - Haskell
  • 154 - C
  • 170 - C
  • 275 - VB.NET
  • 286 - Lisp comum

Nossas próprias soluções foram

  •   92 - Ruby
  • 124 - PowerShell

@Joey eu recebo um erro ao tentar executar test.sh com ./test.sh perl jump.pl- ./test.sh: line 42: syntax error near unexpected token 'done', sob o bash 3.2.48
swilliams

@ Joey eu limpei meu cache, baixei novamente e funciona muito bem agora. Obrigado.
swilliams

Olhando para as soluções, aparentemente era realmente muito trivial. Desculpas.
Joey

1
Presumo que correr para trás / pular não é permitido? Se fosse, tornaria paisagens como - - - solucionáveis.
perfil completo de Keith Randall

Keith: um pouco tarde demais para mudar a tarefa, eu acho.
Joey19 /

Respostas:


7

Perl, 53 caracteres

s/-...(?=(-|-...)*-$)/J/g;y/-/R/;/_/?$_="!":s/.$//

Execute isso com perl -p jumpnrun.pl. Contei 3 caracteres para a -popção, que é a diferença de comprimento entre perl jumpnrun.ple perl -p jumpnrun.pl.

Eu não sou tão fluente em Perl, então tenho certeza que isso pode ser reduzido ainda mais. Isso usa um regexp semelhante à solução de Howard .


3

Ruby, 93 90 79 70 caracteres

Eu pensei que uma solução regex seria bastante fina e compacta (deixe o combinador fazer o trabalho). Infelizmente, todos os casos extremos e tratamentos especiais fizeram esse tempo tão longo - pelo menos eu não toquei nos 100 ;-).

puts gets.gsub(/-...(?=(-|-...)*-$)/,?J).tr(?-,?R)=~/^([JR]*)R$/?$1:?!

Ele passa em todos os casos de teste do script fornecido.

Salva vários caracteres em comparação com o script anterior (agora uma única chamada gsubé suficiente).

Editar 1: alterado puts z!=?-??!:''para z!=?-&&$><<?!após o script de teste não permitir saída para o caso de teste 1.

Editar 2: a versão anterior era

z=gets.chop
z.chars{z.sub!(/^(-|-...)((-|-...)*-)$/){$><<($1==?-??R:?J);$2}}
z!=?-&&$><<?!

Minha idéia original era substituir os personagens usando uma estratégia de olhar para trás e olhar para frente como esta: O padrão era ^(?<=[RJ]*)(-|-...)(?=(-|-...)*-$)e então eu substituiria '-' por 'R' e, caso contrário, por 'J'. Infelizmente, Ruby não permite look-behind de tamanho variável e outro grupo de captura para a primeira parte tornou o código ainda mais longo.

Então, eu fiz a abordagem iterativa: se eu posso começar com uma etapa ou pular ^(-|-...)seguido de uma série de outras etapas ou saltos até a última plataforma, (-|-...)*-$então imprimo a letra correspondente, remova os primeiros um / quatro caracteres e recomeço. On pode até ajustar a prioridade RJ vs. JR alternando as opções dentro da expressão (atualmente ela prefere RJ).

Edit 3: Dividindo a única legenda

puts (z=gets.chop.gsub(/(-...|-)(?=(-|-...)*-$)/){$1==?-??R:?J})=~/_/??!:z.chop

em dois

puts (z=gets.chop.gsub(/-...(?=(-|-...)*-$)/,?J).tr(?-,?R))=~/_/??!:z.chop

deu mais alguns caracteres. Finalmente, consegui me livrar desse problema de final de linha, mas com um custo: a detecção de falhas custa mais alguns caracteres.


Você pode salvar 3 caracteres alterando a última linha para z!=?-&&$><<?!. Fora isso, ótima solução, +1!
Ventero

@Ventero eu tinha um pôs o primeiro teste falhou por causa de qualquer saída para "-" ;-)
Howard

Hm, parece que meu script do PowerShell tem um pequeno bug. Aparentemente, ele não aceita entrada para o Teste 2 e não aceita para o Teste 1. Isso é ... estranho, para dizer o mínimo. Vou tentar consertar.
Joey

Ok, o script de teste deve ser corrigido e não mais rejeitar um resultado realmente vazio para o teste 1. Ok, agora ele deve ser corrigido.
Joey

@Joey Danke. Nun sind es 90 ;-)
Howard

1

Perl - 71 60

$_=<>;y/-/R/;s/R...(?=(R(...)?)*R$)/J/g;print/_/?"!":s/.$//r

Agora passa todos os casos de teste. :) Acontece que eu estava removendo o último caractere muito cedo ... e metade do meu regex original era totalmente redundante.

$ _ = $ ARGV [0]; y / - / R /; s / (R ... (? = R)) (R * (? = R)) / J $ 2 / g; chop; print / /? "!": $ , $ /

Ainda outra solução regex, passa nos 5 casos de teste no post.

Pode ser encurtado executando como uma linha com -Ee em sayvez de print, mas o perl tenta interpretar a entrada como uma opção ... ( Unrecognized switch: -_-_-_-_-_-)


A pergunta afirma que a entrada é dada no stdin. Ao alterar sua solução para ler a partir de stdin, em vez de usar $ARGV, ele ainda falha em 108 casos de teste dos scripts de teste.
Ventero

@Ventero Oh, opa ... Acho que sei por que isso acontece, em breve corrigirei ... é isso que recebo por não passar por todos os casos de teste ...> _>
swilliams

Bem, a intenção dos scripts era permitir que as pessoas verificassem facilmente a validade e a aderência às especificações :-)
Joey

@Joey O problema era que eu de alguma forma conseguiu confundir 'script de teste' com 'implementação de referência' até Ventero postou seu comentário :) ... script é agora quase fixo agora, porém, atualmente só não 20, todos os falsos negativos
swilliams

1

Python - 89 93 97 93 caracteres

Só porque.

import re;i=re.sub('...(?<!---)-','J',input()[1:]);print('!'if'_'in i else re.sub('-','R',i))

No momento, há apenas dez casos de teste com falha (levando em consideração os casos em que há várias soluções válidas). Eu vou consertar isso totalmente depois.


Tomando emprestado um dos regexes de trabalho, ele acaba sendo

import re;i=re.sub('-...(?=(-|-...)*-$)','J',input());print('!'if'_'in i else re.sub('-','R',i))

Com 96 caracteres.


1
Passa apenas 728 dos casos de teste. Coloquei os scripts de teste por um motivo, na verdade.
Joey

@ Joey: Parece que eu esqueci de aparar o caractere principal da entrada. Eu tolo. Agora está corrigido.
JAB

Ainda passa apenas nos testes 766/849.
Ventero

1

Haskell, 90 caracteres:

Minha primeira solução - longa, mas funciona em tempo linear, usando programação dinâmica. :) 150 caracteres :

x!y="!"
q '-'=max
q c=(!)
s i=r where r=zipWith3 q i(0&'R')$3&'J';n&c="":replicate n"!"++map(c#)r
c#"!"="!"
c#s=c:s
main=interact$reverse.last.s.init

A segunda solução - muito mais lenta (tempo exponencial), mas muito mais curta: 90 caracteres

s"-\n"=""
s('-':t)=max('R'#s t)$'J'#s(drop 3 t)
s _="!"
c#"!"="!"
c#s=c:s
main=interact s
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.