Przesuwaj strzałki wzdłuż konturu

28

Piaskownica

Biorąc pod uwagę zestaw zamkniętych nie nakładających się konturów 2d (oddzielonych co najmniej jedną spacją nawet na przekątnych) ze strzałkami zorientowanymi konsekwentnie w tym samym kierunku zgodnym z ruchem wskazówek zegara lub przeciwnie do ruchu wskazówek zegara (każdy kontur ma swój własny kierunek) i liczbą dodatnią n, przesuń strzałki nkroki wzdłuż konturów w odpowiednim kierunku. Strzałki są reprezentowane > v < ^odpowiednio przez kierunki w prawo, w dół, w lewo i w górę. Tam pozostałe znaki to -(poziomo), |(pionowo) i +(narożnik). Gdy strzała jest na rogu, zachowuje swój obecny kierunek i zmienia ją dopiero po wykonaniu skrętu.

Zawsze będzie jakikolwiek prosty odcinek (lub spacja) między dowolnymi dwoma narożnikami (jak +-+dla poziomego i podobnego dla pionowego) - innymi słowy, ostre Uzakręty są zabronione. Segmenty między narożnikami są pionowe lub poziome, a zagięcie w rogu zawsze wynosi 90 stopni.

Wkład:

  • dodatnia liczba całkowita n- liczba kroków
  • reprezentacja konturów ASCII - może to być ciąg wieloliniowy, lista ciągów, lista znaków i tak dalej.

Wydajność:

Te same kontury ze wszystkimi strzałkami przesunęły nkroki w ogólnym kierunku każdego konturu.

Przypadki testowe:

1.

Wkład:

n = 1

 +----->->            
 |       |            
 |       v---+        
 |           |        
 +---<-------+      

Wydajność:

 +------>+
 |       v
 |       +>--+
 |           |
 +--<--------+

2)

Wkład:

n = 2

 +-----+ +---+        
 |     | |   |        
 +-->--+ |   v  
         |   | 
 +--->---+   |        
 |           |         
 +------<<---+       

Wydajność:

 +-----+ +---+
 |     | |   |
 +---->+ |   |
         |   | 
 +----->-+   v
 |           |     
 +----<<-----+        

3)

Wkład:

n = 3

 +---+   +---+   +-------+      
 |   |   |   v   |       |      
 ^   |   |   |   +-<-+   |      
 |   |   ^   |       |   v      
 |   +---+   +-->----+   |      
 |                       |      
 |   +-------+   +---+   |      
 |   |       |   v   |   |      
 +---+       +---+   +---+      

Wydajność:

 +>--+   ^---+   +-------+
 |   |   |   |   ^       |
 |   |   |   |   +---+   |
 |   |   |   |       |   |
 |   +---+   v----->-+   |
 |                       |
 |   +-------+   +---+   v 
 |   |       |   |   |   |
 +---+       +-<-+   +---+  

4

Wkład:

n = 1

+--+ 
|  |
|  +---+
|      |     
+----+ |
     | |
     +-+ 

Wydajność:

+--+ 
|  |
|  +---+
|      |     
+----+ |
     | |
     +-+ 

5

Wkład

n = 4

^>>>>
^   v
^   v>>>>
^       v           
<<<<<<<<v

Wydajność:

^>>>>
^   v
^   v>>>>
^       v           
<<<<<<<<v

6.

Wkład:

n = 1

^->
^ v
<<v

Wydajność:

^>+
^ v
<<v

Napisz funkcję lub program rozwiązujący powyższe zadanie. Wygrywa najkrótszy kod w bajtach w każdym języku. Nie zniechęcaj się językami golfa. Wyjaśnienie algorytmu i kodu jest bardzo mile widziane.

