L'utente CarpetPython ha pubblicato una nuova interpretazione di questo problema che pone una maggiore attenzione alle soluzioni euristiche, a causa di un maggiore spazio di ricerca. Personalmente penso che la sfida sia molto più bella della mia, quindi prova a provarla!
La corsa vettoriale è un gioco avvincente che può essere giocato con una penna e un foglio di carta a quadretti. Disegni una pista arbitraria sulla carta, definisci l'inizio e la fine e poi guidi la tua auto a punti in modo a turni. Arriva alla fine il più velocemente possibile, ma fai attenzione a non finire in un muro!
La traccia
- La mappa è una griglia bidimensionale, in cui ogni cella ha coordinate intere.
- Ti sposti sulle celle della griglia.
- Ogni cella della griglia fa parte della traccia o è un muro.
- Esattamente una cella di traccia è la coordinata iniziale.
- Almeno una cella di traccia è designata come obiettivo. L'atterraggio su uno di questi completa la gara. Più celle obiettivo non sono necessariamente collegate.
Sterzare la macchina
La tua auto parte da una data coordinata e con il vettore di velocità (0, 0)
. In ogni turno, puoi regolare ciascun componente della velocità ±1
o lasciarlo così com'è. Quindi, il vettore di velocità risultante viene aggiunto alla posizione della tua auto.
Un'immagine può aiutare! Il cerchio rosso era la tua posizione nell'ultima curva. Il cerchio blu è la posizione corrente. La tua velocità è il vettore dal cerchio rosso al cerchio blu. In questo turno, a seconda di come si regola la velocità, è possibile spostarsi su uno dei cerchi verdi.
Se atterri in un muro, perdi immediatamente.
Il tuo compito
Hai indovinato: scrivi un programma che, dato un circuito come input, guida la macchina verso una delle celle obiettivo nel minor numero di curve possibile. La tua soluzione dovrebbe essere in grado di gestire ragionevolmente bene le tracce arbitrarie e non essere specificamente ottimizzata per i casi di test forniti.
Ingresso
Quando viene invocato il tuo programma, leggi da stdin :
target
n m
[ASCII representation of an n x m racetrack]
time
target
è il numero massimo di turni che è possibile eseguire per completare la traccia ed time
è il budget di tempo totale per la traccia, in secondi (non necessariamente intero). Vedi sotto per i dettagli sui tempi.
Per la traccia delimitata da newline, vengono utilizzati i seguenti caratteri:
#
- muroS
- l' inizio*
- un obiettivo.
- tutte le altre celle del binario (es. Strada)
Tutte le celle esterne alla n x m
griglia fornite sono implicite come pareti.
L'origine delle coordinate si trova nell'angolo in alto a sinistra.
Qui c'è un semplice esempio:
8
4.0
9 6
###...***
###...***
###...***
......###
S.....###
......###
Usando l'indicizzazione basata su 0, la coordinata iniziale sarebbe (0,4)
.
Dopo ogni mossa riceverai ulteriori input:
x y
u v
time
Dove x
, y
, u
, v
sono tutti gli interi 0-based. (x,y)
è la tua posizione attuale ed (u,v)
è la tua velocità attuale. Nota che x+u
e / o y+v
potrebbe essere fuori dai limiti.
time
è tutto ciò che resta del budget temporale, in pochi secondi. Sentiti libero di ignorare questo. Questo è solo per i partecipanti che vogliono davvero portare la loro implementazione al limite di tempo.
Quando il gioco termina (perché sei atterrato in un muro, hai superato i limiti, superato i target
turni, esaurito il tempo o raggiunto l'obiettivo), riceverai una linea vuota.
Produzione
Per ogni turno, scrivi a stdout :
Δu Δv
dove Δu
e Δv
ciascuno è uno dei -1
, 0
, 1
. Questo verrà aggiunto (u,v)
per determinare la tua nuova posizione. Giusto per chiarire, le indicazioni sono le seguenti
(-1,-1) ( 0,-1) ( 1,-1)
(-1, 0) ( 0, 0) ( 1, 0)
(-1, 1) ( 0, 1) ( 1, 1)
Una soluzione ottimale per l'esempio sopra sarebbe
1 0
1 -1
1 0
Nota che il controller non si collega a stderr , quindi sei libero di usarlo per qualsiasi tipo di output di debug di cui potresti aver bisogno durante lo sviluppo del tuo bot. Tuttavia, rimuovi / commenta qualsiasi output nel codice inviato.
Il bot può impiegare mezzo secondo per rispondere in ogni singolo turno. Per turni che richiedono più tempo, avrai un budget di tempo (per traccia) di target/2
secondi. Ogni volta che un turno impiega più di mezzo secondo, il tempo aggiuntivo verrà sottratto dal budget. Quando il tuo budget cronometrato raggiunge lo zero, la gara corrente verrà interrotta.
Novità: per motivi pratici, devo impostare un limite di memoria (poiché la memoria sembra essere più limitante del tempo per dimensioni di traccia ragionevoli). Pertanto, dovrò interrompere qualsiasi test in cui il pilota utilizza più di 1 GB di memoria misurata da Process Explorer come byte privati .
punteggio
C'è un benchmark di 20 tracce. Per ogni traccia:
- Se completi la traccia, il tuo punteggio è il numero di mosse necessarie per raggiungere una cella obiettivo divisa per
target
. - Se esaurisci il tempo / la memoria o non raggiungi l'obiettivo prima che
target
siano trascorsi i turni o atterri in un muro / fuori limite in qualsiasi momento, il tuo punteggio è2
. - Se il tuo programma non è deterministico, il tuo punteggio è la media di oltre 10 corse su quella traccia (per favore, specifica questo nella tua risposta).
Il tuo punteggio complessivo è la somma dei punteggi dei singoli brani. Il punteggio più basso vince!
Inoltre, ogni partecipante può (ed è fortemente incoraggiato a) fornire una traccia benchmark aggiuntiva , che verrà aggiunta all'elenco ufficiale. Le risposte precedenti verranno rivalutate includendo questa nuova traccia. Questo per assicurarsi che nessuna soluzione sia adattata troppo da vicino ai casi di test esistenti e per tenere conto di casi limite interessanti che potrei aver perso (ma che potresti individuare).
Rottura del legame
Ora che esiste già una soluzione ottimale, questo sarà probabilmente il fattore principale per i punteggi dei partecipanti.
Se c'è un pareggio (a causa di diverse risposte che risolvono tutte le tracce in modo ottimale o meno), aggiungerò ulteriori casi di test (più grandi) per spezzare il pareggio. Per evitare qualsiasi pregiudizio umano durante la creazione di questi tie-breaker, questi saranno generati in modo fisso:
- Io aumentare la lunghezza del lato
n
dal10
rispetto per l'ultimo brano generato in questo modo. (Potrei saltare le taglie se non si rompono la cravatta.) - La base è questa grafica vettoriale
- Questo verrà rasterizzato alla risoluzione desiderata usando questo frammento di Mathematica .
- L'inizio è nell'angolo in alto a sinistra. In particolare, sarà la cella più a sinistra della riga più in alto di quella fine della traccia.
- L'obiettivo è nell'angolo in basso a destra. In particolare, sarà la cella più a destra della riga più in basso di quella fine della traccia.
- La
target
volontà4*n
.
La traccia finale del benchmark iniziale è stata già generata in questo modo, con n = 50
.
Il controller
Il programma che verifica i contributi è scritto in Ruby e può essere trovato su GitHub insieme al file di riferimento che userò. C'è anche un bot di esempio chiamato randomracer.rb
lì, che raccoglie semplicemente mosse casuali. Puoi usare la sua struttura di base come punto di partenza per il tuo bot per vedere come funziona la comunicazione.
Puoi eseguire il tuo bot su un file di traccia a tua scelta come segue:
ruby controller.rb track_file_name command to run your racer
per esempio
ruby controller.rb benchmark.txt ruby randomracer.rb
Il repository contiene anche due classi Point2D
e Track
. Se la tua richiesta è scritta in Ruby, sentiti libero di riutilizzarli per tua comodità.
Opzioni della riga di comando
È possibile aggiungere opzioni della riga di comando -v
, -s
, -t
prima che il nome del file del benchmark. Se si desidera utilizzare più switch, si può anche fare, per esempio, -vs
. Questo è ciò che fanno:
-v
(dettagliato): utilizzare questo per produrre un po 'più di output di debug dal controller.
-s
(silenzioso): se preferisci tenere traccia della tua posizione e della tua velocità e non ti preoccupi del budget di tempo, puoi disattivare quelle tre linee di output ogni turno (inviato alla tua presentazione) con questo flag.
-t
(tracce): consente di selezionare singole tracce da testare. Ad esempio -t "1,2,5..8,15"
testerebbe solo le tracce 1, 2, 5, 6, 7, 8 e 15. Grazie mille a Ventero per questa funzione e per il parser delle opzioni.
La tua presentazione
In sintesi, includere quanto segue nella risposta:
- Il tuo punteggio.
- Se stai usando la casualità, ti preghiamo di indicarlo, in modo che io possa calcolare la media del tuo punteggio su più corse.
- Il codice per l'invio.
- La posizione di un compilatore o interprete gratuito per la tua lingua preferita che gira su un computer Windows 8.
- Istruzioni per la compilazione, se necessario.
- Una stringa della riga di comando di Windows per eseguire l'invio.
- Se la tua richiesta richiede la
-s
bandiera o meno. - (facoltativo) Una nuova traccia risolvibile che verrà aggiunta al benchmark. Determinerò
target
manualmente un ragionevole per la tua traccia. Quando la traccia viene aggiunta al benchmark, la modificherò in base alla tua risposta. Mi riservo il diritto di chiederti una traccia diversa (nel caso in cui aggiungi una traccia sproporzionatamente grande, includi un'oscena arte ASCII nella traccia, ecc.). Quando aggiungo il test case al set di benchmark, sostituirò la traccia nella tua risposta con un link alla traccia nel file di benchmark per ridurre il disordine in questo post.
Come puoi vedere, testerò tutti gli invii su un computer Windows 8. Se non c'è assolutamente alcun modo per far funzionare la tua presentazione su Windows, posso anche provare su una macchina virtuale Ubuntu. Questo sarà notevolmente più lento, quindi se vuoi massimizzare il limite di tempo, assicurati che il tuo programma funzioni su Windows.
Possa il miglior pilota emergere vettoriale!
Ma io voglio giocare!
Se vuoi provare tu stesso il gioco per farti un'idea migliore, c'è questa implementazione . Le regole usate lì sono leggermente più sofisticate, ma è abbastanza simile per essere utile, credo.
Classifica
Ultimo aggiornamento: 01/09/2014, 21:29 UTC
Tracce nel benchmark: 25
dimensioni del demolitore: 290, 440
- 6.86688 - Kuroi Neko
- 8.73108 - user2357112 - 2a presentazione
- 9.86627 - nneonneo
- 10.66109 - user2357112 - 1a presentazione
- 12.49643 - Ray
- 40.0759 - pseudonimo117 (probabilistico)
Risultati dei test dettagliati . (I punteggi per gli invii probabilistici sono stati determinati separatamente.)