Складемо карту підземелля


9

Давно, коли я витрачав більше часу, граючи на RPG, одним із питань, які мали деякі гравці, було відстеження руху партії та складання належної карти. Тож я прийшов з ідеєю, щоб перевірити, як ви, хлопці, підходите до цього питання.

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

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

Тестові шафи

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



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


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

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

Оскільки це виклик коду для гольфу, виграє найкоротший код.

Щасливий гольф.

EDIT Вибачте за пізнє редагування, останнім часом у мене не було багато часу.

Карта формується на основі руху. Він повинен містити лише коридори, які відвідували під час прогулянки. Отже, створення однієї великої кімнати не буде коректною відповіддю.

На карті є три дійсні символи:

  • | вертикальна стіна
  • | горизонтальна стіна
  • + перетин вертикальної та горизонтальної стіни.

Максимальна довжина шляху - 255 символів (але якщо ви можете, не обмежуйте себе).

Більше тестових випадків:

 ><><><><

 +--+
 |  |
 +--+

 >^<v

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

Сподіваюся, зараз усе зрозуміло.


3
Потрібно надати опис завдання. Два тестових випадки навіть не обробляються таким чином, що здається послідовним - перший додає відключену область без видимих ​​причин.
feersum

3
У вашому другому прикладі є закрита кімната, яку я спочатку вважав, що зовнішня межа повинна бути прямокутною, але потім третій приклад спростовує цю ідею. Будь ласка, використовуйте пісочницю, щоб отримати відгук про виклик перед публікацією.
El'endia Starman

2
Відмінно. Я б ще запропонував бути чітким щодо того, як будується підземелля з рухів.
El'endia Starman

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


Ви можете видалити return, замінивши ;з ,і {}з()
Cyoce

@Cyoce - Там є forпетля, яку неможливо вбудувати таким чином.
Арнольд

потім замінити {з eval("і }з , ")щоб видалити поворотні codegolf.stackexchange.com/a/80967/41042
Cyoce

@Cyoce - На жаль, я думаю, що мені потрібно було б уникнути буквальної лінії, як '\\n'ніби я це роблю. Якщо я порахую правильно, це насправді призводить до +1 байту. Або є кращий спосіб вбудувати лінію лінії в евал?
Арнальд

Вам знадобиться лише \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)}}'

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

Виходи до stdout. Використовує той факт, що накладка дозволена навколо карти (створюється карта з довжиною ребра 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)
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.