Yarr! Um mapa para o tesouro escondido!

49

Introdução

"Yarr !! Tivemos um rapaz que se considerava um" programador "fazer um mapa do nosso tesouro escondido! Mas está escrito com 'números e letras estranhos!" E5, N2, E3 "... o que é que isso faz loucura! Não é possível escrever um mapa do tesouro adequado, cretino inútil. Conserte-o! Vamos oferecer uma parte do tesouro! "

Descrição do Desafio

Um grupo de piratas está tendo problemas para ler um mapa do tesouro. Você pode escrever um programa para convertê-lo em um formato mais ... pirata?

Como entrada, você receberá o mapa do tesouro original. É uma lista de sequências separadas por vírgula, cada sequência que consiste em uma parte da letra (que informa aos piratas em que direção eles precisam entrar) e uma parte numérica (que informa aos piratas quantos passos devem ser seguidos nessa direção). Por exemplo, o seguinte mapa do tesouro:

E2,N4,E5,S2,W1,S3

significaria "andar dois passos para o leste, andar quatro passos para o norte, andar cinco passos para o leste, andar dois passos para o sul, andar um passo para o oeste, depois andar três passos para o sul".

Como saída, você vai saída o mapa em um formato gráfico, usando os personagens >, ^, v, e <como ponteiros. Aqui está a saída para a entrada acima:

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

Observe que substituímos o último passo para o sul por um X. Isso ocorre porque o último passo é onde está o tesouro e, como todos sabemos, os piratas devem ter um X em seus mapas, caso contrário eles não saberão como lê-lo.

A propósito, o mapa nunca se cruzará, então você não precisa se preocupar em lidar com sobreposições. Além disso, você pode ter uma nova linha à direita no final da saída.

Amostras de entradas e saídas

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
^        ^<<
absinto
fonte
11
É permitido ter espaços à direita em cada linha? O número sempre será menor que dez?
Downgoat 6/08/15
9
Eu realmente acho que Xdeveria marcar o passo após a última jogada, como todas as outras jogadas são contadas. Imagine que o último passo é N3: você caminha três passos para o norte e cava, mas não há nada aqui, você teve que caminhar 2 passos. Não me importo se você mantiver a regra existente, porque ela adiciona uma pequena caixa de canto para lidar. Mas lembre-se do que aconteceu com esse rapaz.
Coredump
6
@coredump Ou talvez desejemos enganar os piratas, para que possamos levar o tesouro para nós mesmos;) Não, você está certo, os piratas estão cavando um passo cedo demais. Dado que já existem três respostas, manterei a regra para evitar a invalidação de soluções existentes.
absinto
4
@ jpmc26 Bem, estes piratas não sei muito do alfabeto ... eles passaram os últimos anos na C :)
o absinto
4
O quarto exemplo é apenas
trollar

Respostas:

8

Rubi, 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]}*""}

Passe a entrada via stdin.

Isso usa um y -> x -> chardicionário para construir o mapa, onde ambos xe ypodem ser negativos. Depois que a entrada foi analisada, o mínimo global da coordenada x é extraído. Para cada linha, ele itera sobre um intervalo que vai do índice mínimo global ao máximo da linha atual e imprime o caractere correto para esse índice.

Para ficar com o tema, as expressões para ligar NESWpara os índices apropriados foram descaradamente pirateado do SP3000 's resposta .

Versão original que usava um [x,y] -> chardicionário:

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
fonte
20

Python 2, 249 248 244 239 237 bytes

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

Entrada como "E2,N4,E5,S2,W1,S3".

NSEWé mapeado para [1, 3, 2, 0]por d=ord(c)%10%7. A decisão de mudar you xentão é decidida d%2e se o incremento ou decremento é decidido por d-2|1. A primeira e a terceira expressões foram encontradas pela força bruta.

Fora isso, é um uso simples de um dicionário aninhado do formulário {y: {x: char}}.

(Obrigado a @joriki pela ajuda com o mapeamento)

Sp3000
fonte
11
(d + 1 & 2) - 1
joriki
11
@joriki Ah, que expressão legal - obrigado!
Sp3000
2
Aqui está um código que eu escrevi (em um contexto diferente) para encontrar expressões simples para funções inteiras. Não o usei para isso, mas achei que poderia ser interessante para você. (O código relevante começa onde diz "Este é o código que eu usei para otimizar a codificação".)
joriki
3
@joriki Brute forcing é uma ótima idéia - acabou de aparecer 1|d%-3(que é a negação, mas eu percebi que tudo bem também)!
SP3000
14

