17
\$\begingroup\$

Background

It can be shown that for any integer k >= 0, f(k) = tan(atan(0) + atan(1) + atan(2) + ... + atan(k)) is a rational number.

Goal

Write a complete program or function which when given k >= 0, outputs f(k) as a single reduced fraction (the numerator and denominator are coprime).

Test cases

The first few values are

f(0) = (0,1)
f(1) = (1,1)
f(2) = (-3,1)
f(3) = (0,1)
f(4) = (4,1)
f(5) = (-9,19)
f(6) = (105,73)

Rules

  • Standard loopholes are forbidden.
  • Input and output may be in any convenient format. You may output f(k) as a string numerator/denominator, as a tuple of two integers, a fraction or rational object, etc. If you output a string, give two integers only, that is, output 3/2 instead of 1 1/2.
  • This is code-golf, the shortest answer (in bytes) wins.
\$\endgroup\$
10
  • 1
    \$\begingroup\$ Can you further specify in your test cases what the input/output values are? \$\endgroup\$
    – Ian H.
    Commented Aug 8, 2017 at 6:22
  • 1
    \$\begingroup\$ Are the integers in the range in degrees or radians? \$\endgroup\$ Commented Aug 8, 2017 at 6:59
  • 1
    \$\begingroup\$ OEIS: A180657 \$\endgroup\$
    – Sisyphus
    Commented Aug 8, 2017 at 7:00
  • 4
    \$\begingroup\$ The atan(0) term is unnecessary. \$\endgroup\$
    – Adám
    Commented Aug 8, 2017 at 7:08
  • 3
    \$\begingroup\$ @pizzapants184 f(0) = tan∑∅ = tan 0 = 0 \$\endgroup\$
    – Adám
    Commented Aug 8, 2017 at 7:14

12 Answers 12

11
\$\begingroup\$

Mathematica, 28 bytes

Fold[+##/(1-##)&,0,Range@#]&

Try it online!

A longer, but more interesting approach (32 bytes):

Im@#/Re@#&@Product[1+n I,{n,#}]&

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ +1 o'_'o Mathematica and its built-ins o'_'o \$\endgroup\$
    – Mr. Xcoder
    Commented Aug 8, 2017 at 7:37
  • 3
    \$\begingroup\$ @Mr.Xcoder Not really in this case. OP is using series summation cleverly (if I read the code right). \$\endgroup\$
    – Adám
    Commented Aug 8, 2017 at 7:38
11
\$\begingroup\$

Python 2, 76 72 bytes

from fractions import*
f=lambda k:Fraction(k and(k+f(k-1))/(1-k*f(k-1)))

Use the identity:

tan(A + B) = (tan(A) + tan(B)) / (1 - tan(A) * tan(B))

We have:

f(k) = 0                                    if k = 0
     = (k + f(k - 1)) / (1 - k * f(k - 1))  if k > 0

Try it online!

Thanks to Luis Mendo, save 4 bytes.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Hope you do not mind: I added a TiO link. \$\endgroup\$
    – Mr. Xcoder
    Commented Aug 8, 2017 at 7:05
  • \$\begingroup\$ @LuisMendo LGTM, Edited. \$\endgroup\$
    – tsh
    Commented Aug 8, 2017 at 10:08
4
\$\begingroup\$

M, 11 bytes

×C÷@+
R0;ç/

Try it online!

Uses the OEIS formula x(n) = (x(n-1)+n)/(1-n*x(n-1)) with x(0) = 0.

\$\endgroup\$
3
\$\begingroup\$

APL (Dyalog), 14 bytes

Requires ⎕FR←1287 (128 bit Floating-point Representation) for small input. Takes k as right argument.

1(∧÷,)3○¯3+.○⍳

Try it online!

 integers one through k (zero is not needed as 0 = arctan 0)

¯3+.○ sum of arcus tangents

3○ tangent

1() apply the following tacit function with 1 as left argument and the above as right argument:

 the lowest common multiple (of 1 and the right argument); gives the numerator

÷ divided by

, the concatenation (of 1 and the right argument); gives the numerator and the denominator

\$\endgroup\$
3
\$\begingroup\$

Haskell, 52 bytes

This uses the OEIS series expansion:

import Data.Ratio
f 0=0%1
f n|p<-f$n-1=(p+n)/(1-n*p)

Try it online!

Or a pointfree version:

(scanl1(\f n->(f+n)/(1-n*f))[0%1..]!!)
\$\endgroup\$
2
\$\begingroup\$

JavaScript (ES6), 80 bytes

f=n=>n?([a,b]=f(n-1),g=(a,b)=>a?g(b%a,a):b,c=g(d=b*n+a,e=b-n*a),[d/c,e/c]):[0,1]

Returns a [numerator, denominator] pair. Explanation: Let f(n-1) = a/b then f(n) = atan(tan(n)+tan(a/b)) = (n+a/b)/(1-n*a/b) = (b*n+a)/(b-n*a). It then remains to reduce the fraction to its lowest terms.

Online ES6 Environment

\$\endgroup\$
1
\$\begingroup\$

Pari/GP, 36 bytes

n->imag(x=prod(i=0,n,1+i*I))/real(x)

Try it online!

Or the same length:

n->fold((x,y)->(x+y)/(1-x*y),[0..n])

Try it online!

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 33 26 bytes

0X)Iƒ©`N*+®`sN*-‚D¿D_i\¤}/

