24
\$\begingroup\$

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>

\$\endgroup\$
  • \$\begingroup\$ Does the order of the output matter? \$\endgroup\$ – Jakube Sep 19 '15 at 9:07
  • 12
    \$\begingroup\$ 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. \$\endgroup\$ – Hammerite Sep 19 '15 at 10:54
  • \$\begingroup\$ Is capitalization fixed lowercase? I'd like output 'Sine, Cosine ...' \$\endgroup\$ – edc65 Sep 19 '15 at 14:05
  • \$\begingroup\$ Hard to understand Full program vs input through a function call \$\endgroup\$ – edc65 Sep 19 '15 at 14:09
  • 1
    \$\begingroup\$ Is the angle input really greater than 0, so 0 is not allowed? \$\endgroup\$ – edc65 Sep 19 '15 at 14:37

12 Answers 12

8
\$\begingroup\$

CJam, 94 89 85 81 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#
\$\endgroup\$
6
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ Is it me or your "Unfolded" version has an additional loop? \$\endgroup\$ – David Arenburg Sep 19 '15 at 23:08
  • \$\begingroup\$ You'd be better off without exsecant and cotangent. \$\endgroup\$ – lirtosiast Sep 19 '15 at 23:48
  • \$\begingroup\$ @DavidArenburg The longer version has the same number of loops, it's just written differently than the short version. \$\endgroup\$ – Alex A. Sep 20 '15 at 6:16
  • \$\begingroup\$ @ThomasKwa I know, but I'm not going to win anyway. :P \$\endgroup\$ – Alex A. Sep 20 '15 at 6:16
5
\$\begingroup\$

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).

\$\endgroup\$
  • \$\begingroup\$ Does this give 0 for undefined? \$\endgroup\$ – lirtosiast Sep 19 '15 at 23:52
  • \$\begingroup\$ @ThomasKwa Don't think so. \$\endgroup\$ – orlp Sep 20 '15 at 0:42
  • 1
    \$\begingroup\$ Then it is currently invalid. \$\endgroup\$ – lirtosiast Sep 20 '15 at 3:01
5
\$\begingroup\$

Mathematica (Invalid at the moment), 134 121 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:

Example Output

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

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
alert=x=>O.innerHTML=x

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>

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

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
`
\$\endgroup\$
  • \$\begingroup\$ Could you add a comma after "Javascript ES6" in your title so your score will parse correctly? \$\endgroup\$ – Zach Gates Sep 22 '15 at 0:04
3
\$\begingroup\$

R, 122 136 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: 
Read 1 item
sine: 0.8660
cosine: 0.5000
tangent: 1.7321
secant: 2.0000
versine: 0.5000
\$\endgroup\$
  • 2
    \$\begingroup\$ scan()/(180/pi) -> scan()*pi/180? \$\endgroup\$ – lirtosiast Sep 20 '15 at 0:16
3
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ For some reason, your score is parsed even weirder. \$\endgroup\$ – Leif Willerts Sep 21 '15 at 15:44
  • \$\begingroup\$ Could you add a comma after "Perl" so your score is parsed correctly? \$\endgroup\$ – Zach Gates Sep 21 '15 at 16:20
3
\$\begingroup\$

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
\$\endgroup\$
  • \$\begingroup\$ wouldn't '.4f'%(r) be shorter? \$\endgroup\$ – xebtl Sep 21 '15 at 15:38
  • \$\begingroup\$ @xebtl: Thanks. I tend to forget that %-formatting still exists! \$\endgroup\$ – Tim Pederick Sep 22 '15 at 8:38
3
\$\begingroup\$

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.

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

Perl, 100 95 94 bytes

Whoa, lotta perl answers.

$_=<>;printf"sine: %.4f\ncosine: %.4f\ntangent: %.4f\nsecant: %.4f\n",sin,cos,(sin)/cos,1/cos
\$\endgroup\$
  • \$\begingroup\$ 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.) \$\endgroup\$ – xebtl Sep 23 '15 at 5:56
  • \$\begingroup\$ Also, remember that the ancestor of Code Golf was Perl Golf :-) \$\endgroup\$ – xebtl Sep 23 '15 at 6:18
  • \$\begingroup\$ I'm a little confused here... this uses radians. Was I supposed to use degrees? \$\endgroup\$ – a spaghetto Sep 23 '15 at 13:06
2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Thanks! Same for Alex A. and @orlp. The latter should maybe round up the net score. \$\endgroup\$ – Leif Willerts Sep 21 '15 at 15:42

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.