Yarr! Mapa do ukrytego skarbu!

49

Wprowadzenie

„Yarr! Mieliśmy chłopca, który nazywał siebie„ programistą ”, który tworzy mapę naszego ukrytego skarbu! Ale to napisane z dziwnymi liczbami i literami!„ E5, N2, E3 ”… co to w ogóle robi znaczy? Szaleństwo! Nie mogę nawet napisać właściwej mapy skarbów, bezużytecznego kretyna. Napraw to dla nas! Podarujemy ci skarb!

Opis wyzwania

Grupa piratów ma problem z odczytaniem mapy skarbów. Czy potrafisz napisać program, który przekształci go w bardziej ... piracką formę?

Jako dane wejściowe otrzymasz oryginalną mapę skarbów. Jest to lista ciągów oddzielonych przecinkami, każdy ciąg składający się z części literowej (która mówi piratom, w którym kierunku powinni iść) oraz części liczbowej (która informuje piratów, ile kroków należy wykonać w tym kierunku). Na przykład następująca mapa skarbów:

E2,N4,E5,S2,W1,S3

oznaczałoby: „idź dwa kroki na wschód, idź cztery kroki na północ, idź pięć kroków na wschód, idź dwa kroki na południe, idź krok na zachód, a następnie trzy kroki na południe”.

Jako wyjście, będziesz wyjście mapę w formie graficznej, za pomocą znaków >, ^, v, i <jako wskaźniki. Oto wynik dla powyższego wejścia:

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

Zauważ, że zamiast tego ostatni krok na południu zastąpiliśmy X. Dzieje się tak, ponieważ ostatnim krokiem jest miejsce, w którym znajduje się skarb, i jak wszyscy wiemy, piraci muszą mieć X na swoich mapach skarbów, w przeciwnym razie nie będą umieli go czytać.

Nawiasem mówiąc, mapa nigdy się nie przekroczy, więc nie musisz się martwić o nakładanie się. Ponadto możesz mieć końcowy nowy wiersz na końcu danych wyjściowych.

Przykładowe wejścia i wyjścia

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
^        ^<<
Absynt
źródło
1
Czy możemy mieć końcowe spacje w każdej linii? Czy liczba zawsze będzie mniejsza niż dziesięć?
Downgoat
9
Naprawdę uważam, że Xpowinien on oznaczyć krok po ostatnim ruchu, tak jak wszystkie inne ruchy są liczone. Wyobraź sobie, że ostatnim krokiem jest N3: idziesz trzy kroki na północ i kopiesz, ale tu nic nie ma, zamiast tego musiałeś przejść 2 kroki. Nie mam nic przeciwko, jeśli zachowasz istniejącą regułę, ponieważ dodaje ona małą narożną skrzynkę do obsługi. Ale pamiętaj, co się stało z tym chłopcem.
coredump
6
@coredump A może chcemy wprowadzić piratów w błąd, abyśmy mogli zabrać skarb dla siebie;) Nie, masz rację, piraci kopią o krok za wcześnie. Biorąc pod uwagę, że są już trzy odpowiedzi, zachowam tę zasadę, aby uniknąć unieważnienia istniejących rozwiązań.
absynt
4
@ jpmc26 Cóż, ci piraci nie znają dużo alfabetu ... ostatnie kilka lat spędzili w C :)
absynt
4
Czwarty przykład to trollowanie piratów ...
pół

Odpowiedzi:

8

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

Przekaż wejście przez stdin.

To używa y -> x -> charsłownika skonstruować mapę, gdzie zarówno xi ymoże być ujemna. Po przeanalizowaniu danych wejściowych wyodrębniane jest globalne minimum współrzędnej x. Dla każdego wiersza iteruje następnie zakres od globalnego minimum do maksymalnego indeksu dla bieżącej linii i drukuje poprawny znak dla tego indeksu.

