17
\$\begingroup\$

Introduction

The idea is to use the asterisk character (star) * to display an ascii-art star at a specified dimension. The dimension is an input number greater than or equal to \$1\$ that specifies the height in lines of the upper point of the star. The stars here are intended to be six pointed stars with larger sizes looking better from a picture perspective.

In all cases the ascii-art representation of the stars are to appear as two triangles that overlap as shown in the following examples.

Parametrics

The following picture and table of data describes attributes for the first seven sizes of the star. Each of the parameters grows in an arithmetic progression as \$N\$ increases, except \$N=1\$ is different.

enter image description here

enter image description here

Examples

For an input of 1 (the degenerate case) the program output should be as follows:

  *
*****
*****
  *

Input of 2:

    *
   ***
*********
 *******
*********
   ***
    *

(3)

       *
      ***
     *****
***************
 *************          
  ***********
 *************
***************
     *****
      ***
       *

(5)

             *
            ***
           *****
          *******
         *********
***************************
 *************************
  ***********************
   *********************
    *******************
   *********************
  ***********************
 *************************
***************************
         *********
          *******
           *****
            ***
             *

Challenge

Your task is to create a function or program that will accept the number N as input and then output the appropriately sized star using just characters and the * character.

  • You may assume that the input value is always a positive integer.
  • Trailing whitespace on the output lines is OK.
  • The program algorithm should be general enough for any \$N\$ input to produce the star art output. Practical limitations exist of course due to display output size.
  • Output should print to STDOUT.
  • Standard loopholes are forbidden.
  • This is so all usual golfing rules apply.

Scoring

This is so the code with the shortest number of bytes wins!

\$\endgroup\$
  • 5
    \$\begingroup\$ You also say it can be a function but it must "print to STDOUT". Is this intentional? \$\endgroup\$ – Sriotchilism O'Zaic Apr 14 at 14:55
  • 5
    \$\begingroup\$ Yep, a general construction rule would be great... for instance I'm not sure about even inputs, like N = 4... \$\endgroup\$ – digEmAll Apr 14 at 15:12
  • 7
    \$\begingroup\$ Please don't say "The algorithm to produce the stars is part of the programming challenge." This is not something most golfers enjoy when doing an ASCII art challenge, and sounds like an attempt to pawn off something that's the specifiers responsibility. That said, I'm surprised people are unclear on the construction here; it's two triangles overlapped like the challenge says. Would it help to explicitly say the size and offset of the triangles? \$\endgroup\$ – xnor Apr 14 at 15:30
  • 9
    \$\begingroup\$ @TimPederick Good catch about N=1 being different. I put in a note so solvers don't miss this. I think the challenge would be better without this special case though. \$\endgroup\$ – xnor Apr 14 at 15:50
  • 4
    \$\begingroup\$ @xnor: since n=1 was different, I could't infer a general rule...and IMO the rule should always be specified for ASCII art, otherwise I'm well allowed to print whatever I want outside the range of the defined examples ;) \$\endgroup\$ – digEmAll Apr 14 at 16:18

13 Answers 13

7
\$\begingroup\$

05AB1E, 21 bytes

3*s≠-L·<sÅ0«Âø€à'*×.C

Try it online! or as a Test Suite

Explanation

3*                     # multiply input by 3
  s≠-                  # subtract 1 if the input isn't 1
     L                 # push range [1 ... (3*n-(n!=1))]
      ·<               # multiply by 2 and subtract 1 to get odd numbers
        sÅ0«           # append n zeroes
            Âø         # zip with a reversed copy
              ۈ       # get the largest number in each pair
                '*×    # repeat "*" for each number in the list
                   .C  # format centered
