# Introduction

Everyone's heard of sine (sin), cosine (cos), tangent (tan), cotangent (cot), secant (sec), and cosecant (csc). Nearly every angle has them.

Far less known, or remembered, are the exsecant (exsec), excosecant (excsc), versine (versin), and coversine (cvs). Nearly every angle has those as well. There are some that are even less known, but we'll just stick to these.

I've created a visualization of these for angle θ, which is 45°.

# The Challenge

Create a program that takes an input of an angle n, in degrees, and will output:

1. the sine of angle n

2. the cosine of angle n

3. the tangent of angle n

4. the secant of angle n

5. at least one of the following. Every additional item from this list will earn a bonus -5%, for a maximum of -25%.

• exsecant of angle n

• cosecant of angle n

• excosecant of angle n

• versine of angle n

• coversine of angle n

• cotangent of angle n

If your score is a decimal after applying a bonus, round up to the nearest whole number.

# Input

You may accept your input through STDIN or through a function call. A single argument, n, will be passed.

n will always be a whole integer that is greater than 0, but less than or equal to 90.

# Output

Here is an example of the output for sine of 45°. All output items must be in this format. The order of the items does not matter.

sine: 0.70710678118


All items must have exactly 4 numbers after the decimal (precision to the ten-thousandths). Below are a few examples of rounding.

0 -> 0.0000
1 -> 1.0000
0.2588190451 -> 0.2588
5.67128181962 -> 5.6713
10 -> 10.0000
12.4661204396 -> 12.4661


Any nonexistent/undefined results should default to 0.

# Example

myprogram(60)

sine: 0.8660
cosine: 0.5000
tangent: 1.7321
secant: 2.0000
exsecant: 1.0000
cosecant: 1.1547
excosecant: 0.1547
versine: 0.5000
coversine: 0.1340
cotangent: 0.5774


# Scoreboard

For your score to appear on the board, it should be in this format:

# Language, Score


Or if you earned a bonus:

# Language, Score (Bytes - Bonus%)


Strikethroughs shouldn't cause a problem.

