Wprowadzenie
Masz nieszczęście utknąć w uciekającym samochodzie na torze przeszkód. Wszystkie funkcje samochodu nie reagują, z wyjątkiem uszkodzonego układu kierowniczego. Może jechać prosto lub skręcić w prawo. Czy samochód można prowadzić bezpiecznie?
Mechanika
Twój samochód zaczyna się w lewym górnym rogu mapy 8x8 i próbuje się bezpiecznie znaleźć w prawym dolnym rogu. Samochód ma orientację (początkowo w prawo), mierzoną co 90 stopni. Samochód może wykonać jedną z dwóch czynności:
- Jedź o jeden kwadrat do przodu lub
- Obróć o 90 stopni w prawo, a następnie jedź o jeden kwadrat do przodu
Zauważ, że samochód nie jest w stanie skręcić wystarczająco ostro, aby wykonać obrót o 180 stopni na jednym kwadracie.
Niektóre kwadraty są przeszkodami. Jeśli samochód wjedzie na plac przeszkody, ulega awarii. Zakłada się, że wszystko poza polem 8x8 jest przeszkodą, więc zjechanie z niego jest równoznaczne z awarią.
Kwadrat po prawej stronie jest kwadratem bezpiecznym, który pozwala samochodowi uciec z toru przeszkód. Zakłada się, że kwadrat początkowy i bezpieczny kwadrat nie są przeszkodami.
Zadanie
Musisz napisać program lub funkcję, która przyjmuje jako dane wejściowe tablicę 8x8 (matryca, lista list itp.), Reprezentującą tor przeszkód. Program zwraca lub wypisuje wartość logiczną lub coś podobnego prawdziwego. Jeśli możliwe jest, aby samochód dotarł do bezpiecznego kwadratu bez awarii (tzn. Jeśli mapa jest do rozwiązania), wynik jest True
, w przeciwnym razie, jest False
.
Punktacja
Standardowe zasady gry w golfa - zwycięzcą jest kod z najmniejszą liczbą bajtów.
Bonusy:
Jeśli w przypadku mapy możliwej do rozwiązania kod wyprowadza prawidłową serię danych wejściowych kierowcy, które prowadzą samochód do bezpiecznego kwadratu, odejmij 10 punktów procentowych od wyniku. Przykładowym formatem wyjściowym może być
SRSSR
(wskazujący Prosto, Prawo, Prosto, Prosto, Prawo). To wyjście zastąpiłoby standardoweTrue
wyjście.Jeśli w przypadku nierozwiązywalnej mapy wynik kodu rozróżnia sytuacje, w których awaria jest nieunikniona, i sytuacje, w których można pokonywać tor przeszkód na zawsze, odejmij 10 punktów procentowych od swojego wyniku. Przykładem może być
Crash
sytuacja, gdy zderzenie jest nieuniknione lubStuck
samochód utknął na drodze z przeszkodami na zawsze. Te dane wyjściowe zastąpiłyby standardoweFalse
dane wyjściowe dla nierozwiązywalnej mapy.
Przykład
Jeśli program otrzyma tablicę 8x8, taką jak ta:
[[0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0],
[1, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 1, 0],
[0, 1, 1, 0, 0, 0, 1, 0]]
Będzie to interpretowane jako mapa taka z czarnymi kwadratami wskazującymi przeszkody:
Możliwym rozwiązaniem może być:
Ponieważ istnieje rozwiązanie, program powinien zwrócić / wydrukować True
tę mapę. Pokazana sekwencja ruchów to SSSSRSRRRSRSSRRRSSRSSS
.
Crash
iStuck
. Są tutaj ze względu na ich długość. Wiersz 2 wypełniony, wszystko inne puste ->Crash
. Wiersz 7 wypełniony, wszystko inne puste ->Stuck
Odpowiedzi:
JavaScript (ES6) - 122
124148bajtów162172178187190193208Ogromne podziękowania dla Optimizer i DocMax za pomocne sugestie dotyczące ulepszenia tego kodu:
Zwraca
true
(prawda) dla rozwiązania ifalse
(fałsz) dla nierozwiązywalnego.Działa tylko w przeglądarce Firefox ze względu na funkcje JavaScript 1.7.
Tablica testowa
źródło
D=(x,y,d,t,a)=>!t[i=x+y*8+d*64]&&(t[i]=1,x+=d==0?1:d==2?-1:0,y+=d==1?1:d==3?-1:0,x==7&&y==7||!((x|y)&~7||a[y][x])&&G(x,y,d,t,a));G=(x,y,d,t,a)=>D(x,y,d,t,a)||D(x,y,d+1&3,t,a);F=a=>G(0,0,0,[],a)
.D=d=>!t[i=x+y*8+d/4]&&(t[i]=1,x+=d?d^2?0:-1:1,y+=d^1?d^3?0:-1:1,x==7&&y==7||!((x|y)&~7||b[y][x])&&G(x,y,d));G=(X,Y,d)=>D(d,x=X,y=Y)||D(d+1&3,x=X,y=Y);F=a=>G(0,0,0,b=a,t={})
- Testowane.[[0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]
. To powinno dać fałsz.x
iy
oba są globalne, nie można uruchomić dwóch przypadków testowych przed ponownym załadowaniem strony ...x+=d?d^2?0:-1:1
zx+=d&1?0:1-d
iy+=d^1?d^3?0:-1:1
zy+=d&1&&2-d
.Python 2 - 123
125 133 146 148 150 154 160True
na sukces,False
na porażkę.Musisz podać dane wejściowe takie jak
f(b=var_containing_board)
.Wersja Lambda - 154
Zwraca
0
(fałsz) porażkę,True
sukces.Dzięki Willowi i Brandonowi za sprawienie, że funkcja jest krótsza niż lambda. Również w celu dodania przewijania w poziomie: D
Dzięki xnor za doskonałą bit-bash i logikę!
Edytuj notatkę: Jestem dość pewny, że
b[y][x]
nigdy nie zostanie wykonane, gdy wyjdziesz poza zasięg. Ponieważ jesteśmy poza planszą, sprawdzenie historiis in c
będzieFalse
. Wtedy kontrola granicy(x|y)&8
będzie8
. Wówczas python nawet nie sprawdzi ostatniej wartości,==
ponieważ pierwsze dwa są już różne.źródło
x|y>7or
działa, alex|y<0or
nie ...0o
.C (GNU-C), 163 bajty * 0,9 = 146,7
# C (GNU-C), 186 bajtów * 0,9 = 167,4Moja nowa wersja używa liczby całkowitej ze znakiem, a nie bez znaku. Wcześniej bałam się podpisanej prawej zmiany, ale zdałem sobie sprawę, że ponieważ bitem znaku jest pole bramkowe, nie ma znaczenia, co stanie się potem.
Funkcja przyjmuje tablicę bitów (te reprezentują zablokowane kwadraty) w postaci 64-bitowej liczby całkowitej. Bity są ułożone od najmniej do najbardziej znaczących w taki sam sposób, jak czytałbyś książkę. Zwraca -1 za awarię, 0 za wieczną jazdę lub 1 za ucieczkę do prawego dolnego rogu.
Program testowy
Wynik
Konwerter tablic na hex w języku Python:
źródło
memset(&M,~1,8)
(15 znaków) naM=~(-1ULL/255)
(14 znaków).P(0x00fefefefefefefe);
= (Powinien być prosto strzelony w prawy górny róg, jeden obrót, prosto do rogu. To samo dlaP(0x00eeeeeeeeeeeeee);
(ślepy zaułek na 4. kolumnie). Nie sądzę, że musisza
początkowo przypisywać .0x7f7f7f7f7f7f7f00
. Konieczna jest również inicjalizacja,a
ponieważ później jest modyfikowana tylko przez ORing w dodatkowych bitach, więc nie mogę sobie pozwolić na początkowo ustawiony niechciany bit.Python, 187
213207 znaków, 10% bonusu za ścieżkę drukowania
Na wejściu testowym znajduje nieco inną ścieżkę:
SSSSRSRSRRSSRSSRRSRSSRSSSSS
Ogólne podejście polega na tym, aby najpierw przekształcić dane wejściowe w spacje is
o
. Spacje mają heks20
, więc wszystkie cztery dolne bity są nieustawione.o
ma heks6F
, więc wszystkie cztery niskie bity są ustawione.Ramka
o
s jest umieszczona wokół planszy, więc nie musimy się martwić złymi indeksami.Przechodząc przez planszę, używamy bitów na każdym kafelku, aby sprawdzić, czy wolno nam przejść, gdy przychodzimy z tej strony. W ten sposób unikamy nieskończonych pętli. Nie wystarczy mieć jedną wartość logiczną na płytkę, ponieważ kierunek wyjścia zależy od kierunku wejścia, więc płytki można odwiedzać dwukrotnie.
Następnie przeprowadzamy rekurencyjne wyszukiwanie bezpiecznej ścieżki.
źródło
9
zamiastw=len(b[0])+1
itd.?p==79
jep-79
. Mam błąd składniowy, robiąc to w obie strony bez spacji przedelse
. Myślę, że ta sztuczka działa tylko zif
.-~x
==,x+1
ale oba jednoargumentowe operatory mają wyższy priorytet niż mnożenie, dzielenie i moduł! Tak(d+1)%4
może być-~d%4
! To też działałoby,x-1
ale wystarczy użyć~-x
zamiast tego.JavaScript -
270 - 20% = 216262 - 20% = 210 bajtówPonieważ powinno być co najmniej jedno rozwiązanie, które zarabia oba bonusy (i nie prowadzi do absurdalnej głębokości stosu;) ...
Zminimalizowane:
Rozszerzony:
v
jest tablicą mieszającą z kluczami, które są potrójnymi stanami(x,y,d)
odpowiadającymi współrzędnej (x, y) i kierunkowi wprowadzaniad
. Do każdego klawisza przypisana jest wartość, czyli ciągS
(prosty) iR
(skręć w prawo) ruchów wymaganych do osiągnięcia stanu reprezentowanego przez klucz.Kod utrzymuje również stos potrójnych (w zmiennej
n
), które nie zostały jeszcze przetworzone. Stos początkowo zawiera tylko potrójny (0,0,0), odpowiadający stanowi, w którym samochód jest skierowany w prawo w komórce (0,0). W zewnętrznej pętlifor( S = ... )
procedura sprawdza, czy pozostały jakieś nieprzetworzone potrójne. Jeśli tak, to działa każdy nieprzetworzone potrójne przez wewnętrzną pętlęn.map( ...
.Wewnętrzna pętla robi pięć rzeczy:
K
(zablokowany), ponieważ znaleźliśmy co najmniej jedną pętlę, w której samochód może krążyć wiecznie bez awarii.v
) i stosu nieprzetworzonych potrójne (m
) dla następnego przejścia pętli zewnętrznejv
jego wartość jest ustawiana na wartość stanu początkowego (sekwencja ruchów) plusR
lubS
na podstawie bieżącego ruchux
iy
are7
, wartość stanu początkowego (sekwencja ruchów podjęta w celu osiągnięcia stanu początkowego) jest kopiowanaS
, ponieważ ta sekwencja ruchów jest rozwiązaniem problemuPo zakończeniu pętli wewnętrznej
n
(stos) zostaje zastąpiony przezm
(nowy stos).Po zakończeniu pętli zewnętrznej (nie osiągnięto żadnych nowych stanów) funkcja zwraca wynik. Jeśli komórka (7,7) została osiągnięta,
S
będzie zawierać sekwencję ruchów prowadzących do tej komórki, i jest ona generowana. Jeśli komórka nieS
zostanie osiągnięta, będzie pusty ciąg, a procedura przechodzi do wyjściaO
, które będzie zawierałoK
(zablokowane) wtedy i tylko wtedy, gdy zostanie znaleziona pętla, lubC
(awaria), jeśli samochód nieuchronnie ulegnie awarii.źródło
Python 339 - 10% = 305 bajtów
Użyłem rekursywnego wyszukiwania w pierwszej kolejności, które kończy się wcześnie po sukcesie za pośrednictwem
exit
. Również drukuj ścieżkę sukcesu w formie00001010101010101010101110100111001000
,0
na wprost,1
na prawo. Odpowiedź będzie dłuższa niż optymalna, ponieważ najpierw jest głębia. Jestem pewien, że niektóre optymalizacje algorytmu mogą znacznie zmniejszyć licznik bajtów.źródło
a
„sfor
pętli. Nie potrzebujesz również spacji wokół operatorów, np.(v+1) % 4
->(v+1)%4
. Można również dołączyć kilka wypowiedzi na jedną linię za pomocą;
, jeśli nie jestif
lubfor
itp na linii, npc(l+"0");c(l+"1")
. Niektóre inne golfs:x,y,v=0,0,2
,x|y>7 or x|y<0
,x==y==7
. Powodzenia :)