Um pequeno explorador

34

Você é um explorador, mapeando um mundo desconhecido. Seu navio é levado pelo vento. Para onde vai, quem sabe?

Todos os dias, na luneta, você vê recursos ao norte, sul, leste e oeste. Você sempre vê quatro desses recursos, correspondentes às direções cardeais. Sua luneta relata símbolos ASCII como este:

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

Os símbolos estão na ordem (norte, sul, leste, oeste).

Estes são os símbolos: ~= mar, .= costa, ^= montanha, *= árvore, #= inválido (nenhuma observação, isso ocorre sempre que você vê a borda do mundo ou a paisagem é obscurecida pelo nevoeiro). Sua luneta vê exatamente uma unidade em todas as direções.

Todas as noites, você olha para as estrelas para ver até onde você viajou. Olhar para as estrelas relata um símbolo ascii como este:

n, s, e,w

correspondendo a norte, sul, leste e oeste, respectivamente. Você sempre move exatamente uma unidade para o norte, sul, leste ou oeste todas as noites. Então você, como explorador, receberá um fluxo interminável de símbolos:

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

Sua tarefa é produzir um mapa 2D do mundo (onde ?existem partes desconhecidas do mapa, o norte está no alto, o leste está no lado direito):

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

Por uma questão de simplicidade, vamos supor que você comece no canto inferior esquerdo do mapa. Suponha que todos os mapas sejam 8x8.

Aqui está um exemplo simples de 3x3. Suponha que o mapa fique assim:

~.~
~^~
~.~

Com a seguinte entrada: ~#.#n~~^#s

Você obterá esta saída:

~??
~^?
~.?

Mais exemplos de entradas e saídas:

entrada ~#~#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.#~~

saída

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

Entrada:

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

Saída:

?~~~~~?? 
?....~?? 
?.**.~?? 
?~..~~?? 
?~~~~~?? 
?~~..~?? 
~~~.^.?? 
~~~~~~?? 
user52676
fonte
7
Bem-vindo à programação de quebra-cabeças e código de golfe! Este é um bom primeiro desafio. Algumas coisas não estão claras para mim: todos os símbolos da saída devem ser separados por espaço? Esse parece ser o caso na saída de exemplo, mas não é explicitamente declarado em lugar algum. Além disso, a que propósito servem as direções das estrelas? Eu pensei que talvez eles controlassem aonde os símbolos vão no mapa, mas seguindo os exemplos e começando no canto inferior esquerdo, esse não parece ser o caso. Você pode elaborar sobre isso?
Alex A.
A saída não precisa ser separada por espaço, isso é um erro da minha parte. O "#" representa "sem observação". Eles ocorrem sempre que você está no limite do mapa, mas também podem ocorrer aleatoriamente.
user52676
4
Excelente. Como Alex disse, este é um ótimo primeiro desafio. Espero ver mais de você no futuro! :) (FYI, o Sandbox é um ótimo lugar para obter feedback sobre os desafios futuros.)
El'endia Starman
1
Eu suspeito que o primeiro exemplo (onde a entrada é ~#~#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) está errado, ea saída deve ter ??onde diz?.
Leaky Nun
3
É um navio aéreo mágico ;) #
31516

Respostas:

8

MATL , 68 59 58 bytes

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

Experimente online!

Explicação

O mapa é mantido na parte inferior da pilha e preenchido gradualmente. A posição atual do explorador é armazenada na área de transferência J.

O mapa usa coordenadas da matriz, então (1,1) fica no canto superior esquerdo. Além disso, é utilizada a indexação linear principal da coluna. Isso significa que os elementos da matriz 8 × 8 que representam o mapa são acessados ​​com um único índice da seguinte maneira:

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

Assim, por exemplo, o elemento (3,2) da matriz é o elemento com índice linear 11. O movimento em direção ao norte, sul, leste e oeste corresponde, respectivamente, à adição de -1, 1, 8 ou -8 ao índice linear. A matriz [-1 1 8 -8] serve para codificar duas coisas diferentes:

  • Os possíveis deslocamentos do explorador.
  • As posições relativas dos recursos detectados com a luneta. Essas posições são relativas à posição atual do explorador.

