29
\$\begingroup\$

Given the spiral of size S and the step N, output the "square" S*S spiral having N asterisks, built from the outer to inner radius clockwise.

Test cases (examples) below.

  1. Input: 4 3

    Output:

    ***
    
  2. Input: 4 6

    Output:

    ****
       *
       *
    
  3. Input: 4 11

    Output:

    ****
       *
    *  *
    ****
    
  4. Input: 6 18

    Output:

    ******
         *
         *
    *    *
    *    *
    ******
    
  5. Input: 6 22

    Output:

    ******
    ***  *
    *    *
    *    *
    *    *
    ******
    
  6. Input: 6 27

    Output:

    ******
    ******
    *   **
    *   **
    *   **
    ******
    
  7. Input: 1 1

    Output:

    *
    

It's not necessary to handle the cases when:

  • provided N asterisks can't "fit" in the spiral of given S*S dimensions.

  • either N or S is zero.

The challenge is code-golf, shortest bytes answer wins, any languages can be used.

Your output may have as many trailing (but not leading) spaces/newlines as you wish.

\$\endgroup\$
  • \$\begingroup\$ Can we have trailing spaces/newlines? \$\endgroup\$ – user202729 Apr 1 '18 at 15:43
  • 2
    \$\begingroup\$ I'd call S size (or at least diameter) rather than radius \$\endgroup\$ – Luis Mendo Apr 1 '18 at 15:58
  • \$\begingroup\$ @Luis fair point! \$\endgroup\$ – nicael Apr 1 '18 at 16:03
  • 3
    \$\begingroup\$ Dear friends, please vote on answers also, not just question. It's easy to make this challenge. Providing an answer to it is (I think) definitely more difficult. \$\endgroup\$ – nicael Apr 1 '18 at 19:07
  • 2
    \$\begingroup\$ Only you think so. Writing a well-received and clear challenge is very difficult. (just look at the comment thread right here, there are some suggestions after the challenge had been posted) \$\endgroup\$ – user202729 Apr 2 '18 at 2:18

11 Answers 11

16
\$\begingroup\$

MATL, 17 16 bytes

UGlYLGoQ&P->42*c

Try it online!

Explanation (with example)

Consider inputs 4 and 11 as an example.

U       % Implicit input: S. Push S^2
        % STACK: 16
G       % Push S again
        % STACK: 16, 4
lYL     % Outward, clockwise, east-first spiral of that size
        % STACK: 16,
                 [ 7  8  9 10;
                   6  1  2 11;
                   5  4  3 12;
                  16 15 14 13]
GoQ     % Push S, compute parity, add 1. Gives 1 for even S, 2 for odd
        % STACK: 16,
                 [ 7  8  9 10;
                   6  1  2 11;
                   5  4  3 12;
                  16 15 14 13],
                 1
&P      % Flip along that dimension (1 is vertical, 2 is horizontal).
        % This corrects for the orientation of the spiral
        % STACK: 16,
                 [16 15 14 13;
                   5  4  3 12;
                   6  1  2 11;
                   7  8  9 10]
-       % Subtract, element-wise. The upper-left corner becomes 0
        % STACK: [ 0  1  2  3
                  11 12 13  4
                  10 15 14  5
                   9  8  7  6]
>       % Implicit input (below): N. Greater than?, element-wise.
        % This transforms the first N entries, starting from
        % upper-left, inward, east-first, into 1, and the rest
        % into 0
        % STACK: [1 1 1 1;
                  0 0 0 1;
                  1 0 0 1;
                  1 1 1 1]
42*     % Multiply each entry by 42
        % STACK: [42 42 42 42;
                   0  0  0 42;
                  42  0  0 42;
                  42 42 42 42]
c       % Convert to char. Char 0 will be displayed as space.
        % Implicit display
        % STACK: ['****';
                  '   *';
                  '*  *';
                  '****']
\$\endgroup\$
  • 1
    \$\begingroup\$ Wow, I was never good at golfing, but solve it with 17 bytes... That looks like magic :) (I know that possibly the shorter answers are coming, but you're first and here're my impressions :) \$\endgroup\$ – nicael Apr 1 '18 at 16:02
  • 1
    \$\begingroup\$ Part of the job is done by a built-in spiral function. I just added an explanation \$\endgroup\$ – Luis Mendo Apr 1 '18 at 16:05
  • \$\begingroup\$ @nicael Welcome to the world of golfing languages aimed for specific purposes. :) \$\endgroup\$ – Erik the Outgolfer Apr 1 '18 at 17:59
  • 3
    \$\begingroup\$ +1 for full example alongside the explanation \$\endgroup\$ – IanF1 Apr 1 '18 at 21:43
  • 1
    \$\begingroup\$ @user202729 codegolf.stackexchange.com/questions/125966/… \$\endgroup\$ – Luis Mendo Apr 2 '18 at 10:13
