14
\$\begingroup\$

Let's say you have a positive integer N. First, build a regular polygon, that has N vertices, with the distance between neighbouring vertices being 1. Then connect lines from every vertex, to every other vertex. Lastly, calculate the length of all lines summed up together.

Example

Given the input N = 6, build a hexagon with lines connecting every vertex with the other vertices.

Hexagon

As you can see, there are a total of 6 border lines (length=1), 3 lines that have double the border length (length=2) and 6 other lines that we, by using the Pythagoras Theorem, can calculate the length for, which is

If we add the lengths of the lines together we get (6 * 1) + (3 * 2) + (6 * 1.732) = 22.392.

Additional Information

As structures with 2 or less vertices are not being considered polygons, output 0 (or NaN, since distance between a single vertex doesn't make much sense) for N = 1, since a single vertice cannot be connected to other vertices, and 1 for N = 2, since two vertices are connected by a single line.

Input

An integer N, in any reasonable format.

Output

The length of all the lines summed up together, accurate to at least 3 decimal places, either as a function return or directly printed to stdout.

Rules

  • Standard loopholes are forbidden.
  • This is , so the shortest code in bytes, in any language, wins.

Good luck!

Test Cases

(Input) -> (Output)
1 -> 0 or NaN
2 -> 1
3 -> 3
5 -> 13.091
6 -> 22.392
\$\endgroup\$
  • 1
    \$\begingroup\$ Must we really handle 1? My current entry would return nan rather than zero for example, and would just require special casing for it. \$\endgroup\$ – Jonathan Allan Oct 23 '17 at 19:51
  • 1
    \$\begingroup\$ @JonathanAllan I thought about it after seeing your answer, nan is fine too, as distance between a single vertex doesn't make much sense anyways. \$\endgroup\$ – Ian H. Oct 23 '17 at 19:54
  • 6
    \$\begingroup\$ You should probably allow errors to be thrown too for n=1 I think. \$\endgroup\$ – Jonathan Allan Oct 23 '17 at 20:03
  • \$\begingroup\$ It's hard to tell what 3 decimal places of accuracy means without an upper bound for N, since outputs get larger and floats get less precise. \$\endgroup\$ – xnor Oct 23 '17 at 20:16
  • \$\begingroup\$ @xnor As long as it is precise up to 3 decimal places for any reasonable input N, its fine is the result is less precise for huge numbers. \$\endgroup\$ – Ian H. Oct 23 '17 at 20:26
13
\$\begingroup\$

Python 3 (with sympy),  61 60 58 54  48 bytes

-6 (maybe even -10 if we do not need to handle n=1) thanks to xnor (further trigonometric simplification plus further golfing to handle edge case of 1 and save parentheses by moving a (now unnecessary) float cast).

Hopefully beatable with no 3rd party libraries? Yes!! but Lets get things rolling...

lambda n:1%n*n/2/(1-cos(pi/n))
from math import*

Try it online!

This uses a formula for the sum of the lengths if a polygon is inscribed inside a unit circle, n*cot(pi/2/n)/2 and adjusts the result to one for the side length being one by dividing by the sin of that cord length sin(pi/n).

The first formula is acquired by considering the n-1 cord lengths of all the diagonals emanating from one corner which are of lengths sin(pi/n) (again), sin(2*pi/n), ..., sin((n-1)pi/n). The sum of this is cot(pi/2/n), there are n corners so we multiply by n, but then we've double counted all the cords, so we divide by two.

The resulting n*cot(pi/2/n)/2/sin(pi/n) was then simplified by xnor to n/2/(1-cos(pi/n)) (holding for n>1)

...this (so long as the accuracy is acceptable) now no longer requires sympy over the built-in math module (math.pi=3.141592653589793).

\$\endgroup\$
  • 2
    \$\begingroup\$ yes! saved 11 bytes. cool formula! \$\endgroup\$ – J42161217 Oct 23 '17 at 19:57
  • 1
    \$\begingroup\$ It looks like the formula simplifies to n/2/(1-cos(pi/n)). \$\endgroup\$ – xnor Oct 23 '17 at 20:11
  • \$\begingroup\$ Good spot @xnor (so long as we may output 0.25 for n=1 - but special casing may be shorter too...) \$\endgroup\$ – Jonathan Allan Oct 23 '17 at 20:17
  • \$\begingroup\$ @JonathanAllan Huh, weird that 1/4 is the result for n=1. It can be patched with 1%n*. Also, parens can be saved by moving the float inside to float(1-cos(pi/n)). I don't know sympy much, but maybe there's an arithmetic way to force a float. \$\endgroup\$ – xnor Oct 23 '17 at 20:24
  • \$\begingroup\$ @xnor Thanks! (I should have noticed the float move). sympy outputs an expression - e.g. for n=6 no cast results in an expression with a representation 3.0/(-sqrt(3)/2 + 1) - there may well be a shorter way but I don't know it yet. \$\endgroup\$ – Jonathan Allan Oct 23 '17 at 20:34
7
\$\begingroup\$

Python, 34 bytes

lambda n:1%n*n/abs(1-1j**(2/n))**2

Try it online!

Uses the formula n/2/(1-cos(pi/n)) simplified from Jonathan Allan. Neil saved 10 bytes by noting that Python can compute roots of unity as fractional powers of 1j.

Python without imports doesn't have built-in trigonometric functions, pi, or e. To make n=1 give 0 rather than 0.25, we prepend 1%n*.

A longer version using only natural-number powers:

lambda n:1%n*n/abs(1-(1+1e-8j/n)**314159265)**2

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ Cool as a cucumber. \$\endgroup\$ – Jonathan Allan Oct 23 '17 at 20:57
  • \$\begingroup\$ 37 bytes: lambda n:1%n*n/(1-(1j**(2/n)).real)/2 \$\endgroup\$ – Neil Oct 23 '17 at 21:24
  • \$\begingroup\$ @Neil Wow, Python can just compute roots of unity. \$\endgroup\$ – xnor Oct 23 '17 at 21:29
  • \$\begingroup\$ Well, that was the easy bit. I don't know what abs() does though. \$\endgroup\$ – Neil Oct 23 '17 at 21:43
  • \$\begingroup\$ @Neil it gets the absolute value, hence the norm, i.e. the distance from the origin. \$\endgroup\$ – Jonathan Allan Oct 23 '17 at 21:44
6
\$\begingroup\$

MATL, 16 15 bytes

t:=ZF&-|Rst2)/s