function getURL(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function getAnswers(){$.ajax({url:getURL(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),useData(answers)}})}function getOwnerName(e){return e.owner.display_name}function useData(e){var s=[];e.forEach(function(e){var a=e.body.replace(/<s>.*<\/s>/,"").replace(/<strike>.*<\/strike>/,"");console.log(a),VALID_HEAD.test(a)&&s.push({user:getOwnerName(e),language:a.match(VALID_HEAD)[1],score:+a.match(VALID_HEAD)[2],link:e.share_link})}),s.sort(function(e,s){var a=e.score,r=s.score;return a-r}),s.forEach(function(e,s){var a=$("#score-template").html();a=a.replace("{{RANK}}",s+1+"").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SCORE}}",e.score),a=$(a),$("#scores").append(a)})}var QUESTION_ID=58283,ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",answers=[],answer_ids,answers_hash,answer_page=1;getAnswers();var VALID_HEAD=/<h\d>([^\n,]*)[, ]*(\d+).*<\/h\d>/;
body{text-align:left!important}table thead{font-weight:700}table td{padding:10px 0 0 30px}#scores-cont{padding:10px;width:600px}#scores tr td:first-of-type{padding-left:0}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"><div id="scores-cont"><h2>Scores</h2><table class="score-table"><thead> <tr><td></td><td>User</td><td>Language</td><td>Score</td></tr></thead> <tbody id="scores"></tbody></table></div><table style="display: none"> <tbody id="score-template"><tr><td>{{RANK}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SCORE}}</td></tr></tbody></table>

• Does the order of the output matter? Sep 19 '15 at 9:07
• Pedantry ahead: "Every angle has them" - not true; odd multiples of 90 degrees don't have a tangent, for example. (It seems extremely bizarre to me that you require nonexisting values to give an output of zero. Would you really use a program that deliberately gave such misleading answers?) Also, I'd be interested to know why you regard the cosecant and cotangent as being more obscure than the secant; in my A-level maths classes we learned about those three at the same time. Sep 19 '15 at 10:54
• Is capitalization fixed lowercase? I'd like output 'Sine, Cosine ...' Sep 19 '15 at 14:05
• Hard to understand Full program vs input through a function call Sep 19 '15 at 14:09
• Is the angle input really greater than 0, so 0 is not allowed? Sep 19 '15 at 14:37

# CJam, 94898581 80 bytes

"sine tangent secant"S/{"co"1$+}%rd90/_i33Yb@[P*2/__ms\mc@mt]_Wf#W%+?.{d": %.4f"e%N}  The code is 84 bytes long and qualifies for a 5% bonus (cotangent and cosecant). Try it online in the CJam interpreter. ### How it works "sine tangent secant" e# Push that string. S/ e# Split it at spaces. {"co"1$+}%            e# For each chunk, append a copy to the string "co", pushing
e# ["sine" "cosine" "tangent" "cotangent" "secant" "cosecant"].
rd90/                 e# Read a Double from STDIN and divide it by 90.
_i                    e# Push a copy and cast it to integer.
33Yb                  e# Push 33 in base 2, i.e., [1 0 0 0 0 1].
@                     e# Rotate the Double on top of the stack.
[                     e#
P*2/                e# Multiply by Pi and divide by 2.
__                  e# Push two copies of the result.
ms                  e# Compute the sine of the topmost copy.
\mc                 e# Swap and compute the cosine of the next copy.
@mt                 e# Rotate and compute the tangent of the original.
]                    e#
_Wf#                 e# Copy the array and raise all Doubles to the power -1.
e# This computes cosecant, secant and cotangent.
W%                   e# Reverse their order.
+                    e# Append to the original array.
?                    e# Select 33Yb if the integer part of the input divided by 90 is
e# (i.e., if the input is 90), the constructed array otherwise.
.{                   e# For each function name and result:
d                  e# Cast to Double (needed for 33Yb).
": %.4f"           e# Push a format string containing ": " and a 4-decimal float.
e%                 e# Apply the formatting to the Double on the stack.
N                  e# Push a linefeed.
}                    e#


# Julia, 162 - 10% = 144 bytes

n->for z=zip(split("sine cosine tangent secant exsecant cosecant cotangent"),[sind,cosd,tand,secd,i->secd(i)-1,cscd,cotd]) @printf("%s: %.4f\n",z[1],z[2](n))end


Ungolfed:

function f(n)
# Construct a vector of names
s = split("sine cosine tangent secant exsecant cosecant cotangent")

# Construct a vector of functions
o = [sind, cosd, tand, secd, i -> secd(i) - 1, cscd, cotd]

# Print each in a loop
for z = zip(s, o)
@printf("%s: %.4f\n", z[1], z[2](n))
end
end

• Is it me or your "Unfolded" version has an additional loop? Sep 19 '15 at 23:08
• You'd be better off without exsecant and cotangent. Sep 19 '15 at 23:48
• @DavidArenburg The longer version has the same number of loops, it's just written differently than the short version. Sep 20 '15 at 6:16
• @ThomasKwa I know, but I'm not going to win anyway. :P Sep 20 '15 at 6:16

# Pyth, 66 - 10% = 59.4 bytes

j+V+Jc"sine secant tangent")+L"co"Jsmm%": %.4f"^.t.td7k^_1k3,Q-90Q


Calculates the sine, secant and tangent. Then, the co- functions are simply calculated via the formula coF(x) = F(90 - x).

• Does this give 0 for undefined? Sep 19 '15 at 23:52
– orlp
Sep 20 '15 at 0:42
• Then it is currently invalid. Sep 20 '15 at 3:01

## Mathematica (Invalid at the moment), 134121 104

Just for fun, surely it can be golfed down a lot

