La modalità pilota automatico


10

Un elicottero che inizia nell'angolo in alto a sinistra sta scendendo (in uno spazio 2D, ai fini di questa domanda) verso il suolo. Ha una modalità pilota automatico e una modalità manuale.

La modalità autopilota si comporta come segue:

  • Se lo spazio direttamente sotto è libero, scendi ad esso.
  • Altrimenti sposta un passo a sinistra o a destra, totalmente a caso. (Può spostare più passaggi in questo modo.)

E continua a ripetere questi due passaggi fino a quando non colpisce il terreno. La modalità manuale è più intelligente e troverà il percorso ottimale verso terra, anche se ciò richiede un movimento verso l'alto o qualche manovra abile.

Il tuo compito è determinare se

  1. L'autopilota passerà nello scenario indicato,
  2. Il pilota automatico potrebbe non funzionare nello scenario indicato,
  3. L'autopilota fallirà, ma passerà la modalità manuale, o
  4. Entrambe le modalità falliranno (non esiste un percorso valido verso terra).

Ingresso

  • Dato scenario come un array non vuoto 1d o 2d, usando due caratteri diversi per rappresentare spazi liberi e bloccati. Punteggiatura opzionale.
  • Opzionale: dimensioni dell'array

Produzione

Uno dei quattro caratteri predefiniti che indicano quale dei casi si è verificato.

Dati di esempio

Utilizzando 0 (vuoto) e 1 (bloccato) in ingresso, 1 2 3 4 in uscita (come numerato sopra)

0 0 0 0
0 1 0 0
0 0 0 1
1 1 0 0

Produzione: 1

0 0 1 0
1 0 0 1
0 0 0 0
0 1 1 0
0 0 0 1

Output: 2(L'elicottero incontrerà l'1 nella quarta fila ed è possibile che si intrappoli alla fine della riga 5, se in modalità autopilota)

0 0 0 1 0
0 1 1 0 0
0 1 0 0 0
0 0 0 1 0
1 1 1 1 0

Output: 3(questo richiede di spostarsi verso l'alto, quindi l'autopilota fallisce)

1 0 0
0 0 0

Produzione: 4

0 0 0 0 1
1 1 1 0 0
1 0 0 1 0
0 1 0 0 0
0 0 1 1 1

Produzione: 4


@ MartinBüttner Fatto. Come nota a margine, preferisci che le persone pubblicino nella sandbox o pubblicino direttamente e che i loro errori vengano corretti? La seconda opzione è più semplice, quindi a meno che non ci sia qualche incentivo a non farlo, non riesco a immaginare perché seguirò l'opzione 1.
ghosts_in_the_code il

7
Personalmente preferisco il sandbox, perché dà alle persone più tempo per pensare a potenziali errori, scappatoie o casi di test mancanti, prima che le persone inizino a lavorare sulla sfida. Se qualcuno pubblica una risposta anticipata a una sfida imperfetta, non puoi davvero risolvere la sfida senza invalidare le risposte esistenti.
Martin Ender,

Inoltre - gli input sono sempre caratteri o possono essere booleani / numeri interi / ecc? E output: può essere un numero intero o deve essere un carattere?
Non che Charles l'

Risposte:


1

Ruby, 259

Mi sono divertito molto con questo. Grazie! sfide della tendono ad essere un divertimento eccellente con sfide interessanti. Ciò presuppone che i "caratteri" nella domanda possano essere numeri interi.

Penso che i principali punti di miglioramento qui siano:

  1. La creazione di r
  2. L'abuso terribile ternario sulla terza linea può essere probabilmente trasformato in qualcosa di più orribile, ma terser qualcosa.
->a,h,w{f=->l,s=0,y=[0]{r=w-2<s%w ?w:1,1>s%w ?w:-1,w
v=(l ?r+[-w]:a[s+w]==0?[w]:r).map{|d|a[m=s+d]==0&&!y[m]?m:p}-q=[p]
a[s]>0?q:s/w>h-2?8:v[0]?v.map{|o|f[l,y[o]=o,y]}.flatten-q :r.any?{|i|a[s+i]<1}?p: !0}
g=f[p]
[8,g[0]&&g.all?,g.any?,f[8].any?,!p].index !p}

Ungolfed (leggermente obsoleto, ma molto vicino):

# a is a one-dimensional array of 0s and 1s, h is height, w is width
->a,h,w{
  # f recursively walks the array and returns true/false/nil for each path.
  #    True means we can reach ground.
  #    False means we are stuck in a local minimum and cannot escape
  #    Nil means we reached a local dead-end and need to backtrack.
  # l: {true=>"manual", false=>"autopilot"}
  # s: the position index
  # y: an array of booleans - true-ish means we've visited that square before
  #         (this is to prevent infinite loops, esp in manual mode)
  f=->l,s=0,y=[0]{
    # d: all the legal deltas from s (maximally, that's [1,-1,w,-w], aka [LRDU])
    # r: but the right and left get tricky on the edges, so let's pre-calculate those
    #    we'll default to "down" if "left" or "right" are illegal
    r=[w-2<s%w ?w:1,1>s%w ?w:-1]
    # if manual, [LRDU]; if auto, and you can go down, [D]. else, [LR] 
    d=l ?r+[w,-w]:a[s+w]==0?[w]:r
    # v: the legal deltas that you can go to from s (that is, unvisited and unblocked)
    v=d.map{|d|a[m=s+d]==0&&!y[m]?m:p}-[p]


    a[s]>0 ? [p]     # if we're currently blocked, return [nil] (this is only the case when a[0]==1)
      : s/w>h-2 ? !p # if we're at the bottom, return true
        : v[0] ?     # if we have a place to go....
        v.map{|o|f[l,y[o]=o,y]}.flatten-[p] # recurse with each step.
                                            # y[o]=o is a neat trick to make y[o] truthy and return o
          : r.any?{|i|a[s+i]==0} ? # otherwise, we have nowhere to go. If we could visit left/right, but have already been there
            p                      #    this is not a dead-end - return nil to remove this path
            : !!p                  # If we have a true dead-end (auto-mode with a local minimum), false
  }
  # g is the auto flight
  g=f[p]
  # finally, choose the first "true" out of:
  # 0: always 8.  Cuz why not 8?
  # 1: there is at least one auto path, and all are truthy
  # 2: any auto path is truthy
  # 3: any manual path is truthy
  # 4: true
  [8,g[0]&&g.all?,g.any?,f[!p].any?,!p].index !p
}
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.