Spiral Programlama


14

Tek bir tamsayı N kabul eden ve ortadaki dikey çubuktan başlayıp saat yönünde dışarı doğru spirallenen aşağıdaki spiralin ilk N çubuklarını basan (STDOUT'a) veya dönen (dize olarak) adlı bir işlev veya program yazın.

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

0 <N <= 278 olduğunu varsayabilirsiniz. Çıktınızda, spiralin en soldaki karakterin önünde boşluk bulunamaz. İsteğe bağlı olarak tek bir satırsonu yazdırabilirsiniz.

10 giriş için doğru çıkış

   _
  / \ 
  | | 
\___/

2 girişi için doğru çıkış

/
|

20 giriş için doğru çıkış

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

En soldaki karakterin başında boşluk olduğu için yanlış olan bir çıktı

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

Kazanan, bayt cinsinden en kısa gönderimdir.


Bu garip bir sarmal, 6/8 taraf devir başına daha büyük büyüyor ve 2 boyut 1 kaldı
Devon Parsons

1
@DevonParsons Dikey çubukların ( |) yalnızca a /ve ' nin buluşmasını temsil edebilecek en yakın karakter olduğu altıgen bir spiral olduğunu düşünün \.
mbomb007

Yanıtlar:


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*

Çevrimiçi deneyin

1 ila 378 dahil (gerektiğinden 100 daha fazla) girişlerle çalışır

Bu zorluğun yayınlandığı sırada en son taahhüt edilen (hg olarak herkese açık) ancak yayınlanmamış CJam kodunu kullanarak çözüm 147 karaktere kısaltılabilir:

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*

Açıklama:

Program yineleyerek tüm spiralleri [xy karakteri] dizileri olarak oluşturur [0 0 '|], istenen spirali alır, minimum x ve y 0 olacak şekilde koordinatları ayarlar, boşluk matrisi oluşturur (doğru satır ve 50 sütunla) ) daha sonra karakterleri spiralden ayarlar ve satırları yeni satırlarla birleştirir.

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

8

Python 2, 290 289

Muhtemelen gerçekten kötü, ama denedim: D

Çıktının sonunda boşluklar var, ancak bu özellikte yasaklanmış değil.

Güncelleme: değişen 1 byte kaydedilir \niçin ;.

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)

Sondaki boşluklar iyi. Bunu test ettim. İyi iş!
Rainbolt

4

JavaScript (ES6) 257 288 321

Birleştirilen Adımları Düzenle .
Düzen işe yaramaz golfed kodu biraz daha kömürü kesmek

Geçerli x ve y konumunu ve geçerli yönü izleyerek çıkışı r dizisine tekrarlı olarak oluşturun. X veya y konumu <0 olduğunda, tüm r dizisi yeniden ayarlanır.

Ana değişkenler:

  • r sonuç dizisi veya satırları
  • x, y geçerli konumu.
  • s akım yönü (0..7) (veya geçerli durum)
  • d çizilecek geçerli sembol (0..3) -> '| \ _ /'
  • l Mevcut sekans üzerinde çalışma pozisyonu (0'a kadar)
  • w akım spiral yarıçapı (az ya da çok)
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')

Ungolfed

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

Firefox / FireBug konsolunda test (veya JSFiddle thx @Rainbolt)

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

Çıktı

|

/
|

   _
  / \
  | |
\___/

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

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

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

Bunu test ettim ve işe yarıyor. İşte cevabınızın çalıştığını gösteren bir jsfiddle . Cevabınıza dahil etmekten çekinmeyin.
Rainbolt

2

Pyth, 166 165

Sadece tercüme benim Python cevabı benim değil-büyük Pyth becerileri ile, Pyth için. Ortaya çıkan kusma aşağıdadır.

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.