Ucieczka z labiryntu!

20

Jesteś uwięziony w tym labiryncie 5x5 - każdy pokój jest oznaczony od 1 do 25, a wyjście znajduje się w pokoju 1.

wprowadź opis zdjęcia tutaj

Otrzymujesz jako dane wejściowe pomieszczenie, w którym aktualnie się znajdujesz. Twoim zadaniem jest wygenerowanie najkrótszej sekwencji ruchów (północ, wschód, południe, zachód) potrzebnej do dotarcia do pokoju 1.

Ruchy mogą być generowane w dowolnym formacie (lista, łańcuch, tablica ...), o ile używasz znaków n,w,e,s.

Oto wszystkie przypadki testowe:

1 => empty string/list
2 => w
3 => ww
4 => swwnw
5 => wswwnw
6 => seenwnw
7 => nw
8 => wnw
9 => wwnw
10 => swwnwnw
11 => eenwnw
12 => enwnw
13 => nwnw
14 => wnwnw
15 => wwnwnw
16 => enenwnw
17 => nenwnw
18 => wnenwnw
19 => nwnwnw
20 => wnwnwnw
21 => nenenwnw
22 => enwnenwnw
23 => nwnenwnw
24 => wnwnenwnw
25 => nwnwnwnw

Najkrótsza odpowiedź w bajtach wygrywa!

Arnaud
źródło
3
Jak elastyczne jest etykietowanie / wprowadzanie do pomieszczenia? Czy możemy 0-indeks zamiast 1-indeks? Czy możemy potraktować numer pokoju jako znak (myśląc, jak w bazie 36)?
Chas Brown
2
@Therandomguy nie, musisz poradzić sobie z tym konkretnym labiryntem.
Arnaud
6
Ponieważ jest to możliwe, myślę, że wszystkie możliwe przypadki powinny zostać uwzględnione w przypadkach testowych.
Jonathan Frech
1
@UnrelatedString To pytanie wymaga 1 danych wejściowych i wyprowadza inną ścieżkę na podstawie danych wejściowych. Uważam, że to wymaganie nie pasuje do znacznika złożoności kolmogorowa .
tsh
2
Ktoś musi udzielić odpowiedzi w Labiryncie .
Draco18s

Odpowiedzi:

20

Python 2 , 64 bajty

def f(n):d=0x1211252b5375>>2*n-4&3;print"nwes"[d];f(n+d*3+d%2-5)

Wypróbuj online!

Funkcja drukująca jeden kierunek na linię, kończąca się błędem.

Stała 0x1211252b5375koduje w podstawie 4 kierunek, w dktórym podróżujemy z każdego numeru pokoju, jako liczbę od 0 do 3. Cyfra ekstrakcyjna >>2*n-4&3jest również zaprojektowana tak, aby dawała ujemny błąd przesunięcia podczas n=1kończenia kodu. Aktualizujemy numer pokoju nza pomocą przesunięcia obliczanego od kierunku das d*3+d%2-5, który odwzorowuje:

d   d*3+d%2-5
0  -> -5
1  -> -1
2  ->  1
3  ->  5 
xnor
źródło
1
Nie jestem pewien, czy jest to poprawne w obecnej postaci, funkcje muszą być wielokrotnego użytku i potrzebujesz pułapki błędów ( try/ except), aby móc kontynuować wykonywanie po wywołaniu tej funkcji.
Erik the Outgolfer
10

Python 2 , 95 93 bajtów

f=lambda n:n>1and Q[n]+f(n+[-5,5,1,-1]['nsew'.find(Q[n])])or''
Q='  wwswsnwwseenwwenwnwnenwn'

Wypróbuj online!

Mógłby się zgolić 3 2 bajty, jeśli dozwolone jest oznaczenie pokoju 0-indeksowane.

Chas Brown
źródło
89 bajtów
Arnauld
6

05AB1E , 30 29 bajtów

-1 bajt dzięki cudownej zbieżności z liczbami pierwszymi