\$\endgroup\$
  • 1
    \$\begingroup\$ Your output stars look correct. \$\endgroup\$ – Michael Karas Apr 14 at 16:08
  • 1
    \$\begingroup\$ I can find loads of alternatives for 3*s≠-L·< like 6*s≠·-ÅÉ or ≠3/-6*ÅÉ, but unfortunately none are shorter.. Nice answer, as always! :) \$\endgroup\$ – Kevin Cruijssen Apr 14 at 17:47
  • \$\begingroup\$ xs3*<ŸRsLì'*×.º.C.∊ for 19 :). I lied, it doesn't work for 1. Leaving it for inspiration. \$\endgroup\$ – Magic Octopus Urn Apr 29 at 20:49
7
\$\begingroup\$

Haskell, 114 bytes

Builds a function g which takes an number and produces a IO monad that prints the star to STDOUT. I think this is ok.

f=replicate
a%b=mapM_(\n->putStrLn$f(a-n)' '++f(2*n-3)'*')$zipWith max<*>reverse$[2..a]++f b 0
g 1=4%1
g a=(3*a)%a

Try it online!

Explanation

First lets talk about the lambda.

\n->putStrLn$f(a-n)' '++f(2*n-1)'*'

This takes a number, n, to be drawn as stars. We print twice that many stars and then 1 more and pad it on the right to the size of the image. We pad this on the right by a spaces to center the line of stars. We can use this lambda to draw each line.

From this lambda we create (%). (%) starts with doing mapM_ with our lambda to turn a profile into the shape.

Now all we need to do is make a list of the profile for the star. We can do this by making a triangle first with [1..a], then padding it with some zeros ++replicate b 0. If we take the profile of the triangle and reverse it we get the other half of the star. To super impose them we just make a new profile where each entry is the max of the two triangles. This is zipWith max.

We then call this in one of two ways: as 3%1 for input of 1 and with (3*a-1)%a otherwise.

From here we do a little bit of fiddling with some of the values to shave some bytes. Since 3*a-1 is rather long we offset some of our other values by 1 so that everything cancels and we get the intended behavior with 3*a instead. Namely we start our list at 2 instead of 1 and do 2*n-3 instead of 2*n-1 to make up for the change.

Alternative version, 114 bytes

This one builds a point-free function (%)<*>min 2

f=replicate
a%b=mapM_(\n->putStrLn$f(3*a-n)' '++f(2*(n-b)+1)'*')$zipWith max<*>reverse$[b..3*a]++f a 0
(%)<*>min 2

Try it online!

Handles all \$N>1\$, 98 bytes

f=replicate
g a=mapM_(\n->putStrLn$f(3*a-n)' '++f(2*n-3)'*')$zipWith max<*>reverse$[2..3*a]++f a 0

Try it online!

Handles all cases like the \$N=1\$ case, 98 bytes

f=replicate
g a=mapM_(\n->putStrLn$f(3*a-n)' '++f(2*n-1)'*')$zipWith max<*>reverse$[1..3*a]++f a 0

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Your output looks nice now. \$\endgroup\$ – Michael Karas Apr 14 at 16:04
6
\$\begingroup\$

R, 125 107 101 bytes

function(n,S=3*n+!n-1,P=pmax(I<-c(2:S*2-3,!1:n),rev(I)),`~`=strrep)write(paste0(' '~S-1-P/2,'*'~P),1)

Try it online!

  • -24 thanks to @Giuseppe

Previous (different) approach :

R, 150 148 136 135 130 128 bytes