A sequência de entrada é organizada em pedaços de 5caracteres. Como o primeiro pedaço está ausente do primeiro caractere (aquele que indica movimento), uma inicial sé incluída arbitrariamente para tornar todos os pedaços do mesmo tamanho. Para compensar isso, o explorador começa na posição 7, e não 8; portanto, o deslocamento inicial para o sul (adicione 1 ao índice linear) os deixa na posição 8.

Os pedaços de 5 caracteres são processados ​​em um loop. O primeiro caractere atualiza a posição e os 4 restantes, se diferentes #, são gravados nas entradas adequadas da matriz que representa o mapa.

'?'          % 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
fonte
Esse é um truque inteligente! Vou testar seu programa em alguns mapas para ver se ele faz o que eu espero.
user52676
3

C, 210 208 207 bytes

Este usa printf e scanf para ler a entrada e uma matriz linearizada em vez de x, y; então eu sinto que é suficientemente diferente de milibyte .

Golfe:

 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);}

De certa forma não-destruído:

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
}

Representação:

  // 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'

Além disso, você começa na posição 8 porque isso raspa um caractere mais ou menos do loop de impressão.

tucuxi
fonte
2

Fortran, 263 251 247 235 234 216 bytes

Versão 1D (semelhante à de 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

Versão 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

Para ativar a forma livre e o pré-processamento, o arquivo precisa da extensão .F90, por exemplo explorer.F90. A entrada é lida em STDIN:

echo "~#~#e~#~~e~#~~e.#~~e^#~~n.~..n~^~.n~.~~n.~~.n.~~*n~.~.n#.~~w#.~~w#.~~s~*..s..*.s*~.~s.~~~s" | ./a.out 
?~~~~~??
?....~??
?.**.~??
?~..~~??
?~~~~~??
??~..~??
~~~.^.??
~~~~~~??
Alexander Vogt
fonte
O Fortran também possui indexação linear?
Luis Mendo
@DonMuesli Não, na verdade não. Estou operando diretamente em uma matriz 1D. Para imprimir a matriz de caracteres, estou usando o fato de que a matriz é armazenada contiguamente na memória.
Alexander Vogt
2

C, 265 226 224 bytes

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);}

O mapa é 8x8, eu não percebi isso antes. E aqui está a solução de 265 bytes que funciona para mapas com dimensões variáveis:

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);}
mIllIbyte
fonte
Não deveria a[8][8]ser suficiente?
Alexander Vogt
@Alexander Vogt - Ah, certo! Obrigado, isso reduz mais dois bytes.
mIllIbyte 31/03
Eu realmente gosto de como você calcula incrementos / decrementos para x e y. Comparando nosso código C, a estática int a[8][8]permite a inicialização gratuita do mapa e o uso de char m[64]oferece ótimos descontos para a saída do mapa. Contagens de muito perto, embora
tucuxi
Se você reverter ee wna sua representação de mapa, poderá for(x=8;x--;)putchar((i=a[x][y])?i:63)barbear dois bytes na saída.
Tucuxi
Não c=getchar(),c+1é equivalente getchar(),c++ou há algum truque envolvido?
Jonathan Frech
2

Ruby, 169 147 bytes

Programa completo. Pega a sequência de entrada de STDIN (você provavelmente precisará inseri-la em um arquivo para impedir que novas linhas finais atrapalhem as coisas) e envia o mapa resultante para STDOUT.

Aparou uma tonelada colocando todas as cordas em uma e depois dividindo-as mais tarde.

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}/

Ungolfed:

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
Value Ink
fonte
1

Lua, 354 bytes ( experimente online )

Golfe:

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

Ligeiramente não destruído:

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
Freira Furada
fonte
Não pode x=x+(("w e"):find(e)or 2)-2 endser x=x-2+(("w e"):find(e)or 2)end?
Jonathan Frech
1

Kotlin, 242 bytes

{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()}}

As novas linhas podem ser substituídas por ponto e vírgula, se desejado.

Experimente aqui

O número um
fonte