Режим автопилота

10

Вертолет, стартующий в верхнем левом углу, спускается (в двумерном пространстве для целей этого вопроса) к земле. Имеет режим автопилота и ручной режим.

Режим автопилота ведет себя следующим образом:

  • Если пространство прямо внизу свободно, спускайтесь к нему.
  • В противном случае переместите шаг влево или вправо, совершенно случайно. (Это может сделать несколько шагов таким образом.)

И он продолжает повторять эти два шага, пока не упадет на землю. Ручной режим более интеллектуален и найдет оптимальный путь к земле, даже если для этого потребуется движение вверх или какое-то умелое маневрирование.

Ваша задача - определить,

  1. Автопилот пройдет по заданному сценарию,
  2. Автопилот может дать сбой в данном сценарии,
  3. Автопилот не удастся, но ручной режим пройдет, или
  4. Оба режима потерпят неудачу (нет действительного пути к земле).

вход

  • Данный сценарий представляет собой непустой массив 1d или 2d, использующий два разных символа для представления свободных и заблокированных пространств. Пунктуация необязательна.
  • Необязательно: размеры массива

Вывод

Один из четырех предопределенных символов, указывающих, какой из случаев произошел.

Образец данных

Используя 0 (пусто) и 1 (заблокировано) на входе, 1 2 3 4 на выходе (как указано выше)

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

Вывод: 1

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

Вывод: 2(Вертолет встретит 1 в четвертом ряду, и, возможно, он окажется в конце 5-го ряда, если находится в режиме автопилота)

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

Вывод: 3(Это требует движения вверх, поэтому автопилот не работает)

1 0 0
0 0 0

Вывод: 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

Вывод: 4

ghosts_in_the_code
источник
@ MartinBüttner Готово. Как примечание: вы предпочитаете, чтобы люди публиковали в песочнице или непосредственно публиковали и исправляли свои ошибки? Второй вариант проще, поэтому, если нет какого-либо стимула не делать этого, я не могу себе представить, почему я бы выбрал первый вариант.
ghosts_in_the_code
7
Я лично предпочитаю «песочницу», потому что она дает людям больше времени, чтобы подумать о потенциальных ошибках, лазейках или пропущенных тестовых случаях, прежде чем люди начнут работать над проблемой. Если кто-то отправит ранний ответ на некорректный вызов, то вы не сможете действительно решить этот вопрос, не аннулировав существующие ответы.
Мартин Эндер
Кроме того - входные данные всегда являются символами, или они могут быть логическими / целыми числами / и т.д.? И вывод - это может быть целое число, или это должен быть символ?
Не то, что Чарльз

Ответы:

1

Рубин, 259

Мне было очень весело с этим. Спасибо! задач, как правило, очень весело с интересными задачами. Это предполагает, что «символы» в вопросе могут быть целыми числами.

Я думаю, что основные моменты улучшения здесь:

  1. Создание r
  2. Ужасное троичное злоупотребление в третьей строке, вероятно, может быть превращено в нечто более ужасное, но более резкое.
->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 (немного устаревший, но очень близко):

# 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
}
Не тот Чарльз
источник