Quanto è varia la mia corsa ad ostacoli?


21

sfondo

Ho costruito un semplice percorso ad ostacoli posizionando le scatole in una stanza rettangolare. Ora voglio contare il numero di modi essenzialmente diversi in cui può essere risolto. Ho bisogno che tu mi scriva un programma per quello.

Ingresso

Il tuo input è una matrice rettangolare non vuota dei caratteri .#. I punti .sono spazi vuoti e #sono ostacoli.

Un percorso attraverso la corsa ad ostacoli inizia nell'angolo in alto a sinistra e termina nell'angolo in basso a destra, e va solo a destra o in basso. Inoltre, un percorso valido non può superare un ostacolo. Ecco alcuni esempi disegnati con +-caratteri:

Valid path  Invalid path  Invalid path  Invalid path
++........   ++........    +++++.....    ..+.......
.++++++#..   .+.....#..    ....+++#++    ..++...#..
......+#..   .+.++++#..    .......#.+    ...+++.#..
....#.++++   .+++#.++++    ....#....+    ....#+....

Due percorsi sono essenzialmente simili 1 se uno può essere trasformato nell'altro spostandone uno +alla volta. Anche i percorsi intermedi devono essere validi, quindi non è possibile piegare un percorso su un ostacolo. Ad esempio, i primi due percorsi qui sono essenzialmente simili, ma il terzo è sostanzialmente diverso da loro, poiché non può essere spostato sui due ostacoli:

++........   +.........   +++++++++.
.+++++.#..   ++.....#..   .......#+.
.....+.#..   .++++++#..   .......#++
....#+++++   ....#.++++   ....#....+

Produzione

Il tuo output è il numero di percorsi sostanzialmente diversi attraverso la corsa ad ostacoli. In altre parole, se tutti i percorsi validi sono divisi in classi di percorsi essenzialmente simili, l'output è il numero di classi. Si noti che questo numero può essere 0, se non ci sono percorsi validi.

Regole e punteggio

È possibile scrivere un programma completo o una funzione. Vince il conteggio di byte più basso e non sono consentite scappatoie standard. Non ci sono limiti di tempo, tranne che è necessario valutare il programma su ogni caso di test prima di inviarlo.

Casi test

....
....
.... => 1

...#
....
...# => 0

#..#
..#.
.... => 0

......
......
..##..
......
...... => 2

......
...#..
......
..#...
#..... => 3

......
..#...
......
....#.
#..... => 4

.......
##.....
....###
...#...
..##.#.
#....#.
..#.... => 0

......#.
..##....
...#....
.......#
....#...
.##...#.
....#...
##...... => 7

.........
.#.#.#.#.
.........
#.#...#.#
.........
.#.#.#.#.
......... => 17

..........
.#........
..........
.....#....
#.........
........#.
......#...
.......... => 10

.........
.#.......
.........
...#.....
.........
.....#...
.........
.......#.
......... => 16

1 Il termine tecnico corretto è "omotopico" .


1
Cosa intendi con " spostandone uno +alla volta "? Ciò implica che percorsi sostanzialmente simili devono avere la stessa lunghezza?
Peter Taylor,

3
@PeterTaylor Tutti i percorsi hanno la stessa lunghezza, poiché possono solo andare verso il basso e verso destra. "Muovendone uno +" intendo essenzialmente che un angolo del percorso viene invertito in un angolo della direzione opposta.
Zgarb,

1
@Peter: poiché puoi andare solo a destra o in basso, tutti i percorsi hanno la stessa lunghezza.
Deusovi,

Risposte:


8

Lumache , 53 49 byte