Galen Iwanow
źródło
Czy dwa kontury mogą dotykać ich narożników po przekątnej, czy sam kontur może się tak dotykać?
xnor
4
„Biorąc pod uwagę zestaw zamkniętych nie nakładających się konturów 2d ... ze strzałkami zorientowanymi konsekwentnie w tym samym kierunku zgodnym z ruchem wskazówek zegara lub przeciwnie do ruchu wskazówek zegara” brzmi dla mnie, jakby każdy kontur był zorientowany w tym samym kierunku, podczas gdy z przypadków testowych wydaje się, że strzałki mają być spójne tylko w obrębie konturu.
xnor
3
@xnor Dziękujemy za komentarze! - Nie, kontury nie mogą się dotykać na przekątnej. - Każdy kontur ma swój własny directon. Zaktualizuję opis.
Galen Iwanow
2
Czy możliwe jest wprowadzanie bez odstępu między ścianami? Np .: Wypróbuj online! . Wiem, że powiedziałeś „oddzielone przynajmniej jedną spacją”, ale nie byłem pewien, czy dotyczy to tylko niezależnych pętli, czy też dotyczy pojedynczej pętli.
Jonah
1
@Jonah Nie, to niemożliwe:There will always be a straight segment (or a space) between any two corners (like +-+ for the horizontal and similar for the vertical) - in other words the sharp U turns are forbidden.
Galen Iwanow

Odpowiedzi:

14

JavaScript (ES6),  210 ... 182  180 bajtów

Przyjmuje dane jako (m)(n), gdzie jest listą znaków. Zwraca wynik w tym samym formacie.m

m=>g=n=>n?g(n-1,m=m.map((r,y)=>r.map((c,x)=>(i=0,h=$=>~$?(m[Y=y+($-2)%2]||0)[X=x+~-$%2]>h?"-|+"[n+=`;m[${Y}][${X}]=S[${$}]`,i?2:$&1]:h($^++i):c)((S="<^>v").indexOf(c)))),eval(n)):m

Wypróbuj online!

W jaki sposób?

Możesz użyć tego linku, aby zobaczyć sformatowaną wersję źródła.

Obwoluta

Funkcja rekurencyjna jest po prostu używana jako opakowanie, które wywołuje kod główny, aby przesunąć wszystkie strzałki o 1 krok i ciągle wywołuje się za pomocą aż .gn1n=0

Zaktualizuj metodę

Nie możemy bezpiecznie przenosić każdej strzałki pojedynczo, ponieważ groziłoby nam zastąpienie nie zaktualizowanych strzałek zaktualizowanymi. Zamiast tego najpierw usuwamy wszystkie strzałki i obliczamy ich nowe pozycje. Stosujemy nowe stanowiska po raz drugi.

Odbywa się to przez ponowne użycie jako ciągu do przechowywania aktualizacji pozycji jako kodu JS.n

Na przykład w pierwszym przypadku testowym jest ustawione na:n

"1;m[0][7]=S[2];m[1][8]=S[3];m[2][9]=S[2];m[4][3]=S[0]"

(Zauważ, że wiodąca liczba - która jest oryginalną wartością - jest nieszkodliwa).n

Nowe pozycje są stosowane po prostu przez zrobienie eval(n).

Kierunki

Każda strzałka jest konwertowana na kierunek (nazwany w kodzie), przy użyciu następującego kompasu:d$

10+23

Odpowiednie wartości i oblicza się w następujący sposób:dxdy

 d | dx = (d - 1) % 2 | dy = (d - 2) % 2
---+------------------+------------------
 0 |        -1        |         0
 1 |         0        |        -1
 2 |        +1        |         0
 3 |         0        |        +1

Narożniki

Jeśli następny znak w określonym kierunku to spacja lub jest poza zakresem, oznacza to, że znajdujemy się na rogu i musimy skręcić o 90 ° lub 270 °. Właśnie dlatego funkcja pomocnika testuje do 3 różnych kierunków: , nazwa i .hddxor1dxor3

Jeśli znajdujemy się na rogu, nadpisujemy komórkę +. W przeciwnym razie nadpisujemy go albo -albo |, w zależności od parzystości .d

Uwaga : Parametr nie jest nazwany tylko dlatego, że wygląda na Uber L33T, ale także dlatego, że pozwala nam porównać dany znak z (niejawnie przymuszony do łańcucha), aby wiedzieć, czy jest to spacja (poniżej ), znak konturu (powyżej ) lub inną strzałkę (również powyżej ).h$h"$""$""$"

Wersja animowana

Arnauld
źródło
Dziękuję za wyjaśnienie!
Galen Iwanow
8

K (ngn / k) , 183 161 157 bajtów

