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\$
9
  • \$\begingroup\$ Can we have trailing spaces/newlines? \$\endgroup\$
    – DELETE_ME
    Apr 1, 2018 at 15:43
  • 2
    \$\begingroup\$ I'd call S size (or at least diameter) rather than radius \$\endgroup\$
    – Luis Mendo
    Apr 1, 2018 at 15:58
  • \$\begingroup\$ @Luis fair point! \$\endgroup\$
    – nicael
    Apr 1, 2018 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, 2018 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\$
    – DELETE_ME
    Apr 2, 2018 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\$
6
  • 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, 2018 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, 2018 at 16:05
  • \$\begingroup\$ @nicael Welcome to the world of golfing languages aimed for specific purposes. :) \$\endgroup\$ Apr 1, 2018 at 17:59
  • 3
    \$\begingroup\$ +1 for full example alongside the explanation \$\endgroup\$
    – IanF1
    Apr 1, 2018 at 21:43
  • 1
    \$\begingroup\$ @user202729 codegolf.stackexchange.com/questions/125966/… \$\endgroup\$
    – Luis Mendo
    Apr 2, 2018 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\$
4
  • 2
    \$\begingroup\$ It inordinatly amuses me that on android this answer contains an orange blob smiley. \$\endgroup\$
    – Weaver
    Apr 1, 2018 at 21:19
  • \$\begingroup\$ @StarWeaver There are many answers in Stax that do so. \$\endgroup\$ Apr 2, 2018 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, 2018 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, 2018 at 20:34
5
\$\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\$
6
  • \$\begingroup\$ Your code draws the spiral in the wrong direction if the N is odd :) \$\endgroup\$
    – nicael
    Apr 1, 2018 at 19:25
  • \$\begingroup\$ @nicael fixed (more like patched). thanks \$\endgroup\$
    – Uriel
    Apr 1, 2018 at 19:27
  • \$\begingroup\$ But... i.stack.imgur.com/gGJsS.png \$\endgroup\$
    – nicael
    Apr 1, 2018 at 19:30
  • \$\begingroup\$ Maybe I'm using the input in the wrong way? \$\endgroup\$
    – nicael
    Apr 1, 2018 at 19:31
  • \$\begingroup\$ @nicael arghh. OK, I think its fine now. \$\endgroup\$
    – Uriel
    Apr 1, 2018 at 19:32
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\$

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\$
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\$
0
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\$
2
  • \$\begingroup\$ May you also add a link to the executable example? \$\endgroup\$
    – nicael
    Apr 1, 2018 at 16:44
  • \$\begingroup\$ @nicael Added :) \$\endgroup\$ Apr 1, 2018 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\$
6
  • 1
    \$\begingroup\$ I'm not really sure how to try it since the input field is empty. \$\endgroup\$
    – nicael
    Apr 1, 2018 at 20:19
  • 1
    \$\begingroup\$ @nicael It's a function. this may be easier to use - the call is made in the footer. \$\endgroup\$ Apr 1, 2018 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\$ Apr 1, 2018 at 20:42
  • \$\begingroup\$ @nicael you can put two integers in input field, size on first line, number on second. \$\endgroup\$
    – JohnWells
    Apr 1, 2018 at 21:18
  • 1
    \$\begingroup\$ @JohnWells indeed, it works. Somehow it's too slow, but it doesn't matter. \$\endgroup\$
    – nicael
    Apr 1, 2018 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\$
3
  • \$\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\$ Apr 3, 2018 at 7:40
  • \$\begingroup\$ @KevinCruijssen great golf, thanks! \$\endgroup\$ Apr 3, 2018 at 8:41
  • \$\begingroup\$ Suggest if(x>0?i<u:i>l)y=0;else{y=x;x=0;}else if(y>0?j<u:j>l)x=0;else{x=-y;y=0;} instead of {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;} \$\endgroup\$
    – ceilingcat
    Dec 7, 2019 at 1:29
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\$
5
  • 1
    \$\begingroup\$ Nice, it works! Can you remove spaces/newlines to make it even shorter? \$\endgroup\$
    – nicael
    Apr 1, 2018 at 20:19
  • 1
    \$\begingroup\$ @nicael Looks like yes. \$\endgroup\$ Apr 1, 2018 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, 2018 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\$ Apr 4, 2018 at 10:42
  • \$\begingroup\$ @DanielIndie, the newline got formatted away, first join should have a newline. See it \$\endgroup\$
    – micha
    Apr 4, 2018 at 10:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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