A^
\.+d!{.l\.+a3(.|~c!~}\.+r!(.u\.+e(.|~},\.,=~d~

Per una volta non ho dovuto usare tle temute istruzioni di teletrasporto. Di conseguenza, i casi di test terminano all'istante invece di eoni.

Ungolfed:

A^
r\.+
{
    d\.+
    !{ r\.u \.+ a3 (.|~)}
    r\.+
    !{ d\.l \.+ a3 (.|~)}
},
d\.,
!(dr .)

Le opzioni A^significano iniziare nell'angolo in alto a sinistra e contare tutti i percorsi corrispondenti. L'idea principale è quella di verificare una condizione di canonicity per i percorsi. Onestamente non mi aspettavo che funzionasse, ma ha inchiodato i casi di test, quindi .... Ciò che cerca di verificare è che, nel percorso attuale, è stato selezionato il percorso più avido, cioè andando a destra il maggior numero di volte possibile , più volte possibile, ecc. senza attraversare ostacoli. Questo viene fatto controllando, dopo aver spostato a destra 1 o più volte e poi in basso 1 o più volte, che il quadrato successivo (che deve essere a destra) non avrebbe potuto essere raggiunto andando a destra ancora una volta nel precedente segmento a destra. La condizione analoga viene verificata anche dopo aver spostato a destra e poi in basso.


parla della lingua giusta per il lavoro!
Non che Charles il

10

Python 2, 170 131 112 byte

def f(C,t=1):i="#".join(C).find("#")+1;return([]<C)*(i<1or(i<t
and f([r[i:]for r in C],t-i))+(i>1)*f(C[1:],i-1))

Una funzione, fprendendo la corsa ad ostacoli come un elenco di righe e restituendo il numero di percorsi essenzialmente diversi.

Spiegazione

Il concetto di base è questo: scegliamo un certo ostacolo, o , in modo tale che non ci siano altri ostacoli nel riquadro di delimitazione o e nell'angolo in alto a sinistra.

+--+....
|..|....  
+--#<==== o
.....#..
.#......
........

Consideriamo quindi i due sotto-corsi ad est e a sud di o . Noi consideriamo solo uno di questi sotto-corsi se o può effettivamente essere attraversata da una direzione che porta a loro, cioè, attraversato da nord per arrivare ad est, e attraversato da ovest per arrivare al sud. Risolviamo il problema per ciascuno dei corsi secondari selezionati e restituiamo la somma dei risultati. Questi numeri corrispondono al numero di percorsi sostanzialmente diversi quando si incrociano o da sinistra e da destra, rispettivamente, quindi i due insiemi di percorsi risultanti sono sostanzialmente diversi. Dal momento che non ci sono ostacoli tra il punto di partenza e o, esiste un percorso tra il punto di partenza e qualsiasi punto di ingresso in ciascuna di queste regioni e tutti questi percorsi che portano allo stesso punto sono sostanzialmente simili, quindi la somma sopra è il numero completo di percorsi essenzialmente diversi nell'intero corso.

                               A
_
........       ...|////      |....
........       ...|////      |....
...#....  -->  ...#////  -->  ....
.#....#.       .#..//#/       ..#.
........       ....////       ....

   |                           |
   v                           v
                  B
........       ___
........       .#....#.
___#....  -->  ........  -->   +
/#////#/       
////////       

Le cose sono leggermente complicate dal fatto che la corsa ad ostacoli da sola non trasmette tutte le informazioni necessarie. Ad esempio, considera il corso B nel diagramma sopra. Preso da solo, non possiamo determinare se ciascuno degli ostacoli può essere attraversato da nord. Se B fosse la rotta di ingresso, allora, poiché tutti i percorsi iniziano nell'angolo in alto a sinistra, nessuno degli ostacoli avrebbe potuto essere attraversato da nord, ma poiché possiamo raggiungere B da entrambi i lati dell'ostacolo sinistro quando attraversiamo o da est , dovremmo trattare questo ostacolo come se potesse essere attraversato da nord quando si risolve il percorso; lo stesso non vale per l'ostacolo giusto, tuttavia, che non può essere attraversato da questa direzione.

Raccogliamo queste informazioni extra specificando, insieme alla corsa ad ostacoli, il numero di caratteri lungo la prima fila, a partire da sinistra, da cui può iniziare il percorso. Nel diagramma sopra, questo è rappresentato come la linea continua accanto a ciascun corso. Mentre, tecnicamente, dobbiamo anche specificare il numero corrispondente di caratteri lungo la prima colonna da cui può iniziare il percorso, come nel caso del sotto-corso A , in pratica abbiamo sempre selezionato l'ostacolo più alto, quindi questa informazione non è richiesta .

La selezione effettiva di o è la seguente: Facciamo finta che ogni riga, diversa dall'ultima, sia seguita da un ostacolo (ovvero, sia stato #aggiunto ad esso) e selezioniamo il primo ostacolo nel percorso risultante, in ordine di lettura. Per le file (diverse dall'ultima) che inizialmente non avevano ostacoli, ciò significa effettivamente che le saltiamo (notando che il percorso sotto può iniziare da qualsiasi carattere lungo la riga superiore). Alla fine, finiamo con un percorso che ha una sola fila senza ostacoli, per il quale esiste un solo percorso possibile.


questa è praticamente la soluzione che stavo prendendo in considerazione. Sapevo che qualcuno l'avrebbe pubblicato prima che ne avessi la possibilità.
Quintopia,

6

CJam, 85 84 82 81 80 79 byte

qN/:Q,(Qz,(:R_T]2/e~e!{'#Qs@{\(\@>}%s-},{_}{(a\L{@+_@\-_{2$\f.=0fe=2&},}h;}w;],

Provalo online. Oppure esegui l'intera suite di test.

L'efficienza di questa soluzione è probabilmente piuttosto orribile, ma risolve ogni caso di test in pochi secondi.

Spiegazione

Dovrò aggiungere una suddivisione completa del codice in seguito, ma l'idea algoritmica è questa:

  • Lascia che larghezza e altezza della griglia siano We H, rispettivamente.
  • Generiamo tutti i possibili percorsi come permutazioni distinte di W-1copie 0e H-1copie di W-1(dove 0rappresenta un gradino orizzontale e W-1un gradino verticale). Percorriamo tutti questi percorsi prendendo ripetutamente il primo elemento della griglia e quindi saltando le stepcelle nell'ordine di lettura (dove si steptrova 0o W-1). Scartiamo tutti i percorsi che contengono a #.
  • Quindi rimuoviamo ripetutamente un gruppo di percorsi simili (che saranno tutti percorsi simili al primo dei percorsi rimanenti). Il controllo di percorsi simili diventa un po 'più semplice allentando leggermente la condizione per loro: invece di verificare se uno si xè spostato, controlliamo se i percorsi differiscono esattamente in due punti. In tal caso, questi due punti avranno uno spostamento verticale e orizzontale scambiati. Ciò fa spostare l'intero segmento tra quelle mosse in diagonale di una cella. Ma se entrambi questi percorsi sono validi, spostare qualsiasi parte del percorso di una cella in diagonale non può attraversare un ostacolo, quindi sono simili. Dobbiamo ancora trovare la chiusura transitiva, quindi continuiamo a farlo fino a quando non troviamo più percorsi simili prima di passare al gruppo successivo.
  • Infine, contiamo i gruppi che abbiamo trovato, che abbiamo lasciato in fondo alla pila.
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.