[Ð#•θzƶ‰`Ó•4вsè<DˆØ·5-+}'‹™¯è

Wypróbuj online!

[                      }    # infinite loop:
 Ð                          #  triplicate the room number (initially, the input)
  #                         #  break if room number == 1
   •θzƶ‰`Ó•4в               #  compressed list 202232302231102210202010
             sè             #  use the room number to index into that list
               <            #  decrement
                Dˆ          #  add a copy to the global array
                  Ø         #  nth prime (-1 => 0, 0 => 2, 1 => 3, 2 => 5)
                   ·        #  double
                    5-      #  subtract 5
                      +     #  add that to the room number
'‹™                         # dictionary string "western"
   ¯                        # push the global array
    è                       # index (wraps around, so -1 => n, 0 => w, 1 => e, 2 => s)
Ponury
źródło
1
To wyświetla 1dane wejściowe1 zamiast pustego ciągu (łatwym rozwiązaniem byłoby dodanie wiodącego õ?). Poza tym fajna odpowiedź!
Kevin Cruijssen
1
@KevinCruijssen dziękuję za zwrócenie uwagi na ten błąd! Znalazłem poprawkę jednobajtową.
Grimmy
5

Rubin , 72 62 bajty

f=->n{n<2?'':' en  sw'[x=4*18139004[n]+6*4267088[n]-5]+f[n+x]}

Wypróbuj online!

W jaki sposób?

Sztuczka polega na tym, aby użyć 2 stałych, aby zbudować następny krok dla każdej komórki, a następnie rekurencyjnie rozwiązać problem.

Dwie stałe 18139004 i 4267088 są ciągami binarnymi, podającymi kierunek następnego ruchu, poprzez wyodrębnienie jednego bitu z obu dla każdej komórki, możemy uzyskać:

"n" = 4*0+6*0-5 = -5
"w" = 4*1+6*0-5 = -1
"e" = 4*0+6*1-5 = +1
"s" = 4*1+6*1-5 = +5

Łatwiej niż przesuwanie i maskowanie pojedynczej dużej liczby binarnej IMHO.

Kiedy otrzymujemy kierunek, wyodrębniamy odpowiednią literę z ciągu „en sw”:

  1   5
  |   |
" en  sw"
   |   |
  -5  -1

I postępuj rekurencyjnie na komórce [n + x]

GB
źródło
4

JavaScript (ES7),  62  58 bajtów

Odpowiedź portu Xnora .

f=n=>--n?"nwes"[d=79459389361621/4**n&3]+f(n+d*3+d%2-4):''

Wypróbuj online!

Arnauld
źródło
3

Perl 5 ( -n), 94 bajty

-5 bajtów dzięki Grimy

@A=map/./g,__wwswsnwwseenwwenwnwnenwn;%H=(n,-5,s=>5,e,1,w,-1);$_+=$H{$,=$A[$_]},say$,until$_<2

TIO

Nahuel Fouilleul
źródło
-8
Grimmy
-2
Grimmy
-5
Grimmy
1
Czy masz na myśli, że powinienem opublikować to jako osobną odpowiedź?
Grimmy
1
tak, ponieważ wydaje się, że wykonałeś większość pracy, ciekawe było, jak zawsze możemy zaoszczędzić miejsce
Nahuel Fouilleul
2

JavaScript, 80 73 71 bajtów

Zaadaptowano z rozwiązania Pytona Chasa, więc też +1mu się podoba .

f=n=>--n?(d=" wwswsnwwseenwwenwnwnenwn"[n])+f(n+~~{n:-4,s:6,e:2}[d]):``

Wypróbuj online!

1 bajt zapisany dzięki Arnauldowi .

Kudłaty
źródło
Dzięki, @Arnauld :) Sam też to zauważyłem.
Kudłaty
2

Węgiel drzewny , 43 40 bajtów

NθW⊖θ«≔I§”)“⊞x⟧∧⎚⁵2”ιι§nwesι≧⁺⁻⁺﹪ι²×³ι⁵θ

Wypróbuj online! Link jest do pełnej wersji kodu. Na podstawie odpowiedzi zarówno @ ChasBrown, jak i @ xnor. Wyjaśnienie:

Nθ

Wprowadź pokój.

W⊖θ«

Ustaw zmienną pętli ina jedną mniejszą niż numer pokoju i powtarzaj, gdy jest ona różna od zera.

«≔I§”)“⊞x⟧∧⎚⁵2”ιι

Wyodrębnij kierunek ze skompresowanego łańcucha 0113130113220112010102010. (Wiodący 0to tylko cyfra wypełniająca.)

§nwesι

Wydrukuj kierunek.

≧⁺⁻⁺﹪ι²×³ι⁵θ

Użyj wzoru @ xnor, aby obliczyć nowy numer pokoju.

Neil
źródło
2

Galaretka , 30 29 bajtów

“þ&ƊĿñ÷°e’b6Ḥ_5Ż⁸+ị¥ƬI‘ị“®ȯẹ»

Wypróbuj online!

Monadyczny link pobierający komórkę początkową i zwracający ciąg ze wskazówkami.

Uwielbiam fakt, że słownik Jelly ma słowo takie jak „Kennesaw” (miasto na północny zachód od Atlanty w stanie Georgia), użyte tutaj, ponieważ indeksuje się je za pomocą [5, 1, -5, -1] + 1 daje nesw!

Wyjaśnienie

“þ...e’                    | Base-250 integer 1962789844189344852  
       b6                  | Convert to base 6 (2, 2, 5, 2, 5, 0, 2, 2, 5, 3, 3, 0, 2, 2, 3, 0, 2, 0, 2, 0, 3, 0, 2, 0)
         Ḥ                 | Double
          _5               | Subtract 5
            Ż              | Prepend 0
             ⁸  ¥Ƭ         | Using this as the right argument and the original link argument as the left argument, loop the following as a dyad until there is no change, collecting up results
              +            | - Add the left argument to:
               ị           |   - The left argument indexed into the right argument
                  I        | Differences between consecutive numbers
                   ‘       | Increment by 1
                    ị“®ȯẹ» | Index into "Kennesaw"
Nick Kennedy
źródło
2

PHP , 110 bajtów

Rozwiązanie, które nie jest dobrą odpowiedzią Chasa Browna ani doskonałą odpowiedzią xnor . Wiem, że to dłużej, ale chciałem mieć inne rozwiązanie!

for($n=$argn;$n>1;$n=ord($s[$n*2+1])%30)echo($s='0000w<w sEw"s)n w%w&s-e*e+n&w+w,e/n*w/n,w1n.e5n0w5n2')[$n*2];

Wypróbuj online!

Utworzyłem ciąg mapujący, który ma 2 znaki dla każdej komórki na planszy. Pierwszym znakiem dla każdej komórki jest ruch (n / e / s / w) lub0 a kod ASCII drugiego znaku mod 30 zwróci kolejny numer komórki, który powinniśmy śledzić jego ruch w trybie rekurencyjnym, dopóki nie wyjdziemy z komórki ( cell < 2).

Na przykład dla wprowadzenia 8:

  • 2 znaki dla komórki 8to:w%
  • Oznacza wydruk wi kontynuuj ruchy dla komórki%
  • Kod ASCII %to 37, którego mod 30 będzie 7, więc następną komórką jest7 .
  • 2 znaki dla komórki 7to:n (ostatni znak to spacja, kod ASCII = 32)
  • Oznacza wydruk ni kontynuuj ruchy dla komórki 32 mod 30, która jest2 .
  • 2 znaki dla komórki 2to:w< (ostatni znak kod ASCII = 60)
  • Oznacza wydruk wi kontynuuj ruchy dla komórki 60 mod 30, która jest 0.
  • Jeśli liczba komórek jest mniejsza niż 2, pętla zatrzymuje się!
  • Końcowy wydrukowany wynik: wnw

PHP , 75 bajtów

Ta wersja jest napisana przez Grimy'ego , jest o 35 bajtów krótsza niż moja pierwotna odpowiedź, ponieważ on / ona jest mądrzejszy! Komentarz Grimy'ego: „4 * 25 <256, więc potrzebujesz tylko 1 bajtu na komórkę, a nie 2”

for($n=$argn;$n=ord("0\0~f;6o4R:s%ql&rup*@^tIDbx"[$n%25]);)echo news[$n%4];

Wypróbuj online!


PHP , 71 bajtów

Ten port odpowiedzi Arnaulda, który jest portem odpowiedzi xnora , ale jako pętla zamiast funkcji rekurencyjnej, ponieważ okazuje się, że w PHP jest krótszy.

for($n=$argn;--$n;$n+=$d*3+$d%2-4)echo nwes[$d=79459389361621/4**$n&3];

Wypróbuj online!

Noc 2
źródło
2
4 * 25 <256, więc potrzebujesz tylko 1 bajtu na komórkę, a nie 2: Wypróbuj online!
Grimmy
1
@Grimy, niesamowite, myślę, że musisz opublikować to jako osobną odpowiedź, jest wystarczająco inne.
Noc2
1
Nie zrobię tego, więc ty decydujesz, czy uwzględnić to w odpowiedzi, czy zostawić jako komentarz.
Grimmy
1
@Grimy, dodał twoją wersję ze swoim imieniem. W każdym razie dzięki.
Night2
2

C (brzęk) , 81 bajtów

v;f(p){p-1&&putchar(v="00wwswsnwwseenwwenwnwnenwn"[p])+f(p+=v%5?6-v%8:v%2?5:-5);}

Wypróbuj online!

Dzięki sugestii @ Tommylee2k -8! + połączenie rekurencyjne

C (brzęk) , 90 bajtów

v;f(p){for(char*l="00wwswsnwwseenwwenwnwnenwn";p-1;p+=v%5?6-v%8:v%2?5:-5)putchar(v=l[p]);}

Wypróbuj online!

Podobne do wszystkich nieskompresowanych rozwiązań.

AZTECCO
źródło
1
można skrócić:v;f(p){for(;p-1;p+=v%5?6-v%8:v%2?5:-5)putchar(v="00wwswsnwwseenwwenwnwnenwn"[p]);}
Tommylee2k
1

05AB1E , 45 43 bajtów

õ?[Ð#.•DUo¢ê`Ω÷‰₂¡)R€ûK•¦sè©?Ž₁9₂в6-'€Ã®kè+

