15
\$\begingroup\$

We don't have a challenge for conversion between Cartesian and polar coordinates, so ...

The challenge

Write two programs (or functions) in the same language:

  • one that converts from polar to Cartesian coordinates, and
  • the other from Cartesian to polar coodrinates.

The score is the sum of the two program lengths in bytes. Shortest wins.

For reference, the following figure (from the Wikipedia entry linked above) illustrates the relationship between Cartesian coordinates \$(x, y)\$ and polar coordinates \$(r, \varphi)\$:

                         enter image description here

Additional rules

  • Input and output are flexible as usual, except that they cannot be in the form of complex numbers (which would trivialize the problem). Of course, the program can use complex numbers internally, just not as input or output. Input and output methods can be different for the two programs.

  • You can choose to input and output the angle \$\varphi\$ either in radians or in degrees; and to limit its values to any 2π-radian or 360º-degree interval.

  • Builtins for coordinate conversion are allowed. If you use them, you may want to include another solution without the builtins.

  • Floating-point number limitations (accuracy, allowed range of values) are acceptable.

  • Programs or functions are allowed. Standard loopholes are forbidden.

Test cases

Values are shown rounded to 5 decimals. Angles are in radians in the interval \$[0, 2\pi)\$.

Cartesian: x, y       <-->      Polar: r, ϕ
------------------              ------------------

2.5, -3.42                       4.23632, -0.93957
3000, -4000                      5000, -0.92730
0, 0                             0, <any>
-2.08073, 4.54649                5, 2
0.07071, 0.07071                 0.1, 0.78540
\$\endgroup\$
4
  • \$\begingroup\$ Is nan accepted as any value? \$\endgroup\$
    – matteo_c
    Aug 10, 2022 at 18:18
  • \$\begingroup\$ @matteo_c Yes. I assume you mean for output. In fact the angle is undefined when the radius is 0 \$\endgroup\$
    – Luis Mendo
    Aug 10, 2022 at 18:20
  • \$\begingroup\$ May input / output \$r\$ be negative? \$\endgroup\$
    – tsh
    Aug 11, 2022 at 5:55
  • \$\begingroup\$ @tsh No, r in polar coordinates is nonnegative \$\endgroup\$
    – Luis Mendo
    Aug 11, 2022 at 8:33

20 Answers 20

9
\$\begingroup\$

Python, 49 + 48 = 97 bytes

-2 thanks to @Seb

lambda r,a,n=9e9:((x:=r*(a/n-1j)**n).real,x.imag)

Attempt This Online!

lambda x,y,n=1e-9:(abs(c:=x+1j*y),(c**n).imag/n)

Doesn't use any libraries, no exp, no sin, no cos, etc.

How?

All based on \$\tan(x)\approx x\quad|x|\ll1\$ and \$e^x\approx(1+x/n)^n\quad n\gg 1\$

\$\endgroup\$
3
  • \$\begingroup\$ Is there any reason for n=8**9 and n=8**-9 specifically? If not, you could save a byte each with something like n=1e8 and n=7e-9 (particular values chosen to stay close to your original values) \$\endgroup\$
    – Seb
    Aug 11, 2022 at 14:13
  • \$\begingroup\$ @Seb Nope, the first should be divisible by 4, but other than that they just ought to be large and small. \$\endgroup\$
    – loopy walt
    Aug 11, 2022 at 15:00
  • \$\begingroup\$ Another cool solution from loopy :+1: \$\endgroup\$
    – justhalf
    Aug 13, 2022 at 10:55
5
\$\begingroup\$

Wolfram Language (Mathematica), 14+11=25 bytes

