Yarr! Une carte pour le trésor caché!

49

introduction

"Yarr !! Nous avons eu un garçon qui s’appelait" programmeur "pour faire une carte de notre trésor caché! Mais" c’est écrit avec des nombres étranges "n lettres!" E5, N2, E3 " Folie! Impossible même de tracer une carte au trésor appropriée, un crétin inutile. Fixez-la-nous! Nous vous offrirons une part du trésor! "

Description du défi

Un groupe de pirates a du mal à lire une carte au trésor. Pouvez-vous écrire un programme pour le convertir en une forme plus ... piratey?

En entrée, vous recevrez la carte au trésor originale. Il s'agit d'une liste de chaînes séparées par des virgules, chaque chaîne étant composée d'une partie lettre (indiquant aux pirates dans quelle direction emprunter la marche) et d'une partie numérique (indiquant aux pirates le nombre de pas à effectuer dans cette direction). Par exemple, la carte au trésor suivante:

E2,N4,E5,S2,W1,S3

signifierait, "faire deux pas vers l'est, quatre pas vers le nord, cinq pas vers l'est, deux pas vers le sud, un pas vers l'ouest, puis trois pas vers le sud".

En sortie, vous aurez sortie la carte sous une forme graphique, en utilisant les caractères >, ^, vet <comme pointeurs. Voici la sortie pour l'entrée ci-dessus:

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

Notez que nous avons remplacé la dernière étape au sud par un X. C'est parce que la dernière étape est où se trouve le trésor et, comme nous le savons tous, les pirates doivent avoir un X sur leurs cartes au trésor, sinon ils ne sauront pas le lire.

En passant, la carte ne se croisera jamais. Vous n'avez donc pas à vous soucier de la gestion des chevauchements. De plus, vous êtes autorisé à avoir une nouvelle ligne à la fin de la sortie.

Exemples d'entrées et de sorties

S5,W2

 v
 v
 v
 v
 v
X<

N1,E1,S1,E1,N1,E1,S2

>v>v
^>^X

N1

X

N6,E6,S6,W5,N5,E4,S4,W3,N3,E2,S2,W1,N2

>>>>>>v
^>>>>vv
^^>>vvv
^^^Xvvv
^^^^<vv
^^^<<<v
^^<<<<<

E21,S2

>>>>>>>>>>>>>>>>>>>>>v
                     X

N12,E11,S12,W2,N4

>>>>>>>>>>>v
^          v
^          v
^          v
^          v
^          v
^          v
^          v
^          v
^        X v
^        ^ v
^        ^ v
^        ^<<
Absinthe
la source
1
Sommes-nous autorisés à avoir des espaces de fin sur chaque ligne? Le nombre sera-t-il toujours inférieur à dix?
Downgoat
9
Je pense vraiment que le Xdevrait marquer le pas après le dernier coup, comme tous les autres coups sont comptés. Imaginez que la dernière étape est la N3: vous marchez trois fois vers le nord et creusez, mais il n’ya rien ici, vous devez marcher 2 étapes à la place. Cela ne me dérange pas si vous conservez la règle existante, car elle ajoute un petit coin à gérer. Mais rappelez-vous ce qui est arrivé à cette fille.
Coredump
6
@coredump Ou peut-être voulons-nous tromper les pirates afin de pouvoir prendre le trésor pour nous-mêmes;) Non, tu as raison, les pirates creusent un pas trop tôt. Etant donné qu'il y a déjà trois réponses, je vais garder la règle pour éviter d'invalider les solutions existantes.
absinthe
4
@ jpmc26 Eh bien, ces pirates ne connaissent pas beaucoup l'alphabet ... ils ont passé ces dernières années à C :)
absinthe
4
Le quatrième exemple est à la traîne que les pirates ...
de

Réponses:

8

Rubis, 213 209 198 186 178

