Polygonal Numbers!

Introduction

In mathematics, a polygonal number is a number represented as dots or pebbles arranged in the shape of a regular polygon. The dots are thought of as alphas (units). These are one type of 2-dimensional figurate numbers.

The number 10, for example, can be arranged as a triangle:

*
**
***
****


But 10 cannot be arranged as a square. The number 9, on the other hand, can be:

***
***
***


Some numbers, like 36, can be arranged both as a square and as a triangle:

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


By convention, 1 is the first polygonal number for any number of sides. The rule for enlarging the polygon to the next size is to extend two adjacent arms by one point and to then add the required extra sides between those points. In the following diagrams, each extra layer is shown as in red.

Triangular Numbers:

Square Numbers:

Polygons with higher numbers of sides, such as pentagons and hexagons, can also be constructed according to this rule, although the dots will no longer form a perfectly regular lattice like above.

Pentagonal Numbers:

Hexagonal Numbers:

Source: Wikipedia

Given a positive integer N (1 <= N <= 1000), print every type of Polygonal Number N is starting from Triangular Numbers up to and including Icosagonal (20-gon) Numbers.

For example, the number 10 is a triangular number and a decagonal number, so the output should be something like (you can choose your own output format, but it should look somewhat like this):

3 10


Test cases

1 -> 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
2 -> (None)
3 -> 3
6 -> 3 6
36 -> 3 4 13


For reference, the n-th k-gonal number is:

Credit: xnor

Remember, this is , so the code with the fewest bytes wins.

• For reference, the nth k-gonal number is (k-2)*n*(n-1)/2 + n. – xnor Nov 13 '16 at 23:41
• The point of the sandbox is to improve questions. If you post a question in the sandbox and discover that it's not clear what you're asking, the correct response is not to add a comment in the sandbox, wait two hours, and then post the question to main unmodified and delete the sandbox question, hiding the explicatory comment from people with less than a couple of thousand rep. The correct response is to rephrase or ask for suggestions for rephrasing, and give it another day or two to see whether the rephrased question still has problems. – Peter Taylor Nov 14 '16 at 7:37

Python 3, 68 bytes

lambda R:[s+2for s in range(1,19)if(s-2+(4+s*(s-4+8*R))**.5)/2%s==0]


For each potential number of sides s+2, solves the quadratic formula R=s*n*(n-1)/2 + n for n to see if the result is a whole number.

Compare (73 bytes):

lambda R:[s+2for s in range(1,19)if R in[n+s*n*~-n/2for n in range(R+1)]]


An alternative approach of solving for s gives 62 bytes in Python 3, but fails on R=1.

lambda R:{(R-n)*2/n/~-n+2for n in range(2,R+1)}&{*range(3,21)}


JavaScript (ES6), 90 bytes

n=>[...Array(21).keys(n--)].slice(3).filter(i=>(Math.sqrt(i*i+8*i*n-16*n)+i-4)%(i+i-4)==0)


Solves the quadratic equation. 73 bytes on new enough versions of Firefox:

n=>[for(i of Array(18).keys())if(((~-i**2+8*n*-~i)**.5+~-i)/2%-~i==0)i+3]


><>, 62 + 3 = 65 bytes

&1v
v0<;?)+8a:+1~~<
1.292:{<>+n}ao^
>:&:&=?^:&:&)?^:@:@$-{:}++  Expects the input at the top of the stack, so +3 bytes for the -v flag. This is my first time programming in ><>, so I may be missing some obvious tricks to shorten the code. Explanation: Initialization &1v v0< 1  Moves N to the register, pushes the counter to the stack (starting at 1, which corresponds to triangular numbers), and starts the sequence with the values 0 and 1. Main Loop  :&:&=?^:&:&)?^:@:@$-{:}++


Compares the top of the stack with the register. If it is equal, go to the print routine. If it is greater, go to the reset routine. Otherwise take the difference between the top two stack items, add the counter, and add to the previous top stack item. This calculates the next polygonal number.

Print

 .292:{<>+n}ao^
^


Prints the counter + 2, followed by a newline, then moves to the reset routine.

Reset

v0<;?)+8a:+1~~<
1             ^


Removes the top two stack items and increments the counter. Ends the program if the counter is greater than 18, otherwise pushes the starting numbers 0 and 1 to the stack and returns to the main loop.

Jelly, 22 bytes

18pȷµḢ×’×H+µ€_³¬FT:ȷ+3


Try it online!

Explanation

18pȷµḢ×’×H+µ€_³¬FT:ȷ+3
18pȷ                   - All possible (k-2,n) pairs
µ      µ€          - to each pair compute the corresponding polygonal number:
Ḣ                 -   retrieve k-2
×’               -   multiply by n-1
×H             -   multiply by half of n
_³        - subtract the input. There will now be 0's at (k-2,n) pairs which produce the input
¬FT     - retrieve all indices of 0's. The indices are now (k-2)*1000+n
:ȷ   - floor division by 1000, returning k-3
+3 - add 3 to get all possible k.


