Yarr! Eine Karte zum verborgenen Schatz!

49

Einführung

"Yarr !! Wir hatten einen Burschen, der sich" Programmierer "nannte, der eine Karte zu unserem verborgenen Schatz machte! Aber es ist mit seltsamen Zahlen und Buchstaben geschrieben!" E5, N2, E3 "... was macht das überhaupt? Wahnsinn! Ich kann nicht mal eine richtige Schatzkarte schreiben, das ist ein nutzloser Schwachsinn. Repariere es für uns! Wir schenken dir einen Teil des Schatzes! "

Herausforderungsbeschreibung

Eine Gruppe von Piraten hat Probleme, eine Schatzkarte zu lesen. Können Sie ein Programm schreiben, um es in eine ... piratey Form umzuwandeln?

Als Eingabe erhalten Sie die Original-Schatzkarte. Es ist eine Liste von durch Kommas getrennten Zeichenfolgen, wobei jede Zeichenfolge aus einem Buchstabenabschnitt (der den Piraten mitteilt, in welche Richtung sie gehen müssen) und einem Zahlenabschnitt (der den Piraten mitteilt, wie viele Schritte sie in diese Richtung ausführen müssen) besteht. Zum Beispiel die folgende Schatzkarte:

E2,N4,E5,S2,W1,S3

würde bedeuten: "Gehe zwei Schritte nach Osten, gehe vier Schritte nach Norden, gehe fünf Schritte nach Osten, gehe zwei Schritte nach Süden, gehe einen Schritt nach Westen und dann drei Schritte nach Süden."

Als Ausgabe, werden Sie die Karte in graphischer Form ausgegeben, mit den Zeichen >, ^, v, und <als Zeiger. Hier ist die Ausgabe für die obige Eingabe:

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

Beachten Sie, dass wir Xstattdessen den letzten Schritt nach Süden durch einen ersetzt haben . Dies liegt daran, dass der letzte Schritt darin besteht, den Schatz zu finden, und Piraten müssen, wie wir alle wissen, ein X auf ihren Schatzkarten haben, sonst wissen sie nicht, wie sie ihn lesen sollen.

Übrigens, die Karte wird sich nie selbst kreuzen, sodass Sie sich nicht um Überlappungen kümmern müssen. Außerdem darf am Ende der Ausgabe eine nachgestellte neue Zeile stehen.

Beispieleingänge und -ausgänge

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
^        ^<<
Absinth
quelle
1
Dürfen wir in jeder Zeile ein Leerzeichen setzen? Wird die Zahl immer unter zehn liegen?
Downgoat
9
Ich denke wirklich, das Xsollte den Schritt nach dem letzten Zug markieren , so wie alle anderen Züge gezählt werden. Stellen Sie sich vor, der letzte Schritt ist N3: Sie gehen drei Schritte nach Norden und graben, aber hier gibt es nichts, Sie mussten stattdessen zwei Schritte gehen. Es macht mir nichts aus, wenn Sie die bestehende Regel beibehalten, da sie einen kleinen Eckfall hinzufügt, der behandelt werden muss. Aber denk dran, was mit dem Jungen passiert ist.
Coredump
6
@coredump Oder vielleicht wollen wir die Piraten irreführen, damit wir den Schatz für uns nehmen können;) Nein, du hast recht, die Piraten graben einen Schritt zu früh. Da es bereits drei Antworten gibt, werde ich die Regel beibehalten, um zu vermeiden, dass vorhandene Lösungen ungültig werden.
Absinth
4
@ jpmc26 Nun, diese Piraten wissen nicht viel über das Alphabet ... sie verbrachten die letzten Jahre bei C :)
Absinth
4
Das vierte Beispiel ist nur die Piraten zu
trollen

Antworten:

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

Eingabe über stdin weiterleiten.

Dies verwendet ein y -> x -> charWörterbuch, um die Karte zu konstruieren, wobei beide xund ynegativ sein können. Sobald die Eingabe analysiert wurde, wird das globale Minimum der x-Koordinate extrahiert. Für jede Zeile durchläuft es dann einen Bereich, der vom globalen Minimal- zum Maximalindex für die aktuelle Zeile reicht, und gibt das richtige Zeichen für diesen Index aus.