f[n_]:=(a={Sin,Cos,Tan,Sec,Cot,Csc};TableForm[N[#@n,4]&/@a,TableHeadings->{ToString[#]<>":"&/@a,None}])


And it should have a 5% bonus (Cot and Csc), therefore amounting at 99 characters

Example output:

• Wouldn't you get a better score by adding more functions? Sep 19 '15 at 11:25
• @proud haskeller, I can try, but probably I will lose more than gain characters Sep 19 '15 at 11:28
• Does this write the names of the functions out in full, or use 0 for sec(90)? Sep 19 '15 at 15:00
• @Thomas Kwa it shouldn't, I'll test it when I have a chance Sep 19 '15 at 19:59
• I really doubt this show actual function names Sep 20 '15 at 8:03

# JavaScript (ES6), 173 (182 - 5%)

Edit revised after clarification, now the bonus is 5%

Edit realized that the angle can not be 0

// TEST - redefine alert

r=(a=prompt(i=0))*(M=Math).PI/180,V=_=>[s=M.sin(r),c=M.cos(r),(f=a-90)&&s/c,c/s,f&&1/c,1/s][i++].toFixed(4);
alert(sine
tangent
secant.replace(/.+/g,h=>h+: ${V()} co${h}: ${V()})) /* More bonus, but too longer r=(a=prompt(i=0))*(M=Math).PI/180,V=_=>[s=M.sin(r),c=M.cos(r),1-c,1-s,(f=a-90)&&s/c,c/s,f&&1/c,1/s][i++].toFixed(4); alert(sine versine tangent secant.replace(/.+/g,h=>h+:${V()}
co${h}:${V()}))
*/
<pre id=O></pre>

# Javascript ES6, 154 148 (198 - 25%)

(n=0)=>[S='sine',(O='co')+S,T='tangent',C='secant',X=O+C,O+T,V='ver'+S,O+V,'ex'+C,'ex'+X].map((q,i)=>q+': '+[s=Math.sin(n),c=Math.cos(n),t=s/c,e=1/c,o=1/s,1/t,1-c,1-s,e-1,o-1][i].toFixed(4)).join



Ungolfed:

(n=0)=>          // function declaration, accepts number, defaults to 0
[              // create array of trig function names
S='sine',    // sine
(O='co')+S,  // cosine
T='tangent', // tangent
C='secant',  // secant
X=O+C,       // cosecant
O+T,         // cotangent
V='ver'+S,   // versine
O+V,         // coversine
'ex'+C,      // exsecant
'ex'+X       // excosecant
].map((q,i)=>  // map over names
// append ": <value rounded to 4 decimals>" to function name:
q+': '+[s=Math.sin(n),c=Math.cos(n),t=s/c,e=1/c,o=1/s,1/t,1-c,1-s,e-1,o-1][i].toFixed(4)
).join        // add newline between each function


• Could you add a comma after "Javascript ES6" in your title so your score will parse correctly? Sep 22 '15 at 0:04

# R, 122136 134 bytes

n=scan()*pi/180;write(paste0(c("sine","cosine","tangent","secant","versine"),sprintf(": %.4f",c(sin(n),r<-cos(n),tan(n),1/r,1-r))),"")


Example usage

> n=scan()*pi/180;write(paste0(c("sine","cosine","tangent","secant","versine"),sprintf(": %.4f",c(sin(n),r<-cos(n),tan(n),1/r,1-r))),"")
1: 60
2:
sine: 0.8660
cosine: 0.5000
tangent: 1.7321
secant: 2.0000
versine: 0.5000

• scan()/(180/pi) -> scan()*pi/180? Sep 20 '15 at 0:16

# Perl, 182 177 (236 - 25%)

Run with -n (1 byte added to uncorrected score).

$b=$_==90;$_/=57.296;$c=cos;$s=sin;sub f{printf"%s: %.4f\n",@_}$T=tangent;f$T,$b?0:$s/$c;f co.$T,$c/$s;$S=sine;f $S,$s;f co.$S,$c;$C=secant;f$C,$b?0:1/$c;f co.$C,1/$s;f ex.$C,$b?0:1-1/$c;f exco.$C,1/$s-1;$V=ver.$S;f$V,1-$c;f co.$V,1-$s  Nothing fancy. It takes advantage of -n for implicit input, $_ as a default argument to sin and cos, and barewords for strings. The “undefined = 0” rule is hardcoded in using the ternary operator ?: (it applies only for 90°).

One thing I learend is that apparently, you cannot have (or cannot call) a subroutine named s (or m, y, tr): sub s {print 1}; s yields Substitution pattern not terminated at -e line 1.

• For some reason, your score is parsed even weirder. Sep 21 '15 at 15:44
• Could you add a comma after "Perl" so your score is parsed correctly? Sep 21 '15 at 16:20

# Python 3, 282 (375 - 25%)

Error handling turned out to be somewhat complicated by floating-point errors; namely, cos(90) came out to a very small number instead of zero.

It's never going to be the top answer, but I like to think it might be the shortest valid all-functions answer in a non-golfy language that doesn't have the trig functions in the default namespace. ;-)

import math as m
def p(q,r):print(q+':','%.4f'%r)
def a(n):
n=n*m.pi/180
C,S=round(m.cos(n),8),m.sin(n)
A=S,1,0,C,1,S,C,0,C,S,1,C,0,1,S,1,C,-1,1,S,C,1,1,S,1
def t():
nonlocal A;u,v,w,x,y,*A=A;z=-1 if w>0 else 1
try:return z*u/v+w,z*x/y+w
except:return 0,0
def q(y,x=''):J,K=t();p(x+y,J);p(x+'co'+y,K)
q('sine');q('tangent');s='secant';q(s);q(s,'ex');q('versine')


Sample output:

>>> a(60)
sine: 0.8660
cosine: 0.5000
tangent: 1.7321
cotangent: 0.5774
secant: 2.0000
cosecant: 1.1547
exsecant: 1.0000
excosecant: 0.1547
versine: 0.5000
coversine: 0.1340

• wouldn't '.4f'%(r) be shorter? Sep 21 '15 at 15:38
• @xebtl: Thanks. I tend to forget that %-formatting still exists! Sep 22 '15 at 8:38

# Perl, 165 (193 - 15%)

I am submit this a s a new answer because the idea is quite different from the other one. Please let me know if it is more appropriate to replace my first attempt.

$p=atan2 1,0;$b=$_-90;%h=qw(sine$s tangent $b?$s/$c:0 secant$b?1/$c:0 versine 1-$c);$_/=90/$p;sub e{$c=cos;$s=sin}e;sub f{eval"printf'$x$_: %.4f
',$h{$_}"for keys%h}f;$b=1;$_=$p-$_;e;$x=co;f  Run with -n (1 byte added). Ungolfed: # π/2$p=atan2 1,0;

# trouble?
$b=$_-90;

# Construct a hash whose keys are the “base” function names,
# and whose values are the corresponding expressions in terms of sin and cos
%h=qw(sine $s tangent$b?$s/$c:0 secant $b?1/$c:0 versine 1-$c); # Thanks to ‘-n’, input is in$_; convert to radians
$_/=90/$p;

# Compute sin and cos in a reusable way
sub e{$c=cos;$s=sin}
e;

sub f {
eval "printf '$x$_: %.4f
', $h{$_}"
for keys %h
}

f;

# Now the “co” functions
# No trouble here
$b=1; # x ← π/2 - x$_=$p-$_;

e;
$x=co; f  Since it does the four “co”-functions, I think it qualifies for a 3*5% = 15% bonus. # Perl, 10095 94 bytes Whoa, lotta perl answers. $_=<>;printf"sine: %.4f\ncosine: %.4f\ntangent: %.4f\nsecant: %.4f\n",sin,cos,(sin)/cos,1/cos

• Yeah, and you are doing pretty well with this straightforward approach :-). You can shave off some bytes by using -n (counts for 1 byte) instead of $_=<>. However, you have to convert from degrees to radians, and you do not handle the 90° case as prescribed. (With the latter, it seems like you are hardly alone among the answers here.) Sep 23 '15 at 5:56 • Also, remember that the ancestor of Code Golf was Perl Golf :-) Sep 23 '15 at 6:18 • I'm a little confused here... this uses radians. Was I supposed to use degrees? Sep 23 '15 at 13:06 # Haskell, 159 = 186 - 15% bytes s x=zipWith(\a b->a++": "++show b)(concatMap(\n->[n,"co"++n])$words"sine tangent versine secant")$map($(x*pi/180))[sin,cos,t,(1/).t,(1-).cos,(1-).sin,e.t,e.(1/).t]
e=sqrt.(+1).(^2)
t=tan


No ex-thingies to keep my clever naming scheme and since I didn't know how to shorten (\x->x-1). (-1) is just a number.

Please complain if you want me to prettify (mapM_ putStrLn) the lines.

• Thanks! Same for Alex A. and @orlp. The latter should maybe round up the net score. Sep 21 '15 at 15:42