Description :
Given x and y positions of two circles along with their radii, output the area of intersection of the two circle.
Input :
You will be given following input :
array 1 = x and y positions of circle a
array 2 = x and y positions of circle b
radius = radii of the two congruent circles
Input method :
([12 , 20] , [20 , 18] , 12) ---> two array and number
([12 , 20 , 20 , 18] , 12) ---> array and a number
(12 , 20 , 20 , 18 , 12) ---> all five numbers
('12 20' , '20 18' , 12) ---> 2 strings and a number
('12 20 20 18' , 12) ---> string and a number
('12 20 20 18 12') ---> one string
Output :
A non-negative integer (no decimal) equal to area of intersection of two circles.
A string equal to the above mentioned integer.
Note :
- Output must be >= 0, since area can't be negative.
- In case of decimal round down to nearest integer
Examples :
([0, 0], [7, 0], 5) ---> 14
([0, 0], [0, 10], 10) ---> 122
([5, 6], [5, 6], 3) ---> 28
([-5, 0], [5, 0], 3) ---> 0
([10, 20], [-5, -15], 20) ---> 15
([-7, 13], [-25, -5], 17) ---> 132
([-12, 20], [43, -49], 23) ---> 0
Winning criteria :
This is code-golf so shortest code in bytes for each language wins.
Suggestions :
- Provide a TIO link so it can be tested.
- Provide an explanation so others can understand your code
These are only suggestions and are not mandatory.
13 Answers 13
JavaScript (ES6), 72 bytes
Alternate formula suggested by @ceilingcat
Takes input as 5 distinct parameters (x0, y0, x1, y1, r).
with(Math)f=(x,y,X,Y,r)=>-(sin(d=2*acos(hypot(x-X,y-Y)/r/2))-d)*r*r*2>>1
JavaScript (ES7), (削除) 81 (削除ここまで) (削除) 80 (削除ここまで) 77 bytes
Saved 3 bytes thanks to @Neil
Takes input as 5 distinct parameters (x0, y0, x1, y1, r).
(x,y,X,Y,r,d=Math.hypot(x-X,y-Y))=>(r*=2)*r*Math.acos(d/r)-d*(r*r-d*d)**.5>>1
How?
This is based on a generic formula from MathWorld for non-congruent circles:
A = r2.arccos((d2 + r2 - R2) / 2dr) +
R2.arccos((d2 + R2 - r2) / 2dR) -
sqrt((-d + r + R)(d + r - R)(d -r + R)(d + r + R)) / 2
where d is the distance between the two centers and r and R are the radii.
With R = r, this is simplified to:
A = 2r2.arccos(d / 2r) + d.sqrt((2r - d) * (2r + d)) / 2
And with r' = 2r:
A = (r'2.arccos(d / r') + d.sqrt(r'2 - d2)) / 2
Note: If d is greater than 2r, Math.acos() will return NaN, which is coerced to 0 when the right-shift is applied. This is the expected result, because d > 2r means that there's no intersection at all.
-
\$\begingroup\$
d*(r*r-d*d)**.5saves 3 bytes. \$\endgroup\$Neil– Neil2018年04月15日 15:31:44 +00:00Commented Apr 15, 2018 at 15:31 -
\$\begingroup\$ @ceilingcat Thanks! Using
with(Math)and moving the definition ofdsaves 2 more bytes. \$\endgroup\$Arnauld– Arnauld2018年04月17日 06:20:47 +00:00Commented Apr 17, 2018 at 6:20
Jelly, (削除) 27 25 24 (削除ここまで) 22 bytes
×ばつ2}_çHḞ
ạ/çḤ}
A full program accepting a list of the two centres as complex co-ordinates and the radius which prints the result (as a dyadic link it returns a list of length 1).
To take the two co-ordinates as pairs add Uḅı to the main link, like this.
How?
×ばつ,2I1⁄2 - Link 1, get [√(s2d2 - s4)]: separation of centres, s; diameter, d
, - pair = [s, d×ばつ - multiply (vectorises) = [s2, sd]
2 - square (vectorises) = [s4, s2d2]
I - incremental differences = [s2d2 - s4]
1⁄2 - square root (vectorises) = [√(s2d2 - s4)×ばつ2}_çHḞ - Link 2, get intersection area: separation of centres, s; diameter, d
÷ - divide = s/d
ÆA - arccos = acos(s/d)
2} - square right = d2
×ばつ - multiply = acos(s/d)d2
ç - call last Link (1) as a dyad (f(s,d)) = [√(s2d2 - s4)]
_ - subtract (vectorises) = [acos(s/d)d2 - √(s2d2 - s4)]
H - halve (vectorises) = [(acos(s/d)d2 - √(s2d2 - s4))/2]
Ḟ - floor = [⌊(acos(s/d)d2 - √(s2d2 - s4))/2⌋]
- ...Note: Jelly's Ḟ takes the real part of a complex input so when
- the circles are non-overlapping the result is 0 as required
ạ/çḤ} - Main link: centres, a pair of complex numbers, c; radius, r
/ - reduce c by:
ạ - absolute difference = separation of centres, s
- ...Note: Jelly's ạ finds the Euclidean distance when inputs are complex
- i.e. the norm of the difference
Ḥ} - double right = 2r = diameter, d
ç - call last Link (2) as a dyad (f(s,d))
- implicit print
-
\$\begingroup\$ numbers only. And what is that [-7+13j,-25+-5j] ? I don't have that example. You might have to explain what you did ? \$\endgroup\$Muhammad Salman– Muhammad Salman2018年04月15日 16:18:39 +00:00Commented Apr 15, 2018 at 16:18
-
\$\begingroup\$ I explained it in the answer already... they are co-ordinates on the complex plane... I can do
[[x1,y1],[x2,y2]]instead but it costs 3 bytes. (Note also that-7+13jis a number :)) -- the[-7+13j,-25+-5j]corresponds to the example that returns132,[-7, 13], [-25, -5], 17\$\endgroup\$Jonathan Allan– Jonathan Allan2018年04月15日 16:21:46 +00:00Commented Apr 15, 2018 at 16:21 -
\$\begingroup\$ I don't know Jelly so I am lost on that. Also I sent the message before the explanation. But yeah , sure this works (I guess?) \$\endgroup\$Muhammad Salman– Muhammad Salman2018年04月15日 16:30:49 +00:00Commented Apr 15, 2018 at 16:30
-
\$\begingroup\$ It's nothing to do with Jelly per-se, it's just mathematics. A point in 2-space is the same as a complex number. \$\endgroup\$Jonathan Allan– Jonathan Allan2018年04月15日 16:36:20 +00:00Commented Apr 15, 2018 at 16:36
-
\$\begingroup\$ Not what I meant. Normal languages I would be able to read and tell what is going on. Jelly and other such languages are a pain to read. \$\endgroup\$Muhammad Salman– Muhammad Salman2018年04月15日 16:39:47 +00:00Commented Apr 15, 2018 at 16:39
Mathematica (削除) 66 57 (削除ここまで) 51 bytes
Floor@Area@RegionIntersection[#~Disk~#3,#2~Disk~#3]&
A Disk[{x,y},r]refers to the region circumscribed by the circle centered at {x,y} with a radius of r.
RegionIntersection[a,b] returns the intersection of regions a, b.
Area takes the area.
IntegerPart rounds down to the nearest integer.
-
\$\begingroup\$ For the record, I didn't see alephalpha's submission as I was doing my own. His is a shorter (hence a more successful) entry, but I left mine in anyway. \$\endgroup\$DavidC– DavidC2018年04月18日 17:21:23 +00:00Commented Apr 18, 2018 at 17:21
-
\$\begingroup\$ You could replace
IntegerPartwithFloor. \$\endgroup\$matrix42– matrix422019年08月23日 01:05:24 +00:00Commented Aug 23, 2019 at 1:05 -
\$\begingroup\$ @mathe, Thanks. If I use the dedicated Floor brackets, do you know how I am to count the bytes? \$\endgroup\$DavidC– DavidC2019年08月24日 13:02:06 +00:00Commented Aug 24, 2019 at 13:02
-
\$\begingroup\$ @DavidC each one is 3 bytes, so the substitution is neutral in this case for byte count. They're useful if the expression would otherwise need parenthesizing, though (-1 byte compared to
Floor[ ]). \$\endgroup\$att– att2019年08月24日 17:04:05 +00:00Commented Aug 24, 2019 at 17:04
Wolfram Language (Mathematica), 50 bytes
Floor@Area@RegionIntersection[#~Disk~#3,Disk@##2]&
-
\$\begingroup\$ +1
Floor. Of course! \$\endgroup\$DavidC– DavidC2018年04月16日 09:37:41 +00:00Commented Apr 16, 2018 at 9:37
C (gcc), (削除) 83 79 71 (削除ここまで) 66 bytes
f(a,b,c,d,e){float g=cacos(hypot(a-c,b-d)/e/2)*2;e*=(g-sin(g))*e;}
Python 3, 106 chars with centers given as lists
from numpy import*
def f(a,b,r):d=min(1,hypot(*subtract(b,a))/2/r);return(arccos(d)-d*(1-d*d)**.5)*r*r//.5
100 chars with center coords separately
from math import*
def f(a,b,A,B,r):d=min(1,hypot(A-a,B-b)/2/r);return(acos(d)-d*(1-d*d)**.5)*r*r//.5
Haskell, 83 bytes
(k!l)m n r|d<-sqrt$(k-m)^2+(l-n)^2=floor2ドル*r^2*acos(d/2/r)-d/2*sqrt(4*r*r-d*d)::Int
Just the formula, really. Type has to be declared as Int for NaN to map to 0 with floor.
-
\$\begingroup\$ alternate formula \$\endgroup\$ceilingcat– ceilingcat2018年04月17日 07:46:45 +00:00Commented Apr 17, 2018 at 7:46
JavaScript (Node.js), 69 bytes
with(Math)f=(a,b,c,d,r)=>(-sin(x=2*acos(hypot(a-c,b-d)/2/r))+x)*r*r|0
Short not sure if it can be golfed any further. Any suggestions are welcome
Excel, 119 bytes
=INT(IFERROR(2*E1^2*ACOS(((C1-A1)^2+(D1-B1)^2)^.5/2/E1)-((4*E1^2-((C1-A1)^2+(D1-B1)^2))*((C1-A1)^2+(D1-B1)^2))^.5/2,0))
Input taken as 5 separate variables:
x-coordinate y-coordinate x-coordinate y-coordinate radius
A1 B1 C1 D1 E1
Python 2, 109 bytes
from math import*
a,b,x,y,r=input()
d,R=hypot(x-a,y-b),2*r
print int(d<R and R*r*acos(d/R)-d*sqrt(R*R-d*d)/2)
Pretty straightforward. Get the distance between circles, and use R=2r as a substituite in the equation. d<R and to short-circuit if circles don't overlap.
T-SQL, 122 bytes
SELECT FLOOR(Geometry::Parse('POINT'+a).STBuffer(r).STIntersection(
Geometry::Parse('POINT'+b).STBuffer(r)).STArea())FROM t
(line break for readability only).
Uses MS SQL's support of spatial geometry.
Per our IO standards, SQL can take input from a pre-existing table t with int field r and varchar fields
a and b containing coordinates in the format (x y).
My statement parses the coordinates as POINT geometry objects expanded by the radius using the function STBuffer(), then taking the STIntersection() followed by the STArea().
If I am allowed to input the actual geometry objects in the table instead, then my code becomes almost trivial (48 bytes):
SELECT FLOOR(a.STIntersection(b).STArea())FROM t
answer must be positivetoanswer must be >= 0- If the circles don't intersect (as in examples 4, 7, 10) then the correct answer is 0, which last I checked is not positive. \$\endgroup\$