Um beim Thema zu bleiben, wurden die Ausdrücke, die sich NESWin die richtigen Indizes verwandeln , schamlos aus der Antwort von Sp3000 raubkopiert .

Ursprüngliche Version, die ein [x,y] -> charWörterbuch verwendet hat:

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

Eingabe wie "E2,N4,E5,S2,W1,S3".

NSEWwird abgebildet [1, 3, 2, 0]von d=ord(c)%10%7. Ob geändert yoder xdann entschieden wird d%2, und ob inkrementiert oder dekrementiert wird, wird von entschieden d-2|1. Der erste und dritte Ausdruck wurden mit roher Gewalt gefunden.

Ansonsten ist es eine einfache Verwendung eines verschachtelten Wörterbuchs des Formulars {y: {x: char}}.

(Danke an @joriki für die Hilfe beim Mapping)

Sp3000
quelle
1
(d + 1 & 2) - 1
Joriki
1
@joriki Ah, das ist ein schöner Ausdruck - danke!
Sp3000,
2
Hier ist ein Code, den ich (in einem anderen Kontext) geschrieben habe, um einfache Ausdrücke für Ganzzahlfunktionen zu finden. Ich habe es nicht dafür benutzt, sondern dachte nur, dass es für dich interessant sein könnte. (Der entsprechende Code beginnt dort, wo steht "Dies ist der Code, mit dem ich die Codierung optimiert habe".)
joriki
3
@joriki Brute Forcing ist eine großartige Idee - nur aufgetaucht 1|d%-3(das ist die Verneinung, aber ich habe gerade gemerkt, dass das auch in Ordnung ist)!
Sp3000
14

Javascript (ES6), 260

Dies war ein interessanter ...

Vielen Dank an @ETHproductions, @ edc65 und @vihan für die Hilfe!

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}

Dies definiert eine anonyme Funktion. Wenn Sie sie also aufrufen, fügen Sie f=am Anfang einen Namen hinzu.

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

Erläuterung:

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
quelle
3
Das ist eine schöne Möglichkeit, Aussagen zu trennen! Es ist sicherlich viel lesbarer, als alles in eine Zeile zu setzen und durch Semikolons zu trennen. Wenn ich meinen Vorschlag machen darf: In diesem Fall können Sie ein Byte speichern, indem Sie es i++von der forSchleife an die letzte Stelle verschieben, an der es verwendet wird c=i++>r-2?"X":c.
ETHproductions
1
Da Sie ES6 verwenden, würde ich außerdem die Verwendung v[0].repeat(+v.slice(1))von anstelle von Array(v.slice(1)- -1).join(v[0])und " ".repeat(j-p-1)anstelle von Array(j-p).join(" ")insgesamt 11 Byte empfehlen . Ich denke, Sie könnten auch F='forEach'zu Beginn der Funktion setzen und dann .forEachvon dort zu wechseln [F], um weitere 4 zu sparen.
ETHproductions
1
Versuchen Sie, .map anstelle von .forEach zu verwenden. Es ist so kurz, dass Sie es nicht einmal auf F
edc65 07.08.15
1
@UndefinedFunktion Vielleicht möchten Sie Abkürzungen für die ifs verwenden. Es kann hilfreich sein, wenn Sie gleichzeitig Variablen dekrementieren
Downgoat
1
Wenn mein Verständnis korrekt ist, würde das q=x=y=2e3bedeuten, dass die Ausgabe falsch wäre, wenn ich das getan hätte, sagen wir mal W9999?
Sp3000
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";}

Legen Sie es in eine Datei ( treasure.php), entfernen Sie den Einzug, verbinden Sie die Zeilen (es wird hier aus Gründen der Lesbarkeit umbrochen), setzen Sie den <?phpMarker an den Anfang der Datei (hier nicht angezeigt, da es technisch nicht Teil des Programms ist).

Beispiel für die Ausführung:

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

