29
\$\begingroup\$

Given an integer \$n \geq 2\$, print a triangle of height \$n\$ of (triangles of height \$n\$ of asterisks), as in this SO question.

For \$n=2\$, print:

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

For \$n=3\$, print:

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

For \$n=4\$, print:

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

And so on. Some rules:

  • I write "print", but a function returning a string or list of lines is fine too.
  • Trailing whitespace on each line is allowed, but not leading whitespace.
  • Trailing blank lines are allowed.
  • This is : write the shortest program you can, measured in bytes.
\$\endgroup\$
8
  • \$\begingroup\$ This is a bit classic, as far as code golf problems go. But I liked the "single layer of fractal nature", and the solutions offered on the SO question are so wildly different that I'm actually quite curious which is golfiest. \$\endgroup\$
    – lynn
    Commented Nov 2, 2021 at 13:15
  • \$\begingroup\$ I like it. A fun variation would be to take the number of times to iterate as a parameter. So you could have a triangle of triangles of triangles, etc... \$\endgroup\$
    – Jonah
    Commented Nov 2, 2021 at 14:30
  • 1
    \$\begingroup\$ Yeah, I can see that argument for why it's a better CG question as is... my comment wasn't meant as a criticism in any way. Just a thought.... \$\endgroup\$
    – Jonah
    Commented Nov 2, 2021 at 16:02
  • \$\begingroup\$ Can we change * to for example #? \$\endgroup\$
    – Luis Mendo
    Commented Nov 2, 2021 at 17:56
  • \$\begingroup\$ @LuisMendo no, you can not \$\endgroup\$
    – lynn
    Commented Nov 2, 2021 at 20:20

19 Answers 19

12
\$\begingroup\$

Python 3 with numpy, 79 74 bytes

lambda n:where(kron(*[c_[:n]>=abs(r_[1-n:n])]*2),*'* ')
from numpy import*

Try it online!

-5 thanks to ovs, with the use of where.

Step-by-step example of how it works:

>>> from numpy import*
>>> (n:=2)
2
>>> (Y:=c_[:n])
array([[0],
       [1]])
>>> (X:=r_[1-n:n])
array([-1,  0,  1])
>>> (Z:=Y>=abs(X))    # Broadcasts.
array([[False,  True, False],
       [ True,  True,  True]])
>>> (A:=kron(*[Z]*2))    # Listify, double, and unpack to give the same argument twice.
array([[False, False, False, False,  True, False, False, False, False],
       [False, False, False,  True,  True,  True, False, False, False],
       [False,  True, False, False,  True, False, False,  True, False],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True]])
>>> (B:=where(A,*"* "))    # Select asterisk for true and space for false.
array([[' ', ' ', ' ', ' ', '*', ' ', ' ', ' ', ' '],
       [' ', ' ', ' ', '*', '*', '*', ' ', ' ', ' '],
       [' ', '*', ' ', ' ', '*', ' ', ' ', '*', ' '],
       ['*', '*', '*', '*', '*', '*', '*', '*', '*']], dtype='<U1')
\$\endgroup\$
1
  • \$\begingroup\$ Using where instead on indexing saves a few bytes: TIO \$\endgroup\$
    – ovs
    Commented Nov 2, 2021 at 14:29
8
\$\begingroup\$

J, 37 31 bytes

