Programowanie spiralne

14

Napisz nazwaną funkcję lub program, który akceptuje pojedynczą liczbę całkowitą N i wypisuje (do STDOUT) lub zwraca (jako ciąg) pierwsze N ​​słupków spirali poniżej, zaczynając od pionowego paska w środku i spiralnie zgodnie z ruchem wskazówek zegara na zewnątrz.

        _______________
       / _____________ \
      / / ___________ \ \
     / / / _________ \ \ \
    / / / / _______ \ \ \ \
   / / / / / _____ \ \ \ \ \
  / / / / / / ___ \ \ \ \ \ \
 / / / / / / / _ \ \ \ \ \ \ \
/ / / / / / / / \ \ \ \ \ \ \ \
| | | | | | | | | | | | | | | |
\ \ \ \ \ \ \___/ / / / / / / /
 \ \ \ \ \ \_____/ / / / / / /
  \ \ \ \ \_______/ / / / / /
   \ \ \ \_________/ / / / /
    \ \ \___________/ / / /
     \ \_____________/ / /
      \_______________/ /

Możesz założyć, że 0 <N <= 278. Twoje dane wyjściowe nie mogą zawierać żadnych spacji przed skrajnym lewym znakiem spirali. Możesz opcjonalnie wydrukować jedną końcową linię nowego wiersza.

Dla wejścia 10 poprawne wyjście to

   _
  / \ 
  | | 
\___/

Dla wejścia 2 prawidłowe wyjście to

/
|

Dla wejścia 20 poprawne wyjście to

  ___
 / _ \
/ / \ \ 
| | | |
\___/ /

Dane wyjściowe, które byłyby niepoprawne, ponieważ lewy znak jest poprzedzony spacją, to

       ___
      / _ \
     / / \ \ 
     | | | |
     \___/ /

Zwycięzca jest najkrótszym przesłaniem, w bajtach.

Rainbolt
źródło
To dziwna spirala, 6/8 stron rośnie na obrót, a 2 pozostają w rozmiarze 1
Devon Parsons,
1
@DevonParsons Pomyśl o tym, że ma sześciokątną spiralę, w której pionowe kreski ( |) są tylko najbliższymi znakami, które mogą reprezentować spotkanie a /i \.
mbomb007

Odpowiedzi:

5

CJam - 156/147

L{[W1]{:I0'|{IIW*:J'/}X*[0J'_]X2*I+*[J0_]I1={\}*{J_'\}X*0I0}%L*3/{~_{[UV@]a3$+}{;@}?V@+:V;U@+:U;}/}A,1>fX]ri=_z::e<2<f{[\\]z::-}$_W=0=)S50*a*\{~3$3$=\tt}/N*

Wypróbuj online

Działa z wejściami od 1 do 378 włącznie (100 więcej niż wymagane)

Korzystając z najnowszego zatwierdzonego (publicznie dostępnego w hg), ale niepublikowanego kodu CJam w momencie opublikowania tego wyzwania, rozwiązanie można skrócić do 147 znaków:

L{[W1]{:I0'|{IIW*:J'/}X*[0J'_]X2*I+*[J0_]I1={\}*{J_'\}X*0I0}%L*3/{~_{[UV@]a3$+}{;@}?V@+:V;U@+:U;}/}A,1>fX]ri=_:.e<2<f.-$_W=0=)S50*a*\{~3$3$=\tt}/N*

Wyjaśnienie:

Program iteracyjnie konstruuje wszystkie spirale jako tablice [xy znaków] zaczynając od [0 0 '|], pobiera żądaną spiralę, dostosowuje współrzędne tak, aby minimalne xiy wynosiły 0, tworzy macierz odstępów (z prawidłową liczbą wierszy i 50 kolumn ) ustawia znaki ze spirali i łączy wiersze z nowymi wierszami.

L                   start with an empty array (spiral no. 0)
{…}A,1>fX           for X in 1..9 (A=10)
                    each X represents a full 360° tour with groups of X /'es and \'es
    [W1]{…}%        transform the array [-1 1] (W=-1) applying the block to each item
                    the block generates a series of triplets dx, dy, character
                    note: dx is down, dy is right; -1 handles ↑↗→↘, 1 handles ↓↙←↖
        :I          store the current item in I
        0'|         add 0 and |, which will form a triplet with the previous I
        {…}X*       repeat X times
            IIW*    add I and -I
            :J'/    also store -I in J, and add /
        [0J'_]      make an array [0 J _]
        X2*I+*      repeat the array X*2+I times
        [J0_]       make an array [J 0 0]
                    (a 0 instead of a character means only changing the position)
        I1={\}*     if I=1, swap the two arrays (the position adjustment is different
                    for the upper and lower horizontal sections)
        {…}X*       repeat X times
            J_'\    add J, J and \
        0I0         add 0, I and 0 (another position adjustment)
    L*              flatten the array (since we added a few inner arrays)
    3/              split into [dx dy char] triplets
    {…}/            for each triplet
        ~_          dump the 3 items on the stack and duplicate the character
        {…}         if the character is not 0
            [UV@]   make an array [U V char] (U and V are initially 0)
                    U represents "x" and V represents "y"
            a3$+    add it as an element to a copy of the previous spiral
        {…}         else
            ;@      pop the character and bring the previous spiral to the top
        ?           end if
        V@+:V;      V+=dy
        U@+:U;      U+=dx
]                   put all the spirals in an array
ri=                 read token, convert to integer and get that spiral
_z::e<              copy the spiral and get a triplet with the minimum values
2<                  keep only the first 2 items (xmin and ymin)
f{…}                for each triplet and the array [xmin ymin]
    [\\]z::-        subtract xmin and ymin from x and y in the triplet
                    (in the latest CJam code this is simply ".-")
$                   sort the spiral (putting the triplets in order by x then y)
_W=0=)              get the maximum (updated) x and increment it
S50*                make a string of 50 spaces
a*                  put it in an array and repeat it xmax+1 times
                    this is the initial matrix of spaces
\                   swap with the spiral
{…}/                for each triplet in the spiral
    ~               dump the 3 items (x y char) on the stack
    3$3$=           copy the matrix and x, and get the x'th row
    \t              swap with the character and put that character in the y'th position
    t               put the modified row in the x'th position in the matrix
N*                  join the matrix rows with newlines
aditsu zrezygnowało, ponieważ SE jest ZŁEM
źródło
8

Python 2, 290 289

Prawdopodobnie jest naprawdę źle, ale próbowałem: D

Dane wyjściowe zawierają końcowe spacje, ale nie jest to zabronione w specyfikacji.

Aktualizacja: zapisano 1 bajt ze zmianą \nna ;.