function(n,G=n<2,K=4*n-1+G)for(i in 1:K-1)cat(`[<-`(rep(' ',W<-3*n-2+G),1+W+c(-i:i*(i<K-n),-(j=K-i-1):j*(i>=n)),'*'),sep='','
')

Try it online!

  • -14 thanks to @Kirill L.
  • -1 thanks to @t-clausen.dk
  • -7 thanks to @Giuseppe
\$\endgroup\$
  • \$\begingroup\$ Yeah, I also don't like those repeated S[]= assignments, and looks like this works \$\endgroup\$ – Kirill L. Apr 14 at 17:55
  • \$\begingroup\$ Great ! I was thinking to something like that... but I was having dinner :P \$\endgroup\$ – digEmAll Apr 14 at 18:08
  • \$\begingroup\$ Seems you can save a byte: i>n-1 can be rewritten to i>=n \$\endgroup\$ – t-clausen.dk Apr 15 at 12:36
  • \$\begingroup\$ @t-clausen.dk: yep, thanks! \$\endgroup\$ – digEmAll Apr 15 at 16:54
  • 1
    \$\begingroup\$ 117 bytes on the newer version \$\endgroup\$ – Giuseppe Apr 16 at 16:05
5
\$\begingroup\$

Python 2, 101 99 97 bytes

n=input()
x=2*(n>1)
for i in range(1,8*n,2):print('*'*[i,8*n-i-x][i+x>n*6or i/n/2%2]).center(6*n)

Try it online!

-2 bytes, thanks to Lynn

\$\endgroup\$
  • \$\begingroup\$ I'm reasonably sure you don't need the parens in the selector expression, so i+x>n*6or saves two bytes. \$\endgroup\$ – Lynn Apr 15 at 13:25
  • \$\begingroup\$ @Lynn Thanks :) \$\endgroup\$ – TFeld Apr 15 at 14:04
  • \$\begingroup\$ You can even go i+x>~i/n/2%2*6*n or something like i+x>3*n*(~i/n&2) (both 96 bytes.) \$\endgroup\$ – Lynn Apr 15 at 14:15
5
\$\begingroup\$

JavaScript (V8),  101  108 bytes

EDIT: +7 bytes to print to STDOUT

n=>print((k=3*n+!~-n,g=y=>++y<k+n?`
`.padEnd(w=k-Math.max(y>n&&n-y+k,y<k&&y)).padEnd(2*k+~w,'*')+g(y):'')``)

Try it online!

Commented (without print)

n => (                    // n = input
  k =                     // k is half the maximum width of the star + 1.5
    3 * n + !~-n,         // k = 3n if n > 1 or 4 if n = 1
  g = y =>                // g = recursive function taking y
    ++y < k + n ?         //   increment y; if y is less than k + n:
      `\n`                //     append a line feed
      .padEnd(            //     append w - 1 leading spaces:
        w =               //       where w is defined as
          k -             //       k minus
          Math.max(       //       the maximum of:
            y > n         //         - true (coerced to 1) if y > n
            && n - y + k, //           or n - y + k otherwise (bottom triangle)
            y < k &&      //         - true (coerced to 1) if y < k
            y             //           or y otherwise (top triangle)
          )               //       end of Math.max()
      )                   //     end of padEnd()
      .padEnd(            //     append 2 * (k - w) - 1 stars
        2 * k + ~w,       //       by padding to 2 * k - w - 1
        '*'               // 
      ) +                 //     end of padEnd() 
      g(y)                //     append the result of a recursive call
    :                     //   else:
      ''                  //     stop recursion
)``                       // initial call to g with y = [''] (zero-ish)
\$\endgroup\$
  • \$\begingroup\$ Just a heads up the challenge seems to require that your output be printed to the console directly. This doesn't technically meet that requirement. \$\endgroup\$ – Sriotchilism O'Zaic Apr 27 at 3:23
  • \$\begingroup\$ @SriotchilismO'Zaic Thanks for letting me know. This is now 'fixed'. \$\endgroup\$ – Arnauld Apr 27 at 3:56
3
\$\begingroup\$

Jelly, 21 bytes

×3’+ỊR;Ṭ»Ṛ$”*ẋz⁶ṚZŒBY

A full program accepting a positive integer which prints to STDOUT.

Try it online! Or see a test-suite.

How?

×3’+ỊR;Ṭ»Ṛ$”*ẋz⁶ṚZŒBY - Main Link: integer, n   e.g. 3
 3                    - three                        3
