24
\$\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
    Nov 2 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
    Nov 2 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
    Nov 2 at 16:02
  • \$\begingroup\$ Can we change * to for example #? \$\endgroup\$
    – Luis Mendo
    Nov 2 at 17:56
  • \$\begingroup\$ @LuisMendo no, you can not \$\endgroup\$
    – Lynn
    Nov 2 at 20:20

17 Answers 17

10
\$\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
    Nov 2 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\$
6
\$\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
    Nov 2 at 18:38
  • 1
    \$\begingroup\$ @Giuseppe I was working precisely on this edited version using the Kronecker product. Thanks! \$\endgroup\$
    – Luis Mendo
    Nov 2 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
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\$

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
    Nov 3 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
    Nov 5 at 13:27
3
\$\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\$ Nov 3 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
    Nov 3 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
    Nov 5 at 13:30
  • \$\begingroup\$ Cheers, I had wanted for something like that to work. Good point about the f=. \$\endgroup\$
    – Seb
    Nov 5 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\$
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, privacy policy and cookie policy

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