A Sine of Greatness

24

7

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>

Zach Gates

Posted 2015-09-19T04:51:20.727

Reputation: 6 152

Does the order of the output matter? – Jakube – 2015-09-19T09:07:46.313

12Pedantry 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. – Hammerite – 2015-09-19T10:54:08.267

Is capitalization fixed lowercase? I'd like output 'Sine, Cosine ...' – edc65 – 2015-09-19T14:05:47.063

Hard to understand Full program vs input through a function call – edc65 – 2015-09-19T14:09:52.443

1Is the angle input really greater than 0, so 0 is not allowed? – edc65 – 2015-09-19T14:37:46.237

I am probably misreading, but I need some clarifications. As you say a program than can output ..., that means that I may or may not print those items. All I need to print is one of the at least at point 5. If I'm wrong, please clarify... – edc65 – 2015-09-19T15:07:24.203

I've modified the question. To answer your question, you must output sine, cosine, tangent, secant, and at least one item from the list at #5. Every additional item from the list at #5 constitutes a bonus -5%. @edc65 – Zach Gates – 2015-09-19T15:14:59.707

I'm assuming builtins are allowed? – ASCIIThenANSI – 2015-09-22T19:28:21.457

Yes they are. @ASCIIThenANSI – Zach Gates – 2015-09-22T19:34:44.873

It looks like there are a lot of answers who do not convert to radians (input is supposed to be in degrees, right?) or handle the 90° case as prescribed (I cannot say I agree with returning 0, but still). – xebtl – 2015-09-23T05:59:31.680

Answers

8

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#

Dennis

Posted 2015-09-19T04:51:20.727

Reputation: 196 637

6

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

Alex A.

Posted 2015-09-19T04:51:20.727

Reputation: 23 761

Is it me or your "Unfolded" version has an additional loop? – David Arenburg – 2015-09-19T23:08:21.083

You'd be better off without exsecant and cotangent. – lirtosiast – 2015-09-19T23:48:45.080

@DavidArenburg The longer version has the same number of loops, it's just written differently than the short version. – Alex A. – 2015-09-20T06:16:27.900

@ThomasKwa I know, but I'm not going to win anyway. :P – Alex A. – 2015-09-20T06:16:48.743

5

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

WizardOfMenlo

Posted 2015-09-19T04:51:20.727

Reputation: 843

Wouldn't you get a better score by adding more functions? – proud haskeller – 2015-09-19T11:25:06.570

@proud haskeller, I can try, but probably I will lose more than gain characters – WizardOfMenlo – 2015-09-19T11:28:43.907

4Does this write the names of the functions out in full, or use 0 for sec(90)? – lirtosiast – 2015-09-19T15:00:20.013

@Thomas Kwa it shouldn't, I'll test it when I have a chance – WizardOfMenlo – 2015-09-19T19:59:58.530

I really doubt this show actual function names – David Arenburg – 2015-09-20T08:03:42.507

@DavidArenburg see edit, this is what it outputs – WizardOfMenlo – 2015-09-20T09:07:05.837

So the output isn't correct. It should output the full names as per OPs question. I.e., sine:, cosine:, etc. Also, you aren't rounding to the fourth digit. All the numbers should have 4 digits after the dot. See example output per one of the answer in this thread

– David Arenburg – 2015-09-20T09:07:48.763

@DavidArenburg fair enough, I'll add a version which does as soon as I can – WizardOfMenlo – 2015-09-20T09:09:05.790

5

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

orlp

Posted 2015-09-19T04:51:20.727

Reputation: 37 067

Does this give 0 for undefined? – lirtosiast – 2015-09-19T23:52:26.727

@ThomasKwa Don't think so. – orlp – 2015-09-20T00:42:35.307

1Then it is currently invalid. – lirtosiast – 2015-09-20T03:01:30.370

4

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>

edc65

Posted 2015-09-19T04:51:20.727

Reputation: 31 086

4

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
`

Dendrobium

Posted 2015-09-19T04:51:20.727

Reputation: 2 412

Could you add a comma after "Javascript ES6" in your title so your score will parse correctly? – Zach Gates – 2015-09-22T00:04:38.033

3

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

David Arenburg

Posted 2015-09-19T04:51:20.727

Reputation: 531

2scan()/(180/pi) -> scan()*pi/180? – lirtosiast – 2015-09-20T00:16:25.850

3

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

Tim Pederick

Posted 2015-09-19T04:51:20.727

Reputation: 1 411

wouldn't '.4f'%(r) be shorter? – xebtl – 2015-09-21T15:38:05.627

@xebtl: Thanks. I tend to forget that %-formatting still exists! – Tim Pederick – 2015-09-22T08:38:36.577

3

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.

xebtl

Posted 2015-09-19T04:51:20.727

Reputation: 941

For some reason, your score is parsed even weirder. – Leif Willerts – 2015-09-21T15:44:13.100

Could you add a comma after "Perl" so your score is parsed correctly? – Zach Gates – 2015-09-21T16:20:38.493

3

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.

xebtl

Posted 2015-09-19T04:51:20.727

Reputation: 941

3

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

a spaghetto

Posted 2015-09-19T04:51:20.727

Reputation: 10 647

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.) – xebtl – 2015-09-23T05:56:52.693

Also, remember that the ancestor of Code Golf was Perl Golf :-) – xebtl – 2015-09-23T06:18:48.037

I'm a little confused here... this uses radians. Was I supposed to use degrees? – a spaghetto – 2015-09-23T13:06:03.257

2

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.

Leif Willerts

Posted 2015-09-19T04:51:20.727

Reputation: 1 060

Thanks! Same for Alex A. and @orlp. The latter should maybe round up the net score. – Leif Willerts – 2015-09-21T15:42:18.360