6
\$\begingroup\$

Stax, 19 bytes

±♪☺ÿzMæ¡♠à╣♂7☼V♀§9↓

Run and debug it

It starts by building a string that has all the characters in the result with all the asterisks left-aligned. Then it it takes increasingly large slices off the end of the string, and "wraps" them around a grid as it rotates the grid.

Here's the same program, unpacked, ungolfed, and commented.

'**     repeat "*" specified number of times
,J(     square the top of the input stack, and right-pad string to that length
z       push an empty array - this is the result grid built up in the loop
{       begin a block to loop
  ~     push grid to the input stack
  ihNv  push -(i / 2) - 1 where i is the 0-based iteration index using integer division
  :/]   split the string at that index and wrap the second half in a singleton array
  ,     pop the grid from the input stack
  rM+   rotate the grid clockwise, then prepend the split string as the new first row
  n     copy what's left of the original string to top of stack for the loop condition
w       while; execute block until condition is truthy
m       display resulting grid

Run and debug it

\$\endgroup\$
  • 2
    \$\begingroup\$ It inordinatly amuses me that on android this answer contains an orange blob smiley. \$\endgroup\$ – StarWeaver Apr 1 '18 at 21:19
  • \$\begingroup\$ @StarWeaver There are many answers in Stax that do so. \$\endgroup\$ – Weijun Zhou Apr 2 '18 at 9:27
  • \$\begingroup\$ I was really confused when I read the explanation and didn't see one. I just thought that Stax had a really weird code page! \$\endgroup\$ – ndm13 Apr 2 '18 at 17:03
  • \$\begingroup\$ @ndm13: I suppose it does have a weird code page. It's derived from CP437 which is a "real" encoding that has the same character in it. You should see the same smiling face if you follow that link on your phone. \$\endgroup\$ – recursive Apr 3 '18 at 20:34
5
\$\begingroup\$

Python 2, 117 bytes

n,k=input()
i=0;d=1
l=(' '*n+'\n')*n
exec"l=l[:i]+'*'+l[i+1:];d=[~n/d*cmp(d*d,2),d][' '<l[i+d:]<'*'];i+=d;"*k
print l

Try it online!

\$\endgroup\$
4
\$\begingroup\$

APL (Dyalog), 65 bytes

' *'[1+⎕>⊖∘⌽⍣o(⊖×⍨-,⍨⍴∘(⍋+\)×⍨↑(⌈2÷⍨×⍨),(+⍨⍴1,⊢,¯1,-)(/⍨)2/⍳)o←⎕]

Try it online!

The code for the spiral matrix is taken from another answer of mine.

\$\endgroup\$
  • \$\begingroup\$ Your code draws the spiral in the wrong direction if the N is odd :) \$\endgroup\$ – nicael Apr 1 '18 at 19:25
  • \$\begingroup\$ @nicael fixed (more like patched). thanks \$\endgroup\$ – Uriel Apr 1 '18 at 19:27
  • \$\begingroup\$ But... i.stack.imgur.com/gGJsS.png \$\endgroup\$ – nicael Apr 1 '18 at 19:30
  • \$\begingroup\$ Maybe I'm using the input in the wrong way? \$\endgroup\$ – nicael Apr 1 '18 at 19:31
  • \$\begingroup\$ @nicael arghh. OK, I think its fine now. \$\endgroup\$ – Uriel Apr 1 '18 at 19:32
4
\$\begingroup\$

PHP, 118 bytes

adjusted and golfed my solution for the Alphabet Spiral.

for($w=$n=$argv[$s=1],$r="*";--$argv[2];$r[$p+=$s*$d+$s]="*")if(!$c=++$c%$n)($d^=$w)?$n--:$s=-$s;echo wordwrap($r,$w);

Run with php -nr '<code>' <S> <N> or try it online.

\$\endgroup\$
4
\$\begingroup\$

Python 2, 150 bytes

S,N=input()
X=y=n=0
Y=x=c=-1
s=eval(`[[' ']*S]*S`)
exec"if n%S<1:S-=c%2<1;X,Y=-Y,X;c+=1;n=0\nx+=X;y+=Y;s[y][x]='*';n+=1\n"*N
for i in s:print`i`[2::5]

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Charcoal, 34 bytes