Die Option -d error_reporting=0wird benötigt, um Benachrichtigungen über Werte zu unterdrücken, die bei angegebenen Indizes in nicht gefunden wurden $z.

Aktualisieren:

Während ich die unbenutzte Version des Codes für die Veröffentlichung vorbereitete, stellte ich fest, dass sie zwei nicht benötigte Zuweisungen (12 Byte) und ein Leerzeichen enthielt, das entfernt werden kann ( as$i). Außerdem habe ich ein weiteres Byte gespeichert, indem ich a whiledurch eine forSchleife ersetzte und eine Zuweisung in die Schleife drückte (dies ist mit der whileSchleife nicht möglich ).

Axiac
quelle
Ich würde gerne eine ungolfed version sehen.
Lars Ebert
1
@ LarsEbert Ich habe die Antwort mit einem Link zum ungolfed Code aktualisiert. Ich habe Ihre Lösung jetzt überprüft (habe es vorher nicht getan). Wir haben im Grunde den gleichen Algorithmus verwendet. Deiner handhabt den letzten Schritt besser als meiner. Ich kann 25 weitere Bytes entfernen, wenn ich implementiere $count --;.
Axiac
$argnspeichere 3 Bytes chopspeichere 1 Byte "X"-> Xverwende Konstanten speichere mehr Bytes
Jörg Hülsermann
@ JörgHülsermann Ich verstehe den $argnHinweis nicht. Ich bin mir des "X"->XTricks bewusst , habe ihn aber wahrscheinlich vergessen, als ich diese Lösung schrieb. Ich schreibe seit 2002 PHP-Code, aber bis heute habe ich nicht bemerkt, dass PHP die chop()Funktion bietet . Vielen Dank für diesen Hinweis.
Axiac
7

Perl, 702 613 546 474 439 338 260 Bytes

Vielen Dank an Dom Hastings für seine Hilfe und seine Supergolf-Version.
Der Code verwendet ein 2D-Array.

Version von 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$/}

Meine weniger Golf-Version von 338 Bytes (als Referenz):

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

Prüfung

$ 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
quelle
3
Wenn Sie nicht verwenden use strict;, benötigen Sie nicht alle mys, wodurch Sie mindestens ein paar Bytes sparen. Auch ==ist kürzer als eqda letztere Leerzeichen benötigt.
Alex A.
1
Wenn ich mich nicht irre, rufen Sie nur $meinmal auf. Statt das Befehlszeilenargument als Variable zu speichern, können Sie es direkt in aufrufen split, d @m=split(',',$ARGV[0]). H.
Alex A.
1
Hey @ LukStorms, ich freue mich, mehr Perl-Golfer zu sehen! Ein paar Dinge, die helfen, ein paar Bytes zu sparen! Ihre $dund $sVariablen können mit Regex erfasst werden, um Ihnen einige Bytes zu sparen ($d,$s)=/^(.)(.+)$/, und alle foreachkönnen for(wie sie sind) gleich sein. Sie können möglicherweise auch einige Zeichen speichern, indem Sie einige durch map{... ersetzen, }@xda Sie die Parens ignorieren können um das iterierte Element (dies funktioniert gut, wenn Sie andere Schleifen enthalten müssen.) Wenn Sie verwenden $ARGV[0], können Sie das durch pop ersetzen, aber wenn Sie das Skript wie in verwenden perl script.pl <<< "text", können Sie <>stattdessen verwenden!
Dom Hastings
1
Wenn Sie das Skript mit args beibehalten möchten, können Sie popmit ein paar speichern. Anstelle von use Swtichund der switch/ case-Anweisung können Sie auch einzelne Überprüfungen durchführen, um Byte zu sparen. Sowas $y-="N"eq$dwird auch funktionieren (da wahr 1und falsch ist ''). Oft kann man Wörter als Barwörter haben, also $y-=N eq$dwird es funktionieren! Es gibt einige magische Variablen, die Sie verwenden können, um Bytes zu speichern, $/ist '\n'und $"ist ' ', aber manchmal hilft auch ein Literal Newline, ein Zeichen zu speichern. Ein weiterer (schmutziger!) Trick sind mehrere Zuweisungen, um ein paar mehr zu retten, als es sein $a=0;$b=0;kann $a=$b=0.
Dom Hastings
1
Nur noch ein paar, das verspreche ich. Ich hoffe, das ist die Art von Info, nach der Sie suchen! Fehlende off Pars auf Funktionsaufrufe ein ziemlich Standard Änderung ist, so substr($_,0,1)kann sein substr$_,0,1. Postfix für Schleifen und wenn Überprüfungen auch nützlich sein können wie in for(@c){...}vs., ...for@caber Sie können sie nicht ;im Code verwenden, müssen Sie stattdessen ein Komma trennen (was beim Aufrufen von Funktionen nicht immer funktioniert). Es gibt so viele tolle Tipps auch unter codegolf.stackexchange.com/questions/5105/… . Viel Glück!
Dom Hastings
5

