Yarr! Карта со скрытым сокровищем!


49

Введение

«Ярр! У нас был парень, который называл себя« программистом », делающим карту для нашего скрытого сокровища! Но это написано со странными числами и буквами!» E5, N2, E3 «... что это вообще делает? значит? Безумие! Не могу даже написать правильную карту сокровищ, т 'бесполезный кретин. Исправь это нас! Мы подарим тебе долю сокровищ! "

Описание задачи

Группа пиратов с трудом читает карту сокровищ. Можете ли вы написать программу для преобразования ее в более ... пиратскую форму?

В качестве входных данных вы получите оригинальную карту сокровищ. Это список строк, разделенных запятыми, каждая строка состоит из буквенной части (которая сообщает пиратам, в каком направлении им нужно идти) и числовой части (которая сообщает пиратам, сколько шагов нужно предпринять в этом направлении). Например, следующая карта сокровищ:

E2,N4,E5,S2,W1,S3

означало бы: «пройти два шага на восток, пройти четыре шага на север, пять шагов на восток, два шага на юг, один шаг на запад, а затем три шага на юг».

Как выход, вы будете выводить карту в графическом виде, используя символы >, ^, v, и в <качестве указателей. Вот вывод для вышеуказанного ввода:

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

Обратите внимание, что мы заменили последний шаг на юг Xвместо этого. Это потому, что последний шаг - это то, где находится сокровище, и, как мы все знаем, пираты должны иметь X на своих картах сокровищ, иначе они не будут знать, как их прочитать.

Кстати, карта никогда не пересечет сама себя, поэтому вам не нужно беспокоиться о перекрытиях. Кроме того, вам разрешено иметь завершающую новую строку в конце вывода.

Образцы входов и выходов

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

1
Разрешено ли иметь пробелы в каждой строке? Всегда ли число будет меньше десяти?
Downgoat

9
Я действительно думаю, что Xследует отметить шаг после последнего хода, как и все другие ходы. Представьте, что последний шаг - это N3: вы идете три шага на север и копаете, но здесь ничего нет, вместо этого вам пришлось пройти 2 шага. Я не против, если вы сохраните существующее правило, потому что оно добавляет небольшой угловой случай для обработки. Но помни, что случилось с этим парнем.
coredump

6
@coredump Или, может быть, мы хотим ввести в заблуждение пиратов, чтобы мы могли сами взять сокровища;) Нет, вы правы, пираты копают один шаг слишком рано. Поскольку уже есть три ответа, я буду придерживаться правила, чтобы избежать аннулирования существующих решений.
Абсент

4
@ jpmc26 Ну, эти пираты плохо знают алфавит ... последние несколько лет они провели в C :)
абсент

4
Четвертый пример - просто троллинг пиратов ...
justhalf

Ответы:


8

Рубин, 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]}*""}

Пройдите ввод через стандартный ввод.

При этом используется y -> x -> charсловарь для построения карты, где оба xи yмогут быть отрицательными. После анализа входных данных извлекается глобальный минимум координаты x. Затем для каждой строки выполняется итерация по диапазону от глобального минимума до максимального индекса для текущей строки и выводится правильный символ для этого индекса.

Для того, чтобы остаться с темой, выражения для включения NESWв соответствующие индексы бесстыдно пиратский из Sp3000 «s ответа .

Оригинальная версия, которая использовала [x,y] -> charсловарь:

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

20

Python 2, 249 248 244 239 237 байт

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

Ввод как "E2,N4,E5,S2,W1,S3".

NSEWсопоставлен [1, 3, 2, 0]с d=ord(c)%10%7. Изменять yили xзатем решать d%2, а увеличивать или уменьшать - d-2|1. Первое и третье выражения были найдены методом грубой силы.

Помимо этого, это простое использование вложенного словаря в форме {y: {x: char}}.

(Спасибо @joriki за помощь с отображением)


1
(d + 1 & 2) - 1
Йорики

1
@joriki Ах, это хорошее выражение - спасибо!
Sp3000

2
Вот некоторый код, который я написал (в другом контексте) для поиска простых выражений для целочисленных функций. Я не использовал это для этого, но просто подумал, что это может быть интересно для вас. (Соответствующий код начинается там, где написано «Это код, который я использовал для оптимизации кодирования».)
joriki

