| Bytes | Lang | Time | Link |
|---|---|---|---|
| 028 | Pip | 211207T214931Z | DLosc |
| 068 | Julia 1.0 | 220217T212250Z | MarcMush |
| nan | Python 3.8 prerelease | 211105T131700Z | Seb |
| 084 | Python 3.8 | 211102T141308Z | ovs |
| 107 | C gcc | 211103T031237Z | tsh |
| 016 | Japt | 211103T022935Z | AZTECCO |
| 082 | R | 211103T191829Z | Giuseppe |
| 074 | Ruby | 211102T155113Z | G B |
| 016 | 05AB1E | 211103T154740Z | ovs |
| 148 | C gcc | 211102T205834Z | Noodle9 |
| 015 | MATL | 211102T183102Z | Luis Men |
| 019 | 05AB1E | 211103T083620Z | Kevin Cr |
| 186 | Kotlin | 211103T044012Z | JohnWell |
| 015 | Vyxal C | 211103T030247Z | emanresu |
| 3731 | J | 211102T221701Z | Jonah |
| 025 | Charcoal | 211102T171301Z | Neil |
| 076 | Ruby | 211102T205349Z | Level Ri |
| 025 | Vyxal j | 211102T164314Z | wasif |
| 7974 | Python 3 with numpy | 211102T141356Z | m90 |
Pip, 39 29 28 bytes
FiYPZ*\$+REYaFlyP(" *"l*_Mi)
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.
YPZ*\$+REYa
a First command-line argument
EY Identity matrix of that size
R Reverse
\$+ Scan on addition, giving a reversed triangular matrix
PZ* Palindromize each row
Y Yank the resulting nested list into the y variable
For example, with an input of 3, y will be [[0;0;1;0;0]; [0;1;1;1;0]; [1;1;1;1;1]].
Fi...FlyP(" *"l*_Mi)
Fi For each macro-scale row i in
... (the above definition of y):
Fly For each micro-scale row l in y:
Mi Map to each macro-scale element in row i:
l*_ Multiply each element of l by it
(1 -> unchanged, 0 -> 0)
(" *" ) Index into that string, mapping 0 to " " and 1 to "*"
P* Print, joining into a single string by default
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][:]
I wish Julia had a center function
output is a list of lines
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)
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
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)]
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);}
-1 byte by ceilingcat
Japt, 18 17 16 bytes
ÇÑÄ
ïÈçYçÑ ûUÌÃû
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
R, 82 bytes
function(n)write(c(" ","*")[1+(z=outer(c(n:1,2:n),1:n,"<="))%x%z],1,(2*n-1)^2,,"")
Ruby, 82 74 bytes
->n{(r=1.step n+=n-1,2).map{|x|r.map{|y|((?**y).center(n)*x).center n*n}}}
Good golfers copy, great golfers steal.
05AB1E, 16 bytes
L'*×j.ºиøā·<ט.C
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
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);}
Saved 7 bytes thanks to ceilingcat!!!
MATL, 29 16 15 bytes
ZvG:!<~PtX*42*c
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: [' * '
' *** '
' ***** '
' * * * '
' *** *** *** '
' *************** '
' * * * * * '
' *** *** *** *** *** '
'*************************']
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)
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'})}
Vyxal C, 15 bytes
ƛd‹?ɾ×*vømøĊ*;f
ƛ ; # 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 øĊ.
J, 37 31 bytes
' *'{~[:,./^:2[:*/~i.>:/|@i:@<:
-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.
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.
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}}
Python 3 with numpy, 79 74 bytes
lambda n:where(kron(*[c_[:n]>=abs(r_[1-n:n])]*2),*'* ')
from numpy import*
-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')