Try it online!

Explanation

0X)                          # initialize stack with [0,1]
   Iƒ                        # for N in range [0 ... input] do:
     ©                       # store a copy of the current pair in the register
      `                      # push the pair separately to the stack
       N*                    # multiply the denominator with N
         +                   # add the numerator
          ®`s                # push the denominator then the numerator to the stack
             N*              # multiply the numerator by N
               -             # subtract it from the denominator
                D¿D          # get 2 copies of the greatest common divisor
                   0Qi  }    # if the gcd equals 0
                      \¤     # replace it with the denominator
                         /   # divide the pair with this number
\$\endgroup\$
1
\$\begingroup\$

Octave, 30 bytes

format rat
tan(sum(atan(0:k)))

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Casio-Basic, 35 bytes

tExpand(tan(sum(seq(tan⁻¹(n),n,0,k

tan-1 should be entered as the one on the Trig keyboard; or the -1 can be entered separately from the abc>Math keyboard. According to the fx-CP400's manual, it's a single two-byte character (764).

Function, 34 bytes for the code, +1 byte to add k as an argument.

Explanation

seq(tan-1(n),n,0,k) generates all the values for tan-1(n) from 0 to k.

sum adds them all together, then tan does the tangent function on them.

tExpand will then turn them into a single fraction.

\$\endgroup\$
3
  • \$\begingroup\$ @Adám This is Casio, not TI, so it's not done the same way. \$\endgroup\$ Commented Aug 8, 2017 at 7:55
  • \$\begingroup\$ According to Wikipedia, and ¹ are two bytes each; E5CC and E5C1. \$\endgroup\$
    – Adám
    Commented Aug 8, 2017 at 8:05
  • \$\begingroup\$ @Adám oh nice, I didn't realise that article existed! However, this is an fx-CP400, not the 9860G; I just checked the manual, and the superscript -1 is actually a single character, code 764; so it's a single two byte character. \$\endgroup\$ Commented Aug 8, 2017 at 8:14
1
\$\begingroup\$

Forth (gforth), 130 bytes

: g dup if tuck mod recurse then ;
: f 0 1 rot for 2dup i * + -rot swap i * - next
2dup g + abs over 0< 2* 1+ * >r i / swap r> / ;

Try it online!

Uses my own implementation of gcd, and the OEIS formula. Takes k from the stack and returns two integers denom num on the stack. It took a lot of effort (and bytes) to normalize the fraction.

: g ( x y -- gcd 0 )
  dup if tuck mod recurse then
;

: f ( k -- denom num )
  0 1               \ push initial fraction with num=0, denom=1
  rot for           \ ( num denom ) loop from k to 0 inclusive
    2dup i * + -rot \ ( denom*k+num num denom )
    swap i * -      \ ( denom*k+num denom-num*k )
  next
  2dup g + abs      \ ( num denom gcd ) evaluate positive gcd and remove 0
  over 0< 2* 1+ *   \ ( num denom gcd' ) negate gcd if denom < 0
  >r i / swap r> /  \ ( denom/gcd' num/gcd' )
;
\$\endgroup\$
0
\$\begingroup\$

Julia 0.6.0 40 bytes

k->rationalize(tan(sum(x->atan(x),1:k)))

It's a straightforward implementation of the question. The precision of rationalize can sometimes be weird but works fine 99% of the time.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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