The Knight's estate

5

1

And then the King said: You fought bravely, Knight, and your deed will not be forgotten for centuries. For your valor I grant you this castle and the lands around it. Things rush me, and I can not take you to the castle. Therefore, I will give you the way from this place to the castle. Now go and come back after the deadline. - as it is written in the Green Book of Years.

In addition, it is known from the Green Book of Years that the lands with which the castle was granted were in the shape of a circle. The king was very wise and, in order to avoid unnecessary proceedings regarding the right to land, always granted only areas of land on the map that have a convex shape.

Recently, historians have had information about where the castle was located and where this historical conversation took place. They want to know how much land did the Knight get on the assumption that the road to the castle was perfectly straight.

Explanation

The following figure shows in light gray the territory originally granted to the knight, and in dark gray, the one that came to him as a result of the king giving him the way.

Input

The first line of the input contains two floating-point numbers: xk and yk - the coordinates of the place where the dialogue took place. The second line contains three floating-point numbers: xc, yc and rc - the coordinates of the castle and the radius of the circle that bounds the land granted with it.

Output

Print one floating-point number - the area of ​​the land obtained by the Knight, with an accuracy of at least three characters after the decimal point.

Tests

Input    Output

2 5       5.69646
2 1 1


3 9       80.7130
2 3 5


1 3       3.141
1 2 1



Note: A triangle may not include the entire semicircle if it is too close to the center, as in the test I have given.

Ver Nick says Reinstate Monica

Posted 2019-08-23T13:37:12.490

Reputation: 555

4

Hi there! Please consider using The Sandbox for your challenges. I've read this several times and I'm not sure what area we're supposed to find. The dark grey? The light grey? The sum of those regions?

– Giuseppe – 2019-08-23T13:53:55.590

5

