Zróbmy mapę lochu

9

Dawno, dawno temu, kiedy spędzałem więcej czasu grając w RPG, jednym z problemów, jakie mieli niektórzy gracze, było śledzenie ruchu drużyny i narysowanie odpowiedniej mapy. Wpadłem na pomysł, żeby sprawdzić, jak sobie radzicie z tym problemem.

Zadanie polega na napisaniu funkcji, która jako listę parametrów wejściowych przyjmuje kierunki (przekazane jako wybrana przez Ciebie struktura) ^v<>, wyświetla mapę lochu. Na przykład dla danych wejściowych: >>>vvv<<<^^^wyjście będzie:

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

Przypadki testowe

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



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


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

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

Ponieważ jest to wyzwanie dla kodu golfowego, wygrywa najkrótszy kod.

Wesołego golfa.

EDYCJA Przepraszam za późną edycję, ostatnio nie miałem dużo czasu.

Mapa jest generowana na podstawie ruchu. Powinien zawierać tylko korytarze, które odwiedzono podczas spaceru. Dlatego utworzenie jednego dużego pokoju nie będzie prawidłową odpowiedzią.

Na mapie znajdują się trzy prawidłowe symbole:

  • | pionowa ściana
  • | ściana pozioma
  • + przecięcie ściany pionowej i poziomej.

Maksymalna długość ścieżki wynosi 255 znaków (ale jeśli możesz, nie ograniczaj się).

Więcej przypadków testowych:

 ><><><><

 +--+
 |  |
 +--+

 >^<v

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

Mam nadzieję, że teraz wszystko jest jasne.

użytkownik902383
źródło
3
Musisz podać opis zadania. Dwa przypadki testowe nie są nawet obsługiwane w sposób, który wydaje się spójny - pierwszy dodaje odłączony region bez wyraźnego powodu.
feersum
3
W twoim drugim przykładzie jest zamknięty pokój, co początkowo myślałem, że zewnętrzna krawędź powinna być prostokątna, ale trzeci przykład obala ten pomysł. Skorzystaj z piaskownicy, aby uzyskać opinię na temat wyzwania przed opublikowaniem.
El'endia Starman
2
Świetny. Nadal sugeruję wyraźne określenie budowy lochu na podstawie ruchów.
El'endia Starman
1
Co rozumiesz przez „wyświetl mapę”? Czy dozwolone jest zwracanie mapy z funkcji?
Paul Schmitz
3
To wygląda interesująco. Czy jest jakaś szansa na edycję, aby ponownie otworzyć? Rzeczy, na które należy zwrócić szczególną uwagę: z przykładów wygląda na to, że nie przeszkadza ci dodatkowe białe znaki wokół wyjścia, ale dobrze byłoby wyjaśnić. Również jeśli wyraźnie opisujesz wygląd ściany i odpowiadasz na pytanie mleka, powinno ono być wystarczająco jasne. Jedną z rzeczy, myślę, że nie zostały pokryte, co wyjście vvv>>^^^<<będzie produkować (krzyże rur?)
Dave

Odpowiedzi:

3

JavaScript (ES6), 261 254 243 bajtów

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
źródło
Można usunąć returnprzez zastąpienie ;z ,oraz {}z()
Cyoce
@Cyoce - Jest tam forpętla, której nie można osadzić w ten sposób.
Arnauld,
następnie zastąpić {z eval("i }w ")celu usunięcia powrotne codegolf.stackexchange.com/a/80967/41042
Cyoce
@Cyoce - Niestety, myślę, że musiałbym uciec od dosłownego przełamania linii '\\n', jakbym to zrobił. Jeśli policzę poprawnie, to faktycznie prowadzi do +1 bajtu. Czy jest lepszy sposób na osadzenie podziału linii w eval?
Arnauld,
Będziesz potrzebował tylko, \nponieważ ciągi szablonów obsługują dosłownie nowe wiersze, ale nadal pozostawiłoby to tę samą liczbę bajtów. No cóż
Cyoce,
3

C, 246 bajtów

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

Traktuje dane wejściowe jako osobne znaki, na przykład:

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

Lub wygodniej ten (celowo nie cytowany!) Format:

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

Lub dla (dość nieefektywnego) losowego wprowadzania danych:

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

I wreszcie, użycie awkdo przycięcia wyniku oznacza, że ​​możemy stać się znacznie większy:

./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)}}'

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

Wyjścia na standardowe wyjście. Wykorzystuje fakt, że dopełnienie jest dozwolone wokół mapy (tworzy mapę, która ma długość krawędzi 2 * n + 1, umieszczając ostateczną pozycję na środku).

Awaria

Działa to poprzez zapętlanie argumentów w odwrotnej kolejności i poruszanie się w odwrotnej kolejności. Wykorzystuje fakt, że arg 0 jest nazwą programu; nie ma znaczenia, jak się nazywa, ale pozwala nam odwiedzić zarówno początkową, jak i ostatnią komórkę (a także wszystkie komórki pomiędzy nimi) bez potrzeby specjalnej obsługi.

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