×                     - multiply (n by)              9
  ’                   - decrement                    8
    Ị                 - insignificant (abs(n)<=1)?   0
   +                  - add                          8
     R                - range                        [1,2,3,4,5,6,7,8]
       Ṭ              - un-truth (n)                 [0,0,1]
      ;               - concatenate                  [1,2,3,4,5,6,7,8,0,0,1]
          $           - last two links as a monad:
         Ṛ            -   reverse                    [1,0,0,8,7,6,5,4,3,2,1]
        »             -   maximum (vectorises)       [1,2,3,8,7,6,7,8,3,2,1]
           ”*         - an asterisk character        '*' 
             ẋ        - repeat (vectorises)          ["*","**",...]
               ⁶      - a space character            ' '
              z       - transpose with filler        ["***********"," ********* ",...]
                Ṛ     - reverse                      ["   *   *   ","   ** **   ",...]
                 Z    - transpose                    ["       *","      **",...]
                  ŒB  - bounce (vectorises)          ["       *       ","      ***      ",...]
                    Y - join with newline characters "       *       \n      ***      \n..."
                      - implicit print
\$\endgroup\$
2
\$\begingroup\$

Canvas, 25 23 bytes

R:{⁸3×4M∔]∔{*×]↔⁸1≡?╪]┼

Try it here!

15 bytes without handling 1

\$\endgroup\$
  • \$\begingroup\$ Makes nice stars. \$\endgroup\$ – Michael Karas Apr 14 at 16:07
2
\$\begingroup\$

Jelly, 21 bytes

×’»ɗ3”*xⱮz⁶ɓ⁶x;»Ṛ$ŒBY

Try it online!

A monadic link accepting a single integer as its left argument and returning a newline-separated Jelly string with the star as its output. When run as a full program implicitly prints the star to STDOUT.

Explanation

   ɗ3                 | Last three links as a dyad with 3 as right argument:
×                     |   Multiply (by 3)
 ’                    |   Decrease by 1
  »                   |   Maximum of this (and 3)
     ”*xⱮ             | An implicit range from 1 to this many asterisks
         z⁶           | Zip with space as filler
           ɓ          | Start a new dyadic chain with the input as left argument and the list of asterisks as right argument
            ⁶x        | Input many spaces
              ;       | Concatenated to the asterisk list
                 $    | Last two links as a monad:
               »Ṛ     |   Maximum of this list and its reverse
                  ŒB  | Bounce each list (i.e. mirror it without duplicating the middle entry)
                    Y | Join with newlines
\$\endgroup\$
  • 1
    \$\begingroup\$ I appreciate you writing the start the stylish way even though ×3’»3 is the same length ^_^ \$\endgroup\$ – Lynn Apr 15 at 13:28
  • 1
    \$\begingroup\$ @Lynn at the point I did that I thought I was going to be using another quick to merge multiple links, and it meant that I could do so within the maximum 4 allowed. However, once I decided to use ɓ it didn’t matter but I kept it because I still liked it! \$\endgroup\$ – Nick Kennedy Apr 15 at 13:32
2
\$\begingroup\$

Charcoal, 25 bytes

G↙θ←⁺⊗θ¬⊖θ↑⊗θ↘⊕θ*‖O¬C⁰¬⊖θ

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

G↙θ←⁺⊗θ¬⊖θ↑⊗θ↘⊕θ*

Draw an irregular pentagon representing the top right quarter of the star, but special-casing 1 to make the row an extra column wider.

‖O¬

Reflect to complete the star.

C⁰¬⊖θ

More special-casing to make the star for 1 an extra row taller.

Alternative solution, also 25 bytes:

∧¬⊖θ*G↗↓⊖׳N*‖O‖OO↓∧⊖θ⊖⊗θ

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

∧¬⊖θ*

Print an extra * for the case of 1.

G↗↓⊖׳N*

Draw the left half of a triangle of the appropriate size.

‖O

Reflect to complete the triangle.

‖OO↓∧⊖θ⊖⊗θ

Overlap it with its reflection, except in the case of 1, in which case just reflect it.

14 bytes without special-casing for 1:

G<⊖׳N*‖OO↑⊖⊗θ

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

