Le mode pilote automatique

10

Un hélicoptère partant du coin supérieur gauche descend (dans un espace 2D, aux fins de cette question) vers le sol. Il a un mode pilote automatique et un mode manuel.

Le mode pilote automatique se comporte comme suit:

  • Si l'espace juste en dessous est libre, descendez-y.
  • Sinon, déplacez un pas vers la gauche ou la droite, totalement au hasard. (Il peut déplacer plusieurs étapes de cette manière.)

Et il continue de répéter ces deux étapes jusqu'à ce qu'il touche le sol. Le mode manuel est plus intelligent et trouvera le chemin optimal vers le sol, même si cela nécessite un déplacement vers le haut ou une manœuvre habile.

Votre travail consiste à déterminer si

  1. Le pilote automatique passera dans le scénario donné,
  2. Le pilote automatique peut échouer dans le scénario donné,
  3. Le pilote automatique échouera, mais le mode manuel passera, ou
  4. Les deux modes échoueront (il n'y a pas de chemin valide vers le sol).

Contribution

  • Scénario donné sous la forme d'un tableau non vide 1d ou 2d, utilisant deux caractères différents pour représenter les espaces libres et bloqués. Ponctuation facultative.
  • Facultatif: dimensions du tableau

Production

L'un des quatre caractères prédéfinis indiquant lequel des cas s'est produit.

Exemples de données

Utilisation de 0 (vide) et 1 (bloqué) en entrée, 1 2 3 4 en sortie (comme numéroté ci-dessus)

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

Production: 1

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

Sortie: 2(l'hélicoptère rencontrera le 1 dans la quatrième rangée, et il est possible qu'il se piège à la fin de la rangée 5, s'il est en mode pilote automatique)

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

Sortie: 3(Cela nécessite un déplacement vers le haut, donc le pilote automatique échoue)

1 0 0
0 0 0

Production: 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

Production: 4

ghosts_in_the_code
la source
@ MartinBüttner Fait. En guise de remarque, préférez-vous que les gens publient dans le bac à sable, ou qu'ils publient directement et que leurs erreurs soient corrigées? La deuxième option est plus simple, donc à moins qu'il y ait une incitation à ne pas le faire, je ne peux pas imaginer pourquoi je suivrais la première option.
ghosts_in_the_code
7
Personnellement, je préfère le bac à sable, car il donne aux gens plus de temps pour réfléchir aux erreurs potentielles, aux lacunes ou aux cas de test manquants, avant que les gens commencent à travailler sur le défi. Si quelqu'un publie une réponse précoce à un défi imparfait, vous ne pouvez pas vraiment résoudre le défi sans invalider les réponses existantes.
Martin Ender
Aussi - les entrées sont-elles toujours des caractères, ou peuvent-elles être booléennes / entières / etc? Et la sortie - cela peut-il être un entier, ou faut-il être un caractère?
Pas que Charles

Réponses:

1

Rubis, 259

Je me suis beaucoup amusé avec ça. Je vous remercie! défis de la ont tendance à être très amusants avec des défis intéressants. Cela suppose que les "caractères" dans la question peuvent être des entiers.

Je pense que les principaux points d'amélioration ici sont:

  1. La création de r
  2. L'abrutissement ternaire horrible sur la troisième ligne peut probablement être transformé en quelque chose de plus horrible, mais de basculement.
->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}

Non golfé (légèrement obsolète, mais très proche):

# 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
}
Pas que Charles
la source