Давайте сделаем карту подземелья

9

Давным-давно, когда я проводил больше времени за игрой в RPG, одной из проблем, с которой сталкивались некоторые игроки, было отслеживание движения группы и составление правильной карты. Итак, я пришел с идеей, чтобы проверить, как вы, ребята, решаете эту проблему.

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

+----+               +----+
|    |               |>>>v|
| ++ |               |^++v|
| ++ |  because      |^++v|
|    |               |^<<<|
+----+               +----+

Testcases

>>>>>>vvvvv<<<<^^^>>v



 +-------+
 |       |
 +-+---+ |
   |   | |
   | + | |
   | +-+ |
   |     |
   +-----+


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

          +-+ 
       +-+| | +-++-+
       | || | | ++ ++
       | ++ +-+     |
       |        +-+ |
       +--+ +-+ +-+-+
          | | |   |
          +-+ +---+

Так как это вызов гольф-кода, выигрывает самый короткий код.

Счастливого гольфа.

РЕДАКТИРОВАТЬ Извините за позднее редактирование, у меня не было много времени в последнее время.

Карта генерируется на основе движения. Он должен содержать только коридоры, которые посещали во время прогулки. Следовательно, создание одной большой комнаты не будет правильным ответом.

На карте есть три действительных символа:

  • | вертикальная стена
  • | горизонтальная стена
  • + пересечение вертикальной и горизонтальной стен.

Максимальная длина пути составляет 255 символов (но если вы можете, не ограничивайте себя).

Больше тестовых случаев:

 ><><><><

 +--+
 |  |
 +--+

 >^<v

 +--+
 |  |
 |  |
 +--+

Надеюсь теперь все ясно.

user902383
источник
3
Вам необходимо предоставить описание задачи. Два тестовых примера даже не обрабатываются таким образом, который выглядит согласованным - первый добавляет отключенную область без видимой причины.
февраля
3
Ваш второй пример имеет закрытую комнату, которую я изначально думал, потому что внешняя граница должна быть прямоугольной, но затем третий пример опровергает эту идею. Пожалуйста, используйте Песочницу, чтобы получить отзыв о проблеме перед публикацией.
El'endia Starman
2
Отлично. Я бы по-прежнему предлагал подробно рассказать о том, как подземелье строится из движений.
Эльендия Старман
1
Что вы подразумеваете под «отображать карту»? Разрешен ли возврат карты из функции?
Пол Шмитц
3
Это выглядит интересно. Есть ли какой-нибудь шанс на редактирование, чтобы открыть его заново? На что стоит обратить особое внимание: из примеров видно, что вы не возражаете против лишних пробелов в выводе, но было бы хорошо уточнить. Также, если вы явно опишите внешний вид стены и ответите на вопрос молока, это должно сделать вопрос достаточно ясным. Я думаю, вы не рассмотрели одну вещь: какой выход vvv>>^^^<<будет производить (пересекает? Трубы?)
Дейв

Ответы:

3

Javascript (ES6), 261 254 243 байта

s=>{v=Array(w=32);p=526;b=n=>v[n>>5]&(1<<(n&31));B=(n,i)=>b(p+n)|b(p-n)?i:0;[...0+s].map(c=>v[(p+=[0,1,-1,w,-w]['0><v^'.indexOf(c)])>>5]|=1<<(p&31));for(z='',p=0;p<w*w;z+=' |-+'[b(p)?0:B(1,1)|B(w,2)||B(31,3)|B(33,3)],p++%w||(z+=`
`));return z}

JSFiddle