Aby pozostać z tematem, wyrażenia, aby włączyć NESWdo odpowiednich indeksów były bezwstydnie pirackich od SP3000 jest odpowiedź .

Oryginalna wersja wykorzystująca [x,y] -> charsłownik:

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
źródło
20

Python 2, 249 248 244 239 237 bajtów

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

Dane wejściowe jak "E2,N4,E5,S2,W1,S3".

NSEWjest mapowany [1, 3, 2, 0]przez d=ord(c)%10%7. O tym, czy zmienić, yczy też xdecyduje d%2, a czy o zwiększaniu czy zmniejszaniu decyduje d-2|1. Pierwsze i trzecie wyrażenie zostało znalezione brutalną siłą.

Poza tym jest to proste użycie zagnieżdżonego słownika formularza {y: {x: char}}.

(Podziękowania dla @joriki za pomoc w mapowaniu)

Sp3000
źródło
1
(d + 1 & 2) - 1
joriki,
1
@ joriki Ah to miłe wyrażenie - dzięki!
Sp3000,
2
Oto kod, który napisałem (w innym kontekście), aby znaleźć proste wyrażenia dla funkcji liczb całkowitych. Nie wykorzystałem tego do tego, ale pomyślałem, że może być dla ciebie interesujące. (Odpowiedni kod zaczyna się tam, gdzie jest napisane: „To jest kod, którego użyłem do optymalizacji kodowania”.)
joriki
3
@joriki Brute forcing to świetny pomysł - właśnie się pojawił 1|d%-3(co jest negacją, ale zdałem sobie sprawę, że to też jest w porządku)!
Sp3000,
14

JavaScript (ES6), 260

To było interesujące ...

Dzięki @ETHproductions, @ edc65 i @vihan za pomoc!

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}

Definiuje to funkcję anonimową, więc jej wywołanie dodaj f=do początku, aby nadać jej nazwę.

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

Wyjaśnienie:

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
źródło
3
To dobry sposób na oddzielne zestawienia! Jest to z pewnością znacznie bardziej czytelne niż umieszczanie wszystkiego w jednym wierszu i oddzielanie ich średnikami. Jeśli mogę zaoferować moją sugestię: możesz zaoszczędzić bajt, przenosząc swój i++z forpętli do ostatniego miejsca, w którym jest używany, w tym przypadku c=i++>r-2?"X":c.
ETHproductions
1
Ponadto, ponieważ używasz ES6, sugeruję użycie v[0].repeat(+v.slice(1))zamiast Array(v.slice(1)- -1).join(v[0])i " ".repeat(j-p-1)zamiast Array(j-p).join(" ")oszczędzania 11 bajtów ogółem. Myślę, że możesz również umieścić F='forEach'na początku funkcji, a następnie zmienić każdy .forEachz nich na [F], oszczędzając kolejne 4.
ETHproductions
1
Spróbuj użyć .map zamiast .forEach. Jest tak krótki, że nie powinieneś go nawet skracać do F
edc65,
1
@UndefinedFunction możesz użyć skrótów dla ifs, może to pomóc, jeśli zmniejszysz również zmienne w tym samym czasie
Downgoat
1
Jeśli moje rozumowanie jest prawidłowe, czy q=x=y=2e3oznacza to, że dane wyjściowe byłyby niepoprawne, gdybym tak powiedział W9999?
Sp3000,
7

PHP, 431 417 bajtów

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

Umieść go w pliku ( treasure.php), usuń wcięcie, połącz linie (jest on tutaj zawinięty dla czytelności), umieść <?phpznacznik na początku pliku (nie jest wyświetlany tutaj, ponieważ technicznie nie jest częścią programu).

Przykład wykonania:

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

Opcja -d error_reporting=0jest potrzebna, aby ukryć powiadomienia o wartościach nie znalezionych przy określonych indeksach w $z.

Aktualizacja:

