Un pequeño explorador


34

Eres un explorador, mapeando un mundo desconocido. Tu barco es transportado por el viento. A dónde va, ¿quién sabe?

Cada día, en tu catalejo, ves características hacia el norte, sur, este y oeste. Siempre ve cuatro de estas características, correspondientes a las direcciones cardinales. Su catalejo informa símbolos ASCII como este:

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

Los símbolos están en el orden (norte, sur, este, oeste).

Estos son los símbolos: ~= mar, .= costa, ^= montaña, *= árbol, #= inválido (sin observación, esto ocurre cada vez que se ve el borde del mundo, o el paisaje está oscurecido por la niebla). Su catalejo ve exactamente una unidad en cada dirección.

Cada noche, miras las estrellas para ver qué tan lejos has viajado. Al mirar las estrellas se informa un símbolo ascii como este:

n, s, e,w

correspondiente a Norte, Sur, Este y Oeste, respectivamente. Siempre se mueve exactamente una unidad al norte, sur, este u oeste todas las noches. Entonces, como explorador, recibirás un flujo interminable de símbolos:

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

Su tarea es generar un mapa 2D del mundo (donde ?hay partes desconocidas del mapa, el norte está arriba, el este está a la derecha):

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

En aras de la simplicidad, supongamos que comienza en la esquina inferior izquierda del mapa. Suponga que todos los mapas son 8x8.

Aquí hay un ejemplo simple de 3x3. Suponga que el mapa se ve así:

~.~
~^~
~.~

Con la siguiente entrada: ~#.#n~~^#s

Obtendrá esta salida:

~??
~^?
~.?

Más entradas y salidas de ejemplo:

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

salida

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

Entrada:

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

Salida:

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

77
¡Bienvenido a Programming Puzzles & Code Golf! Este es un buen primer desafío. Sin embargo, un par de cosas no me quedan claras: ¿todos los símbolos en la salida deben estar separados por espacios? Ese parece ser el caso en el resultado del ejemplo, pero no se menciona explícitamente en ningún lado. Además, ¿para qué sirven las direcciones de las estrellas? Pensé que tal vez controlaban en qué parte del mapa iban los símbolos, pero siguiendo los ejemplos y comenzando en la parte inferior izquierda, ese no parece ser el caso. Puedes profundizar sobre eso?
Alex A.

La salida no tiene que estar separada por espacios, eso es un error de mi parte. El "#" representa "sin observación". Se producen cada vez que se encuentra en el límite del mapa, pero también pueden ocurrir al azar.
user52676

44
Excelente. Como Alex dijo, este es un gran primer desafío. ¡Espero ver más de ti en el futuro! :) (Para su información, el Sandbox es un gran lugar para recibir comentarios sobre los desafíos futuros.)
El'endia Starman

1
Sospecho que el primer ejemplo (donde está la 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) es incorrecto, y la salida debería tener ??donde dice?.
Leaky Nun

3
Es un barco aéreo mágico ;)
usuario52676

Respuestas:


8

MATL , 68 59 58 bytes

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

Pruébalo en línea!

Explicación

El mapa se mantiene en la parte inferior de la pila y se llena gradualmente. La posición actual del explorador se almacena en el portapapeles J.

El mapa usa coordenadas de matriz, por lo que (1,1) está en la esquina superior izquierda. Además, se utiliza la indexación lineal de columna mayor. Esto significa que se accede a los elementos de la matriz 8 × 8 que representan el mapa con un solo índice de la siguiente manera:

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

Entonces, por ejemplo, el elemento (3,2) de la matriz es el elemento con índice lineal 11. El movimiento hacia el Norte, Sur, Este y Oeste, respectivamente, corresponde a sumar -1, 1, 8 u -8 al índice lineal. La matriz [-1 1 8 -8] sirve para codificar dos cosas diferentes:

  • Los posibles desplazamientos del explorador.
  • Las posiciones relativas de las características detectadas con el catalejo. Estas posiciones son relativas a la posición actual del explorador.

La cadena de entrada se organiza en trozos de 5caracteres. Como al primer fragmento le falta el primer carácter (el que indica movimiento), sse incluye una inicial arbitrariamente para hacer que todos los fragmentos tengan el mismo tamaño. Para compensar esto, el explorador comienza en la posición 7, no en la 8, por lo que el desplazamiento inicial hacia el Sur (agregue 1 al índice lineal) los deja en la posición 8.

Los fragmentos de 5 caracteres se procesan en un bucle. El primer carácter actualiza la posición, y los 4 restantes, si son diferentes #, se escriben en las entradas adecuadas de la matriz que representa el 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

Ese es un truco inteligente! Probaré su programa contra algunos mapas para ver si hace lo que espero.
user52676

3

C, 210 208 207 bytes

Éste usa printf y scanf para leer la entrada, y una matriz linealizada en lugar de x, y; así que siento que es lo suficientemente diferente a la de milibyte .

Golfizado:

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

Algo sin golf:

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
}

Representación:

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

Además, comienza en la posición 8 porque esto afeita un char más o menos del ciclo de impresión.


2

Fortran, 263 251 247 235 234 216 bytes

Versión 1D (similar a la 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

Versión 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 habilitar la forma libre y el procesamiento previo, el archivo necesita la extensión .F90, por ejemplo explorer.F90. La entrada se lee desde STDIN:

echo "~#~#e~#~~e~#~~e.#~~e^#~~n.~..n~^~.n~.~~n.~~.n.~~*n~.~.n#.~~w#.~~w#.~~s~*..s..*.s*~.~s.~~~s" | ./a.out 
?~~~~~??
?....~??
?.**.~??
?~..~~??
?~~~~~??
??~..~??
~~~.^.??
~~~~~~??

Entonces, ¿Fortran también tiene indexación lineal?
Luis Mendo

@DonMuesli No, en realidad no. Estoy operando en una matriz 1D directamente. Para imprimir la matriz de caracteres, estoy usando el hecho de que la matriz se almacena contiguamente en la memoria.
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);}

El mapa es 8x8, no lo noté antes. Y aquí está la solución de 265 bytes que funciona para mapas con dimensiones variables:

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

¿No debería a[8][8]ser suficiente?
Alexander Vogt

@Alexander Vogt - ¡Oh, cierto! Gracias, eso reduce dos bytes más.
mIllIbyte

Realmente me gusta cómo calculas incrementos / decrementos a x e y. Comparando nuestro código C, static int a[8][8]le permite inicializar el mapa gratis, y el uso de char m[64]me da grandes descuentos para la salida del mapa. Sin embargo, cuentas muy cercanas
tucuxi el

Si invierte ey wen su representación de mapa, puede usar for(x=8;x--;)putchar((i=a[x][y])?i:63)para afeitar dos bytes en la salida.
tucuxi

¿ c=getchar(),c+1No es equivalente getchar(),c++o hay algún truco involucrado?
Jonathan Frech

2

Rubí, 169 147 bytes

Programa completo Toma la cadena de entrada de STDIN (es probable que necesite canalizarla desde un archivo para evitar que las nuevas líneas finales estropeen las cosas) y envía el mapa resultante a STDOUT.

Recortó una tonelada poniendo todas las cuerdas en una y luego dividiéndolas más 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}/

Sin golf:

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

1

Lua, 354 bytes ( pruébelo en línea )

Golfizado:

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

Ligeramente incólume:

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

No x=x+(("w e"):find(e)or 2)-2 endpuede ser 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()}}

Las líneas nuevas se pueden reemplazar con punto y coma si se desea.

Intenta aquí

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.