Port odpowiedzi @ChasBrown w Python 2 .

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie:

õ?               # Output an empty string
                 # (to overwrite the implicit output if the input is 1)
[                # Start an infinite loop:
 Ð               #  Triplicate the top of the stack
                 #  (which is the (implicit) input in the first iteration)
  #              #  If it's exactly 1: stop the infinite loop
  .•DUo¢ê`Ω÷‰₂¡)R€ûK
                 #  Push compressed string "a  wwswsnwwseenwwenwnwnenwn"
   ¦             #  Remove the first character
    sè           #  Swap to get the number, and use it to index into the string
      ©          #  Store it in variable `®` (without popping)
       ?         #  Print it without trailing newline
  Ž₁9            #  Push compressed integer 22449
     ₂в          #  Convert to base-26 as list: [1,7,5,11]
       6-        #  Subtract 6 from each: [-5,1,-1,5]
         '€Ã    '#  Push dictionary string "news"
            ®k   #  Get the index in this string of character `®`
              è  #  And use that to index into the integer-list
               + #  And add it to the originally triplicated integer

Zobacz moją wskazówkę 05AB1E (wszystkie cztery sekcje), aby zrozumieć, dlaczego tak .•DUo¢ê`Ω÷‰₂¡)R€ûK•jest "a wwswsnwwseenwwenwnwnenwn"; Ž₁9jest 22449; Ž₁9₂вjest [1,7,5,11]; i '€Ãjest "news".

