Mały odkrywca

34

Jesteś odkrywcą, który mapuje nieznany świat. Twój statek jest unoszony na wietrze. Gdzie to idzie, kto wie?

Każdego dnia w lunecie obserwujesz elementy na północy, południu, wschodzie i zachodzie. Zawsze widzisz cztery takie cechy, odpowiadające głównym kierunkom. Twój spyglass zgłasza następujące symbole ASCII:

~~.*, ~~~~, ~.^^,~#~#

Symbole są w kolejności (północ, południe, wschód, zachód).

Są to symbole: ~= morze, .= wybrzeże, ^= góra, *= drzewo, #= nieważne (brak obserwacji, dzieje się to za każdym razem, gdy zobaczysz skraj świata lub krajobraz jest zasłonięty mgłą). Twoja luneta widzi dokładnie jedną jednostkę we wszystkich kierunkach.

Każdej nocy spoglądasz na gwiazdy, aby zobaczyć, jak daleko podróżowałeś. Patrząc na gwiazdy zgłasza taki symbol ascii:

n, s, e,w

odpowiednio do północy, południa, wschodu i zachodu. Każdej nocy zawsze przenosisz dokładnie jedną jednostkę na północ, południe, wschód lub zachód. Więc jako odkrywca będziesz otrzymywać niekończący się strumień symboli:

~~.*n~~~~s~~.*s~.**

Twoim zadaniem jest wygenerowanie mapy 2D świata (gdzie ?są nieznane części mapy, północ jest w górze, wschód jest w prawo):

?~~~??????
?~~~??????
?~~~.^^.??
?~~.***.~~
~~.*^^*.~~
~~~..~~~~~
~~~~~~~~~~
~~~~~~~~~~

Dla uproszczenia załóżmy, że zaczynasz w lewym dolnym rogu mapy. Załóż, że wszystkie mapy mają wymiary 8 x 8.

Oto prosty przykład 3x3. Załóżmy, że mapa wygląda następująco:

~.~
~^~
~.~

Z następującymi danymi wejściowymi: ~#.#n~~^#s

Otrzymasz ten wynik:

~??
~^?
~.?

Więcej przykładowych danych wejściowych i wyjściowych:

wkład ~#~#n~~~#n~~~#n~~~#n~~~#n~~.#n~~.#n#~~#e#.~~e#.~~e#.~~e#.~~e#~~~e#~~~e#~#~s~~#~s~~#~s~~#~s~~#.s~~#~s~~#~s~##~w~#~~w.#~~w^#~~w.#~~

wydajność

~~~~~~~~ 
~....~~~ 
~.????~~ 
~~????~~ 
~~????.~ 
~~????~~ 
~~?.^.~~ 
~~~~~~~~

Wkład:

~#~#e~#~~e~#~~e.#~~e^#~~n.~..n~^~.n~.~~n.~~.n.~~*n~.~.n#.~~w#.~~w#.~~s~*..s..*.s*~.~s.~~~s

Wydajność:

?~~~~~?? 
?....~?? 
?.**.~?? 
?~..~~?? 
?~~~~~?? 
?~~..~?? 
~~~.^.?? 
~~~~~~?? 
użytkownik52676
źródło
7
Witamy w Programowaniu Puzzle i Code Golf! To miłe pierwsze wyzwanie. Kilka rzeczy jest dla mnie niejasnych: Czy wszystkie symbole na wyjściu muszą być oddzielone spacją? Wydaje się, że tak jest w przykładzie wyjściowym, ale nigdzie nie zostało to wyraźnie określone. Ponadto, do czego służą kierunki gwiazd? Myślałem, że może kontrolowali, gdzie na mapie idą symbole, ale naśladowanie przykładów i rozpoczynanie w lewym dolnym rogu nie wydaje się być prawdą. Czy możesz to rozwinąć?
Alex A.
Dane wyjściowe nie muszą być rozdzielane przestrzennie, to błąd z mojej strony. „#” Oznacza „brak obserwacji”. Występują one zawsze, gdy znajdujesz się na granicy mapy, ale mogą również występować losowo.
user52676,
4
Doskonały. Jak powiedział Alex, jest to świetne pierwsze wyzwanie. Mam nadzieję, że zobaczę więcej w przyszłości! :) (FYI, Sandbox to świetne miejsce, aby uzyskać informacje zwrotne na temat przyszłych wyzwań.)
El'endia Starman
1
Podejrzewam, że pierwszy przykład (gdzie jest wejście ~#~#n~~~#n~~~#n~~~#n~~~#n~~.#n~~.#n#~~#e#.~~e#.~~e#.~~e#.~~e#~~~e#~~~e#~#~s~~#~s~~#~s~~#~s~~#.s~~#~s~~#~s~##~w~#~~w.#~~w^#~~w) jest niepoprawny, a wyjście powinno mieć miejsce, w ??którym jest napisane?.
Leaky Nun
3
To magiczny statek powietrzny ;)
user52676,