3
@joriki Грубое принуждение - отличная идея - только что появился 1|d%-3(что является отрицанием, но я только что понял, что это тоже хорошо)!
Sp3000

14

Javascript (ES6), 260

Это было интересно ...

Спасибо @ETHproductions, @ edc65 и @vihan за помощь!

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}

Это определяет анонимную функцию, поэтому для ее вызова добавьте f=в начало, чтобы дать ей имя.

Тестировать: console.log(f("E2,N4,E5,S2,W1,S3"))

Объяснение:

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

3
Это хороший способ отделить утверждения! Это, безусловно, гораздо удобнее для чтения, чем помещать все в одну строку и разделять их точками с запятой. Если я могу предложить мое предложение: вы можете сохранить байты, перемещая i++из forпетли на последнее место он используется, в этом случае c=i++>r-2?"X":c.
ETHproductions

1
Кроме того, поскольку вы используете ES6, я бы посоветовал использовать v[0].repeat(+v.slice(1))вместо Array(v.slice(1)- -1).join(v[0])и " ".repeat(j-p-1)вместо Array(j-p).join(" ")экономии всего 11 байт. Я думаю, что вы также можете поместить F='forEach'в начало функции, а затем поменять каждую .forEachиз них на [F]другую, сохранив еще 4.
ETHproductions

1
Попробуйте использовать .map вместо .forEach. Оно настолько короткое, что его даже не нужно сокращать до F
edc65

1
@UndefinedFunction, вы можете использовать сокращения для ifs, это может помочь, если вы уменьшаете переменные одновременно
Downgoat

1
Если мое понимание правильное, q=x=y=2e3значит ли это, что вывод был бы неправильным, если бы я сказал, скажем W9999,?
Sp3000

7

PHP, 431 417 байт

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

Поместите его в файл ( treasure.php), удалите отступы, соедините строки (здесь они обернуты для удобства чтения), поместите <?phpмаркер в начало файла (здесь не отображается, поскольку технически он не является частью программы).

Пример исполнения:

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

Опция -d error_reporting=0необходима для подавления уведомлений о значениях, не найденных по указанным индексам в $z.

Обновить:

Пока я готовил версию кода для публикации, я обнаружил, что он содержит два ненужных назначения (12 байт) и пробел, который можно удалить ( as$i); Кроме того , путем замены whileс forпетлей и сжимая назначение в него (не возможно с помощью whileпетли) Я сохранил другие байты.


Я хотел бы увидеть версию без гольфа.
Ларс Эберт

1
@LarsEbert Я обновил ответ со ссылкой на неопрятный код. Я проверил ваше решение сейчас (раньше не делал); мы в основном использовали тот же алгоритм. Ваш последний шаг лучше, чем мой. Я могу удалить еще 25 байтов, если я реализую $count --;.
Axiac

$argnсохранить 3 байта chopсохранить 1 байт "X"-> Xиспользовать константы сохранить больше байтов
Йорг Хюльсерманн

@ JörgHülsermann Я не понимаю, $argnнамек. Я знаю об этом "X"->Xтрюке, но я, вероятно, забыл об этом, когда писал это решение. Я пишу код PHP с 2002 года, но до сегодняшнего дня я не заметил, что PHP предоставляет эту chop()функцию. Спасибо за этот совет.
Аксиак

7

Perl 702 613 546 474 439 338 260 байт

Спасибо Dom Hastings за его помощь и его супергольфированную версию.
Код использует 2D-массив.

Версия от Дома Гастингса:

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

Моя маленькая играющая в гольф версия 338 байт (для справки):

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

Контрольная работа

$ 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< ^<<
 >>>>>^

3
Если вы не используете use strict;, вам не нужны все mys, которые сэкономят вам хотя бы несколько байтов. Также ==короче, чем eqпоследний требует пробелов.
Алекс А.

1
Если я не ошибаюсь, вы только вызова $mодин раз, так что вместо того , чтобы хранить аргумент командной строки в качестве переменной, вы можете вызвать его непосредственно в split, то есть @m=split(',',$ARGV[0]).
Алекс А.