G<⊖׳N*

Draw a triangle of the appropriate size.

‖OO↑⊖⊗θ

Overlap it with its reflection.

\$\endgroup\$
2
\$\begingroup\$

Perl 6, 74 bytes

{$_ Z~|[R,] $_}o{.&{|((' 'x--$+$_*3~'*'x$++*2+1)xx$_*3-($_>1)),|($ xx$_)}}

Try it online!

Literally creates a triangle with the right proportions and overlaps it with a upside-down copy using the string or operator (~|). Outputs as a list of lines with a leading and trailing line whitespace.

Explanation:

                {.&{                                                     }  # Anonymous code block
                      (                        )xx$_*3-($_>1)   # Repeat n*3-(n!=1) times
                       ' 'x--$+$_*3      # With a decreasing indentation
                                   ~'*'x$++*2+1  # Append an increasing triangle
                                       # This creates the triangle
                                                            ,|($ xx$_)  # And add some padding lines
{             }o   # Pass the triangle to the combining function
    Z~|            # Zip string bitwise or
 $_                # The list
       [R,] $_     # With its reverse
\$\endgroup\$
2
\$\begingroup\$

J, 53 50 bytes

' *'{~[:(+.|.),.@#&0,~[:(|.,}.)"1*@<:>:/~@i.@-~3*]

Try it online!

ungolfed

' *' {~ [: (+. |.) ,.@#&0 ,~ [: (|. , }.)"1 *@<: >:/~@i.@-~ 3 * ]

how

Use a function table (like a 3rd grade times table) to construct half the triangle by using >: (greater than or equal) as the function. Then reverse each row, chop of the last column, and stitch the two sides together to get the full triangle (but made of 1 and 0). Add n rows of zeros at the bottom. Finally reverse the whole thing, and overlay it on the original, using boolean or +. to get the result. Then turn the 1 to * and 0 to spaces.

\$\endgroup\$
  • \$\begingroup\$ Nice! Here's my solution - same length, different approach: Try it online! \$\endgroup\$ – Galen Ivanov Apr 16 at 7:35
  • 1
    \$\begingroup\$ Thanks. It sure feels like it could be golfed more, but I tried a handful of other approaches and wasn't able to do it. \$\endgroup\$ – Jonah Apr 16 at 13:07
2
\$\begingroup\$

T-SQL, 194 bytes

@ is the input value

@c handles the width of the top triangle

@d handles the width bottom triangle

@e contains the output either @c or @d - this saves a few bytes

@f handles the special case of 1 as input. @c*@=3 determines when to use @f. 5 bytes cheaper than writing @c=3and @=1

DECLARE @ INT=8

,@c INT=1,@e INT=1,@d INT,@f INT=0SET @d=@*8-3r:PRINT
space(@*3-@e/2+@f/2)+replicate('*',@e-@f)SELECT
@c=nullif(@c,@*6-3)+2,@f=iif(@c*@=3,2,0),@d-=2-@f,@e=iif(@c>@d
or @c/2<@,@c,@d)IF @d>0goto r

Try it online

\$\endgroup\$
1
\$\begingroup\$

Japt -R, 25 bytes

+5 bytes for n=1 :\

õ cUon3*U-´UÎ)®ç* êÃê!U û

Try it

õ cUon3*U-´UÎ)®ç* êÃê!U û     :Implicit input of integer U
õ                             :Range [1,U]
  c                           :Concatenate
   Uo                         :  Range [0,U)
     n                        :  Subtract each from
      3*U-                    :    Multiply U by 3 and subtract
          ´U                  :      Decrement U
            Î                 :      Get sign
             )                :End concat
              ®               :Map each Z
               ç*             :  Repeat "*" Z times
                  ê           :  Palindromise
                   Ã          :End map
                    ê!U       :If decremented U is 0, append reverse, else, palindromise
                        û     :Centre pad each line with spaces to the length of the longest
                              :Implicitly join with newlines and output
\$\endgroup\$

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.