Odpowiedzi:

8

MATL , 68 59 58 bajtów

'?'7XJQtX"'s'jh5e"@2#1)t35>)-1l8t_4$h9M)b'nsew'=8M*sJ+XJ+(

Wypróbuj online!

Wyjaśnienie

Mapa znajduje się na dole stosu i stopniowo się zapełnia. Aktualna pozycja eksploratora jest zapisana w schowku J.

Mapa wykorzystuje współrzędne macierzy, więc (1,1) znajduje się w lewym górnym rogu. Ponadto stosuje się indeksowanie liniowe głównych kolumn. Oznacza to, że do elementów macierzy 8 × 8 reprezentujących mapę można uzyskać dostęp za pomocą jednego indeksu w następujący sposób:

1  9 17 25 33 41 49 57
2 10 18 26 34 42 50 58
3 11 19 27 35 43 51 59
4 12 20 28 36 44 52 60
5 13 21 29 37 45 53 61
6 14 22 30 38 46 54 62
7 15 23 31 39 47 55 63
8 16 24 32 40 48 56 64

Na przykład element (3,2) macierzy jest elementem o indeksie liniowym 11. Ruch w kierunku odpowiednio na północ, południe, wschód i zachód odpowiada dodaniu -1, 1, 8 lub -8 do wskaźnika liniowego. Tablica [-1 1 8 -8] służy do kodowania dwóch różnych rzeczy:

  • Możliwe przemieszczenia odkrywcy.
  • Względne pozycje obiektów wykrytych za pomocą lunety. Pozycje te odnoszą się do aktualnej pozycji eksploratora.

Łańcuch wejściowy jest podzielony na części 5znaków. Ponieważ w pierwszym fragmencie brakuje pierwszego znaku (oznaczającego ruch), inicjał sjest arbitralnie dołączany, aby wszystkie fragmenty miały ten sam rozmiar. Aby to zrekompensować, badacz zaczyna od pozycji 7, a nie 8, więc początkowe przemieszczenie na południe (dodaj 1 do indeksu liniowego) pozostawia je na pozycji 8.

Części 5 znaków są przetwarzane w pętli. Pierwszy znak aktualizuje pozycję, a pozostałe 4, jeśli inne niż #, są zapisywane w odpowiednich wpisach macierzy reprezentującej mapę.

