Jesteś myszką Wszyscy twoi przyjaciele myszy zostali schwytani, są nieprzytomni i uwięzieni w labiryncie, który ma tylko jedno wejście / wyjście. Zdarza się, że masz idealną mapę labiryntu, dzięki czemu możesz opracować rozwiązanie, które pozwoli Ci wskoczyć i zabrać je wszystkie w bezpieczne miejsce. Jednak labirynt jest strzeżony przez system bezpieczeństwa, który wywoła alarm, jeśli próg 1000
zostanie osiągnięty, co spowoduje, że zostaniesz schwytany i nie powiedzie się Twoja misja ratunkowa.
Na podstawie poprzednich badań labiryntu każdy kwadrat, na który wchodzisz (tj. Każdy ruch poziomy lub pionowy - myszy nie mogą się poruszać po przekątnej ) dodaje 1
do licznika systemu bezpieczeństwa. Jeśli jednak nosisz ciężar (blok dynamitu lub nieprzytomny przyjaciel myszy), dodaje się, 2
ponieważ wykrywa dodatkowy nacisk. Kwadrat wejścia / wyjścia nie ma tego systemu bezpieczeństwa, więc nie dodaje się do licznika.
Masz nieograniczoną podaż dynamitu, który doprowadziłeś do wejścia, więc możesz po prostu wysadzić wszystkie ściany, aby uwolnić przyjaciół. Musisz jednak zachować ostrożność, ponieważ każda eksplozja zwiększa 50
kontratak wywołany wstrząsającą presją. Dodatkowo możesz nosić tylko jedną rzecz na raz, jedną mysz lub jeden blok dynamitu. Ponieważ każdy blok dynamitu może zdetonować tylko jedno miejsce na ścianie, oznacza to, że jeśli jest wiele ścian w rzędzie, musisz zrobić pustą podróż z powrotem do wejścia, aby złapać więcej.
Przepracowany przykład
Załóżmy, że nasz labirynt wygląda następująco:
######
#M# E#
######
Użyję c
do licznika. Zaczynamy na E
N-Trance, przesuń jeden lewy kwadrat podczas przenoszenia dynamitu c=2
. Mamy detonować dynamit eksploduje ściany, c=52
. Przesuwamy się o dwa kwadraty w lewo, z pustymi rękami, aby się dostać c=54
, i teraz stoimy na polu myszy. E
Podnosimy naszego przyjaciela i przenosimy 3 kwadraty z powrotem do xitu, ale ostatni kwadrat się nie liczy, ponieważ nie ma żadnych czujników, więc są to tylko 2 kwadraty z czymś na plecach. Oznacza to, że kiedy dotrzemy do wyjścia ostatnią myszą c=58
, czyli mniej niż 1000
, i dlatego misja się powiedzie.
Wyzwanie
Biorąc pod uwagę labirynt wejściowy, wypowiedz, czy ty, mysz-bohater, możesz skutecznie uratować wszystkie uwięzione myszy w ramach ograniczeń opisanych powyżej, czy też misja kończy się niepowodzeniem.
Wkład
- Labirynt 2D w dowolnym akceptowalnym formacie (ciąg wielowierszowy, tablica ciągów itp.).
- Do tego wyzwania użyję
#
zarówno ścian wewnętrznych, jak i zewnętrznych,M
przyjaciół myszy iE
wejścia. - Wejście nigdy nie będzie bezpośrednio przylegać do ściany wewnętrznej (zawsze będzie co najmniej jedno miejsce do swobodnego poruszania się).
- Możesz zastąpić dowolne znaki ASCII do wydruku , o ile są spójne. Pozwala to na użycie dwóch różnych symboli dla ścian wewnętrznych i zewnętrznych, o ile zachowasz spójność (np. Jeśli
@
zamiast tego zdecydujesz się na wewnętrzne ściany i pozostawisz#
na zewnątrz, każda ściana wewnętrzna musi być@
i każda ściana zewnętrzna#
). - Labirynt zawsze będzie całkowicie otoczony ścianami, ale niekoniecznie będzie prostokątny. W razie potrzeby możesz założyć, że labirynt jest wypełniony spacjami, aby wprowadzić prostokątne dane (opcjonalnie).
- Labirynt może mieć sekcje, które są nieosiągalne bez dynamitu.
- Nie można dynamitować zewnętrznych ścian labiryntu.
Wydajność
Truthy / falsey wartość. Prawda dla „Tak, mysz może uratować każdą inną mysz” lub Falsey dla „Nie, system alarmowy zostanie wyzwolony”.
Zasady
- Dopuszczalny jest pełny program lub funkcja.
- Standardowe luki są zabronione.
- To jest golf golfowy, więc obowiązują wszystkie zwykłe zasady gry w golfa, a wygrywa najkrótszy kod (w bajtach).
Przykłady
Prawdziwe przykłady oddzielone pustymi liniami.
#####
#M E#
#####
######
#M# E#
######
########
#E # M#
# # #
# # #
# #
########
#############################
# ## # # #
# M ## M # # #
# ## # M # E #
#M ## # # #
#############################
###############
#MMMMMMMMMMMMM#
#MMMMMMMMMMMMM#
#MMMMMMMMMMMMM#
#MMMMMMMMMM MM#
#MMMMMMMMMMMME#
###############
Przykłady Falsey, oddzielone pustymi liniami
#############################
#M ## ## ## #
# M ## M ## ## #
# ## ## M ## E #
#M ## ## ## #
#############################
#############################
########
########
# # #
# M # M#
########
#####
# M #
#####
#####
#####
#####
###################
# # # ## ## # # #
#M#M#M## E ##M#M#M#
# # # ## ## # # #
###################
#######
######
#####
####
# M#
####
###############
#MMMMMMMMMMMMM#
#MMMMMMMMMMMMM#
#MMMMMMMMMMMMM#
#MMMMMMMMMMMMM#
#MMMMMMMMMMMME#
###############
źródło
Odpowiedzi:
Perl,
216215 bajtówObejmuje +2 za
-0p
Podaj dane na STDIN. Użyj
%
do ścian zewnętrznych, ścian#
wewnętrznych,0
pustych przestrzeni,8
myszy ir
pozycji wyjściowej. Całe deski muszą być wyściełane, aby tworzyły prostokąt. Możesz przekształcić i uruchomić przykłady w następujący sposób:dynamite.pl
:Wymień
\xhh
ucieczki dla żądanego wyniku.Program nie może realistycznie obsługiwać skomplikowanych przypadków. W szczególności nie może obsłużyć żadnego z przypadków awarii. Wynika to z faktu, że istnieje po prostu zbyt wiele różnych sposobów wysadzenia wewnętrznych ścian lub podnoszenia myszy, więc wyszukiwanie staje się zbyt szerokie i zużywa zbyt dużo pamięci, mimo że jest przynajmniej wystarczająco inteligentne, aby nigdy nie przetwarzać tego samego stanu wiele razy. Limit ciśnienia musi zostać obniżony do
100
mniej więcej w celu nieco znośnego czasu działania i zużycia pamięci.Wyjaśnienie
Używam wzorca bitowego znaku do reprezentowania stanu pola:
Na przykład bohater (
01000000
) niosący dynamit (00000001
) musi znajdować się w miejscu, do którego może chodzić (00010000
), a my chcemy, aby wszystkie wartości były drukowalne ASCII (00100000
). Biorąc bitowąor
maskę wszystkich tych bitmasek daje01110001
kod ASCIIq
. W sumie staje się to:Program uwzględni tylko bohatera poruszającego się w prawo (obrót wyjaśniony później zajmie się innymi kierunkami). Maski bitowe zostały starannie wybrane, tak aby bohater zawsze był reprezentowany przez literę, a miejsce, do którego może się przenieść, za pomocą cyfry (z wyjątkiem bohatera w domu niosącego ofiarę, ale znowu jest to celowe, aby jedynym ruchem bohatera było upuszczenie ofiara). Tak więc dopasowuje się bohater, który może iść naprzód
/\pL\d/
. Dopasowany podciąg musi zostać zmodyfikowany, aby bohater i to, co nosi, zostało usunięte z pierwszej postaci i dodane do drugiej, co można zrobić za pomocą bitówxor
o tej samej wartości dla obu postaci. Wartość xor składa się z bitu bohatera (01000000
), bitu dynamitu (00000001
) i bitu myszy przenoszenia (00000100
). Razemor
do01000101
który jest ASCIIE
. Zatem poruszenie bohatera staje się:Bohater może wysadzić ścianę, jeśli jest on stał tuż przed nim i przewozi dynamit (
q
,s
luby
). Bohater straci swój dynamit (xor
z00000001
), a ściana#
zmieni się w przejście0
(xor z00010011
), więcAby obsłużyć inne kierunki, cała deska jest obracana (obracana deska kończy się w
$o
):Oprócz poruszania się bohater ma także wiele innych możliwości do wyboru:
Odbywa się to przez
Plansza jest zakończona, jeśli bohater jest w domu
x
i nie ma nic ( ) i nie ma już ofiar do uratowania (nie2
). Można to dogodnie przetestować za pomocąPo rozwiązaniu planszy chcę zapamiętać ten stan i na końcu go wydrukować. W tym celu noszę flagę „jest rozwiązany”
$\
i drukuję ją na końcu programu bez drukowania$_
, więcStany, które mają być przetwarzane przy ciśnieniu 0 są utrzymywane
@0
, przy ciśnieniu 1@1
itd. Utrzymywane jest bieżące ciśnienie$%
. Korzystanie$n
lub coś podobnego byłoby krócej, ale kod nie działa, jeśli zmienna nie jest zainicjowana do czegoś, bo inaczej będzie zmienić autovivification$n
do reference.Looping ARRAY nad państw pod pewnym ciśnieniem odbywa się za pomocąfor
, a niemap
dlatego, za pomocąfor
możesz rozszerzyć tablicę, gdy jest ona jeszcze zapętlona i zbierze nowe elementy. Jest to potrzebne, ponieważ obroty i wybory pojedynczego pola bohatera następują za 0 i kończą się w tym samym układzie nacisku. Więc pętla dla danego ciśnienia jest wykonywana przezJest to powtarzane, aż ciśnienie osiągnie 1000 lub zostanie znalezione rozwiązanie:
Pozostało tylko dodać nowo odkryte stany do odpowiednich tablic ciśnienia. Zostanie to wykonane przez podprogram
f
. Chcemy dodać stan tylko wtedy, gdy jeszcze go nie widzieliśmy. Stany, które widziały wcześniej, są przechowywane w następujący%a
sposób:$n
reprezentuje nową presję na państwo. Wyprowadzę to ze stanu, który zmienne wyrażenia regularne nadal mają w wyniku akcji bohatera prowadzącej do tego wezwania:Prowadzi to do następującej formuły dla
$n
:Wszystkie podstawienia otrzymują
r
modyfikator, więc zwracają zmieniony stan i pozostawiają bieżący stan w$_
spokoju.f
jest wywoływany w tym zmienionym stanie, więc otrzymujesz kod podobny doPonieważ obliczenia
$n
wymagają zmiennych wyrażeń regularnych, muszą one zostać domyślnie wyłączone, w przypadku gdy podstawienia nic nie zmienią (ponieważ warunek ich uruchomienia nie jest spełniony). Nie wolno mi również odbierać żadnych zmiennych wyrażeń regularnych z poprzedniej pętli. Dlatego podstawienia są zawijane w{}
bloki, aby zapisać i przywrócić stan wyrażenia regularnego. Tak otrzymujesz takie stwierdzeniaW szczególności obrót jest tak zawinięty, że wywołuje
f
bez zmiennych wyrażeń regularnych i otrzymuje wkład ciśnienia równy 0.Jedyne, co pozostaje do zrobienia, to przygotować się do
@0
stanu początkowego na początkuJest to w głównej pętli, więc próbuje również dodać
$_
do późniejszych tablic ciśnienia, ale ponieważ stan początkowy już%a
nie będzie, nic się nie stanie.Razem wszystko to w zasadzie znajduje najkrótsze rozwiązanie przy użyciu algorytmu Dijkstry . Istnieje jednak potencjalny problem. Bieżący kod nie doda stanu, jeśli zostanie ponownie odkryty z mniejszą presją niż pierwsze odkrycie. Nie byłem w stanie zbudować planszy, która by to wywołała, ale nie byłem również w stanie udowodnić, że jest to niemożliwe.
źródło
JavaScript,
863834785781 bajtówZaoszczędź 29 bajtów dzięki ETHproductions
Zaoszczędź 53 bajty dzięki Jordanowi
Pobiera dane wejściowe jako ciąg multilinii.
Definiuje to anonimową funkcję, która korzysta z funkcji rekurencyjnej w
f
celu ustalenia, czy wyłączysz alarm przed pobraniem wszystkich myszy.f
zwraca,1000
jeśli ciśnienie jest wyższe niż 1000 (aby uniknąć niekończącej się rekurencji), zwraca ciśnienie, jeśli nie ma już myszy do uratowania i myszy na wyjściu, i zwraca minimalne ciśnienie wszystkich możliwych ruchów z bieżącego stanu w przeciwnym razie. Używa tablicyL
do śledzenia odwiedzonych pozycji,L[pos]==0
jeśli są odwiedzane, i niezdefiniowanych, jeśli nie są. Może to nie być konieczne, ale uniemożliwia myszy wykonywanie bezużytecznych ruchów i co najmniej generowanie błędów rekurencji. (Oznacza to, że powinieneś przedefiniować,L
jeśli testujesz to wiele razy)Używa formatu z pytania innego niż to, że wymaga użycia innego znaku dla ścian zewnętrznych. (Wszystko inne niż
# MEmecd
)Bardziej czytelna wersja:
źródło
s in L|p > 999
.eval
i zastępując@
go$1
(nie jestem pewien, czy to zadziała, ale$1
dużo piszesz )f
f=(...)=>s in L|p>999?1e3:!/M/.test(s,L[s]=0)&/E/.test(s)?p:Math.min(...
$1
18 razy i.replace("@","$1")
ma 18 bajtów. Nie widzę sposobu, żeby to ściągnąć.