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


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


@ 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
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.