Javascript (ES6), 260

Este foi um interessante ...

Obrigado @ETHproductions, @ edc65 e @vihan pela ajuda!

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}

Isso define uma função anônima, para chamá-la de adicionar f=ao início para dar um nome a ela.

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

Explicação:

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
fonte
3
Essa é uma boa maneira de separar declarações! É certamente muito mais legível do que colocar tudo em uma linha e separá-los com ponto e vírgula. Se eu puder oferecer minha sugestão: você pode salvar um byte movendo o i++do forloop para o último local em que é usado, neste caso c=i++>r-2?"X":c.
ETHproductions
11
Além disso, como você usa o ES6, sugiro usar v[0].repeat(+v.slice(1))no lugar Array(v.slice(1)- -1).join(v[0])e " ".repeat(j-p-1)no lugar de Array(j-p).join(" ")salvar 11 bytes no geral. Eu acho que você também pode colocar F='forEach'no início da função, em seguida, mudar a cada .forEachde lá para [F], economizando mais 4.
ETHproductions
11
Tente usar .map em vez de .forEach. É tão curto você não deve mesmo encurtar a F
edc65
11
@UndefinedFunction você pode querer usar atalhos para os ifs, pode ajudar se você diminuir variáveis ao mesmo tempo também
Downgoat
11
Se meu entendimento estiver correto, q=x=y=2e3significa que a saída estaria incorreta se eu dissesse, digamos W9999?
Sp3000 8/08/15
7

PHP, 431 417 bytes

$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";}

Coloque-o em um arquivo ( treasure.php), remova o recuo, junte-se às linhas (ele está encapsulado aqui para facilitar a leitura), coloque o <?phpmarcador no início do arquivo (não exibido aqui, pois tecnicamente não faz parte do programa).

Exemplo de execução:

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

A opção -d error_reporting=0é necessária para suprimir avisos sobre valores não encontrados nos índices especificados em $z.

Atualizar:

Enquanto eu preparava a versão não-gasta do código para publicação, descobri que ela continha duas atribuições desnecessárias (12 bytes) e um espaço em branco que pode ser removido ( as$i); além disso, substituindo a whilepor um forloop e pressionando uma atribuição (não é possível usando o whileloop), salvei outro byte.

axiac
fonte
Eu adoraria ver uma versão não-destruída.
Lars Ebert
11
@LarsEbert Atualizei a resposta com um link para o código não utilizado. Eu verifiquei sua solução agora (não fiz isso antes); basicamente usamos o mesmo algoritmo. O seu lida com o último passo melhor que o meu. Eu posso extrair mais 25 bytes se implementar $count --;.
axiac
$argnsalvar 3 Bytes chopsave 1 Byte "X"-> Xconstantes uso economizar mais bytes
Jörg Hülsermann
@ JörgHülsermann Não entendi a $argndica. Estou ciente do "X"->Xtruque, mas provavelmente me esqueci disso quando escrevi esta solução. Eu escrevo código PHP desde 2002, mas até hoje eu não percebi que o PHP fornece a chop()função. Obrigado por esta dica.
axiac
7

Perl, 702 613 546 474 439 338 260 bytes

Obrigado a Dom Hastings por sua ajuda e sua versão supergolfada.
O código usa uma matriz 2D.

Versão 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$/}

Minha versão menor de 338 bytes (para referência):

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

Teste