M={};x=0,m=q=0
gets.scan(/.(\d+)/){?1.upto($1){m,y=x
x[d=$&.ord%10%7-2]+=1|($u=M[y]||={})[m]=d
m<q&&q=m}}
$u[m]=2
puts M.sort.map{|_,b|(q..b.max[0]).map{|k|">vX <^"[b[k]||3]}*""}

Passer la saisie via stdin.

Cela utilise un y -> x -> chardictionnaire pour construire la carte, où les deux xet ypeuvent être négatifs. Une fois l’entrée analysée, le minimum global de la coordonnée x est extrait. Pour chaque ligne, il effectue ensuite une itération sur une plage allant du minimum global à l'index maximum pour la ligne actuelle et imprime le caractère correct pour cet index.

Pour rester avec le thème, les expressions à tourner NESWdans les indices appropriés ont été sans vergogne piraté SP3000 de réponse .

Version originale utilisant un [x,y] -> chardictionnaire:

M={};x=0,0
gets.scan(/.(\d+)/){(?1..$1).map{x[d=$&.ord%10%7-2]+=1|M[$y=x+[]]=d}}
M[$y]=2
a,*q=M.minmax.flatten
M.map{|(x,y),v|($*[y-M.map{|a,|a[1]}.min]||=?\s.*q[2]-a)[x-a]=">vX<^"[v]}
puts$*.map &:rstrip
Ventero
la source
20

Python 2, 249 248 244 239 237 octets

D={}
m=X=Y=0
for s in input().split(","):d=ord(s[0])%10%7;exec"a,b=X,Y;E=D[Y]=D.get(Y,{});E[X]='<^>v'[d];m=min(m,X);%c+=d-2|1;"%(88+d%2)*int(s[1:])
D[b][a]="X"
for Y in sorted(D):print"".join(D[Y].get(n," ")for n in range(m,max(D[Y])+1))

Entrée comme "E2,N4,E5,S2,W1,S3".

NSEWest mappé sur [1, 3, 2, 0]par d=ord(c)%10%7. Que ce soit pour changer you xest ensuite décidé par d%2, et si incrémenter ou décrémenter est décidé par d-2|1. Les première et troisième expressions ont été trouvées par force brute.

Autre que cela, c'est une utilisation simple d'un dictionnaire imbriqué du formulaire {y: {x: char}}.

