2
\$\begingroup\$

This challenge is very simple:

Given an angle measure in degrees or radians (your choice), output the angle between 0 and 2π non-inclusive [0º, 360º) that is coterminal with it.

Input

A positive or negative angle measure. You can pick if you want to take it in degrees or in radians.

Output

The angle on [0, 2π) that is coterminal with the input angle. If you take the input in degrees, the output must also be in degrees; if you take it in radians, the output must be in radians too. The coterminal angle is essentially a the angle mod 360°.

Examples (in degrees)

745 -> 25
1728 -> 288
90 -> 90
0 -> 0
360 -> 0
-50 -> 310
-543.21 -> 176.79
\$\endgroup\$
  • 9
    \$\begingroup\$ Please define "coterminal". \$\endgroup\$ – HyperNeutrino May 4 '17 at 13:15
  • \$\begingroup\$ I'm guessing on the basis of the examples that answers have to support floating point or fixed point input, but it would be good to have that in the spec (and rule out the GolfScript answer I would otherwise submit) \$\endgroup\$ – Peter Taylor May 4 '17 at 13:22
  • \$\begingroup\$ For reference of what a coterminal angle is: softschools.com/math/trigonometry/coterminal_angles \$\endgroup\$ – DimP May 4 '17 at 13:23
  • 2
    \$\begingroup\$ The test cases converted to radians: pastebin.com/hUuUkqqg \$\endgroup\$ – Business Cat May 4 '17 at 13:57
  • 5
    \$\begingroup\$ I feel like this challenge is too trivial. Honestly, a a % b challenge would be more interesting, although I feel like we've had that before. \$\endgroup\$ – Erik the Outgolfer May 4 '17 at 14:35

18 Answers 18

2
\$\begingroup\$

05AB1E, 4 bytes

360%

Try it online!

360  # push 360
   % # pop a,b: push (a % b)
\$\endgroup\$
5
\$\begingroup\$

Python 3, 14 bytes

lambda n:n%360

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Wait, % always returns positive? \$\endgroup\$ – HyperNeutrino May 4 '17 at 13:42
  • 2
    \$\begingroup\$ @HyperNeutrino As long as the divisor is positive, yes \$\endgroup\$ – ovs May 4 '17 at 13:44
  • 1
    \$\begingroup\$ Oh, cool! (I'm still used to Java where it's the same sign lol). \$\endgroup\$ – HyperNeutrino May 4 '17 at 13:47
4
\$\begingroup\$

R, 11 bytes

takes input from stdin in degrees

scan()%%360

Try it online!

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

05AB1E, 4 bytes

Just because there were no answers using radians.

žq·%

Try it online!

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

MATL, 5 4 bytes

360\

Try it online!

My first attempt with MATL!

-1 byte, just realised i is not necessary for recording the input...

\$\endgroup\$
  • \$\begingroup\$ ...How on earth does this work? :o \$\endgroup\$ – Beta Decay May 4 '17 at 18:02
  • \$\begingroup\$ @BetaDecay: Likely just a modulo with mathematically well-behaved behaviour for negative numbers. That's basically what the question is asking for. \$\endgroup\$ – user62131 May 5 '17 at 11:41
  • \$\begingroup\$ Yeap, basically it uses Matlab's mod() function I think. \$\endgroup\$ – DimP May 5 '17 at 11:45
4
\$\begingroup\$

Python 3, 13 bytes

360..__rmod__

Explanation: num.__rmod__(x) is equivalent to x%num (rmod is modulo from the right.).

\$\endgroup\$
  • \$\begingroup\$ Do not works for the last test case -543.21 (or any other float number) -> NotImplemented \$\endgroup\$ – Rod May 4 '17 at 16:10
  • 1
    \$\begingroup\$ 360..__rmod__ works for floats as well. \$\endgroup\$ – Dennis May 4 '17 at 18:40
3
\$\begingroup\$

CJam, 12 bytes

rd360:X%X+X%

All those extra bytes because CJam gives negative results for mods...

Try it online!

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

Jelly, 4 bytes

%360

Try it online!

I was kind of hoping Æ°° would do it for 3.

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

Java 7, 44 43 bytes