Please also avoid excessively long backstories. In this case, because the challenge refers back to the backstory, it actually hinders your challenge. :-(

– Giuseppe – 2019-08-23T13:55:16.513

@Giuseppe The sum of those regions. – Ver Nick says Reinstate Monica – 2019-08-23T14:14:06.080

@Giuseppe A triangle may not include the entire semicircle if it is too close to the center (as in the test I have given). – Ver Nick says Reinstate Monica – 2019-08-23T14:19:48.460

1Can you please provide examples with a radius unequal to 1? – Jitse – 2019-08-23T14:51:53.713

Can you also please provide examples where the traveled distance lies within the circle? – Jitse – 2019-08-23T15:06:33.363

1Also, the triangle will never, ever include the entire semicircle, unless the radius is infinite, which it cannot be. – Jitse – 2019-08-23T15:08:28.750

4Why is the outcome of the third test case not 3.141? – Joel – 2019-08-23T19:43:58.420

Also, your challenge should be understandable if you deleted the backstory, as people normally skip the backstory – MilkyWay90 – 2019-08-24T00:57:51.847

@Joel Oh, I'm sorry, thanks for mentioning. – Ver Nick says Reinstate Monica – 2019-08-24T08:16:43.673

@MilkyWay90 I cut off unnecessary parts of the backstory, leaving only the needed ones. – Ver Nick says Reinstate Monica – 2019-08-24T08:22:20.810

A note about trying to use "real numbers" for input. It is not possible to have a program that can accept a real number, this is because there are more real numbers than there are finite binary strings. You likely mean something other than a real number and it would be good if you said what. It seems like most people have taken this to mean floats. – Post Rock Garf Hunter – 2019-08-24T13:06:08.737

I'm more worried about the "decimals". Are the last three values supposed to be integers? – G. Sliepen – 2019-08-24T13:07:48.580

1@G.Sliepen No. I edited to make it more clear. – Ver Nick says Reinstate Monica – 2019-08-24T13:26:28.457

@SriotchilismO'Zaic Edited. – Ver Nick says Reinstate Monica – 2019-08-24T13:26:40.387

Answers

7

Wolfram Language (Mathematica), 51 bytes

Area@ConvexHullMesh[CirclePoints[##2,7!]~Append~#]&

Try it online!

                    CirclePoints[##2,7!]            (* generate 5040 points on the perimeter of the circle *)
                                        ~Append~#   (* append the point at the end of the way, *)
Area@ConvexHullMesh[                             ]& (* and find the area of the convex hull of those points *)

attinat

Posted 2019-08-23T13:37:12.490

Reputation: 3 495

6

JavaScript (ES7), 76 bytes

Port of Jitse's answer.

with(Math)f=(X,Y,x,y,r,h=hypot(X-x,Y-y))=>r*(r*(PI-acos(r/h))+(h*h-r*r)**.5)

Try it online!

Arnauld

Posted 2019-08-23T13:37:12.490

Reputation: 111 334

I borrowed your argument names for clarity – Jitse – 2019-08-23T14:46:41.563

7@Jitse Sounds fair enough since I borrowed your entire logic. :p – Arnauld – 2019-08-23T14:48:05.397

Friendly reminder that I made a mistake in the calcualtion of the triangle's area. It worked because the radius in the example is 1. – Jitse – 2019-08-23T14:55:40.510

@Jitse Thanks. :) – Arnauld – 2019-08-23T15:03:56.333

It's been a while but +1 for with - always +1 for with! – Shaggy – 2019-08-24T00:35:58.303

5

Python 3, 107 bytes

from math import*
def f(X,Y,x,y,r):d=hypot(X-x,Y-y);return(r>d)*pi*r*r or(pi-acos(r/d))*r*r+(d*d-r*r)**.5*r

Try it online!

-3 bytes thanks to Arnauld

-4 bytes thanks to squid

-5 bytes thanks to Greg Martin

Explanation

First, we calculate the traveled distance between both coordinates using the Pythagorean theorem. Let's call it d.

Then, we construct a rectangular triangle between coordinate 1, coordinate 2 and the point on the circle where it meets with the straight line. Using the Pythaogrean theorem again, the area of this triangle is given by $$\frac{1}{2}\times\sqrt{d^2-r^2}\times r$$ where d is the distance between the coordinates and r is the radius of the circle. Since we have two of those triangles, this area is resembled in the code by (d*d-r*r)**.5*r

Next, we need to calculate the remaining area of the circle. A circle's area is given by $$ a = \pi\times r^2$$ However, part of the circle is already taken into account. The angular fraction of the circle that is already described by the triangles is given as $$\cos^{-1}(r/d)$$ so that the remaining area in the circle can be described by (pi-acos(r/d))*r*r.

And then some code juggle to make it as short as possible.

Except...

when the traveled distance lies within the circle. Then just return the circle area.

Jitse

Posted 2019-08-23T13:37:12.490

Reputation: 3 566

I think you forgot the case, when X-x and Y-y are 0. In this case, there is division by zero. – Ver Nick says Reinstate Monica – 2019-08-23T15:01:42.170

@VerNick Ah yes, you're right. It fails if the traveled distance lies within the circle. Fixed now. – Jitse – 2019-08-23T15:07:34.133

BTW, a very good explanation, might be useful for those code golfers, that are not very good with geometry ;-) – Ver Nick says Reinstate Monica – 2019-08-23T17:11:46.917

1Shouldn't it be r*r>d rather than r>d? – Joel – 2019-08-23T18:39:25.953

If you change acos(r/d**.5) to acos(max(1,r/d**.5)) (if that's the right syntax), then you don't need to or the return computation at all ... this saves 8 bytes or so. I don't know whether this works when d=0; if there's an arcsecant function, it can be applied to d**.5/r to get around this. – Greg Martin – 2019-08-24T03:10:02.193

Also, hypot(X-x,Y-y) should calculate d**.5 directly, saving some additional bytes. – Greg Martin – 2019-08-24T03:14:31.140

@GregMartin I need some sort of evaluation to avoid a ZeroDivisionError, so max( ... ) will not work, sadly. I'll try to find a solution with arcesant. Not sure if it is readily available though. Thanks for the hypot( ... ) suggestion! – Jitse – 2019-08-24T09:22:22.427

@Joel you're right. Fixed by using hypot. – Jitse – 2019-08-24T09:23:15.437

Ok, let's try this: use the fact that $$\cos^{-1}(r/d) = \tan^{-1}(\sqrt{d^2-r^2}/r).$$ So you could set $$e=\max{0,\sqrt{d^2-r^2}}$$and replace the acos(r/d) with atan(e/r) and the last summand with +e*r. This should allow deletion of (r>d)*pi*r*r or while avoiding division by 0. (Can we assume that r is never zero...?) And then d is never called other than in the definition of e, so that can be golfed as well. – Greg Martin – 2019-08-24T17:31:36.153

@Greg Martin See my solution

– Joel – 2019-08-24T18:36:32.457

4

Jelly, 33 bytes

½÷@ÆAØP_ײ}
I²SḢ_²}½×ʋ+çɗṛ²×ØPʋ>?

Try it online!

Port of @jitse’s Python answer so be sure to upvote that one! A full program taking as its arguments [[xk, xc], [yk, yx]] and r.

Nick Kennedy

Posted 2019-08-23T13:37:12.490

Reputation: 11 829

3

Python 3, 96 bytes

from math import*
def f(X,Y,x,y,r):t=max(hypot(X-x,Y-y)**2/r/r-1,0)**.5;return(t-atan(t)+pi)*r*r

Try it online!

In Python 3.8, the solution can be further improved using assignment expressions:

Python 3.8 (pre-release), 91 bytes

lambda X,Y,x,y,r:((t:=max(hypot(X-x,Y-y)**2/r/r-1,0)**.5)-atan(t)+pi)*r*r
from math import*

Try it online!

-2 bytes thanks to @Jitse

This solution is based on a bit more math manipulation of the formula. Let \$\theta\$ be the size of common angle of each triangle and its corresponding sector. The area of each triangle equals to \$\frac{1}{2}\times r\tan{\theta}\times r\$ and the area of the common sector of the triangles and the circle equals to \$\theta\times r\times r\$. Hence, the total area $$S=\tan{\theta}\cdot r^2 +\pi r^2-\theta r^2=(\pi+\tan{\theta}-\theta)r^2$$

We define \$t\$ to be $$t=\tan{\theta}=\frac{\sqrt{d^2-r^2}}{r}=\sqrt{\frac{d^2}{r^2}-1}$$ Here, \$d\$ is the distance between the two given coordinate pairs. Then we have $$S=(\pi+t-\arctan{t})r^2$$

Joel

Posted 2019-08-23T13:37:12.490

Reputation: 1 691

Welcome to Codegolf! You have a nice approach to this problem. It is very clear and consise. Since your lambda function is not recursive, you can make it anonymous and save 2 bytes like so: Try it online!

– Jitse – 2019-08-24T09:07:36.003

@Jitse Thanks for the suggestion. The rules here are unclear to me and I cannot find the answer about this in other posts. I understand that one-line solutions using lambdas are accepted because the whole code block returns a function that can be applied to the arguments (i.e. (#code#)(arg1, ...)). However, when the program has multiple lines, the whole code block can no longer be used as a single function. In this case, do the returned functions need to be named (for later reuse) or not? – Joel – 2019-08-24T10:56:55.000

As long as you make the import statement before defining your function, it can still be called using (lambda s: [do something])(s). Therefore, the consensus is that it is still valid to leave it anonymous, so long as you don't need to refer to it from within your core code. In this case, you only need to name it to demonstrate its functionality. Due to the way that TiO counts characters, the easiest approach is to define the funtion name in the header and import other stuff afterwards. For demonstration purposes, it doesn't really matter. – Jitse – 2019-08-24T11:08:48.170

You can find more basic golfing rules for Python here and in other meta threads.

– Jitse – 2019-08-24T11:09:46.670

Thanks much for the clarification. I've updated the answer. – Joel – 2019-08-24T11:23:06.090

1

C (clang), 111 103 93 bytes

float f(X,x,r)_Complex X,x,r;{X=cabs(X-x)/r;return(4*atan(1)-atan(X=csqrt(X*X-1))+X)*r*r;}

Try it online!

It's 90 bytes for the code, but +3 bytes because we need to pass -lm to the compiler.

Thanks to @ceilingcat for shaving off 12 bytes, and the brilliant use of csqrt() inspired me to take the coordinates as complex numbers, to shave off another 10 bytes.

G. Sliepen

Posted 2019-08-23T13:37:12.490

Reputation: 580