$ 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
fonte
3
Se você não estiver usando use strict;, não precisará de todos os mys, o que economizará pelo menos alguns bytes. Também ==é mais curto do eqque o último requer espaços.
Alex A.
11
Se não me engano, você está chamando apenas $muma vez; portanto, em vez de armazenar o argumento da linha de comando como uma variável, você pode chamá-lo diretamente split, ie @m=split(',',$ARGV[0]).
Alex A.
11
Hey @LukStorms, feliz em ver mais jogadores de Perl! Algumas coisas para ajudar a economizar alguns bytes! Suas variáveis $de $spodem ser capturadas usando o regex para economizar alguns bytes ($d,$s)=/^(.)(.+)$/, e todos os foreachs podem ser for(como são iguais. Você também pode salvar alguns caracteres substituindo alguns deles por map{... }@xdesde que você possa ignorar os parênteses ao redor do item iterado (isso funciona bem se você tem que conter outros ciclos) Se você está usando. $ARGV[0]você pode substituir isso com pop, mas se você usar o script como perl script.pl <<< "text"você pode usar <>em vez disso!
Dom Hastings
11
Se você deseja manter o script usando args, pode usar poppara salvar alguns. Em vez de use Swtiche as instruções switch/ case, você pode fazer verificações individuais que podem economizar bytes. Algo como $y-="N"eq$dirá funcionar também (já que verdadeiro 1e falso é ''). Freqüentemente, você pode ter palavras como palavras de baralho, assim $y-=N eq$dfuncionará! Existem algumas variáveis ​​mágicas que você pode usar para salvar bytes, $/é '\n'e $"é ' ', mas às vezes uma nova linha literal pode ajudar a salvar um caractere também. Outro truque (sujo!) São várias atribuições para economizar um pouco mais, como $a=0;$b=0;pode ser $a=$b=0.
Dom Hastings
11
Só mais alguns, eu prometo. Espero que esta seja a informação que você procura! A falta de parênteses nas chamadas de função é uma alteração bastante padrão, por isso substr($_,0,1)pode ser substr$_,0,1. O Postfix para loops e se as verificações também puderem ser úteis, como em for(@c){...}vs., ...for@cmas você não pode usar ;o código, será necessário separar vírgulas (o que nem sempre funciona quando você está chamando funções). Há muitas ótimas dicas também em codegolf.stackexchange.com/questions/5105/… . Boa sorte!
Dom Hastings
5

Python 2, 394 bytes

Execute o programa e cole na entrada padrão como por exemplo "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])

Isso não é muito otimizado. Primeiro, ele percorre a entrada para gravar o caminho. Depois, faz algumas contas para determinar a posição inicial correta e o tamanho de o. Em seguida, ele é executado novamente e define as entradas apropriadas ocomo um dos >v<^X. A principal inteligência está em reutilizar a mesma função para ambos os percursos.

Alex L
fonte
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' ','')

O XQuery nem sempre é um pouco competitivo, então isso foi divertido.

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
fonte
4

PHP, 496 514 528

Tentei a sorte no PHP, o resultado é bastante longo, ainda quero publicá-lo, apenas por diversão.

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
fonte
11
Pode ser reduzido muito. Por exemplo, você pode apenas escrever for(;$i++<$f;), tentar remover suportes desnecessários, usar constantes indefinidos ( N) em vez de cordas ( 'N'), ...
Blackhole
11
Em vez de ifs, tente usar operadores trenários ou ands lógicos. Além disso, ajudará se você usar PHP4.1 e usar uma matriz GET com os pontos.
Ismael Miguel
3

JavaScript (ES6), 244249274

Os espaços à esquerda e as novas linhas foram adicionados para maior clareza e não são contados, exceto a nova linha no final da chamada de junção, que é significativa e contada.

Teste a execução do snippet (sendo apenas ECMAScript 6, Firefox e Safari 9)

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

Versão não destruída:

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

A alocação dinâmica de memória não é muito mais difícil, mas o malloc é um identificador muito longo para ser usado no código golf. Eu sinto que deveria haver algum tipo de cabeçalho PCG.h legalmente incluído automaticamente para jogar golfe em c, apenas para colocar em curto alguns identificadores.

LambdaBeta
fonte
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
fonte
1

Lisp comum - 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))))

Implementação sem matriz: imprime de cima para baixo, da esquerda para a direita.

  • Analise e expanda as direções em um rastreamento de (x y char)elementos:

    A entrada "N3" simples produz ((0 0 #\^) (0 -1 #\^) (0 -2 #\X))

  • Além disso, calcule o mínimo xey
  • Classifique o rastreio resultante por yprimeiro e depois porx
  • Iterar sobre a lista classificada enquanto move o cursor

    1. Adicione novas linhas e espaços para mover o cursor atual na posição correta
    2. Quando na posição x - minx, y - miny, imprimir o caractere desejado

Exemplos

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

Resultado:

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

>v>v
^>^X

>>>>>>>>>>>v
^          v
^          v
^          v
^          v
^          v
^          v
^          v
^          v
^        X v
^        ^ v
^        ^ v
^        ^<<
coredump
fonte
1

CoffeeScript, 303   285 bytes

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'

metalim
fonte