Saltare e correre


18

A Matthew piace risolvere enigmi. Ogni volta che riesce a risolverne uno, salta felicemente. Di recente ha davvero bisogno di fare questo perché una pioggia di meteoriti ha aperto crateri e buchi nel terreno in cui non vorrebbe cadere.

Ti viene data una parte del paesaggio che Matthew vuole attraversare, sperando di arrivare sano alla fine. Il terreno è dato in metri, con ogni metro che è o terreno normale o un buco. Quando corre riesce a attraversare un metro per passo; l'alternativa è saltare che attraversa quattro metri per passo. Matthew inizia all'estrema sinistra del primo metro di terra e vuole arrivare all'ultimo (non oltre, però - immagina solo un buco infinito oltre l'ultimo metro dato nel paesaggio).

Ingresso

L'input viene dato come una riga singola sull'input standard, terminato da un'interruzione di riga. La linea è composta da trattini ( -) o caratteri di sottolineatura ( _), che rappresentano rispettivamente un metro da terra o da foro. Un input di esempio potrebbe essere:

----__--___---

Il paesaggio dato è lungo almeno uno e al massimo 30 metri e inizia sempre con il terreno.

Produzione

L'output viene fornito sull'output standard e rappresenta una serie di comandi di movimento per Matthew, run ( R) o jump ( J). Come notato sopra, un comando di corsa fa correre Matthew per un metro mentre il salto lo porta avanti esattamente di quattro metri. Per l'esempio sopra riportato è possibile il seguente movimento:

RRJRJRR

che appare approssimativamente come segue:

Illustrazione del movimento RRJRJRR

Se non esiste un percorso sicuro attraverso il paesaggio, è !necessario stampare un punto esclamativo ( ).

Ingressi campione

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

Output di esempio

JRRR
RRJRJRR
!
!

(l'ultimo output è vuoto in quanto non è necessario alcun movimento, ma immagino, Markdown non può analizzarlo)

Nota

È necessario un solo percorso possibile, quindi l'output del programma non deve conformarsi esattamente agli output di esempio. Finché viene fornita una soluzione se esiste e ogni comando di movimento si sposta a terra e viene raggiunto l'ultimo metro, l'uscita è valida.

L'output aggiuntivo in caso di errore standard viene ignorato.

Condizioni vincenti

Vince il codice più corto, come è consuetudine nel golf. In caso di pareggio, vince la soluzione precedente.

Casi test

Esistono due script di test, contenenti casi di test identici:

L'invocazione è in entrambi i casi: <test script> <my program> [arguments]ad es. ./test ruby jumprun.rbO./test.ps1 ./jumprun.exe .

Un'altra nota

Questo compito faceva parte di una gara di golf tenutasi nella mia università durante il 2011-W24. I punteggi e le lingue dei nostri concorrenti erano i seguenti:

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

Le nostre soluzioni erano

  •   92 - Ruby
  • 124 - PowerShell

@Joey Ottengo un errore nel tentativo di eseguire test.sh con ./test.sh perl jump.pl- ./test.sh: line 42: syntax error near unexpected token 'done', in bash 3.2.48
swilliams,

@Joey Ho cancellato la mia cache, scaricato di nuovo e ora funziona alla grande. Grazie.
Swilliams,

Guardando le soluzioni, apparentemente era davvero troppo banale. Scuse.
Joey,

1
Presumo che correre / saltare all'indietro non sia consentito? Se lo fosse, renderebbe i paesaggi come - - - risolvibili.
Keith Randall,

Keith: un po 'troppo tardi ora per cambiare compito, immagino.
Joey,

Risposte:


7

Perl, 53 caratteri

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

Esegui questo con perl -p jumpnrun.pl. Ho contato 3 caratteri per l' -popzione, che è la differenza di lunghezza tra perl jumpnrun.pleperl -p jumpnrun.pl .

Non sono così fluente in Perl, quindi sono abbastanza sicuro che questo possa essere abbreviato ulteriormente. Questo utilizza una regexp simile alla soluzione di Howard .


3

Rubino, 93 90 79 70 caratteri

Ho pensato che una soluzione regex sarebbe stata abbastanza bella e compatta (lascia che il matcher faccia il lavoro). Purtroppo tutti i casi limite e i trattamenti speciali hanno reso questo così lungo - almeno non ho toccato il 100 ;-).

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

Passa tutti i test di script forniti.

Salvati diversi caratteri rispetto allo script precedente (ora gsubè sufficiente una sola chiamata a ).

