Un petit explorateur

34

Vous êtes un explorateur, cartographiant un monde inconnu. Votre bateau est transporté par le vent. Où ça va, qui sait?

Chaque jour, dans votre spyglass, vous voyez des caractéristiques au nord, au sud, à l'est et à l'ouest. Vous voyez toujours quatre caractéristiques de ce type, correspondant aux directions cardinales. Votre spyglass affiche les symboles ASCII suivants:

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

Les symboles sont dans l'ordre (nord, sud, est, ouest).

Ce sont les symboles: ~= mer, .= côte, ^= montagne, *= arbre, #= invalide (aucune observation, cela se produit chaque fois que vous voyez la lisière du monde ou que le paysage est obscurci par le brouillard). Votre spyglass voit exactement une unité dans chaque direction.

Chaque soir, vous regardez les étoiles pour voir votre chemin parcouru. En regardant les étoiles, on voit un symbole ascii comme celui-ci:

n, s, e,w

correspondant au nord, sud, est et ouest, respectivement. Vous déplacez toujours exactement une unité au nord, au sud, à l'est ou à l'ouest chaque nuit. Ainsi, en tant qu'explorateur, vous recevrez un flot infini de symboles:

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

Votre tâche consiste à produire une carte 2D du monde (où se ?trouvent des parties inconnues de la carte, le nord est en haut, l’est est à droite):

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

Par souci de simplicité, supposons que vous commenciez dans le coin inférieur gauche de la carte. Supposons que toutes les cartes sont 8x8.

Voici un exemple simple 3x3. Supposons que la carte ressemble à ceci:

~.~
~^~
~.~

Avec l'entrée suivante: ~#.#n~~^#s

Vous obtiendrez cette sortie:

~??
~^?
~.?

Autres exemples d'entrées et de sorties:

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

sortie

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

Contribution:

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

Sortie:

?~~~~~?? 
?....~?? 
?.**.~?? 
?~..~~?? 
?~~~~~?? 
?~~..~?? 
~~~.^.?? 
~~~~~~?? 
utilisateur52676
la source
7
Bienvenue dans Programming Puzzles & Code Golf! C'est un beau premier défi. Cependant, certaines choses ne sont pas claires pour moi: tous les symboles de la sortie doivent-ils être séparés par des espaces? Cela semble être le cas dans l'exemple de sortie, mais ce n'est explicitement indiqué nulle part. Aussi, à quoi servent les directions d'étoiles? Je pensais que peut-être ils contrôlaient où les symboles allaient sur la carte, mais suivre les exemples et commencer en bas à gauche ne semble pas être le cas. Pourriez-vous préciser ceci?
Alex A.
La sortie ne doit pas nécessairement être séparée de l'espace, c'est une erreur de ma part. Le "#" représente "pas d'observation". Ils se produisent chaque fois que vous vous trouvez sur les limites de la carte, mais peuvent également se produire de manière aléatoire.
user52676
4
Excellent. Comme Alex l'a dit, c'est un excellent premier défi. J'espère voir plus de vous dans le futur! :) (Pour info, le bac à sable est un endroit idéal pour obtenir des retours sur les défis à venir.)
El'endia Starman
1
Je soupçonne que le premier exemple (où l'entrée est ~#~#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 erroné et que la sortie devrait ???.
indiquer exactement
3
C'est un navire aérien magique ;)
user52676 Le

Réponses:

8

MATL , 68 59 58 octets

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

Essayez-le en ligne!

Explication

La carte est conservée dans le bas de la pile et progressivement remplie. La position actuelle de l'explorateur est stockée dans le presse-papier J.

La carte utilise les coordonnées de la matrice, donc (1,1) est en haut à gauche. De plus, l'indexation linéaire colonne-majeur est utilisée. Cela signifie que les éléments de la matrice 8 × 8 représentant la carte sont accessibles avec un seul index, comme suit:

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

Ainsi, par exemple, l'élément (3,2) de la matrice est l'élément d'indice linéaire 11. Les mouvements vers le nord, le sud, l'est et l'ouest correspondent respectivement à l'ajout de -1, 1, 8 ou -8 à l'indice linéaire. Le tableau [-1 1 8 -8] sert à coder deux choses différentes:

  • Les déplacements possibles de l'explorateur.
  • Les positions relatives des caractéristiques détectées avec la spyglass. Ces positions sont relatives à la position actuelle de l'explorateur.

La chaîne d'entrée est organisée en morceaux de 5 caractères. Étant donné que le premier caractère manque pour le premier caractère (celui qui indique un mouvement), une initiale sest arbitrairement incluse pour donner à tous les morceaux la même taille. Pour compenser cela, l'explorateur commence à la position 7 et non à la position 8, de sorte que le déplacement initial vers le sud (ajoute 1 à l'index linéaire) les laisse à la position 8.

Les morceaux de 5 caractères sont traités en boucle. Le premier caractère met à jour la position et les 4 autres, s'ils sont différents de #, sont écrits dans les entrées appropriées de la matrice qui représente la carte.

'?'          % 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
la source
C'est un truc intelligent! Je vais tester votre programme avec quelques cartes pour voir s'il fait ce que j'attendais.
user52676
3

C, 210 208 207 octets

Celui-ci utilise printf et scanf pour lire les entrées et un tableau linéarisé au lieu de x, y; donc je pense qu'il est suffisamment différent de millibyte .

Golfé:

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

Un peu-non-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
}

Représentation:

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

En outre, vous commencez à la position 8 car cela élimine un caractère de la boucle d’impression.

tucuxi
la source
2

Fortran, 263 251 247 235 234 216 octets

Version 1D (similaire à celle 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

Version 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

Pour activer la forme libre et le pré-traitement, le fichier a besoin de l'extension .F90, par exemple explorer.F90. L'entrée est lue à partir de STDIN:

echo "~#~#e~#~~e~#~~e.#~~e^#~~n.~..n~^~.n~.~~n.~~.n.~~*n~.~.n#.~~w#.~~w#.~~s~*..s..*.s*~.~s.~~~s" | ./a.out 
?~~~~~??
?....~??
?.**.~??
?~..~~??
?~~~~~??
??~..~??
~~~.^.??
~~~~~~??
Alexander Vogt
la source
Donc, Fortran a-t-il également une indexation linéaire?
Luis Mendo
@DonMuesli Non, pas vraiment. J'opère directement sur un tableau 1D. Pour imprimer le tableau de caractères, j'utilise le fait que le tableau est stocké de manière contiguë en mémoire.
Alexander Vogt
2

C, 265 226 224 octets

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

La carte est en 8x8, je ne l’avais pas remarqué auparavant. Et voici la solution de 265 octets qui fonctionne pour les cartes à dimensions 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);}
MlllIbyte
la source
Ne devrait pas a[8][8]être suffisant?
Alexander Vogt
@ Alexander Vogt - Oh, c'est vrai! Merci, cela réduit deux octets supplémentaires.
mIllIbyte
J'aime beaucoup la façon dont vous calculez les incréments / décréments vers x et y. En comparant notre code C, statique int a[8][8]vous obtenez une initialisation de carte gratuite, et l'utilisation de char m[64]me procure d'excellents rabais pour la sortie de carte. Compte vraiment proche, cependant
tucuxi
Si vous inversez eet wdans votre représentation de carte, vous pouvez alors utiliser for(x=8;x--;)putchar((i=a[x][y])?i:63)pour raser deux octets en sortie.
Tucuxi
N'est-ce c=getchar(),c+1pas équivalent getchar(),c++ou y a-t-il des ruses impliquées?
Jonathan Frech
2

Ruby, 169 147 octets

Programme complet. Prend la chaîne d'entrée à partir de STDIN (vous aurez probablement besoin de la canaliser à partir d'un fichier pour empêcher tout saut de fin de ligne de déranger) et envoie la carte résultante à STDOUT.

Coupé une tonne en mettant toutes les cordes en une, puis en les séparant plus tard.

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
Valeur d'encre
la source
1

Lua, 354 octets ( essayez-le en ligne )

Golfé:

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

Légèrement non-golfé:

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
Fuite, nonne
la source
Ne peut x=x+(("w e"):find(e)or 2)-2 endpas être x=x-2+(("w e"):find(e)or 2)end?
Jonathan Frech
1

Kotlin, 242 octets

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

Les nouvelles lignes peuvent être remplacées par des points-virgules si vous le souhaitez.

Essayez ici

Le numéro un
la source