Podczas przygotowywania niepublikowanej wersji kodu do opublikowania odkryłem, że zawiera on dwa niepotrzebne przypisania (12 bajtów) i spację, którą można usunąć ( as$i); Również, wymieniając whilez forpętli i ściskając zadanie go (nie jest możliwe przy użyciu whilepętli) I zapisane innego bajtu.

aksjomat
źródło
Bardzo chciałbym zobaczyć wersję bez golfa.
Lars Ebert,
1
@LarsEbert Zaktualizowałem odpowiedź, dodając link do kodu bez golfa. Sprawdziłem teraz twoje rozwiązanie (wcześniej tego nie robiłem); zasadniczo użyliśmy tego samego algorytmu. Twój obsługuje ostatni krok lepiej niż mój. Mogę usunąć 25 bajtów więcej, jeśli zaimplementuję $count --;.
axiac
$argnzapisz 3 bajty chopzapisz 1 bajt "X"-> Xużyj stałych zapisz więcej bajtów
Jörg Hülsermann
@ JörgHülsermann Nie rozumiem $argn. Zdaję sobie sprawę z tej "X"->Xsztuczki, ale prawdopodobnie zapomniałem o niej, kiedy napisałem to rozwiązanie. Piszę kod PHP od 2002 roku, ale do dzisiaj nie zauważyłem, że PHP zapewnia tę chop()funkcję. Dziękuję za tę wskazówkę.
axiac
7

Perl, 702 613 546 474 439 338 260 bajtów

Dzięki Dom Hastings za pomoc i jego wersję supergolfed.
Kod wykorzystuje tablicę 2D.

Wersja autorstwa 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$/}

Moja mniej golfowa wersja 338 bajtów (dla odniesienia):

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

Test