Arnauld
источник
Вы можете удалить return, заменив ;с ,и {}с()
Cyoce
@Cyoce - там есть forцикл, который не может быть встроен таким образом.
Арнаулд
затем заменить {с eval("и }с , ")чтобы удалить возвратные codegolf.stackexchange.com/a/80967/41042
Cyoce
@Cyoce - К сожалению, я думаю, что мне нужно избежать буквального разрыва строки, как '\\n'если бы я это сделал. Если я считаю правильно, это на самом деле приводит к +1 байт. Или есть лучший способ вставить разрыв строки в Eval?
Арнаулд
Вам понадобится только то, что \nстроки шаблона поддерживают буквально новые строки, но это все равно оставит его при том же количестве байтов. О, хорошо
Cyoce
3

C 246 байт

n,y,*g,*p;main(c,v)char**v;{for(n=c*2+3,g=calloc(n*n,8),p=g+(n+1)*(c+1);c--;y=*v[c],p-=(y>70?n:1)*(y%5%4?-1:1))*p=1;for(y=n-1;--y;)for(c=n-1;c--;putchar(c?" |-++|-+"[*p?0:p[1]|p[-1]|(p[n]|p[-n])*2|(p[1+n]|p[1-n]|p[n-1]|p[-n-1])*4]:10))p=g+y*n+c;}

Принимает ввод как отдельные символы, например:

./mapper '>' '>' '>' 'v' 'v' 'v' '<' '<' '<' '^' '^' '^'

Или, что более удобно, этот (намеренно без кавычек!) Формат:

./mapper $(echo '>>>vvv<<<^^^' | fold -w1)

Или для (довольно неэффективного) случайного ввода:

./mapper $(LC_CTYPE=C tr -dc '0-3' < /dev/urandom | tr '0123' '<>^v' | head -c 10 | fold -w1)

И, наконец, использование awkдля обрезки результата означает, что мы можем получить гораздо больше:

./mapper $(LC_CTYPE=C tr -dc '0-3' < /dev/urandom | tr '0123' '<>^v' | head -c 500 | fold -w1) | awk '/[^ ]/{l=match($0,"\\+");if(l&&(l<L||!L))L=l;v[i++]=$0}END{for(;j<i;){l=v[j++];print substr(l,L,match(l," *$")-L)}}'

 +-----+
 |     |
 |     +-+  +-----+
 |       |+-+     |
++       +|      ++
|         |      |
|         +      +-+
+--+               |
 +-+               +--+
 |     ++             |
 +-+  +-++           +-+
   ++   |+--+          |
    +-+ | |        ++  |
     ++ | ++   + +--+ ++
     |  |  +---|      |
     |  |     ++  +---+
     ++ |-+   |   |
      | | +--+-+  |
      | +    +    |
      |        +--+
      +--------+

Выходы в стандартный вывод. Используется тот факт, что для карты разрешено заполнение (создается карта с длиной ребра 2 * n + 1, в которой конечная позиция находится посередине).

Сломать

Это работает, перебирая аргументы в обратном направлении и двигаясь в обратном направлении. На самом деле он использует тот факт, что arg 0 - это имя программы; Неважно, какое это имя, но оно позволяет нам посещать как начальную, так и последнюю ячейку (а также все промежуточные ячейки) без специальной обработки.

n,                                  // Size of internal grid
y,                                  // Loop counter / current character
*g,                                 // Internal grid memory
*p;                                 // Current working pointer
main(c,v)char**v;{                  // K&R style function declaration
    for(                            // Step 1: identify visited cells
        n=c*2+3,                    //  Set output grid size
        g=calloc(n*n,8),            //  Allocate map storage space
        p=g+(n+1)*(c+1);            //  Start at centre
        c--;                        //  Loop over directions in reverse
        y=*v[c],                    //  Get current direction
        p-=(y>70?n:1)*(y%5%4?-1:1)  //  Move in reverse
    )*p=1;                          //  Mark cell visited
    for(y=n-1;--y;)                 // For each row (except edges)
        for(c=n-1;c--;              //   For each column (except edges, +1 for \n)
            putchar(c?" |-++|-+"[   //   Print wall using lookup table
                *p?0:p[1]|p[-1]|(p[n]|p[-n])*2|(p[1+n]|p[1-n]|p[n-1]|p[-n-1])*4
            ]:10)                   //   Or newline
        )p=g+y*n+c;                 //   Set current cell (happens first)
}
Дейв
источник