' *'{~[:,./^:2[:*/~i.>:/|@i:@<:

Try it online!

-6 after seeing the phrase "Kronecker product" in m90's python answer, realizing that's what I was doing, and finding a golfier implementation in this essay.

\$\endgroup\$
8
\$\begingroup\$

MATL, 29 16 15 bytes

ZvG:!<~PtX*42*c

Try it online!

How it works

Consider input 3 as an example. The stack is shown upside down, with the most recent element below.

Zv    % Implicit input. Symmetric range
      % STACK: [1 2 3 2 1]
G:    % Push input again. Range
      % STACK: [1 2 3 2 1],
               [1 2 3]
!     % Transpose
      % STACK: [1 2 3 2 1],
               [1
                2
                3]
<~    % Less than?, negate; element-wise with broadcast
      % STACK: [1 1 1 1 1
                0 1 1 1 0
                0 0 1 0 0]
P     % Flip vertically
      % STACK: [0 0 1 0 0
                0 1 1 1 0
                1 1 1 1 1]
tX*   % Duplicate. Kronecker product
      % STACK: [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
                0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0
                0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
                0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0
                0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 0
                0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0
                0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0
                0 1 1 1 0 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0 0 1 1 1 0
                1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
42*   % Multiply by 42 (ASCII for '*'). Convert to char
      % Implicit display. Char 0 is displayed as space
      % STACK: ['            *            '
                '           ***           '
                '          *****          '
                '       *    *    *       '
                '      ***  ***  ***      '
                '     ***************     '
                '  *    *    *    *    *  '
                ' ***  ***  ***  ***  *** '
                '*************************']
\$\endgroup\$
2
  • \$\begingroup\$ You could maybe port the python + numpy answer? Should be less than 20 bytes, I think. \$\endgroup\$
    – Giuseppe
    Commented Nov 2, 2021 at 18:38
  • 1
    \$\begingroup\$ @Giuseppe I was working precisely on this edited version using the Kronecker product. Thanks! \$\endgroup\$
    – Luis Mendo
    Commented Nov 2, 2021 at 18:41
5
\$\begingroup\$

C (gcc), 160 153 148 bytes

p(c,n){n&&p(putchar(c),n-1);}r;t;l;i;f(n){for(r=0;r<n*n;p(10,1))for(t=r/n,l=r++%n,p(32,(n+~t)*(n*2-1)),i=t-~t;i--;p(32,n+~l))p(32,n+~l),p(42,l-~l);}

Try it online!

Saved 7 bytes thanks to ceilingcat!!!

\$\endgroup\$
0
5
\$\begingroup\$

C (gcc), 107 bytes

m,x,y;f(n){for(y=n*n;y--;)for(x*=x=m=2*n-1;x--;)putchar(abs(x%m-n+1)+y%n<n&abs(x/m-n+1)+y/n<n?42:x?32:10);}

Try it online!

-1 byte by ceilingcat

\$\endgroup\$
0
5
\$\begingroup\$

Python 3.8, 91 86 84 bytes

-2 bytes thanks to Lynn!

lambda n:[f"{(o%n*'**'+'*').center(w:=2*n-1)*(o//n*2+1):^{w*w}}"for o in range(n*n)]

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ You can save two bytes using f-strings for the outer centering: lambda n:[f"{(o%n*'**'+'*').center(w:=2*n-1)*(o//n*2+1):^{w*w}}"for o in range(n*n)] \$\endgroup\$
    – lynn
    Commented Nov 3, 2021 at 17:28
  • \$\begingroup\$ @Lynn thanks a lot, for some reason I discarded that idea after noticing that this can't be used for both centerings. \$\endgroup\$
    – ovs
    Commented Nov 5, 2021 at 13:27
4
\$\begingroup\$

Ruby, 76 bytes

->n{(0...n*n).map{|i|((?**(i%n*2+1)).center(j=n*2-1)*(i/n*2+1)).center j*j}}

Try it online!

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

Charcoal, 25 bytes

NθFθF⊕⊗ι«J×⊖⊗θ⁻κι×θιG↗↘θ*

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

Nθ

Input n.

Fθ

Loop over each row.

F⊕⊗ι«

Loop over each of the 2i+1 triangles in each row.

J×⊖⊗θ⁻κι×θι

Jump to the (bottom left of the) triangle.

G↗↘θ*

Draw the triangle.

24 bytes if a leading blank line is allowed:

NθFθ«M×⊖⊗θ⊗ιθF⊕⊗ι«G↖↙θ*←

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

Nθ

Input n.

Fθ«

Loop over each row.

M×⊖⊗θ⊗ιθ

Jump to the end of the row.

F⊕⊗ι«

Loop over each of the 2i+1 triangles in each row.

G↖↙θ*

Draw the triangle.

Move to the next triangle.

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

Ruby, 82 74 bytes

->n{(r=1.step n+=n-1,2).map{|x|r.map{|y|((?**y).center(n)*x).center n*n}}}

Try it online!

Good golfers copy, great golfers steal.

\$\endgroup\$
2
  • \$\begingroup\$ I saw your now deleted comment on my answer but I was at work. I acknowledge that my answer was similar to your original answer but I didn't copy - there's a comment in my TIO with the expansion of (2x-1)**2 which was originally part of my code. We just converged on similar solutions. I see you've removed the g function and inlined the centers so it now looks superficially even more like mine. I congratulate you on your improved looping. \$\endgroup\$ Commented Nov 3, 2021 at 18:33
  • \$\begingroup\$ @LevelRiverSt No problem, the comment was meant as a joke, but reading it twice it looked too serious and I had to remove it. The real improvement was not inlining the g function, but nesting 2 maps, which is a different approach. I tried to remove one of the 2 center() but it's no improvement. \$\endgroup\$
    – G B
    Commented Nov 3, 2021 at 20:56
2
\$\begingroup\$

Vyxal j, 25 bytes

d‹£²ʁƛ?%›‛***Ḣ¥⋏n?ḭd›*¥²⋏

Try it Online!

I think mirroring might help, but cannot think of how

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

Vyxal C, 15 bytes

ƛd‹?ɾ×*vømøĊ*;f

Try it Online!

ƛ            ;  # Map 1...n to...
   ?ɾ           # 1...input...
     ×*         # Asterisks
       vøm      # Each palindromised
          øĊ    # Centered
            *   # Repeated...
 d‹             # (2 * value) - 1 times
              f # Flatten
                # (C flag) output centered

17 bytes without the flag by appending a øĊ.

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

Japt, 18 17 16 bytes

ÇÑÄ
ïÈçYçÑ ûUÌÃû

Try it

o_ÑÄ         - range [0..input] *2+1
ï          - pair each with itself
 È         - then pass pairs by f(X,Y)
  ç        - repeat result X times
   YçÑ    - repeat '*' Y times
ûNÑÉ       - centre pad
Ãû         - centre pad all
\$\endgroup\$
2
\$\begingroup\$

Python 3.8 (pre-release), 111 100 bytes

f=lambda n,b=['*'],p=1:p>2 and b or f(n,[f'{2*r*l+l:^{(2*n-1)**p}}'for r in range(n)for l in b],p+1)

Try it online!

Nowhere near the best Python 3 answers, but it's got recursion. See my answer on the source SO question for an ungolfed version with the same mechanisms.

-11 bytes thanks to @ovs

\$\endgroup\$
2
  • 2
    \$\begingroup\$ You can do all the string formatting with a single f-string: Try it online! (The f= has to be included in the byte count because the recursive function relies on being assigned to that name) \$\endgroup\$
    – ovs
    Commented Nov 5, 2021 at 13:30
  • \$\begingroup\$ Cheers, I had wanted for something like that to work. Good point about the f=. \$\endgroup\$
    – Seb
    Commented Nov 5, 2021 at 13:32
1
\$\begingroup\$

R, 82 bytes

function(n)write(c(" ","*")[1+(z=outer(c(n:1,2:n),1:n,"<="))%x%z],1,(2*n-1)^2,,"")

Try it online!

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

Pip, 39 bytes

YPZ0Xa-_.1X_M\,a(J*Z_M_*^yMMy)TRt"* "Jn

Replit! Or, here's a 41-byte equivalent in Pip Classic: Try it online!

Explanation

We create a structure out of 0's and 1's and then use it for both the micro- and macro-structure of the desired output.

YPZ0Xa-_.1X_M\,a
               a  First command-line argument
             \,   Inclusive range from 1 to that number
            M     To each element of that range, map this function:
     a-_           a minus the function argument
   0X              That many 0's
           _       Function argument
         1X        That many 1's
        .          Concatenate those two strings
 PZ                Palindromize
Y                 Yank the resulting list of strings into the y variable

For example, with an input of 3, y is [00100; 01110; 11111].

(J*Z_M_*^yMMy)TRt"* "Jn
          MMy            Map this function to each character of each string in y:
         y                Take another copy of y
        ^                 Split it into a list of lists of characters
      _*                  Multiply each character by the function argument
     M                   To each sublist of the resulting list, map this function:
   Z_                     Transpose
 J*                       Join each sublist of the transposition into a single string
(            )TR         Transliterate the result:
                t         Replace characters "10"
                 "* "     with characters "* "
                     Jn  Join on newlines
\$\endgroup\$
1
\$\begingroup\$

Julia 1.0, 68 bytes

~n=2n-1
!n=[' '^(2n^2-j*~n-i)*rpad('*'^~i,~n)^~j for i=1:n,j=1:n][:]

Try it online!

I wish Julia had a center function

output is a list of lines

\$\endgroup\$
0
\$\begingroup\$

Kotlin, 186 bytes

val p={n:Int->for(p in n downTo 1)for(l in n downTo 1)for(g in n-1 downTo 1-n)for(c in n-1 downTo 1-n)print(when{p+Math.abs(g)<=n&&l+Math.abs(c)<=n->'*'
g!=1-n||c!=1-n->' '
else->'\n'})}

Try it online!

\$\endgroup\$
0
\$\begingroup\$

05AB1E, 19 bytes

·ÅÉεIL'*×.Bí€û×}˜.c

Try it online or verify all test cases.

Explanation:

·                # Double the (implicit) input-integer
 ÅÉ              # Push a list of all odd numbers smaller than or equal to this 2*input
   ε             # Map over each odd integer:
    IL           #  Push a list in the range [1,input] again
      '*×       '#  Repeat "*" each integer amount of times as string
         .B      #  Box this list of strings, adding trailing spaces to make them all of
                 #  equal length
           í     #  Reverse each so the spaces are leading
            €û   #  Palindromize each string
              ×  #  Repeat each the current odd integer amount of times
   }˜            # After the map: flatten the list of lists
     .c          # Join this list of strings by newlines, and centralize it
                 # (after which it is output implicitly as result)
\$\endgroup\$
0
\$\begingroup\$

05AB1E, 16 bytes

L'*×j.ºиøā·<ט.C

Try it online!

L                -- range from 1 to n
 '*×             -- repeat "*" that many times
    j            -- pad to length n with spaces to the left
     .º          -- self-intersected mirror
       и         -- for each string, make a list of n copies
       ​ ø        -- transpose to get the rows of the big triangle
​​         ā       -- get the range from 1 to the number of rows (n)
          ​·<     -- double and decrement to get a list of the first n odd numbers
            ​×    -- repeat each string in the i-th row 2*i-1 times
             ​˜   -- flatten into a list of lines
              ​.C -- center and join by newlines

Try it with step-by-step output!

\$\endgroup\$

Your Answer

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

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