(Merci à @joriki pour l'aide avec la cartographie)

Sp3000
la source
1
(d + 1 & 2) - 1
Joriki
1
@joriki Ah c'est une belle expression - merci!
Sp3000
2
Voici le code que j'ai écrit (dans un contexte différent) pour trouver des expressions simples pour les fonctions entières. Je ne l'ai pas utilisé pour cela, mais j'ai pensé que cela pourrait vous intéresser. (Le code correspondant commence par "Il s'agit du code que j'ai utilisé pour optimiser l'encodage".)
joriki
3
@joriki Le forçage de brutes est une excellente idée - vient d'arriver 1|d%-3(ce qui est la négation, mais je viens de me rendre compte que ça va aussi)!
Sp3000
14

Javascript (ES6), 260

C'était intéressant ...

Merci @ETHproductions, @ edc65 et @vihan pour l'aide!

s=>{z=o=""
m=[]
q=x=y=2e3
s.split`,`.map(v=>z+=v[0].repeat(+v.slice(1)))
for(i=0;d=z[i];q=x<q?x:q)(m[y]=m[y]||[])[x]=z[++i]?d=="N"&&--y?"^":d=="S"&&++y?"v":d=="W"&&--x?"<":++x?">":o:"X"
m.map(a=>a.map((b,j)=>o+=" ".repeat(-p-1+(p=j))+b,p=q-1,o+=`
`))
return o}

Ceci définit une fonction anonyme, donc pour l'appeler, ajoutez f=au début pour lui donner un nom.

Tester: console.log(f("E2,N4,E5,S2,W1,S3"))

Explication:

s=>{ //define function w/ parameter s
z=o=""      //z=modified input, o=final output
m=[]        //map of characters
q=x=y=2e3   //q=minimum value of x; x+y=coordinates. These start high to leave room to go backwards
s.split`,`.map(v=>z+=v[0].repeat(+v.slice(1)))    //change "N3,E4" -> "NNNEEEE", and put in z
for(i=0;d=z[i];q=x<q?x:q)   //for each direction d in z, while updating q:
    (m[y]=m[y]||[])[x]=     //in the right place on the map, put:
        z[++i]?                 //if last character of z, "X"
            d=="N"&&--y?"^":    
            d=="S"&&++y?"v":    //otherwise get the right character and change x+y accordingly
            d=="W"&&--x?"<":
            ++x?">":o
        :"X"
m.map(a=>a.map((b,j)=>o+=" ".repeat(-p-1+(p=j))+b,p=q-1,o+=`
`)) //dump map to o, with correct padding
return o}   //return
jrich
la source
3
C'est un bon moyen de séparer les déclarations! C'est certainement beaucoup plus lisible que de tout mettre sur une ligne et de les séparer par des points-virgules. Si je peux offrir ma suggestion: vous pourriez économiser un octet en déplaçant votre i++de la forboucle vers le dernier endroit où il est utilisé, dans ce cas c=i++>r-2?"X":c.
ETHproductions
1
En outre, puisque vous utilisez ES6, je suggère d' utiliser v[0].repeat(+v.slice(1))à la place Array(v.slice(1)- -1).join(v[0]), et " ".repeat(j-p-1)à la place Array(j-p).join(" "), et de 11 octets d' ensemble. Je pense que vous pourriez également placer F='forEach'au début de la fonction, puis changer chacun .forEachd'eux en en [F]économisant 4 autres.
ETHproductions
1
Essayez d’utiliser .map au lieu de .forEach. C'est si court que vous ne devriez même pas le raccourcir à F
edc65
1
@UndefinedFunction vous voudrez peut-être utiliser des raccourcis pour le ifs, cela pourrait être utile si vous décrémentez des variables en même temps
Downgoat
1
Si ma compréhension est correcte, cela q=x=y=2e3signifie- t -il que la sortie serait incorrecte si je disais, par exemple W9999?
Sp3000
7

PHP, 431 417 octets

$g=explode(',',$argv[1]);$x=$y=$a=$b=$c=$d=$e=$f=0;
foreach($g as$i=>$h){list($k,$l,$m)=
    ['N'=>[-1,0,'^'],'E'=>[0,1,'>'],'S'=>[1,0,'v'],'W'=>[0,-1,'<']][$h[0]];
    for($s=substr($h,1);$s--;){$z[$f=$y][$e=$x]=$m;$y+=$k;$x+=$l;}
    if($i==count($g)-1){$x=$e;$y=$f;}
    $a=min($a,$x);$b=max($b,$x);$c=min($c,$y);$d=max($d,$y);
}$z[$y][$x]='X';for($y=$c;$y<=$d;$y++)
{$o='';for($x=$a;$x<=$b;$x++)$o.=$z[$y][$x]?:' ';echo rtrim($o)."\n";}

Placez-le dans un fichier ( treasure.php), supprimez l'indentation, joignez les lignes (il est enveloppé ici pour des raisons de lisibilité), placez le <?phpmarqueur au début du fichier (non affiché ici car techniquement, il ne fait pas partie du programme).

Exemple d'exécution:

$ php -d error_reporting=0 treasure.php E2,N4,E5,S2,W1,S3
  >>>>>v
  ^    v
  ^   v<
  ^   v
>>^   X
$

L'option -d error_reporting=0est nécessaire pour supprimer les avis concernant les valeurs non trouvées aux index spécifiés dans $z.

Mise à jour:

Pendant que je préparais la version non golfée du code pour publication, j'ai découvert qu'elle contenait deux assignations inutiles (12 octets) et un espace pouvant être supprimé ( as$i); aussi, en remplaçant un whilepar une forboucle et en y insérant une assignation (impossible avec la whileboucle), j’ai sauvegardé un autre octet.

axiaque
la source
J'aimerais voir une version non-golfée.
Lars Ebert
1
@LarsEbert J'ai mis à jour la réponse avec un lien vers le code non-golfé. J'ai vérifié votre solution maintenant (je ne l'avais pas fait avant); nous avons essentiellement utilisé le même algorithme. Le vôtre gère la dernière étape mieux que le mien. Je peux supprimer 25 octets supplémentaires si je les implémente $count --;.
axiac
$argnéconomiser 3 octets chopenregistrer 1 octet "X"-> Xutiliser les constantes enregistrer davantage d'octets
Jörg Hülsermann
@ JörgHülsermann Je ne comprends pas l' $argnallusion. Je suis au courant du "X"->Xtruc mais j’en ai probablement oublié lorsque j’ai écrit cette solution. J'écris du code PHP depuis 2002, mais jusqu'à aujourd'hui, je n'avais pas remarqué que PHP en fournissait la chop()fonction. Merci pour cet indice.
axiac
7

Perl, 702 613 546 474 439 338 260 octets

Merci à Dom Hastings pour son aide et sa version supergolfée.
Le code utilise un tableau 2D.

Version de Dom Hastings:

$x=$y=$a=$b=99;map{/^./;$a=($c=$x)<$a?$x:$a,$A=$x>$A?$x:$A,$b=($C=$y)<$b?$y:$b,$B=$y>$B?$y:$B,$q[$c][$C]={split'','W<E>N^Sv'}->{$&},$x+={W,-1,E,1}->{$&},$y+={N,-1,S,1}->{$&}for 1..$'}split',',pop;$q[$c][$C]=X;for$y($b..$B){print$q[$_][$y]||$"for$a..$A;print$/}

Ma version inférieure de golf de 338 octets (pour référence):

@m=split(',',pop);$x=$y=$a=$b=99;map{($d,$s)=/^(.)(.+)$/;for(1..$s){$c=$x;$C=$y;if($x<$a){$a=$x}if($x>$A){$A=$x}if($y<$b){$b=$y}if($y>$B){$B=$y}if($d eq"W"){$r="<";$x--}if($d eq"E"){$r=">";$x++}if($d eq"N"){$r="^";$y--}if($d eq"S"){$r=v;$y++}$q[$c][$C]=$r}}@m;$q[$c][$C]=X;for$y($b..$B){for$x($a..$A){$t=$q[$x][$y];print$t?$t:$"}print$/}

Tester

$ perl piratemap_golf.pl E4,N3,W6,S10,W1,S1,E5,N1,W2,N6,E6,N5,W10,S1,E2
v<<<<<<<<<<
>Xv<<<<<< ^
  v     ^ ^
  v     ^ ^
  v >>>>^ ^
  v >>>>>>^
  v ^
  v ^
  v ^
  v ^
  v ^
 v< ^<<
 >>>>>^
LukStorms
la source
3
Si vous n'utilisez pas use strict;, vous n'avez pas besoin de tous les mys, ce qui vous fera économiser au moins quelques octets. Aussi ==est plus courte que eqpuisque ce dernier nécessite des espaces.
Alex A.
1
Si je ne me trompe pas, vous n'appelez qu'une seule $mfois. Par conséquent, plutôt que de stocker l'argument de ligne de commande en tant que variable, vous pouvez l'appeler directement split, c'est- à -dire @m=split(',',$ARGV[0]).
Alex A.
1
Hey @LukStorms, content de voir plus de golfeurs Perl! Quelques astuces pour économiser des octets! Vos variables $det $speuvent être récupérées en utilisant regex pour vous sauver quelques octets ($d,$s)=/^(.)(.+)$/, et tous les foreachs peuvent être for(car ils sont identiques). Vous pourriez aussi être capable de sauvegarder certains caractères en remplaçant certains d'entre eux par map{... }@xpuisque vous pouvez ignorer les parenthèses autour de l'élément itéré (cela fonctionne bien si vous devez contenir d'autres boucles). Si vous utilisez, $ARGV[0]vous pouvez le remplacer par pop, mais si vous utilisez le script dans, perl script.pl <<< "text"vous pouvez utiliser la <>place!
Dom Hastings
1
Si vous souhaitez conserver le script en utilisant args, vous pouvez utiliser poppour enregistrer un couple. Au lieu de use Swtichet des instructions switch/ case, vous pouvez effectuer des vérifications individuelles qui pourraient vous faire économiser des octets. Quelque chose comme $y-="N"eq$dfonctionnera aussi bien (puisque vrai 1et faux est ''). Souvent, vous pouvez avoir des mots comme mots nus, alors ça $y-=N eq$dva marcher! Il y a certaines variables magiques que vous pouvez utiliser pour économiser des octets, $/est '\n'et $"est ' ', mais parfois une aide pourrait newline littérale sauver char aussi. Une autre astuce (sale!) Consiste à attribuer plusieurs tâches afin d’économiser un peu plus, comme $a=0;$b=0;il se peut $a=$b=0.
Dom Hastings
1
Juste un peu plus, je le promets. J'espère que c'est le genre d'informations que vous recherchez! Manquer des parens lors d'appels de fonction est un changement assez standard, donc substr($_,0,1)peut l'être substr$_,0,1. Postfixe pour les boucles et si les vérifications peuvent être utiles aussi comme dans for(@c){...}vs ...for@cmais que vous ne pouvez pas utiliser ;dans le code, vous devrez plutôt séparer les virgules (ce qui ne fonctionne pas toujours lorsque vous appelez des fonctions). Il y a tellement de bons conseils également sur codegolf.stackexchange.com/questions/5105/… . Bonne chance!
Dom Hastings
5

Python 2, 394 octets

Exécuter le programme puis coller dans l’entrée standard comme par exemple "E2,N4,E5,S2,W1,S3"

m=input().split(',')
def f(x,y,h,o,s=[]):
 for c in m:
  for _ in range(int(c[1:])):
   a,b,l={'E':(1,0,'>'),'W':(-1,0,'<'),'N':(0,1,'^'),'S':(0,-1,'v')}[c[0]]
   if o:o[h-y][x]=l
   s+=[(x,y)];x+=a;y+=b
 if o:o[h-y+b][x-a]='X'
 return s
p,q=zip(*f(*[0]*4))
w,h=max(p)-min(p),max(q)-min(q)
o=[[' ']*-~w for _ in range(h+1)]
f(-min(p),-min(q),h,o)
print'\n'.join(["".join(l).rstrip()for l in o])

Ce n'est pas très optimisé. Il passe d'abord par l'entrée pour enregistrer le chemin. Il fait ensuite quelques calculs pour déterminer la bonne position de départ et la bonne taille de o. Ensuite, il répète et définit les entrées appropriées de ocomme l'une des >v<^X. L'intérêt principal consiste à réutiliser la même fonction pour ces deux traversées.

Alex L
la source
4

XQuery 3.0, 498

declare variable $v external;let $m:=<v>{tokenize($v,',')!(for $j in(1 to xs:int(substring(.,2)))return<c>{translate(substring(.,1,1),'NESW','^>v<')}</c>)}</v>/c!(let $p:=./preceding-sibling::c return<p x="{count($p[.='>'])-count($p[.='<'])}" y="{count($p[.='v'])-count($p[.='^'])}">{if(./following::*)then .else'X'}</p>)for $y in(min(xs:int($m/@y))to max(xs:int($m/@y)))return string-join(for $x in(min(xs:int($m/@x))to max(xs:int($m/@x)))let $d:=$m[@x=$x and @y=$y]return if($d)then$d else' ','')

XQuery n’est pas souvent très compétitif, c’était donc amusant.

Ungolfed

declare variable $v external;
let $map := <vector>{ tokenize($v,',') ! 
        (for $j in (1 to xs:int(substring(.,2)))
            return <step>{ translate(substring(.,1,1),'NESW','^>v<') }</step> ) 
         }</vector>/step !
            (let $path_so_far := ./preceding-sibling::step
            return <point 
                x="{ count($path_so_far[.='>']) - count($path_so_far[.='<']) }" 
                y="{ count($path_so_far[.='v']) - count($path_so_far[.='^']) }">
                {if(./following::*) then string(.) else 'X'}
            </point>)
for $y in (min(xs:int($map/@y)) to max(xs:int($map/@y)))
return string-join(
    for $x in (min(xs:int($map/@x)) to max(xs:int($map/@x)))
    let $d := $map[@x=$x and @y=$y]
    return if($d) then string($d) else ' '
    ,'')
Kniffler
la source
4

PHP, 496 514 528

J'ai tenté ma chance en PHP, le résultat est plutôt long, je veux toujours le poster, juste pour le fun.

function a($c){global$a,$b;$a[$b[1]][$b[0]]=$c;}$c=explode(',',$argv[1]);$a=[];$b=[0,0];foreach($c as$d=>$e){$f=substr($e,1);if($d==count($c)-1)$f--;for($i=0;$i++<$f;){if($e[0]==N){a('^');$b[1]--;}elseif($e[0]==E){a('>');$b[0]++;}elseif($e[0]==S){a(v);$b[1]++;}else{a('<');$b[0]--;}}}a(X);$d=$e=$f=$g=0;foreach($a as$y=>$h){$f=min($f,$y);$g=max($g,$y);foreach($h as$x=>$i){$d=min($d,$x);$e=max($e,$x);}}for($y=$f;$y<=$g;$y++){for($x=$d;$x<=$e;$x++)echo isset($a[$y][$x])?$a[$y][$x]:' ';echo "
";}

Ungolfed

<?php

    function setInMap($char) {
        global $map, $position;
        $map[$position[1]][$position[0]] = $char;
    }

    $instructions = explode(',', $argv[1]);

    $map = [];

    $position = [0, 0];

    foreach($instructions as $index => $instruction) {
        $count = substr($instruction, 1);
        if($index === count($instructions) - 1) {
            $count--;
        }
        for($i = 0; $i < $count; $i++) {
            if($instruction[0] === 'N') {
                setInMap('^');
                $position[1]--;
            } elseif($instruction[0] === 'E') {
                setInMap('>');
                $position[0]++;
            } elseif($instruction[0] === 'S') {
                setInMap('v');
                $position[1]++;
            } else($instruction[0] === 'W') {
                setInMap('<');
                $position[0]--;
            }
        }
    }
    setInMap('X');

    $minX = $maxX = $minY = $maxY = 0;
    foreach($map as $y => $row) {
        $minY = min($minY, $y);
        $maxY = max($maxY, $y);
        foreach($row as $x => $cell) {
            $minX = min($minX, $x);
            $maxX = max($maxX, $x);
        }
    }
    for($y = $minY; $y <= $maxY; $y++) {
        for($x = $minX; $x <= $maxX; $x++) {
            if(isset($map[$y][$x])) {
                echo $map[$y][$x];
            } else {
                echo ' ';
            }
        }
        echo "\n";
    }

?>
Lars Ebert
la source
1
Peut être réduit beaucoup. Par exemple, vous pouvez simplement écrire for(;$i++<$f;), essayer de supprimer les crochets inutiles, utiliser des constantes non définies ( N) au lieu de chaînes ( 'N'),…
Blackhole
1
Au lieu de ifs, essayez d’utiliser des opérateurs trenary ou des opérateurs logiques. En outre, cela vous aidera si vous utilisez PHP 4.1 et utilisez un tableau GET avec les points.
Ismael Miguel
3

JavaScript (ES6), 244 249 274

Les espaces principaux et les nouvelles lignes ont été ajoutés pour plus de clarté et ne sont pas comptés, à l' exception de la nouvelle ligne proche de la fin de l'appel de jointure, qui est significative et comptabilisée.

Tester l'exécution de l'extrait de code (ECMAScript 6, Firefox et Safari 9 uniquement)

F=m=>(
  x=y=0,p=[],
  m.replace(/\w(\d+)/g,(d,z)=>{
    for(d='NWSE'.search(d[0]);
        z--&&(p=~x?~y?p:[y=0,...p]:p.map(r=>' '+r,x=0));
        p[u=y]=(w=r.slice(0,x))+'^<v>'[d]+(v=r.slice(x+1)),
        d&1?x+=d-2:y+=d-1)
      for(r=p[y]||'';!r[x];)r+=' ';
  }),
  p[u]=w+'X'+v,
  p.join`
`
)

// TEST

out=x=>O.innerHTML+=x.replace(/</g,'&lt;')+'\n'

;['S5,W2','N1,E1,S1,E1,N1,E1,S2','N1','N6,E6,S6,W5,N5,E4,S4,W3,N3,E2,S2,W1,N2','E21,S2','N12,E11,S12,W2,N4']
.forEach(a=>out(a+'\n'+F(a)+'\n'))
<pre id=O></pre>

edc65
la source
2

C, 557

main(_,a,minX,maxX,minY,maxY,x,y,v,dir,dist)char**a;char*v;{char o[998][999];for(y=0;y-998;++y){for(x=0;x-998;++x)o[y][x]=32;o[y][998]=0;}y=x=minY=minX=maxY=maxX=499;v=a[1];while(*v){dir=*v++;dist=atoi(v);while(*v&&*v!=44)v++;v+=!!*v;if(dir==78){while(dist--)o[y--][x]=94;if(y<minY)minY=y;y+=!*v;}if(dir==69){while(dist--)o[y][x++]=62;if(x>maxX)maxX=x;x-=!*v;}if(dir==83){while(dist--)o[y++][x]=86;if(y>maxY)maxY=y;y-=!*v;}if(dir==87){while(dist--)o[y][x--]=60;if(x<minX)minX=x;x+=!*v;}}o[y][x]=88;for(y=minY;y<=maxY;++y){o[y][maxX+1]=0;puts(o[y]+minX);}}

Version non-golfée:

#include <stdio.h>

#define MAX_WIDTH 998
#define MAX_HEIGHT 998

int main(int argc, char *argv[]) {
    int minX,maxX,minY,maxY;
    int x,y;
    char output[MAX_HEIGHT][MAX_WIDTH+1];
    char *v;

    for (y=0; y<MAX_HEIGHT; ++y) {
        for (x=0; x<MAX_WIDTH; ++x) 
            output[y][x] = ' ';
        output[y][MAX_WIDTH] = 0;
    }

    x = minX = maxX = MAX_WIDTH/2;
    y = minY = maxY = MAX_HEIGHT/2;

    v = argv[1];
    while (*v) {
        char dir; int dist;
        dir = *(v++);
        dist = atoi(v);
        while (*v && *v != ',') v++;
        if (*v) v++;

        switch (dir) {
            case 'N':case 'n':
                while (dist--) output[y--][x] = '^';
                if (y < minY) minY = y;
                if (!*v) y++;
                break;
            case 'E':case 'e':
                while (dist--) output[y][x++] = '>';
                if (x > maxX) maxX = x;
                if (!*v) x--;
                break;
            case 'S':case 's':
                while (dist--) output[y++][x] = 'v';
                if (y > maxY) maxY = y;
                if (!*v) y--;
                break;
            case 'W':case 'w':
                while (dist--) output[y][x--] = '<';
                if (x < minX) minX = x;
                if (!*v) x++;
                break;
        }
    }

    output[y][x] = 'x';
    for (y = minY; y <= maxY; ++y) {
        output[y][maxX+1] = 0;
        puts(output[y]+minX);
    }

    return 0;
}

L'allocation dynamique de mémoire n'est pas beaucoup plus difficile, mais malloc est un identifiant beaucoup trop long pour être utilisé en code golf. Je pense qu'il devrait y avoir une sorte d'en-tête PCG.h légalement auto-inclus pour jouer au golf en c, juste pour raccourcir certains identifiants.

LambdaBeta
la source
1

Groovy, 359

c=args[0].split(',').collect{[it[0],it[1..-1]as int]}
m=[[]]
x=y=0
d=["N":["^",0,1],"S":["v",0,-1],"E":[">",1,0],"W":["<",-1,0]]
c.each{z->(1..z[1]).each{if(x<0){m*.add(0," ");x=0};if(y<0){m.add(0,[]);y=0};m[y]=m[y]?:[];m[y][x]=d[z[0]][0];if(c.last()==z&&it==z[1])m[y][x]='X';y+=d[z[0]][2];x+=d[z[0]][1]}}
m.reverse().each{println it.collect{it?:" "}.join()}
Dbramwell
la source
1

Common Lisp - 603

(lambda(s)(do((x 0)i(y 0)j(p 0)r(q 0)(g(mapcar(lambda(x)`(,(aref x 0),(parse-integer x :start 1)))(split-sequence:split-sequence #\, s))(cdr g))c)((not g)(setf x 0 y 0)(dolist(e(stable-sort(sort r #'<= :key #'car)#'< :key #'cadr))(dotimes(_(-(cadr e)p y))(terpri)(incf y)(setf x 0))(dotimes(_(-(car e)q x))(princ" ")(incf x))(princ(caddr e))(incf x)))(case(caar g)(#\N(setf i 0 j -1 c #\^))(#\E(setf i 1 j 0 c #\>))(#\W(setf i -1 j 0 c #\<))(#\S(setf i 0 j 1 c #\v)))(dotimes(_(-(cadar g)(if(cdr g)0 1)))(push`(,x,y,c)r)(incf x i)(incf y j))(setf q(min q x)p(min p y))(unless(cdr g)(push`(,x,y #\X)r))))

Implémentation sans matrice: imprime de haut en bas, de gauche à droite.

  • Analyser et développer les directions en une trace d' (x y char)éléments:

    La simple entrée "N3" produit ((0 0 #\^) (0 -1 #\^) (0 -2 #\X))

  • De plus, calculez le minimum xety
  • Triez la trace obtenue en ypremier, puis enx
  • Itérer sur la liste triée en déplaçant le curseur

    1. Ajouter des nouvelles lignes et des espaces pour déplacer le curseur actuel à la bonne position
    2. Quand à la position x - minx, y - miny, imprimer le caractère désiré

Exemples

(loop for input in  '("N6,E6,S6,W5,N5,E4,S4,W3,N3,E2,S2,W1,N2" 
                      "N1,E1,S1,E1,N1,E1,S2" 
                      "N12,E11,S12,W2,N4")
      do (fresh-line)
         (terpri)
      (funcall *fun* input))

Résultat:

>>>>>>v
^>>>>vv
^^>>vvv
^^^Xvvv
^^^^<vv
^^^<<<v
^^<<<<<

>v>v
^>^X

>>>>>>>>>>>v
^          v
^          v
^          v
^          v
^          v
^          v
^          v
^          v
^        X v
^        ^ v
^        ^ v
^        ^<<
coredump
la source
1

CoffeeScript, 303   285 octets

Y=(s)->o=[];t=l=x=y=0;q='';q+=s[0]for[1..s[1..]]for s in s.split ',';q=q[..-2];(i='NWSE'.search c;(o[y]?=[])[x]='^<v>'[i];j=(i&2)-1;x+=j*(i&1);y+=j*(!(i&1));y<t&&t=y;x<l&&l=x)for c in q;(o[y]?=[])[x]='X';((o[y][x]||' 'for x in[l...o[y].length]).join ''for y in[t...o.length]).join '\n'

métalim
la source