$ 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
źródło
3
Jeśli nie używasz use strict;, nie potrzebujesz wszystkich mys, co pozwoli Ci zaoszczędzić co najmniej kilka bajtów. ==Jest także krótszy niż eqten ostatni wymaga spacji.
Alex A.,
1
Jeśli się nie mylę, dzwonisz tylko $mraz, więc zamiast przechowywać argument linii poleceń jako zmienną, możesz wywołać go bezpośrednio w split, tj @m=split(',',$ARGV[0]).
Alex A.,
1
Hej @LukStorms, cieszę się, że widzę więcej golfistów Perla! Kilka rzeczy, które pomogą zaoszczędzić trochę bajtów! Twoje $di $szmienne mogą być pobierane za pomocą wyrażenia regularnego, aby zaoszczędzić ci niektóre bajty ($d,$s)=/^(.)(.+)$/, i wszystkie foreachmogą być for(ponieważ są takie same. Możesz również być w stanie zapisać niektóre znaki zastępując niektóre z nich map{... }@xponieważ możesz zignorować parens wokół iterowanego elementu (działa to dobrze, jeśli musisz zawierać inne pętle). Jeśli używasz $ARGV[0], możesz zastąpić go popem, ale jeśli używasz skryptu tak, jak perl script.pl <<< "text"możesz, możesz go użyć <>!
Dom Hastings
1
Jeśli chcesz zachować skrypt za pomocą argumentów, możesz użyć, popaby zapisać kilka. Zamiast instrukcji use Swtichi switch/ casemożna wykonać indywidualne kontrole, które mogą zaoszczędzić bajty. Coś jak również $y-="N"eq$dbędzie działać (ponieważ prawda 1i fałsz są ''). Często możesz używać słów jako słów kluczowych, więc $y-=N eq$dzadziała! Istnieje kilka magicznych zmiennych, których można użyć do zapisania bajtów, $/jest '\n'i $"jest ' ', ale czasami dosłowna nowa linia może również pomóc w zapisaniu znaku. Kolejną sztuczką (brudną!) Jest wielokrotne przypisywanie, aby zaoszczędzić jeszcze kilka, jak $a=0;$b=0;może być $a=$b=0.
Dom Hastings,
1
Jeszcze tylko kilka, obiecuję. Mam nadzieję, że jest to rodzaj informacji, której szukasz! Pomijanie parens w wywołaniach funkcji jest dość standardową zmianą, więc substr($_,0,1)może być substr$_,0,1. Postfiks dla pętli i jeśli sprawdzanie może być również przydatne, jak w for(@c){...}vs, ...for@cale nie możesz użyć ;w kodzie, musisz zamiast tego przecinek oddzielić (co nie zawsze działa, gdy wywołujesz funkcje). Istnieje wiele wspaniałych wskazówek także na codegolf.stackexchange.com/questions/5105/… . Powodzenia!
Dom Hastings,
5

Python 2, 394 bajty

Uruchom program, a następnie wklej do standardowego wejścia, np "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])

To nie jest bardzo zoptymalizowane. Najpierw przebiega przez wejście, aby zarejestrować ścieżkę. Następnie wykonuje matematykę, aby określić właściwą pozycję początkową i rozmiar o. Następnie biegnie ponownie i ustawia odpowiednie wpisy ojako jeden z >v<^X. Główna spryt polega na ponownym użyciu tej samej funkcji dla obu tych przejść.

Alex L.
źródło
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 często nie jest nawet lekko konkurencyjny, więc było fajnie.

Bez golfa

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
źródło
4

PHP, 496 514 528

Próbowałem szczęścia w PHP, wynik jest raczej długi, wciąż chcę to opublikować, dla zabawy.

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

Bez golfa

<?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
źródło
1
Można znacznie zmniejszyć. Na przykład możesz po prostu pisać for(;$i++<$f;), próbować usuwać niepotrzebne nawiasy klamrowe, używać niezdefiniowanych stałych ( N) zamiast string ( 'N'),…
Blackhole
1
Zamiast ifs spróbuj użyć operatorów trenary lub logicznych is. Pomoże to również, jeśli używasz PHP4.1 i używasz tablicy GET z punktami.
Ismael Miguel
3

JavaScript (ES6), 244 249 274

Wiodące spacje i znaki nowej linii zostały dodane dla jasności i nie zostały policzone, z wyjątkiem nowej linii pod koniec połączenia połączenia, która jest znacząca i została policzona.

Przetestuj uruchomienie fragmentu kodu (tylko ECMAScript 6, Firefox i 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
źródło
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);}}

Wersja bez golfa:

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

Dynamiczna alokacja pamięci nie jest trudniejsza, ale malloc jest zdecydowanie za długim identyfikatorem, aby można go było zastosować w golfie kodowym. Wydaje mi się, że powinien istnieć jakiś nagłówek PCG.h, który jest automatycznie dołączany do gry w golfa w c, tylko po to, aby zewrzeć niektóre identyfikatory.

LambdaBeta
źródło
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
źródło
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))))

Implementacja bez macierzy: drukuje od góry do dołu, od lewej do prawej.

  • Analizuj i rozwija kierunki w ślad (x y char)elementów:

    Powstaje proste wejście „N3” ((0 0 #\^) (0 -1 #\^) (0 -2 #\X))

  • Oblicz także minimalne xiy
  • Posortuj powstały ślad według ynajpierw, a następnie wedługx
  • Iteruj po posortowanej liście podczas przesuwania kursora

    1. Dodaj nowe linie i spacje, aby przesunąć bieżący kursor we właściwej pozycji
    2. Gdy w pozycji x - minx, y - minynależy wydrukować żądany znak

Przykłady

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

Wynik:

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

>v>v
^>^X

>>>>>>>>>>>v
^          v
^          v
^          v
^          v
^          v
^          v
^          v
^          v
^        X v
^        ^ v
^        ^ v
^        ^<<
rdzeń rdzeniowy
źródło
1

CoffeeScript, 303   285 bajtów

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
źródło