{A:"^>v<";D,:-D:(-1 0;!2);s:(#x;#*x);c:~^x;r:" -+|"c*+/'3'0,c,0;$[#p:+s\&~^t:A?,/x;;:r];q:q@'*'&'~^x ./:/:q:+p+/:D@4!(t^0N)+/:0 1 3;s#@[,/r;s/+q;:;A@D?q-p]}/

Wypróbuj online!

{ }/wywołany z int lewym arg n, spowoduje zastosowanie tej funkcji w { }n razy do prawego arg

A:"^>v<" strzały

D,:-D:(-1 0;!2) ,Y, forx dla 4 głównych kierunków

s:(#x;#*x) kształt wejścia: wysokość, szerokość

c:~^x kontury - macierz logiczna pokazująca, gdzie znajdują się spacje

r:" -+|"c*+/'3'0,c,0odtwórz matrycę znaków z konturem, ale bez strzałek, licząc self + górny + dolny dla każdej komórki ci zastępując 1-> -, 2-> +, 3->|

t:A?,/xrodzaje strzałek: 0 1 2 3 dla ^>v<, wszystkie pozostałe komórki są reprezentowane jako 0N(null)

p:+s\&~^t współrzędne strzałek

$[#p ;;:r] jeśli nie ma żadnych strzałek, wróć r

q:+p+/:D@4!(t^0N)+/:0 1 3 wszystkie 3 możliwe nowe pozycje dla każdej strzały - jeśli idzie naprzód, jeśli skręca w lewo i skręca w prawo

q:q@'*'&'~^x ./:/:q dla każdej strzałki wybierz pierwszą opcję, która wyląduje na kontrze

@[,/r;s/+q;:;A@D?q-p]spłaszcz ri umieść na niej strzały w ich nowych pozycjach i w nowych kierunkach

s# zmienić kształt do oryginalnego kształtu

ngn
źródło
2
Jesteś szybki! Mam nadzieję, że wyjaśnisz kod po zakończeniu gry w golfa.
Galen Iwanow
Dziękuję za wyjaśnienie!
Galen Iwanow
4

Węgiel drzewny , 105 bajtów

W¬ΦυΣκ⊞υS≔⊟υη≔⪫υ⸿θ≔⟦⟧υ≔>^<vζPθFθ¿№ζι«⊞υ⟦⌕ζιⅉⅈ⟧§+|-↨EKV›κ ²»ιFυ«J⊟ι⊟ι≔⊟ιιFIη«≔⊟Φ⁴∧﹪⁻⊖ι⊕λ⁴›§KV⁻⁵λ ιM✳⊗黧ζι

Wypróbuj online! Link jest do pełnej wersji kodu. Obejmuje 22 bajty używane w celu uniknięcia konieczności uciążliwego formatu wejściowego. Wyjaśnienie:

W¬ΦυΣκ⊞υS≔⊟υη≔⪫υ⸿θ≔⟦⟧υ

Dogodnie wprowadź kontury i liczbę kroków.

≔>^<vζ

Znaki kierunku są używane kilka razy, więc łańcuch jest tutaj buforowany. Indeks znaku kierunku w tym ciągu nazywany jest jego kierunkiem.

Pθ

Wydrukuj oryginalne kontury bez przesuwania kursora.

Fθ

Pętla nad postaciami w konturze.

¿№ζι«

Jeśli obecne znaki są znakami kierunku ...

⊞υ⟦⌕ζιⅉⅈ⟧

... następnie zapisz kierunek i pozycję na liście ...

§+|-↨EKV›κ ²

... i zamień znak na odpowiedni znak linii.

»ι

W przeciwnym razie wypisz postać i przejdź do następnej postaci.

Fυ«

Pętla nad zapisanymi pozycjami.

J⊟ι⊟ι

Przejdź do zapisanej pozycji.

≔⊟ιι

Wyodrębnij zapisany kierunek.

FIη«

Zapętlaj odpowiednią liczbę kroków.

≔⊟Φ⁴∧﹪⁻⊖ι⊕λ⁴›§KV⁻⁵λ ι

Znajdź kierunek następnego kroku, którym jest dowolny kierunek, który nie jest ani odwrotny, ani pusty.

M✳⊗ι

Zrób krok w tym kierunku. (Wskaźniki kierunku węgla dla Movepolecenia są dwa razy większe niż mój kierunek).

»§ζι

Wydrukuj odpowiedni znak kierunku.

Neil
źródło
Dziękuję za wyjaśnienie!
Galen Iwanow