Python 2, 394 Bytes

Führen Sie das Programm aus und fügen Sie es in die Standardeingabe ein, z "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])

Dies ist nicht sehr optimiert. Zuerst durchläuft es die Eingabe, um den Pfad aufzuzeichnen. Dann werden einige Berechnungen durchgeführt, um die richtige Startposition und Größe von zu bestimmen o. Dann läuft es nochmal durch und setzt die entsprechenden Einträge oals einen von >v<^X. Der Hauptgrund liegt in der Wiederverwendung der gleichen Funktion für beide Traversen.

Alex L
quelle
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 ist oft nicht einmal leicht umkämpft, also hat es Spaß gemacht.

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 ' '
    ,'')
Messer
quelle
4

PHP, 496 514 528

Ich habe mein Glück in PHP versucht, das Ergebnis ist ziemlich lang, ich möchte es trotzdem posten, nur zum Spaß.

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
quelle
1
Kann stark reduziert werden. Zum Beispiel können Sie einfach schreiben for(;$i++<$f;), versuchen, unnötige Klammern zu entfernen, undefinierte Konstanten ( N) anstelle von Strings ( 'N') zu verwenden, ...
Blackhole
1
ifVerwenden Sie anstelle von s Trenary Operators oder Logical Ands. Es ist auch hilfreich, wenn Sie PHP4.1 verwenden und ein GET-Array mit den Punkten verwenden.
Ismael Miguel
3

JavaScript (ES6), 244 249 274

Führende Leerzeichen und Zeilenumbrüche wurden der Übersichtlichkeit halber hinzugefügt und nicht gezählt, mit Ausnahme der Zeilenumbrüche am Ende des Join-Aufrufs, die signifikant und gezählt sind.

Testlauf des Snippets (nur ECMAScript 6, Firefox und 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
quelle
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);}}

Ungolfed-Version:

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

Die dynamische Speicherzuweisung ist nicht viel schwieriger, aber malloc ist eine viel zu lange Kennung, um im Codegolf verwendet zu werden. Ich denke, es sollte eine Art PCG.h-Header geben, der legal automatisch für das Golfen in c enthalten ist, nur um einige Bezeichner zu verkürzen.

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

Array-freie Implementierung: Druckt von oben nach unten, von links nach rechts.

  • Analysiert und erweitert Richtungen in eine Spur von (x y char)Elementen:

    Der einfache "N3" -Eingang erzeugt ((0 0 #\^) (0 -1 #\^) (0 -2 #\X))

  • Berechnen Sie auch die minimalen xundy
  • Sortieren Sie die resultierende Ablaufverfolgung yzuerst nach und dann nachx
  • Durchlaufen Sie die sortierte Liste, während Sie den Cursor bewegen

    1. Fügen Sie neue Zeilen und Leerzeichen hinzu, um den aktuellen Cursor an die richtige Position zu bewegen
    2. Wenn an der Position x - minx, y - minydrucken, um das gewünschte Zeichen

Beispiele

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

Ergebnis:

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

>v>v
^>^X

>>>>>>>>>>>v
^          v
^          v
^          v
^          v
^          v
^          v
^          v
^          v
^        X v
^        ^ v
^        ^ v
^        ^<<
Core-Dump
quelle
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
quelle