There are 4 regular polygons that we can construct using ASCII art:
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
That is, a triangle, a square, a hexagon and an octagon.
Your task is to take two inputs and produce the corresponding ASCII art polygon.
Input
The two inputs will be:
- A string/list of printable ASCII characters (i.e. with code points in the range \33ドル\$ (
!) to \126ドル\$ (~) - An indicator as to which polygon you should output. This indicator can be any \4ドル\$ distinct and consistent values (e.g.
1234,ABCD, etc.), but each must be only one character long, to avoid any exploitation of this input.
The string will be a perfect fit for the polygon, meaning that, if the shape to be outputted is:
- A triangle, then the length of the string will be a triangular number
- A square, then the length of the string will be a square number
- A hexagon, then the length of the string will be a centered hexagonal number
- An octagon, then the length of the string will be an octo number
The string may have repeated characters, but will always fit the appropriate lengths for the given shape/sequence, so there is no need to worry about too many/few characters.
Output
You should output a shape, indicated by the second input, in the format shown at the top of the challenge with the . replaced with the characters in the inputted string. Each character must be separated by a single space, and leading/trailing whitespace is acceptable, so long as the shape is preserved. The characters may be used in any order, but each character in the string must only appear once. For example, for a hexagon using ABCDABC, the following are valid:
A B B A C D A A B C B C D C
as each character from the string is used once. However,
A A A B AD A A A A B C ABC A A C A BC
are not valid (the first only has A, the second doesn't have a D and the third doesn't have spaces between characters).
This is code-golf so the shortest code in bytes wins
Test cases
These test cases use T, S, H and O to indicate which shape the output should be in. The string of characters is on the first line and the indicator on the second
i1+K8{^wsW
O
i 1
+ K 8
{ ^ w
s W
,r1~vi4l{W@+r<vzP;mq>:8gJcgg$j`$RFhDV
H
, r 1 ~
v i 4 l {
W @ + r < v
z P ; m q > :
8 g J c g g
$ j ` $ R
F h D V
0J++
S
0 J
+ +
Kn[Vyj
T
K
n [
V y j
#5~m
S
# 5
~ m
'*g(AUFV~Ou2n=172s'|S11q&j=+#
O
' * g
( A U F
V ~ O u 2
n = 1 7 2
s ' | S 1
1 q & j
= + #
5 Answers 5
Ruby, (削除) 139 (削除ここまで) 138 bytes
->s,n{w=(((s=s.chars*' ').size/n=n.hex)**0.5).to_i+k=1&~n
(0..h=w+n/5*~-w).map{|i|s.slice!(0,[w+n/6*~-w,w**k+i,w+h+~i].min*2).center w*4}}
A function taking 2 arguments: a string s and a shape n as a single character in hexadecimal of value 1,2,6 or A. It returns an array of strings.
Explanation
The input string is converted to an array, then joined back into a string with spaces between the characters. The length of this combined string is twice the length of the original string, minus 1. This is divided by a constant, square rooted and rounded to determine the side length w of the polygon to be drawn. The value of the constant is per the table below. For triangles, the square root is rounded down. For others, it needs to be rounded up, so we round down then add k=1&~n to correct.
Shape Triangle Square Hexagon Octagon
n = 1 2 6 10
We iterate through h rows of output. For the triangle and square, h=w. For the other shapes we need to add w-1 for the hexagon and twice this amount for the octagon. This is done by adding n/5*~-w.
Each line of output is centred and padded to w*4 characters which is enough for all cases. Chunks of s are removed using slice! and outputted. For the octagon the number of symbols to be outputted on each line is the minimum of three numbers: w+w-1 for the centre section, w+i for the top section and w+h-i-1 = w+h+~i for the bottom section. These formulas also work for the hexagon. Note that the numbers have to be multiplied by 2 to account for the spaces.
For the square and triangle, the width of the output is restricted to w. Therefore the formula for the centre section becomes w+n/6*~-w to cover all shapes . For the triangle, the width of the output is further restricted to 1+i. Therefore the formula for the top section becomes w**k+i to cover all shapes.
JavaScript (ES8), (削除) 191 176 174 (削除ここまで) 171 bytes
Takes input as (type)(string), where the 1st parameter is 0123 instead of TSHO and the 2nd parameter is an array of characters.
i=>g=(s,n=1,p=0)=>s[o=(h=k=>k?(F=j=>j?s.slice(p,p+=w+=k&6?k&2&&1:-1).join` `.padStart(n*2+w)+`
`+F(j-1):'')(n-k%2)+h(k>>3):'')([2,4,10,106][i],w=i>1?n-1:n*i),p]?g(s,n+1):o
How?
The shape of each polygon is encoded as groups of 3 bits, packed into a single integer.
Each group of bits is decoded as follows:
- bit 0: if set, repeat \$n-1\$ times; if cleared, repeat \$n\$ times
- bits 1-2: if both bits are cleared, decrement the width at each iteration; if only bit 1 is set, increment the width after at iteration; otherwise, leave it unchanged
The initial width of the shape is:
$$w=\cases{ 0,&\text{if $i=0$}\\ n,&\text{if $i=1$}\\ n-1,&\text{if $i>1$} }$$
Triangle (\$i=0\$)
..1
.1.1
1.1.1
One group: repeat \$n\$ times, increment the width → encoded as \2ドル\$
Square (\$i=1\$)
1.1.1
1.1.1
1.1.1
One group: repeat \$n\$ times, leave the width unchanged → encoded as \4ドル\$
Hexagon (\$i=2\$)
..1.1.1
.1.1.1.1
1.1.1.1.1
.2.2.2.2
..2.2.2
Two groups:
- group 1: repeat \$n\$ times, increment the width → encoded as \2ドル\$
- group 2: repeat \$n-1\$ times, decrement the width → encoded as \1ドル\$
Final encoding: \2ドル+8\times1=10\$
Octagon (\$i=3\$)
..1.1.1
.1.1.1.1
1.1.1.1.1
2.2.2.2.2
2.2.2.2.2
.3.3.3.3
..3.3.3
Three groups:
- group 1: repeat \$n\$ times, increment the width → encoded as \2ドル\$
- group 2: repeat \$n-1\$ times, leave the width unchanged → encoded as \5ドル\$
- group 3: repeat \$n-1\$ times, decrement the width → encoded as \1ドル\$
Final encoding: \2ドル+8\times5+8^2\times1=106\$
Charcoal, 70 bytes
≔0ζWφ«⎚≦⊕ζ≔∨=θ3ζδ≔E⮌ηκφP⪫Eδ⊟φ F§⪪";↧↷$↑R{P≧⍘",IθF⊖ζ«M✳Iκ≧+−6IκδP⪫Eδ⊟φ
Try it online! Link is to verbose version of code. Takes input as the number of sides and the characters. Explanation:
≔0ζ
Keep track of the size of the polygon.
Wφ«
Repeat until we find a size that consumes the input. (This variable is predefined to the truthy value 1000 but I'm going to redefine it.)
⎚
Clear the previous attempt from the canvas.
≦⊕ζ
Increment the polygon size.
≔∨=θ3ζ
Calculate the number of characters in the first row, which is 1 for the triangle and the size for the other shapes.
δ≔E⮌ηκφ
Convert the characters from a string into a list and reverse them. This allows us to iterate over them by popping from the list, which will become empty if we pop all of them.
P⪫Eδ⊟φ
Print the first row of the polygon.
F§⪪";↧↷$↑R{P≧⍘",Iθ
Loop over one of four strings, 5, 6, 57 or 567, depending on the number of sides. These correspond to the Charcoal directions of the left-most character in each row.
F⊖ζ«
Loop for one fewer row than the polygon size.
M✳Iκ
Move in the desired direction.
≧+−6Iκδ
Calculate the number of characters in this row.
P⪫Eδ⊟φ
Print the row.
05AB1E, 32 bytes
∞εLDN+DûsÂćNиì«yDи)1è}.ΔO∍Q}£».c
First input is 0 for triangle, 1 for hex, 2 for oct, 3 for square. Second input is a list of characters. The program will hang forever if the list isn't of a valid length.
∞ # infinite list [1, 2, 3...]
ε } # map each integer y to a polygon with side length y:
L # range 1..y (=> triangle)
D # duplicate
N # 0-based iteration count (effectively y-1)
+ # vectorized add, yielding y..(2y-1)
D # duplicate
û # palindromize (=> hexagon)
s # swap to get the other copy of y..(2y-1)
 # push a reversed copy: (2y-1)..y
ć # head extract: 2y-1
Nи # repeat that y-1 times
ì # prepend that to the reversed list
« # append it to the original list (=> octogon)
y # push y
Dи # repeat it y times (=> square)
) # wrap all polygons in a list
1è # index into the list using the first input
.Δ } # get the first polygon such that:
O # its sum
∍Q # is equal to the length of the input
£ # cut the input in this shape
» # join by newlines, joining sublists with spaces
.c # center
Python 3, (削除) 600 (削除ここまで) (削除) 548 (削除ここまで) (削除) 503 (削除ここまで) (削除) 458 (削除ここまで) (削除) 358 (削除ここまで) (削除) 349 (削除ここまで) (削除) 346 (削除ここまで) (削除) 326 (削除ここまで) 324 bytes
lambda n,s:p(s,q(s,(0,1,1,1.2)[n],(1,.5,3,5)[n]),n)
q=lambda s,p,q:int(p/2+(p*p/4+len(s)/q)**.5)
g=lambda s,j,i,c,n=1,l=[]:s and-~i and g(s[i:],j,i+(-1,1,0)[(2,1,n<j,(n<j*2-1)+(0<=n-j<j-1))[c]],c,n+1,l+[s[:i]])or l
p=lambda s,k,c:"\n".join([" ".join(i).center(k*(1,(2,4)[c>1])[c>0]-2)for i in g(s,(0,k)[c>1],(k,0)[c==1],c)])
I Know it is a bit long but i want to commit it and improve it over time...
The inputs are:
0 = Triangle
1 = square
2 = Hexagon
3 = Octagon
Thanks to:
- @caird coinheringaahing for saving 2 bytes
-
\$\begingroup\$ You can use an unnamed function as a submission here, so you can remove the
f=for -2 bytes: Try it online! \$\endgroup\$2019年10月29日 00:15:35 +00:00Commented Oct 29, 2019 at 0:15 -
\$\begingroup\$ @cairdcoinheringaahing Thank you for allowing this :) \$\endgroup\$Paul-B98– Paul-B982019年10月29日 10:32:15 +00:00Commented Oct 29, 2019 at 10:32
[[0,0,1,0],[0,1,0,1],[1,0,1,0,1]]for example, and so avoid the need to encode the triangle within code. Or is that ok? \$\endgroup\$eval. The four distinct inputs just define functions which format the four shapes. @cairdcoinheringaahing, I recommend scoring aslength(code)+length(indicators); or restrict indicator to one character. \$\endgroup\$However, I'd expect the community to downvote answers which violate the spirit of the challenge, such as an answer that uses that "loophole", and I certainly would downvote such a boring answerI really do not think that we should downvote an answer to a code golf question that is both golfed and fits the defined spec! \$\endgroup\$<and>characters didn't work with the<pre>tags. Updated to fix that \$\endgroup\$