NθFE⮌E⊗N∨ι¹÷⁺鬬겫F‹θι≔θι×ι*≧⁻ιθ↷

Try it online! Link is to verbose version of code. Explanation:

Nθ

Input N.

FE⮌E⊗N∨ι¹÷⁺鬬겫

The lengths of the spiral arms (excluding corners) are S-1, S-1, S-1, S-2, S-2, S-3, ..., 3, 2, 2, 1, 1, 1. This is formed by starting with the range from 0 up to but excluding 2S, changing the 0 to 1, reversing it, adding 1 to each element after the first, and finally integer dividing all the elements by 2. This list is then looped over.

F‹θι≔θι

If there are fewer stars left to draw than the length of the next arm, reduce the arm to that length.

×ι*

Draw the appropriate number of stars.

≧⁻ιθ

Subtract from the number of stars remaining.

Rotate the drawing direction by 90° clockwise.

\$\endgroup\$
3
\$\begingroup\$

J, 60 56 Bytes

-4 Bytes by modifying the build proccess for the spiral so that subtracting it from y^2 was unnecessary

4 :'''* ''{~x<|."1|.(|:@|.,<:@{:@{:-i.@#)^:(+:<:y),.*:y'

Try it online!

Explanation coming soon now.

Explanation:

4 :'''* ''{~x<|."1|.(|:@|.,<:@{:@{:-i.@#)^:(+:<:y),.*:y'  | Explicit dyad definition
                    (|:@|.,<:@{:@{:-i.@#)^:(+:<:y),.*:y   | Generate a y by y inward spiral
                                                  ,.*:y   | The matrix [[y^2]]
                    (                   )^:(+:<:y)        | 2*(y-1) times...
                     |:@|.                                | Rotate
                          ,                               | Append
                                    i.@#                  | [0..len(n)-1]
                           <:@{:@{:-                      | Subtracted from the previous value and decremented
              |."1|.                                      | Flip around antidiagonal
            x>                                            | Test if each entry is less than x
    '' *''{~                                              | ' ' for 0, '*' for 1

Examples:

   3 :'(|:@|.,<:@{:@{:-i.@#)^:(+:<:y),.*:y' 4
7  8  9 10
6 15 16 11
5 14 13 12
4  3  2  1
   3 :'|."1|.(|:@|.,<:@{:@{:-i.@#)^:(+:<:y),.*:y' 4
1  2  3 4
12 13 14 5
11 16 15 6
10  9  8 7
   11(4 :'x<|."1|.(|:@|.,<:@{:@{:-i.@#)^:(+:<:y),.*:y') 4
0 0 0 0
1 1 1 0
0 1 1 0
0 0 0 0
   11(4 :'''* ''{~x<|."1|.(|:@|.,<:@{:@{:-i.@#)^:(+:<:y),.*:y') 4
****
   *
*  *
****
\$\endgroup\$
  • \$\begingroup\$ May you also add a link to the executable example? \$\endgroup\$ – nicael Apr 1 '18 at 16:44
  • \$\begingroup\$ @nicael Added :) \$\endgroup\$ – Bolce Bussiere Apr 1 '18 at 17:05
2
\$\begingroup\$

Kotlin, 361 355 353 334 bytes

6 bytes saved thanks to Jonathan
2 bytes saved changing to when
19 bytes saved switching to lambda & tracking outer edges

{s:Int,n:Int->var a=Array(s,{_->Array(s,{_->' '})})
var r=0
var c=0
var d=0
var e=0
var f=1
var g=s-1
var h=g
for(i in 1..n){a[r][c]='*'
when(d){0->if(c<g)c++
else{d=1
r++
g--}
1->if(r<h)r++
else{d=2
c--
h--}
2->if(c>e)c--
else{d=3
r--
e++}
3->if(r>f)r--
else{d=0
c++
f++}}}
for(i in 0..s-1){for(j in 0..s-1)print(a[i][j])
println()}}

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ I'm not really sure how to try it since the input field is empty. \$\endgroup\$ – nicael Apr 1 '18 at 20:19
  • 1
    \$\begingroup\$ @nicael It's a function. this may be easier to use - the call is made in the footer. \$\endgroup\$ – Jonathan Allan Apr 1 '18 at 20:32
  • 1
    \$\begingroup\$ I don't know Kotlin much at all but believe ==' ' may be replaced by <'*'. Also d==0 with d<1 and d==3 with d>2. These seem like pretty fundamental golfs so there are probably others too! \$\endgroup\$ – Jonathan Allan Apr 1 '18 at 20:42
  • \$\begingroup\$ @nicael you can put two integers in input field, size on first line, number on second. \$\endgroup\$ – JohnWells Apr 1 '18 at 21:18
  • 1
    \$\begingroup\$ @JohnWells indeed, it works. Somehow it's too slow, but it doesn't matter. \$\endgroup\$ – nicael Apr 1 '18 at 21:22
2
\$\begingroup\$

Java 10, 284 282 281 263 bytes

s->n->{var c=new char[s][s];for(var d:c)java.util.Arrays.fill(d,' ');for(int i=0,j=0,y=0,x=1,u=s-1,l=0;n-->0;c[j][i]=42,i+=x,j+=y,l+=i==l&x==0?1:0,u-=i==l&j==l&y<1?1:0)if(x!=0){var b=x>0?i<u:i>l;y=b?0:x;x=b?x:0;}else{var b=y>0?j<u:j>l;x=b?0:-y;y=b?y:0;}return c;}

A fun challenge!

Try it online here.

Thanks to Kevin Cruijssen for golfing 18 bytes.

Ungolfed version:

s -> n -> { // lambda taking two integer arguments in currying syntax
    var c = new char[s][s]; // the matrix containing the spiral
    for(var d : c) // for every row
        java.util.Arrays.fill(d, ' '); // fill it with spaces
    for(int i = 0, j = 0, // the coordinates of the next '*'
            y = 0, x = 1, // the direction to move in
            u = s-1, l = 0; // the upper and lower bounds
        n-- > 0; // decrecement the length of the spiral and repeat as many times
        c[j][i] = 42, // draw the '*', 42 is ASCII code
        i += x, j += y, // move to the next cell
        l += i == l & x == 0 ? 1 : 0, // adjust lower bound if necessary
        u -= i == l & j == l & y < 1 ? 1 : 0) // adjust upper bound if necessary
        if(x != 0) { // if moving in x direction
            var b = x > 0 ? i < u : i > l; // if we hit the bounds
            y = b ? 0 : x; // flip directions,
            x = b ? x : 0; // turning around
        } else { // if moving in y direction
            var b = y > 0 ? j < u : j > l; // if we hit the bounds
            x = b ? 0 : -y; // flip directions,
            y = b ? y : 0;  // turning around
        }
    return c; // return the matrix
}
\$\endgroup\$
  • \$\begingroup\$ 263 bytes Last two loops are mainly changed, and a var b is added so you only have to do the x>0?i<u:i>l and y>0?j<u:j>l once each, instead of twice each. \$\endgroup\$ – Kevin Cruijssen Apr 3 '18 at 7:40
  • \$\begingroup\$ @KevinCruijssen great golf, thanks! \$\endgroup\$ – O.O.Balance Apr 3 '18 at 8:41
2
\$\begingroup\$

JavaScript (Node.js), 167 164 163 bytes

  • thanks to @Erik the Outgolfer and @nicael for spaces (3 bytes)
  • thanks to @micha for join``split, instead of map (1 byte)
(l,s)=>{a=(b=[...Array(l)]).map(x=>b.map(_=>" "))
for(d=1,x=y=D=0;s--;x+=d,y+=D)a[y][x]="*",(a[y+D]||[])[x+d]!=" "?[d,D]=[-D,d]:0
return a.join`
`.split`,`.join``}

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ Nice, it works! Can you remove spaces/newlines to make it even shorter? \$\endgroup\$ – nicael Apr 1 '18 at 20:19
  • 1
    \$\begingroup\$ @nicael Looks like yes. \$\endgroup\$ – Erik the Outgolfer Apr 1 '18 at 20:34
  • 1
    \$\begingroup\$ Beautiful! If Kotlin and Java version would use the same method they would be a lot shorter! Such an elegant way of detecting when you hit the spiral or border and then turn the "turtle". Very clever! One byte less: change the return into return a.join` `.split`,`.join``. \$\endgroup\$ – micha Apr 4 '18 at 10:38
  • \$\begingroup\$ @micha first of all thank you :). second a.join` .split,`.join`` doesnt output the spiral "nicely"(with new lines) so i think its a problem \$\endgroup\$ – DanielIndie Apr 4 '18 at 10:42
  • \$\begingroup\$ @DanielIndie, the newline got formatted away, first join should have a newline. See it \$\endgroup\$ – micha Apr 4 '18 at 10:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.