m=x=y=c=0
l,f=1,[31*[' ']for t in[0]*31]
for i in[0]*input():
 k=m%4;f[14+y+(2<m<6)][14+x-(m>3)],x,y,c='|/_\\'[k],x+(k>0)*(2*(4>m)-1),y+(k!=2)*(2*(2<m<6)-1),c+1
 if(c==l)*(m%2)+(k==0)+(k==2)*(c==2*l-1+m//3):m,c,l=(m+1)%8,0,l+m//7
print'\n'.join(''.join(e[16-l*2:])for e in f if[' ']*31!=e)
PurkkaKoodari
źródło
Spacje końcowe są w porządku. Przetestowałem to. Dobra robota!
Rainbolt,
4

JavaScript (ES6) 257 288 321

Scalono edycję kroków.
Edytuj kodowanie gry w golfa, aby wyciąć więcej znaków

Wbuduj wynik iteracyjnie w tablicę r, śledząc bieżącą pozycję xiy oraz kierunek prądu. Gdy pozycja x lub y wynosi <0, cała tablica r jest ponownie dostosowywana.

Główne zmienne:

  • tablica wyników lub wiersze
  • x, y aktualna pozycja.
  • s aktualny kierunek (0..7) (lub aktualny stan)
  • d obecny symbol do narysowania (0..3) -> '| \ _ /'
  • l pozycja bieżąca w bieżącej sekwencji (do 0)
  • w aktualny promień spiralny (mniej więcej)
F=n=>
  (w=>{
    for(r=b=[],s=y=x=d=0;n--;
      d&&--l||((s=s+1&7,d=s&3)?l=d-2?w:s/2-2+w+w:w+=!s))
      s>0&s<4?++x:s>4?x?--x:r=r.map(v=>' '+v):b+='  ',
      q=r[s>2&s<6?++y:y]||b,
      r[y]=(q+b).slice(0,x)+'|/_\\'[d]+q.slice(x+1),
      s<2|s>6?y?--y:r=[,...r]:x+=!d*2,x-=!d
  })(1)||r.join('\n')

Nie golfił

F=n=>{
  var r=[], s,x,y,d,w,l, q
  for(l=w=1, s=x=y=d=0; n--;)
  {
    if (s>2 && s<6) ++y; // right side, inc y before drawing

    if (x < 0) // too left, adjust
    {
      r = r.map(v=>' '+v) // shift all to right
      ++x; // move current position to right
    }
    if (y < 0) // too up
    {
      r = [q='',...r] // shift all to bottom
      ++y; // move current position to bottom
    }
    q = r[y] || ''; // current row, if undefined convert to empty string
    r[y] = (q+' '.repeat(x)).slice(0,x) + '|/_\\'[d] + q.slice(x+1); // add current symbol in the x column

    if (s<2 || s>6) --y; // left side, dec y after drawing

    if (s>0 && s<4) // always change x after drawing
      ++x;
    else if (s > 4)
      --x;

    --l; // decrement current run
    if (l == 0) // if 0, need to change direction
    {
      s = (s+1) % 8; // change direction
      d = s % 4; // change symbol
      if (d == 0)
      { 
        // vertical direction, adjust x and if at 0 increase radius
        l = 1 // always 1 vertical step
        if (s == 0)
          ++x, ++w
        else
          --x
      }
      else
      {
        if (d != 2)
        {
          l = w; // diaagonal length is always w
        }
        else if (s == 2)
        {
          l = w+w-1 // top is radius * 2 -1
        }
        else
        {
          l = w+w+1 // bottom is radius * 2 +1
        }
      }
    }
  }    
  return r.join('\n')
}  

Test w konsoli Firefox / FireBug (lub JSFiddle thx @Rainbolt)

;[1, 2, 10, 20, 155, 278].forEach(x=>console.log(F(x)))

Wynik

|

/
|

   _
  / \
  | |
\___/

  ___
 / _ \
/ / \ \
| | | |
\___/ /

      ___________
     / _________ \
    / / _______ \ \
   / / / _____ \ \ \
  / / / / ___ \ \ \ \
 / / / / / _ \ \ \ \ \
/ / / / / / \ \ \ \ \ \
| | | | | | | | | | | |
\ \ \ \ \___/ / / / /
 \ \ \ \_____/ / / /
  \ \ \_______/ / /
   \ \_________/ /
    \___________/

        _______________
       / _____________ \
      / / ___________ \ \
     / / / _________ \ \ \
    / / / / _______ \ \ \ \
   / / / / / _____ \ \ \ \ \
  / / / / / / ___ \ \ \ \ \ \
 / / / / / / / _ \ \ \ \ \ \ \
/ / / / / / / / \ \ \ \ \ \ \ \
| | | | | | | | | | | | | | | |
\ \ \ \ \ \ \___/ / / / / / / /
 \ \ \ \ \ \_____/ / / / / / /
  \ \ \ \ \_______/ / / / / /
   \ \ \ \_________/ / / / /
    \ \ \___________/ / / /
     \ \_____________/ / /
      \_______________/ /
edc65
źródło
Przetestowałem to i działa. Oto jsfiddle, który pokazuje, że twoja odpowiedź działa. Dołącz ją do swojej odpowiedzi.
Rainbolt,
2

Pyth 166 165

Właśnie przetłumaczyłem moją odpowiedź na Pythona na Pyth, używając moich niezbyt dobrych umiejętności w Pythonie. Powstałe wymioty są poniżej.

Jm*31]d*31dK0=G0=H0=Y1VQ X@J++14H&<2K<K6+14-G<3K@"|/_\\"%K4~G*<0%K4-*2>4K1~H*n2%K4-*2&<2K>6K1~Z1I||&qZY%K2!%K4&q2%K4qZ+-*2Y1/K3~Y/K7=K%+1K8=Z0;jbmj>d-16*2Ykfn*31]dTJ
PurkkaKoodari
źródło