Kevin Cruijssen
źródło
1
Ten wygodny ciąg słownika musiał być dobrą wiadomością!
Neil
@Neil Zdecydowanie. :) Chociaż podobno ciąg słownika westernjest lepszy. ; p
Kevin Cruijssen
1

Bash , 120 bajtów

S=__wwswsnwwseenwwenwnwnenwn
N=n-5w-1s05e01
for((i=$1;$i>1;i+=$j)){ d=${S:$i:1};j=${N:`expr index $N $d`:2};printf $d; }

Wypróbuj online!

Przez chwilę bawiłem się, próbując spakować bit jako ciąg, ale dekodowanie wymagałoby więcej znaków niż zapisana liczba.

Jak to działa:

S=__wwswsnwwseenwwenwnwnenwn

Łańcuch $ S zawiera pojedynczy znak (n, w, s, e) dla każdego pokoju, wskazujący kierunek, w którym należy przejść, aby przesunąć jeden pokój w kierunku wyjścia, pomijając pokoje 0 i 1.

N=n-5w-1s05e01

Ciąg $ N ma deltę do dodawania / odejmowania od bieżącego numeru pokoju dla każdej zmiany kierunku (n: -5, w: -1, s: +5, e: +1)

for((i=$1;$i>1;i+=$j)){ d=${S:$i:1};j=${N:`expr index $N $d`:2};printf $d; }

Zacznij od $ i równego numerowi pokoju podanemu w wierszu poleceń (1 $). Przypisz znak o indeksie $ i w ciągu $ S do $ d. Odzyskaj wartość delty z $ N dla kierunku do następnego pokoju, przypisując ją do $ j.

Wydrukuj następny kierunek, aby wziąć $ d.

Dodaj / odejmij różnicę w $ j do / z $ i.

Pętlę aż do opuszczenia pokoju nr 2 (podczas gdy $ i> 1).

spuck
źródło
1

Kotlin , 112 bajtów

val d="  113130113220112010102010"
fun p(r:Int):String=if(r>1)"nwes"[d[r]-'0']+p("046:"[d[r]-'0']-'5'+r)
else ""

Wypróbuj online!

JohnWells
źródło