1
Привет @LukStorms, рад видеть больше игроков в Perl! Несколько вещей, которые помогут сэкономить несколько байтов! Ваши $dи $sпеременные могут быть получены с помощью регулярных выражений, чтобы сэкономить вам несколько байтов ($d,$s)=/^(.)(.+)$/, и все foreachs могут быть for(так как они одинаковые. Вы также можете сохранить некоторые символы, заменив некоторые из них на map{..., }@xтак как вы можете игнорировать парены вокруг повторяющегося элемента (это хорошо работает, если вам нужно содержать другие циклы). Если вы используете, $ARGV[0]вы можете заменить его на pop, но если вы используете сценарий, как в, perl script.pl <<< "text"вы можете использовать <>вместо этого
Dom Hastings

1
Если вы хотите сохранить скрипт, используя args, вы можете использовать, popчтобы сохранить пару. Вместо того , чтобы use Swtichи switch/ caseзаявления, вы могли бы сделать отдельные проверки , которые могут спасти вас байтов. Нечто подобное также $y-="N"eq$dбудет работать (так как true 1и false есть ''). Часто вы можете иметь слова как голые слова, так что $y-=N eq$dбудет работать! Есть некоторые магические переменные, которые вы можете использовать для сохранения байтов, $/есть '\n'и $"есть ' ', но иногда буквальный символ новой строки может также помочь сохранить символ. Еще один (грязный!) Трюк - это несколько назначений, чтобы сохранить еще несколько, как это $a=0;$b=0;может быть $a=$b=0.
Дом Гастингс

1
Еще несколько, я обещаю. Я надеюсь, что это та информация, которая вам нужна! Отсутствие паренов в вызовах функций - довольно стандартное изменение, поэтому substr($_,0,1)может быть substr$_,0,1. Постфикс для циклов, и если проверки также могут быть полезны, как в for(@c){...}сравнении, ...for@cно вы не можете использовать их ;в коде, вам придется вместо этого использовать запятую (что не всегда работает при вызове функций). На codegolf.stackexchange.com/questions/5105/… есть много отличных советов . Удачи!
Дом Гастингс

5

Python 2, 394 байта

Запустите программу и вставьте в стандартный ввод, например: "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])

Это не очень оптимизировано. Сначала он проходит через вход для записи пути. Затем он делает некоторые математические вычисления, чтобы определить правильную начальную позицию и размер o. Затем он запускается снова и устанавливает соответствующие записи в oкачестве одного из >v<^X. Основной ум заключается в повторном использовании одной и той же функции для обоих этих обходов.


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 не часто даже немного конкурентоспособен, так что это было весело.

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

4

PHP, 496 514 528

Я попытал счастья в PHP, результат довольно длинный, я все еще хочу опубликовать его, просто для удовольствия.

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

?>

1
Может быть много уменьшено. Например, вы можете просто написать for(;$i++<$f;), попробовать удалить ненужные скобки, использовать неопределенные константы ( N) вместо strings ( 'N'),…
Blackhole

1
Вместо ifs попробуйте использовать trenary-операторы или логические ands. Кроме того, это поможет, если вы используете PHP4.1 и используете массив GET с точками.
Исмаэль Мигель

3

JavaScript (ES6), 244 249 274

Лидирующие пробелы и символы новой строки добавлены для ясности и не учитываются, кроме новой строки ближе к концу в вызове соединения, который является значимым и учитывается.

Тестовый запуск фрагмента (только ECMAScript 6, Firefox и 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>


2

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

Безголовая версия:

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

Динамическое распределение памяти не намного сложнее, но malloc слишком длинный идентификатор, чтобы использовать его в коде гольф. Я чувствую, что должен быть какой-то заголовок PCG.h, юридически включенный автоматически для игры в гольф в c, просто чтобы замкнуть некоторые идентификаторы.


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

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

Реализация без массивов: печатает сверху вниз, слева направо.

  • Разобрать и расширить направления в след (x y char)элементов:

    Простой "N3" ввод производит ((0 0 #\^) (0 -1 #\^) (0 -2 #\X))

  • Кроме того, рассчитать минимальное xиy
  • Сортировать полученный след yсначала, а затем поx
  • Перебирать отсортированный список при перемещении курсора

    1. Добавьте новые строки и пробелы, чтобы переместить текущий курсор в нужную позицию
    2. В положении x - minx, y - minyраспечатайте нужный символ

Примеры

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

Результат:

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

>v>v
^>^X

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

1

CoffeeScript, 303   285 байт

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'

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.