Edit 1: Cambiato puts z!=?-??!:''a z!=?-&&$><<?!dopo lo script di test ha permesso nessuna uscita per il caso del test 1.

Modifica 2: la versione precedente era

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

La mia idea originale era quella di sostituire i personaggi usando una strategia look-behind e look-ahead come questa: lo schema era ^(?<=[RJ]*)(-|-...)(?=(-|-...)*-$)e quindi sostituivo '-' con 'R' e altrimenti con 'J'. Sfortunatamente Ruby non consente look-behind a lunghezza variabile e un altro gruppo di acquisizione per la prima parte ha reso il codice ancora più lungo.

Quindi ho seguito l'approccio iterativo: se posso iniziare con un passo o un salto ^(-|-...)seguito da una serie di altri passi o salti fino all'ultima piattaforma, (-|-...)*-$allora stampo la lettera corrispondente, rimuovo il primo / quattro caratteri e ricomincio. On può persino regolare la priorità RJ vs. JR cambiando le scelte all'interno dell'espressione (attualmente preferisce RJ).

Modifica 3: suddivisione della singola sottotitolazione

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

in due

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

ha dato altri pochi caratteri. Finalmente sono riuscito a sbarazzarmi di questo problema di fine linea, ma a un costo: il rilevamento dei guasti costa alcuni caratteri in più.


È possibile salvare 3 caratteri modificando l'ultima riga in z!=?-&&$><<?!. A parte questo, ottima soluzione, +1!
Ventero,

@Ventero ho avuto quello che ha messo il primo test fallito a causa della mancanza di output per "-" ;-)
Howard

Hm, sembra che il mio script PowerShell abbia un piccolo bug. Apparentemente non accetta input per Test 2 e non lo accetta per Test 1. Questo è ... strano, per non dire altro. Proverò a sistemare.
Joey,

Ok, lo script di test dovrebbe essere corretto e non rifiutare più un risultato effettivamente vuoto per il test 1. Ok, ora dovrebbe essere corretto.
Joey,

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

1

Perl - 71 60

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

Ora passa tutti i test. :) Ho scoperto che stavo rimuovendo troppo presto l'ultimo personaggio ... e metà del mio regex originale era completamente ridondante.

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

Ancora un'altra soluzione regex, supera i 5 testcase nel post.

Potrebbe essere abbreviato eseguendo il comando one-liner con -Ee sayinvece di print, ma perl tenta di interpretare l'input come switch ... ( Unrecognized switch: -_-_-_-_-_-)


La domanda afferma che l'input è dato su stdin. Quando si modifica la soluzione in modo che $ARGVvenga letta da stdin anziché utilizzare , non riesce ancora a eseguire 108 testcase dagli script di test.
Ventero,

@Ventero Oh oops ... Penso di sapere perché lo fa, metterò presto una soluzione ... questo è quello che ottengo per non aver superato tutti i test ...> _>
Swilliams

Bene, l'intenzione degli script era di consentire alle persone di verificare facilmente la validità e l'adesione alle specifiche :-)
Joey,

@Joey Il problema era che in qualche modo sono riuscito a confondere 'script di test' con 'implementazione di riferimento' fino a quando Ventero non ha pubblicato il suo commento :) ... lo script ora è quasi risolto ora sebbene, attualmente fallisca solo 20, tutti i falsi negativi
Swilliams

1

Python - 89 93 97 93 caratteri

Solo perché.

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

Ora falliscono solo dieci casi di test (tenendo conto dei casi in cui esistono più soluzioni valide). Lo riparerò completamente più tardi.


Prendendo in prestito una delle regex funzionanti, finisce come

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

Con 96 caratteri.


1
Passa solo 728 dei casi di test. Ho messo lì gli script di prova per un motivo, in realtà.
Joey,

@Joey: sembra che mi sia dimenticato di tagliare il personaggio principale dall'input. Sciocco me Ora è corretto.
JAB,

Passa ancora solo 766/849 testcase.
Ventero,

1

Haskell, 90 caratteri:

La mia prima soluzione - lunga, ma funziona in tempo lineare, usando la programmazione dinamica. :) 150 caratteri :

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

La seconda soluzione - molto più lenta (tempo esponenziale), ma molto più breve: 90 caratteri

s"-\n"=""
s('-':t)=max('R'#s t)$'J'#s(drop 3 t)
s _="!"
c#"!"="!"
c#s=c:s
main=interact s
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.