AbsArg[#+I#2]&
AngleVector

Try it online!

Input [x,y]/[{r,ϕ}] and output {r,ϕ}/{x,y}.

       #+I#2    convert to complex
AbsArg[     ]   get abs (r) and arg (ϕ)
AngleVector     built-in.
\$\endgroup\$
4
\$\begingroup\$

J 10 (5 + 5)

to polar, 5 bytes

*.@j.

Try it online!

to cartesian, 5 bytes

+.@r.

Try it online!

Both of these amount to one built-in for the poler/cc conversion, combined with another builtin for the complex/x-y conversion.

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

Desmos, 33+19 = 52 score

Both functions take in two arguments representing either polar or Cartesian coordinates (depending on which function is being used), and returns a list representing the converted coordinates.

Cartesian to polar: 33 bytes

f(a,b)=[(aa+bb)^{.5},arctan(b,a)]

Polar to Cartesian: 19 bytes

g(a,b)=[cosb,sinb]a

Try Both Online On Desmos!

Try Both Online On Desmos! - Prettified

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

Mathematica, 18+20 = 38 bytes

ToPolarCoordinates
FromPolarCoordinates

Try it online!

For the <any> case, it will output a warning and use Indeterminate.

In some cases, it will not directly return the number, and instead return something like ArcTan[4/3] or 5*Cos[2]. If that's not allowed:

Mathematica, 21+23 = 44 bytes

N@*ToPolarCoordinates
N@*FromPolarCoordinates

Try it online!

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

Pip -p, 10 + 12 = 22 bytes

Polar to Cartesian:

a*[CObSIb]

Takes angle in radians. Outputs a list containing x and y. Try it online!

Cartesian to polar:

PRT$+SQgbATa

Outputs radius and angle (in radians) on separate lines. Try it online!

Explanations

a*[CObSIb]
            a is radius, b is angle
  [      ]  List containing
   COb       Cosine of b
      SIb    Sine of b
a*          Multiply each by a

PRT$+SQgbATa
              a is x-coordinate, b is y-coordinate, g is list containing both
     SQg      Square both coordinates
   $+         Fold the list of squares on addition
 RT           Square root
P             Print
        bATa  Two-argument arctangent of b and a
              Autoprint
\$\endgroup\$
3
\$\begingroup\$

Jelly, 7 + 6 bytes = 13

Polar to Cartesian:

×ıÆe×Æi

A dyadic Link accepting \$\theta\$ on the left and \$r\$ on the right that yields a list \$[x, y]\$.

Try it online!

Cartesian to polar:

æịA,æA

A dyadic Link accepting \$y\$ on the left and \$x\$ on the right that yields a list \$[r, \theta]\$.

Try it online!

How?

×ıÆe×Æi - Link: theta; r
 ı      - the imaginary unit, i
×       - (theta) multiplied by (i)
  Æe    - apply the exponential function -> e^(i.theta)
    ×   - multiply that by r -> r.e^(i.theta)
     Æi - Separate that into real and imaginary parts
æịA,æA - Link: y; x
æị     - y+i.x
  A    - absolute value -> r (same as for x+iy - we've just reflected in Re=Im)
    æA - atan2(y, x) -> theta (by definition)
   ,   - pair

Alternative \$7\$ byte Polar to Cartesian: ÆẠ,ÆSƊ×
(pair , the cosine ÆẠ and sin ÆS of Ɗ \$\theta\$ and multiply × by \$r\$).

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

Factor, 16 + 15 = 31 bytes

[ rect> >polar ]

Try it online!

[ cis * >rect ]

Try it online!

cis does e^(x*i) and cis * is 1 byte shorter than polar>.

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

x86 64-bit machine code, 23 + 13 = 36 bytes

D9 06 D9 07 D9 F3 D9 07 D8 C8 D9 06 D8 C8 DE C1 D9 FA D9 1E D9 1F C3
D9 07 D9 FB D8 0E D9 1F D8 0E D9 1E C3

Try it online!

These functions take addresses of two 32-bit floating-point numbers in RDI and RSI, and modify those numbers. The first transforms x,y into ϕ,r and the second does the opposite.

In assembly:

f:                      # FPU register stack contents
    fld DWORD PTR [rsi] #          y
    fld DWORD PTR [rdi] #      x   y
    fpatan              #          ϕ
    fld DWORD PTR [rdi] #      x   ϕ
    fmul st(0), st(0)   #     x²   ϕ
    fld DWORD PTR [rsi] #  y  x²   ϕ
    fmul st(0), st(0)   # y²  x²   ϕ
    faddp               #  x²+y²   ϕ
    fsqrt               #      r   ϕ
    fstp DWORD PTR [rsi]#          ϕ
    fstp DWORD PTR [rdi]#           
    ret

g:                      # FPU register stack contents
    fld DWORD PTR [rdi] #          ϕ
    fsincos             # cosϕ  sinϕ
    fmul DWORD PTR [rsi]#    x  sinϕ
    fstp DWORD PTR [rdi]#       sinϕ
    fmul DWORD PTR [rsi]#          y
    fstp DWORD PTR [rsi]#           
    ret
\$\endgroup\$
4
  • \$\begingroup\$ Doesn't this work with any processor all the way back to the 8087? \$\endgroup\$
    – Neil
    Aug 11, 2022 at 22:51
  • \$\begingroup\$ @Neil I guess so. \$\endgroup\$
    – m90
    Aug 12, 2022 at 17:30
  • \$\begingroup\$ No, it would not, @Neil. One obvious issue is that it uses 64-bit integer registers, which weren't introduced until the x86-64 extensions to the ISA. But another not-so-obvious issue is that it uses the fsincos instruction, which did not exist on the 8087 (wasn't added until the 80387). On the 8087, you were supposed to compute all trigonometric functions via fptan (and inverse trig functions via fpatan), so no sine or cosine functions were included in hardware. So, this could be trivially made to work on the 387 by removing use of 64-bit int registers, but not further back than that. \$\endgroup\$ Aug 13, 2022 at 10:46
  • \$\begingroup\$ @CodyGray I get your point about fsincos, but now that I'm back at a PC, online disassemblers says that those bytes work fine on the '387 with no changes at all (obviously the code uses 32-bit registers in that case), but the 8087 interprets some of those byte sequences differently. \$\endgroup\$
    – Neil
    Aug 13, 2022 at 12:33
3
+300
\$\begingroup\$

Prolog (SWI), 43+37=80 bytes

Cartesian to Polar, 43 bytes

X+Y+R+T:-R is(X^2+Y^2)^0.5,T is atan2(Y,X).

Try it online!

Polar to Cartesian, 37 bytes

R+T+X+Y:-X is R*cos(T),Y is R*sin(T).

Try it online!

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

MATLAB/Octave, 9+9=18 bytes, builtins

Simple builtins, convert between (x,y) and (angle[radians],radius)

Cartesian to polar:

@cart2pol

Try it online!

Polar to cartesian:

@pol2cart

Try it online!

23+29=52 bytes, without builtins

Same input/output as before

Cartesian to polar:

@(x,y)[atan2(y,x),abs(x+y*i)]

Try it online!

Polar to cartesian:

@(a,r)r*[cos(a),sin(a)]

Try it online!

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

Python, 48+48 = 96 bytes

lambda*t:(hypot(*t),atan2(*t))
from math import*

Attempt This Online!

-4 bytes thanks to xnor.

lambda a,b:(a*cos(b),a*sin(b))
from math import*

Attempt This Online!

\$\endgroup\$
3
  • \$\begingroup\$ Are you allowed to share the from math import* between the two functions? \$\endgroup\$
    – mousetail
    Aug 10, 2022 at 18:59
  • 1
    \$\begingroup\$ I don't think so. \$\endgroup\$
    – naffetS
    Aug 10, 2022 at 19:01
  • \$\begingroup\$ 48 for the first one lambda*t:(hypot(*t),atan2(*t)) from math import* \$\endgroup\$
    – xnor
    Aug 10, 2022 at 22:56
2
\$\begingroup\$

SageMath, 69 68 bytes

lambda x,y:((x^2+y^2)^.5,arctan2(y,x))
lambda r,t:(r*cos(t),r*sin(t))   

Try it online!

Adjusted score correctly thanks to Steffan.
Saved a byte thanks to Luis Mendo!!!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ This is 69 bytes. You don't count the p=, c=, or the newline \$\endgroup\$
    – naffetS
    Aug 10, 2022 at 22:05
  • \$\begingroup\$ @Steffan Easiest golf ever - thanks! :D \$\endgroup\$
    – Noodle9
    Aug 10, 2022 at 23:37
2
\$\begingroup\$

R, 30+24=54 bytes

Cartesian to polar, 30 bytes

\(x,y)c(Mod(z<-x+1i*y),Arg(z))

Attempt This Online!

No imaginary numbers for +2:

\(x,y)c((x^2+y^2)^.5,atan2(y,x))

Attempt This Online!

Polar to cartesian, 24 bytes

\(r,a)r*c(cos(a),sin(a))

Attempt This Online!

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

05AB1E (legacy), 7 + 22 = 29 bytes

Polar to Cartesian (7 bytes):

.¾¹.½‚*

Loose inputs in the order \$\phi,r\$; outputs as a pair \$[x,y]\$.

Try it online or verify all test cases.

Cartesian to Polar (22 bytes):

nOtI`’£×.aÇâ2(ÿ,ÿ)’.E‚

Input as a pair in the order \$[x,y]\$; outputs as a pair \$[r,\phi]\$.

Try it online or verify all test cases.

Explanation:

.¾      # Calculate the cosine of the first (implicit) input ϕ
  ¹.½   # Also push the sine of the first input ϕ
     ‚  # Pair them together
      * # Multiply them to the second (implicit) input r
        # (after which the pair is output implicitly as result)

Although 05AB1E does have tangent, sine, and cosine builtins, it lacks arctan; arcsin; and arccos builtins (both with 1 or 2 arguments). So we'll use a Python eval for it instead (hence the use of the legacy version of 05AB1E)†:

n       # Get the square of the values in the (implicit) input-pair [y,x]
 O      # Sum them together
  t     # Take the square root of that
I       # Push the input-pair [x,y]
 `      # Pop and push both separated to the stack
  ’£×.aÇâ2(ÿ,ÿ)’
        # Push dictionary string "math.atan2(ÿ,ÿ)",
        # where the two `ÿ` are replaced with `y,x` respectively
   .E   # Evaluate and execute it as Python code
‚       # Pair it with the earlier calculated sqrt(y²+x²)
        # (after which it is output implicitly as result)

See this 05AB1E tip of mine (section How to use the dictionary?) to understand why ’£×.aÇâ2(ÿ,ÿ)’ is "math.atan2(ÿ,ÿ)".

† The new version of 05AB1E is possible as well, but .E is eval as Elixir instead of Python, in which case the math.atan2(a,b) would be :math.atan2(a,b), which is 1 byte longer.

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

Lua, 41 + 41 = 82 bytes

Cartesian to Polar, 41 bytes

x,y=...print((x^2+y^2)^.5,math.atan(y,x))

Try it online!

Polar to Cartesian, 41 bytes

r,t=...print(r*math.cos(t),r*math.sin(t))

Try it online!

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

Vyxal, 10 + 7 = 17 bytes

Cartesian to Polar, 10 bytes

²∑√?Ṙƒ/∆T"

Try it Online!

Polar to Cartesian, 7 bytes

⁰₍∆c∆s*

Try it Online!

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

C (gcc), 88 bytes

C(x,b,t)float*x,t;{t=x[1];x[1]=b?*x*sin(t):atan(t/(*x));*x=b?*x*cos(t):sqrt(*x**x+t*t);}

86 bytes

2 bytes can be saved by inverting the order of the cartesian coordinates, that is, \$(y, x)\$ instead of \$(x, y)\$,

C(x,b,t)float*x,t;{t=x[1];x[1]=b?*x*cos(t):atan(*x/t);*x=b?*x*sin(t):sqrt(*x**x+t*t);}

Try it online!

Pointer x is used for both input and output. b specifies which conversion must be applied (0 for cartesian to polar, any non-zero value for polar to cartesian).

The solution is not made up by two different functions, but I think should be acceptable.

62 + 53 = 115 bytes

As two separate functions:

A(x,t)float*x,t;{t=x[1];x[1]=atan(t/(*x));*x=sqrt(*x**x+t*t);}
B(x,t)float*x,t;{t=x[1];x[1]=*x*sin(t);*x=*x*cos(t);}

Try it online!

2 bytes can be saved using the same trick as above described.

\$\endgroup\$
2
  • \$\begingroup\$ I like the idea of using the same function, but I’m afraid that goes against the challenge rules (you would have to count it twice, and the additional input is not allowed) \$\endgroup\$
    – Luis Mendo
    Aug 10, 2022 at 18:50
  • 1
    \$\begingroup\$ Suggest hypot(x,y) instead of sqrt(x*x+y*y) and *x*=cos(t) instead of *x=*x*cos(t) \$\endgroup\$
    – ceilingcat
    Aug 11, 2022 at 7:31
1
\$\begingroup\$

lin, 28 + 17 = 45 bytes

To Polar ([a b] -> [a b]):

"2^.$_ +.5^"".$_.~ atant", Q

To Cartesian (a b -> [a b]):

"cos *""sin *", Q

Try it here!

For testing purposes:

[2.5 3.42_ ][3000 4000_ ][0 0][2.08073_ 4.54649][0.07071 0.07071] ;
( ;.+.$_.; \form.'.$$ " -> "join outln ).'
"2^.$_ +.5^"".$_.~ atant", Q
"cos *""sin *", Q

Explanation

Prettified code:

( 2^.$_ + .5^ )(.$_.~ atant ) , Q
( cos * )( sin * ) , '

Both of these expressions utilize a somewhat odd feature of lin. Data structures of strings/functions* passed to certain commands will "fork" and execute each function, preserving the structure's shape. For example:

1 2 [( 1+ )( 2+ )] es

would leave on the stack:

1 2 [[1 3] [1 4]]

The Q command ("quarantine") executes a function on an isolated copy of the current stack and pushes the resulting top item. So the following:

1 2 [( 1+ )( 2+ )] Q

would leave on the stack:

1 2 [3 4]

*: In lin, strings and functions are the same datatype.

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

PARI/GP, 34 + 24 = 58 bytes

f(x,y)=[abs(z=x+I*y),if(z,arg(z))]
g(r,a)=r*[cos(a),sin(a)]

Attempt This Online!

\$\endgroup\$

Your Answer

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

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