Axiom 203 bytes

 l(x)==(local q,m,a;v:List INT:=[];for i in 3..20 repeat(q:=solve((i-2)*n*(n-1)+2*n-2*x=0,n);if #q>1 then(m:=rhs q.1;a:=rhs q.2;if(m>0 and denom(m)=1)or(a>0 and denom(a)=1)then v:=cons(i,v)));v:=sort v;v)


here is less golfed and routine that show numbers

 l(x)==
local q,m,a
v:List INT:=[]
for i in 3..20 repeat
q:=solve((i-2)*n*(n-1)+2*n-2*x=0,n)  -- this would find only rational solutions as r/s with r,s INT
if #q>1 then -- if exist rational solution and denominator =1=> add to list of result
m:=rhs q.1;a:=rhs q.2;
if(m>0 and denom(m)=1)or(a>0 and denom(a)=1)then v:=cons(i,v)
v:=sort v
v

(2) ->  [[i,l(i)]  for i in 1..45]
Compiling function l with type PositiveInteger -> List Integer

(2)
[[1,[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]], [2,[]], [3,[3]],
[4,[4]], [5,[5]], [6,[3,6]], [7,[7]], [8,[8]], [9,[4,9]], [10,[3,10]],
[11,[11]], [12,[5,12]], [13,[13]], [14,[14]], [15,[3,6,15]], [16,[4,16]],
[17,[17]], [18,[7,18]], [19,[19]], [20,[20]], [21,[3,8]], [22,[5]],
[23,[]], [24,[9]], [25,[4]], [26,[]], [27,[10]], [28,[3,6]], [29,[]],
[30,[11]], [31,[]], [32,[]], [33,[12]], [34,[7]], [35,[5]], [36,[3,4,13]],
[37,[]], [38,[]], [39,[14]], [40,[8]], [41,[]], [42,[15]], [43,[]],
[44,[]], [45,[3,6,16]]]
Type: List List Any


AWK, 67 bytes

{for(k=2;++k<21;)for(n=0;++n<=$1;)if((k/2-1)*(n*n-n)+n==$1)print k}


Try it online!

I tried actually solving the quadratic, but checking each value to see if it works is shorter (and less error-prone for me)

R, 68 66 bytes

N=scan();m=expand.grid(k=1:18,1:N);n=m$V;m$k[m$k*n*(n-1)/2+n==N]+2  Reads N from stdin. Computes the first N k-gonal numbers and gets the k where they equal N, using xnor's formula; however, saves bytes on parentheses by using 1:18 instead of 3:20 and adding 2 at the end. expand.grid by default names the columns Var1, Var2, ..., if a name is not given. $ indexes by partial matching, so m$V corresponds to m$Var2, the second column.

old version:

N=scan();m=expand.grid(k=3:20,1:N);n=m$V;m$k[(m\$k-2)*n*(n-1)/2+n==N]


Try it online!

Pari/GP, 34 bytes

Pari/GP has a built-in to test whether a number is a polygonal number.

x->[s|s<-[3..20],ispolygonal(x,s)]


Try it online!

Jelly, 20 bytes

I just started writing an effective dupe of this challenge (albeit covering all k>1 not just [1,20]) ...so instead I'll answer it!

Ṫð’××H+⁸
18pÇċ¥Ðf⁸+2


A full program printing a Jelly list representation of the results*

Try it online!

a single result prints just that number;
multiple results prints a [] enclosed, ,  separated list of the numbers

How?

Ṫð’××H+⁸ - Link 1, ith (x+2)-gonal number: list [x,i]   e.g. [3,4] (for 4th Pentagonal)
Ṫ        - tail & modify (i.e. yield i & make input [x])     4
ð       - new dyadic chain, i.e. left = i, right = [x]
’      - decrement i                                       3
×     - multiply by [x]                                   [9]
H   - halve [x]                                         [2]
×    - multiply                                          [18]
⁸ - chain's left argument, i                          4

18pÇċ¥Ðf⁸+2 - Main link: number, n                      e.g. 36
18p         - Cartesian product of range [1,18] with n       [[1,1],[1,2],...,[1,36],[2,1],...,[18,1],[18,2],[18,36]]
-   (all pairs of [(k-2),i] which could result in the ith k-gonal number being n)
Ðf    - filter keep if this is truthy:
⁸   -   chain's left argument, n                     36
Ç        -     call the last link as a monad (note this removes the tail of each)
ċ       -     count (this is 1 if the result is [n] and 0 otherwise)
-                            filter keep result: [[1],[2],[11]]