Try it online! Or verify all test cases.

This uses a commit which introduced the FFT (Fast Fourier Transform) function, and which predates the challenge by 8 days.

Explanation

The code uses this trick (adapted to MATL) to generate the roots of unity. These give the positions of the vertices as complex numbers, except that the distance between consecutive vertices is not normalized to 1. To solve that, after computing all pairwise distances, the program divides them by the distance between consecutive vertices.

t       % Implicit input, n. Duplicate
:       % Range: [1 2 ... n-1 n]
=       % Isequal, element-wise. Gives [0 0 ... 0 1]
ZF      % FFT. Gives the n complex n-th roots of unity
&-|     % Matrix of pairwise absolute differences
R       % Upper triangular matrix. This avoids counting each line twice.
s       % Sum of each column. The second entry gives the distance between
        % consecutive vertices
t2)/    % Divide all entries by the second entry
s       % Sum. Implicit display
\$\endgroup\$
  • 1
    \$\begingroup\$ this is beautiful \$\endgroup\$ – Jonah Oct 26 '17 at 10:47
  • \$\begingroup\$ @Jonah Complex numbers FTW :-) \$\endgroup\$ – Luis Mendo Oct 26 '17 at 11:17
5
\$\begingroup\$

Grasshopper, 25 primitives (11 components, 14 wires)

I read a meta post about programs in GH and LabVIEW, and follow similar instructions to measure a visual language.

grasshopper program

Print <null> for N = 0, 1, 2,because Polygon Primitive cannot generate a polygon with 2 or fewer edges and you will get an empty list of lines.

Components from left to right:

  • Side count slider: input
  • Polygon Primitive: draw a polygon on canvas
  • Explode: Explode a polyline into segements and vertices
  • Cross reference: build holistic cross reference between all vertices
  • Line: draw a line between all pairs
  • Delete Duplicate Lines
  • Length of curve
  • (upper) Sum
  • (lower) Division: because Polygon Primitive draws polygon based on radius, we need to scale the shape
  • Multipication
  • Panel: output

rhino screenshot

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

Mathematica, 26 bytes

uses @Jonathan Allan's formula

N@Cot[Pi/2/#]/2Csc[Pi/#]#&   

Try it online!

-1 byte junghwan min

\$\endgroup\$
  • \$\begingroup\$ -1 byte: N@Cot[Pi/2/#]/2Csc[Pi/#]#& since 1/sin(x) = csc(x) \$\endgroup\$ – JungHwan Min Oct 23 '17 at 21:02
  • 2
    \$\begingroup\$ .5Csc[x=Pi/#]Cot[x/2]#& \$\endgroup\$ – Misha Lavrov Oct 24 '17 at 0:50
2
\$\begingroup\$

Haskell, 27 bytes

f 1=0
f n=n/2/(1-cos(pi/n))

Try it online!

I just dove into Haskell, so this turns out to be a fair beginner golf (that is, copying the formula from other answers).

I've also tried hard to put $ somewhere but the compiler keeps yelling at me, so this is the best I've got. :P

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

Jelly, 13 12 11 bytes

Uses Jonathan Allan's formula (and thanks to him for saving 2 bytes)

ØP÷ÆẠCḤɓ’ȧ÷

Try it online!

I've always been pretty fascinated with Jelly, but haven't used it much, so this might not be the simplest form.

\$\endgroup\$
  • \$\begingroup\$ Save a byte by using "argument swapping dyadic chain separation", ɓ, to inline your helper link like so: ØP÷ÆẠCḤɓn1×÷ \$\endgroup\$ – Jonathan Allan Oct 24 '17 at 19:45
  • \$\begingroup\$ @JonathanAllan oh thanks, I'm still a beginner and knew there probably was a better way than having a new chain but didn't know how to do it \$\endgroup\$ – Jeffmagma Oct 24 '17 at 20:48
  • \$\begingroup\$ Oh, we can save another by using decrement, , and logical-and, ȧ: ØP÷ÆẠCḤɓ’ȧ÷ :) \$\endgroup\$ – Jonathan Allan Oct 24 '17 at 20:59
  • \$\begingroup\$ oh wow thanks I hadn't thought of that \$\endgroup\$ – Jeffmagma Oct 24 '17 at 21:07
1
\$\begingroup\$

Javascript (ES6), 36 bytes

n=>1%n*n/2/(1-Math.cos(Math.PI/n))

Port of @JonathanAllan's Python 3 answer

f=n=>1%n*n/2/(1-Math.cos(Math.PI/n))
<input id=i type=number oninput="o.innerText=f(i.value)" /><pre id=o>

\$\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.