'?'          % push '?'. The map will initially be filled with this
7XJ          % push 7: initial position of the explorer. Copy into clipboard J
Qt           % add 1. Duplicate
X"           % 8x8 matrix containing '?'
'n'jh        % take input string. Prepend 'n'
5e           % reshape into a 5-column matrix
"            % for each column (chunk)
  @          %   push current chunk
  2#1)       %   split chunk into its first char and an array with the other 4
  t35>       %   duplicate. Logical index of chars different than #
  )          %   apply that index to keep characters different than #
  -1l8t_4$h  %   array [-1 1 8 -8]
  9M         %   push logical index again
  )          %   apply that index to keep only relevant relative positions
  b          %   bubble up in stack: move first char of chunk to top
  'nsew'=    %   logical index that tells if that char is 'n', 's', 'e' or 'w'
  8M         %   push array [-1 1 8 -8] again
  *          %   multiply element-wise. Only one of the four results will be nonzero
  s          %   sum of the array. Gives displacement of the explorer
  J+         %   push position of the explorer and add to compute new position
  XJ         %   update position in clipboard J
  +          %   add updated position of explorer to relative positions of features
  (          %   write those fearttures into the indexed entries of the map
             % end for each. Implicitly display
Luis Mendo
źródło
To sprytna sztuczka! Przetestuję twój program na kilku mapach, aby sprawdzić, czy działa zgodnie z oczekiwaniami.
user52676,
3

C, 210 208 207 bajtów

Ten używa printf i scanf do odczytu danych wejściowych oraz tablicy zlinearyzowanej zamiast x, y; więc uważam, że wystarczająco różni się od milibajtów .

Gra w golfa:

 main(p){char*i,*j,m[80];for(p=73,i=m+p;p--;m[p]=63);for(p=8;scanf("%5s",i)>0;p+=*j=='n'?8:*j=='s'?-8:*j=='e'?1:-1)for(j=i;j-i<4;j++)if(*j^35)m[p+"qajh"[j-i]-'i']=*j;for(p=72;m[p]=0,p-=8;)printf("%s\n",m+p);}

Nieco golfa:

main(p){
    char*i,*j,m[80];
    for(p=73,i=m+p;p--;m[p]=63);                   // fill with ?
    for(p=8;scanf("%5s",i)>0;
            p+=*j=='n'?8:*j=='s'?-8:*j=='e'?1:-1)  // read 5-at-a-time
        for(j=i;j-i<4;j++)
            if(*j^35)m[p+"qajh"[j-i]-'i']=*j;      // update map positions
    for(p=72;m[p]=0,p-=8;)printf("%s\n",m+p);      // output line-by-line
}

Reprezentacja:

  // board: (vertically reversed when printed)
    0  1  2  3  4  5  6  7
    8  9  10 ...
    16 18 19 ...
    ...
    56 57 58 59 60 61 62 63

  // offsets and offset order, or why "qajh": 
    s2      -8       a
  w4  e3  -1 0+1   h i j
    n1      +8       q   <- offset by +'i'

Zaczynasz także od pozycji 8, ponieważ powoduje to odcięcie znaku od pętli.

Tucuxi
źródło
2

Fortran, 263 251 247 235 234 216 bajtów

Wersja 1D (podobna do wersji Don Muesli):

#define R read(*,'(a)',advance='no',eor=1)c
#define F(x)R;if(c/='#')a(x+i)=c
program t
character::a(64)='?',c
integer::k(4)=[8,-8,1,-1],i=57
do
F(-8)
F(8)
F(1)
F(-1)
R
i=i+k(index('snew',c))
enddo
1 print'(8a)',a
end

Wersja 2D:

#define R read(*,'(a)',advance='no',eor=1)c
#define F(x,y)R;if(c/='#')a(x+m,y+l)=c
#define G(x,y)j=index(x,c);if(j==2)j=-1;y=y+j
program t
character::a(8,8)='?',c
l=8;m=1
do
F(,-1)
F(,1)
F(1,)
F(-1,)
R
G('sn',l)
G('ew',m)
enddo
1 print'(8a)',a
end

Aby włączyć dowolną formę i wstępne przetwarzanie, plik wymaga rozszerzenia .F90, np explorer.F90. Dane wejściowe są odczytywane ze STDIN:

echo "~#~#e~#~~e~#~~e.#~~e^#~~n.~..n~^~.n~.~~n.~~.n.~~*n~.~.n#.~~w#.~~w#.~~s~*..s..*.s*~.~s.~~~s" | ./a.out 
?~~~~~??
?....~??
?.**.~??
?~..~~??
?~~~~~??
??~..~??
~~~.^.??
~~~~~~??
Alexander Vogt
źródło
Czy Fortran ma również indeksowanie liniowe?
Luis Mendo
@DonMuesli Nie, nie bardzo. Pracuję bezpośrednio na macierzy 1D. Do drukowania tablicy znaków korzystam z faktu, że tablica jest przechowywana w pamięci w sposób ciągły.
Alexander Vogt
2

C, 265 226 224 bajtów

a[8][8];x;y;i;main(c){for(;c=getchar(),c+1;y+=(c=='n')-(c=='s'),x+=(c=='e')-(c=='w'))for(i=5;--i;c=getchar())i&&c-35&&(a[x+(i==2)-(i==1)][y-(i==3)+(i==4)]=c);for(y=8;y--;putchar(10))for(x=0;x<8;)putchar((i=a[x++][y])?i:63);}

Mapa jest 8x8, nie zauważyłem tego wcześniej. A oto rozwiązanie 265 bajtów, które działa dla map o zmiennych wymiarach:

a[99][99];c;x;X;y;i;k;p;main(Y){for(;c=getchar(),c+1;y+=(c=='n')-(c=='s'),x+=(c=='e')-(c=='w'))for(i=5;--i;c=getchar())i&&c-35&&(a[k=x+(i==2)-(i==1),X=X<k?k:X,k][p=y-(i==3)+(i==4),Y=Y<p?p:Y,p]=c);for(y=Y+1;y--;putchar(10))for(x=0;x<=X;)putchar((i=a[x++][y])?i:63);}
Mllllbyte
źródło
Nie powinno a[8][8]być wystarczające?
Alexander Vogt
@Alexander Vogt - Och, racja! Dziękuję, to zmniejsza dwa kolejne bajty.
mIllIbyte
Naprawdę podoba mi się sposób, w jaki obliczasz przyrosty / zmniejszenia x i y. Porównując nasz kod C, static int a[8][8]daje ci darmową inicjalizację mapy, a użycie char daje m[64]mi świetne zniżki na wydruk mapy. Jednak naprawdę blisko liczy się
tucuxi
Jeśli odwrócisz mapę ei ww jej odwzorowaniu, możesz użyć for(x=8;x--;)putchar((i=a[x][y])?i:63)do golenia dwóch bajtów na wyjściu.
tucuxi
Czy c=getchar(),c+1nie jest to równoważne z getchar(),c++pewnymi sztuczkami?
Jonathan Frech,
2

Rubin, 169 147 bajtów

Pełny program Pobiera ciąg wejściowy ze STDIN (prawdopodobnie trzeba go wpakować z pliku, aby uniemożliwić spływającym nowym wierszom bałagan) i wysyła wynikową mapę do STDOUT.

Przytnij tonę, łącząc wszystkie struny w jedną, a następnie dzieląc je później.

m=??*64
d=0
x=56
gets.each_char{|c|d<4?(w=x+(d>2?-1:d>1?1:d<1?-8:d<2?8:0)
m[w]=c if c>?$):x+=c>?v?-1:c<?f?1:c>?q?8:-8
d+=1;d%=5}
puts m.scan /.{8}/

Nie golfowany:

m = ?? * 64                 # 64 "?" symbols
                            # y axis counts downwards; 0-7 is top row
d = 0                       # Keep track of which direction we're looking
x = 56                      # Position, bottom left corner (0,7)
gets.each_char do |c|       # For each character from first line of STDIN
    if d < 4                # Looking in a direction
        if    d > 2         # d == 3; looking west
            w = x - 1
        elsif d > 1         # d == 2; looking east
            w = x + 1
        elsif d < 1         # d == 0; looking north
            w = x - 8
        else                # d == 1; looking south
            w = x + 8
        end
        m[w] = c if c > ?$  # Only '#' gets rejected by this step
    else                    # Moving in a direction
        if    c > ?v        # c == 'w'
            x -= 1
        elsif c < ?f        # c == 'e'
            x += 1
        elsif c > ?q        # c == 's'
            x += 8
        else                # c == 'n'
            x -= 8
        end
    end
    d = (d + 1) % 5         # Look in the next direction
end
puts m.scan /.{8}/          # Split map into rows of 8
Wartość tuszu
źródło
1

Lua, 354 bajtów ( wypróbuj online )

Gra w golfa:

n=(...)r={}y=8x=1q="?"for i=1,8 do r[i]={q,q,q,q,q,q,q,q}end for u in n:gsub("#",q):gmatch(".....")do a,b,c,d,e=u:match("(.)(.)(.)(.)(.)")if a~=q then r[y-1][x]=a end if b~=q then r[y+1][x]=b end if c~=q then r[y][x+1]=c end if d~=q then r[y][x-1]=d end y=y+(("n s"):find(e)or 2)-2x=x+(("w e"):find(e)or 2)-2 end for i=1,8 do print(table.concat(r[i]))end

Nieznacznie nie golfista:

n = "~#~#e~#~~e~#~~e.#~~e^#~~n.~..n~^~.n~.~~n.~~.n.~~*n~.~.n#.~~w#.~~w#.~~s~*..s..*.s*~.~s.~~~s"

r={} y=8 x=1 q="?"
for i=1,8 do r[i]={q,q,q,q,q,q,q,q} end
for u in n:gsub("#",q):gmatch(".....") do
  a,b,c,d,e=u:match("(.)(.)(.)(.)(.)")
  if a~=q then r[y-1][x]=a end
  if b~=q then r[y+1][x]=b end
  if c~=q then r[y][x+1]=c end
  if d~=q then r[y][x-1]=d end
  y=y+(("n s"):find(e)or 2)-2
  x=x+(("w e"):find(e)or 2)-2
end
for i=1,8 do print(table.concat(r[i])) end
Leaky Nun
źródło
Może x=x+(("w e"):find(e)or 2)-2 endnie być x=x-2+(("w e"):find(e)or 2)end?
Jonathan Frech,
1

Kotlin, 242 bajty

{val m=Array(8){Array(8){'?'}}
var d=7
var i=0
for(c in it)(mapOf('n' to{d--},'s' to{d++},'w' to{d-=8},'e' to{d+=8},'#' to{i++})[c]?:{m[d%8+listOf(-1,1,0,0)[i%4]][d/8+listOf(0,0,1,-1)[i%4]]=c
i++})()
m.forEach{for(c in it)print(c);println()}}

W razie potrzeby nowe znaki można zastąpić średnikami.

Spróbuj tutaj

Numer jeden
źródło