Tryb autopilota

10

Helikopter startujący w lewym górnym rogu schodzi (w przestrzeni 2D, do celów tego pytania) w kierunku ziemi. Ma tryb autopilota i tryb ręczny.

Tryb autopilota działa w następujący sposób:

  • Jeśli przestrzeń bezpośrednio poniżej jest wolna, zejdź do niej.
  • W przeciwnym razie przesuń krok w lewo lub w prawo, całkowicie losowo. (Może przesuwać wiele kroków w ten sposób.)

Powtarzają te dwa kroki, dopóki nie uderzą o ziemię. Tryb ręczny jest bardziej inteligentny i znajdzie optymalną ścieżkę na ziemię, nawet jeśli wymaga to przesunięcia w górę lub zręcznego manewru.

Twoim zadaniem jest ustalenie, czy

  1. Autopilot przejdzie w danym scenariuszu,
  2. Autopilot może zawieść w danym scenariuszu,
  3. Autopilot zawiedzie, ale tryb ręczny przejdzie, lub
  4. Oba tryby zawiodą (nie ma prawidłowej ścieżki do ziemi).

Wejście

  • Podany scenariusz jako niepusta tablica 1d lub 2d, wykorzystująca dwa różne znaki do przedstawienia wolnych i zablokowanych spacji. Interpunkcja opcjonalna.
  • Opcjonalnie: wymiary tablicy

Wynik

Jeden z czterech predefiniowanych znaków wskazujących, który przypadek wystąpił.

Przykładowe dane

Przy użyciu 0 (pusty) i 1 (zablokowany) na wejściu, 1 2 3 4 na wyjściu (jak wyżej)

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

Wynik: 1

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

Wyjście: 2(helikopter napotka 1 w czwartym rzędzie i możliwe jest, że złapie się pułapki na końcu rzędu 5, jeśli jest w trybie 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

Wyjście: 3(Wymaga przesunięcia w górę, więc autopilot zawiedzie)

1 0 0
0 0 0

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

Wynik: 4

ghosts_in_the_code
źródło
@ MartinBüttner Gotowe. Na marginesie, czy wolisz, aby ludzie publikowali w piaskownicy, czy bezpośrednio, a ich błędy zostały naprawione? Druga opcja jest prostsza, więc jeśli nie ma takiej zachęty, nie wyobrażam sobie, dlaczego wybrałbym opcję pierwszą.
ghosts_in_the_code
7
Ja osobiście wolę piaskownicę, ponieważ daje ludziom więcej czasu na zastanowienie się nad potencjalnymi błędami, lukami lub brakującymi przypadkami testowymi, zanim ludzie zaczną pracować nad wyzwaniem. Jeśli ktoś opublikuje wczesną odpowiedź na błędne wyzwanie, nie można go naprawdę naprawić bez unieważnienia istniejących odpowiedzi.
Martin Ender
Ponadto - czy dane wejściowe są zawsze znakami, czy mogą to być wartości logiczne / liczby całkowite / itd.? I wynik - czy może być liczbą całkowitą, czy też musi być znakiem?
Nie, że Charles

Odpowiedzi:

1

Ruby, 259

Świetnie się z tym bawiłem. Dziękuję Ci! Wyzwania zazwyczaj świetna zabawa z interesującymi wyzwaniami. Zakłada się, że „znaki” w pytaniu mogą być liczbami całkowitymi.

Myślę, że głównymi punktami poprawy są tutaj:

  1. Stworzenie r
  2. Upiorne potworne znęcanie się nad trzecią linią można prawdopodobnie przekształcić w coś bardziej upiornego, ale bardziej zwięzłego.
->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}

Niegolfowany (nieco nieaktualny, ale naprawdę blisko):

# 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
}
Nie ten Charles
źródło