Crossed out 44 is still regular 44 ;(

float c(float n){return(n%=360)<0?n+360:n;}

Explanation:

Java uses remainder instead of actual modulo for negative numbers (source). So we'll have to manually fix the negative cases.

float c(float n){    // Method with float input and float return-type
  return(n%=360)<0?  //  If input mod-360 is negative
   n+360             //   Return input mod-360 + 360
  :                  //  Else:
   n;                //   Return input mod-360
}                    // End of method

Test code:

Try it here.

class M{
  static float c(float n){return(n%=360)<0?n+360:n;}

  public static void main(String[] a){
    System.out.print(c(745) + "; ");
    System.out.print(c(1728) + "; ");
    System.out.print(c(90) + "; ");
    System.out.print(c(0) + "; ");
    System.out.print(c(360) + "; ");
    System.out.print(c(-50) + "; ");
    System.out.print(c(-543.21f));
  }
}

Output:

25.0; 288.0; 90.0; 0.0; 0.0; 310.0; 176.78998
\$\endgroup\$
  • \$\begingroup\$ float c(float n){return(n<0&&360)+n%360;} for 41 bytes. \$\endgroup\$ – Luke May 4 '17 at 14:18
  • \$\begingroup\$ @Luke That doesn't work in Java, unlike JavaScript for example, because n<0 is a boolean and 360 is an integer. So it gives this error: "The operator && is undefined for the argument type(s) boolean, int". \$\endgroup\$ – Kevin Cruijssen May 4 '17 at 14:35
  • \$\begingroup\$ Ah, yeah. Shouldn't have expected every language is as loosely typed as JS... \$\endgroup\$ – Luke May 4 '17 at 14:36
  • \$\begingroup\$ @Luke That doesn't work for -360 either. \$\endgroup\$ – Neil May 4 '17 at 17:05
  • \$\begingroup\$ On the other hand, I think (n%360+360)%360 is good. \$\endgroup\$ – Neil May 4 '17 at 17:06
2
\$\begingroup\$

Japt, 14 11 10 4 bytes

u#Ũ

Try it online!

Takes input in degrees.

Explanation

 u#Ũ
Uu360
U     # (implicit input)
 u    # modulo
  360 # 360
      # (implicit output)
\$\endgroup\$
  • 1
    \$\begingroup\$ Numbers have a u function for just this purpose, if I recall correctly, so u#Ũ) should work :-) (Also, Ũ is actually two bytes) \$\endgroup\$ – ETHproductions May 4 '17 at 17:49
  • \$\begingroup\$ Both TIO and your transpiler say it's just one byte... \$\endgroup\$ – Luke May 4 '17 at 19:50
2
\$\begingroup\$

C, 69 43 bytes

This seems like an excessively trivial challenge, and indeed in many languages it is. The trick is in the implementation details of the modulo operator.

When both modulo operands are positive, nothing interesting happens. But when one of the operands is negative, then the results start depending on your interpretation of what should happen. You can either always return a positive result, return a result whose sign depends on the dividend, or return a result whose sign depends on the divisor.

Programming languages are quite divided on which behavior they choose to implement. The lucky ones for this challenge are the ones that always return a positive result, since that's what the test cases call for.

If you happen to be golfing in a language that implements modulo dependent on the sign of the dividend, then you have to do extra work to compensate for negative inputs—and to make sure that this compensation does not break positive inputs!

Here's a further golfed implementation in C (thanks to ais523):

f(double*n){*n=fmod(fmod(*n,360)+360,360);}

Try it online!

Notice that C is also hobbled here by the unfortunate omission of a modulo operator (a la %) for floating-point operations. Instead, you have to call a library function.

\$\endgroup\$
  • 2
    \$\begingroup\$ Several possible improvements: remove the #include (it's not required for the code to work, as all arguments to fmod have non-autopromoted types); remove the space after n,; instead of returning via the return value, take a float* as your argument, and return via assigning back to the argument (i.e. *n=…fmod(*n,360), not return…fmod(n,360)). \$\endgroup\$ – user62131 May 5 '17 at 11:41
  • 1
    \$\begingroup\$ My poor golfing skills are showing. Thanks for the suggestions, @ais523! I've incorporated them into my answer. I still feel incredibly dirty writing code like this. It's one thing to make things small and correct, but I'm not sure how I feel about making them small and dubious, taking advantage of implicit int with no actual return value. \$\endgroup\$ – Cody Gray May 5 '17 at 16:38
1
\$\begingroup\$

JavaScript (ES6), 21 19 18 bytes

Takes input in degrees.

n=>(n%360+360)%360
  • Saved 2 bytes thanks to Luke.
  • Saved 1 byte thanks to Neil.

Try it

f=
n=>(n%360+360)%360
i.addEventListener("input",_=>o.innerText=f(+i.value))
console.log(f(745)) // 25
console.log(f(1728)) // 288
console.log(f(90)) // 90
console.log(f(0)) // 0
console.log(f(360)) // 0
console.log(f(-50)) // 310
console.log(f(-543.21)) // 176.79
<input id=i type=number><pre id=o>

\$\endgroup\$
  • 1
    \$\begingroup\$ Beat me by 50 secs... 19 bytes: n=>n%360+(n<0&&360) \$\endgroup\$ – Luke May 4 '17 at 14:02
  • \$\begingroup\$ And you beat me to that improvement! Thanks, @Luke. \$\endgroup\$ – Shaggy May 4 '17 at 14:07
  • 1
    \$\begingroup\$ I don't think that works for -360, but try (n%360+360)%360. \$\endgroup\$ – Neil May 4 '17 at 17:06
  • \$\begingroup\$ You're right. And you saved me a byte. Thanks, @Neil. \$\endgroup\$ – Shaggy May 4 '17 at 17:18
1
\$\begingroup\$

Mathematica, 10 bytes

#~Mod~360&

Pure function taking any type of numerical input in degrees. Does what it says on the tin.

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

Fourier, 22 14 6 bytes

I%360o

Try it online!

Simply outputs the input modulo 360.

Note that since the interpreter for TIO is written in Python, this will not work on http://beta-decay.github.io/editor

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

x86 Assembly (targeting the x87 FPU), 23 bytes

As is standard with 32-bit calling conventions, the double-precision floating-point parameter is passed on the stack, and returned at the top of the x87 FPU stack. Assemble with MASM:

.MODEL flat
.686                              ; fucomip requires a Pentium Pro or later CPU

CONST SEGMENT
divisor  DD  043b40000r           ; 360.0f
CONST ENDS

PUBLIC _CoterminalAngle
_TEXT SEGMENT
_CoterminalAngle PROC
   fld      DWORD PTR [divisor]   ; single-precision takes fewer bytes to store; we don't need the precision
   fld      QWORD PTR [esp + 4]   ; load parameter from stack

   fprem                          ; st(0) = parameter % 360
                                  ; st(1) = 360

   fldz
   fucomip  st(0), st(1)          ; st(0) < 0?
   jbe      Finished
   fadd     st(0), st(1)          ; fixup negative modulo by adding 360
Finished:

    fstp    st(1)                 ; discard st(1); result is left in st(0)
    ret
_CoterminalAngle ENDP
_TEXT ENDS

END 

To call from C:

extern double CoterminalAngle(double value);

In bytes:

43B40000

D9 05 00 00 00 00
DD 44 24 04
D9 F8
D9 EE
DF E9
76 02
D8 C1
DD D9
C3

Notes:

As the comment indicates, to minimize code size, I've stored the divisor constant (360.0f) as a single-precision floating-point value. This means it is half the length it would be if it were a double-precision value, and we don't need the precision to store a proper representation of the value. Upon loading, the x87 FPU will implicitly extend it to its native ten-byte extended-precision format.

We're also playing it fast-and-lose with the FPREM instruction for golfing purposes, assuming it does not need to reduce the exponent of the input value by more than 63. The careful (read: correct) way to call it would be iteratively, in a loop, continuing to execute it as long as the "parity" flag is set.
For example:

RemainderLoop:
   fprem
   fstsw  ax
   sahf
   jp     RemainderLoop

That would add 6 bytes to the total.


x86 Assembly (targeting AVX), 47 bytes

By way of comparison (and for completeness), here's an AVX implementation. It's more bytes, but also more efficient. The parameter is passed in XMM0, and the result is returned in the same register, as with any x86-64 or vector x86-32 calling convention.

43 B4 00 00    | divisor  DD  043b40000r           ; 360.0f
               | ; Load single-precision FP value, and convert it to double-precision.
C5 EA 5A 15 00 | vcvtss2sd  xmm2, xmm2, DWORD PTR [divisor]
    00 00 00   |
               | ; Divide input parameter (XMM0) by divisor (XMM2), and store result in XMM1.
C5 FB 5E CA    | vdivsd     xmm1, xmm0, xmm2
               |
               | ; Truncate the result of the division to the nearest integer.
C5 FB 2C C1    | vcvttsd2si eax, xmm1
C5 F3 2A C8    | vcvtsi2sd  xmm1, xmm1, eax
               |
               | ; Multiply the truncated result by divisor (XMM2).
C5 F3 59 CA    | vmulsd     xmm1, xmm1, xmm2
               |
               | ; Subtract this temporary value (XMM1) from the original input (XMM0).
C5 FB 5C C1    | vsubsd     xmm0, xmm0, xmm1
               |
               | ; See if the result is negative.
C5 F1 57 C9    | vxorpd     xmm1, xmm1, xmm1   ; xmm1 = 0
C5 F9 2F C8    | vcomisd    xmm1, xmm0         ; result < 0?
76 04          | jbe        Finished
C5 FB 58 C2    | vaddsd     xmm0, xmm0, xmm2   ; fixup negative modulo by adding divisor (XMM2)
               | 
               | Finished:
C3             | ret

Of course, it would be even more efficient to multiply by the reciprocal, instead of dividing. But that means more precision is required to store the divisor, and would thus slightly increase the size of the code.

\$\endgroup\$
0
\$\begingroup\$

PHP, 29 Bytes

<?=($v=$argn%360)>=0?:$v+360;
\$\endgroup\$
0
\$\begingroup\$

Pyth - 5 bytes

%Q360

Would be shorter if %360 meant Q%360 instead of 360%Q, but oh well...

\$\endgroup\$
0
\$\begingroup\$

Python 2 REPL - 11 bytes

input()%360

If we've got a wierd input function, we might as well abuse it, right?

\$\endgroup\$
  • \$\begingroup\$ +6 bytes for printing the output \$\endgroup\$ – Julian Wolf May 5 '17 at 14:46
  • \$\begingroup\$ @JulianWolf Or cheat and say use the REPL :) \$\endgroup\$ – matsjoyce May 5 '17 at 15:58

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.