식당을 어디에 두어야합니까?


15

당신은 식당의 주인입니다. Cartesia에서 y 축으로 알려진 하나의 주요 도로가있는 새 영역에서 문을 열었습니다. 식당과 해당 지역의 각 주택과의 총 거리를 최소화하도록 식당을 배치하려고합니다.

입력 :

입력은

n, the number of houses
house1
house2
house3
...
houseN

여기서 각 집은 형태의 좌표입니다 x y. 각 단위는 1km를 나타냅니다.

입력을 문자열로 취하거나 선택한 형식에 상관없이 입력을 인수로 취하는 함수를 제공 할 수 있습니다.

출력 : 식당의 y 좌표 (y 축에 위치 함)를 기억하십시오. 실제로 도로의 측면에 있지만 차이는 무시할 만합니다.

n 번째 집이 경우 본질적으로, h_n그리고 D거리의 함수이다, 당신은 찾으려는 k그러한 D(h_0, (0, k)) + D(h_1, (0, k)) + D(h_2, (0, k)) + ... + D(h_n, (0, k))최소화됩니다.

거리는 고객이 집에서 식당까지 정확히 직선으로 여행하는 것처럼 계산됩니다. 그것은 (x, y)당신의 식당 에서 거리 입니다 sqrt(x^2 + (y - k)^2).

출력은 소수점 2 자리 이상이어야합니다.

출력은 문자열로 인쇄되거나 함수에서 반환 될 수 있습니다.

입력 / 출력 예 :

Input:
2
5.7 3.2
8.9 8.1
Output:
5.113013698630137

이 예에서 총 거리는 약 15.4003킬로미터입니다.

이것은 코드 골프입니다-가장 짧은 코드가 승리합니다.

추신 : 나는 또한 단순한 무력이 아닌 수학적 솔루션에 관심이 있습니다. 코드 골프에서이기는 것은 아니지만 약간의 공감대를 얻습니다. 다음은 예제 문제를 수행 한 방법입니다.

점 A를 A (5.7, 3.2)에, B를 B (8.9, 8.1)에 놓으십시오. (0, k)의 해를 C로하자. y 축에 A를 반영하여 (-5.7, 3.2)에 A '를 만든다. A '에서 C까지의 거리는 A에서 C까지의 거리와 동일하다. 따라서, 문제는 A'C + CB가 최소화되도록 C 점으로 감소 될 수있다. 분명히, 이것은 선 A'B에있는 점 C 일 것입니다.

이것이 3 점 이상으로 일반화 될지 모르겠습니다.


거리 함수에 어떤 메트릭이 사용 D됩니까? 유클리드?
Reto Koradi

1
주요 도로는 하나만 있지만 고객이 집에서 식당까지 직선으로 이동한다고 가정합니까? 아니면 먼저 y 축으로 직접 이동합니까? (즉, 우리는 D에 유클리드 또는 맨해튼 거리를 사용합니까?)
trichoplax

1
(이 예제에서 해결할 수 있지만 명시 적으로 언급하는 것이 좋을 것입니다.)
trichoplax

@trichoplax 유클리드? 유클리드가 무슨 뜻 sqrt(diffX^2 + diffY^2)인가요? 그런 다음 유클리드. 나는 그것이 시나리오에 완벽하게 맞지 않는다는 것을 알고 있지만 고객이 어떻게 든 자신의 집에서 직선으로 여행한다고 가정합니다.
soktinpk

5
복잡한 평면에서 주택의 위치를 ​​나타내는 복잡한 숫자의 목록으로 입력을 받아 들일 수 있습니까?
lirtosiast

답변:


27

C, 315302 바이트

t,i;double o,w,h,x,y,k,a,b,c;double g(N,S)double N,S[][2];{for(t=0;t<N;t++)k+=S[t][1];k/=N;for(i=0;i<9;i++){o=w=h=0;for(t=0;t<N;t++)x=S[t][0],y=S[t][1],a=y-k,c=k*k-2*k*y+x*x+y*y,o+=-a/sqrt(x*x+a*a),w+=x*x/pow(c,1.5),h+=3*x*x*a/pow(c,2.5);a=h/2;b=w-h*k;c=o-w*k+a*k*k;k=(-b+sqrt(b*b-4*a*c))/h;}return k;}

이것은 꽤 멀지 않으며 짧지도 않습니다. 나는 길이 콘테스트에서 이기지 못할 것이라고 생각하면서 (이론적) 정확성 콘테스트에서 이길 수 있습니다! 이 코드는 아마도 bruteforce 솔루션보다 1 ~ 2 배 빠르며 약간의 수학적 토모 일에 의존합니다.

g(N,S)주택 수와 주택 N배열을 입력으로 받는 함수 를 정의합니다 S[][2].

다음은 테스트 사례와 함께 해결되었습니다.

t,i;
double o,w,h,x,y,k,a,b,c;
double g(N,S)double N,S[][2];{
    /* Initially, let k hold the geometric mean of given y-values */
    for(t=0;t<N;t++)
        k+=S[t][1];
    k/=N;

    /* We approximate 9 times to ensure accuracy */
    for(i=0;i<9;i++){
        o=w=h=0;
        for(t=0;t<N;t++)
            /* Here, we are making running totals of partial derivatives */
            /* o is the first, w the second, and h the third*/
            x=S[t][0],
            y=S[t][1],
            a=y-k,
            c=k*k-2*k*y+x*x+y*y,
            o+=-a/sqrt(x*x+a*a),
            w+=x*x/pow(c,1.5),
            h+=3*x*x*a/pow(c,2.5);
        /* We now use these derivatives to find a (hopefully) closer k */
        a=h/2;
        b=w-h*k;
        c=o-w*k+a*k*k;
        k=(-b+sqrt(b*b-4*a*c))/h;
    }
    return k;
}
/* Our testing code */
int main(int argc, char** argv) {
    double test[2][2] = {
        {5.7, 3.2},
        {8.9, 8.1}
    };    
    printf("%.20lf\n", g(2, test));
    return 0;
}

어떤 출력 :

5.11301369863013732697

경고 : 완전히 이해하려면 일부 미적분학 지식이 필요할 수 있습니다!

수학에 대해 이야기 해 봅시다.

우리는 원하는 지점 (0, k)과 집과 의 거리를 알고 있습니다 i.

D_i의 정의

그리고 이렇게 총 거리 D에서 n다음과 같이 집은 정의 할 수 있습니다 :

D의 정의

우리가하고 싶은 것은에 대해 미분을 취하고 k동일하게 설정 함으로써이 기능을 최소화 하는 것 0입니다. 해 봅시다. 우리는 파생 상품이 D다음과 같이 설명 될 수 있음을 알고 있습니다.

D의 미분

그러나 각각의 첫 부분 미분 Di은 꽤 나쁩니다 ...

Di의 미분 1

불행히도으로도 n == 2이러한 파생 상품을 설정 0하고 해결하는 k것은 매우 재앙이됩니다. 근사치가 필요하더라도보다 강력한 방법이 필요합니다.

Taylor Polynomials를 입력하십시오.

D(k0)에서 모든 D파생 상품 의 가치와 가치를 알고 있다면 Taylor 시리즈로 k0다시 쓸 수 있습니다 D.

Taylor Series에 의한 정의

이제이 공식에는 많은 것들이 들어 있고 그 파생물은 다루기 어려울 수 있지만 이제 다항식 근사값이 D !

약간의 미적분학을 수행함으로써, 우리 는 이전과 같이 D의 파생 상품을 평가하여 다음 두 파생 상품을 찾습니다 Di.

Di의 미분 2

Di의 미분 3

파생 상품을 자르고 평가함으로써, 이제 D다음과 같은 형태의 3 차 다항식으로 근사 할 수 있습니다 .

D의 대략적인 형태

A, B, C, D실수는 어디에 있습니까 ?

지금 우리가 최소화 할 수 있습니다. 미분을 취하여 0으로 설정하면 다음과 같은 형식의 방정식으로 끝납니다.

D '의 근사

미적분과 대입을 수행하면 다음과 같은 공식이 나옵니다 a, b, and c.

의 가치

b의 가치

c의 가치

이제 우리의 문제는 2 차 공식으로 주어진 두 가지 솔루션을 제공합니다.

k의 가치

에 대한 전체 공식은 k작성하는 데 큰 부담이 될 것이므로 여기와 코드로 조각을 작성합니다.

우리가 높을수록 k항상 근사 거리가 최소가 된다는 것을 알기 때문에 D(이 논문의 여백이 포함하기에 충분하지 않다는 사실에 대한 놀라운 증거가 있습니다 ...) 솔루션.

하나의 마지막 문제가 남아 있습니다. 정확한 목적을 위해, k0적어도 우리가 답을 기대하는 곳의 야구장에서 시작 해야합니다. 이를 위해 내 코드는 모든 집의 y 값에 대한 기하학적 평균을 선택합니다.

A는 페일 세이프 (fail-safe), 우리는 대체, 다시 9 번 전체 문제를 반복 k0하여 k정확성을 보장하기 위해, 모든 반복에.

나는 얼마나 많은 반복과 얼마나 많은 파생물이 필요한지에 대한 수학을 수행하지는 않았지만 정확성을 확인할 수있을 때까지주의 측면에서 잘못 선택했습니다.

당신이 나와 함께 그것을 통해 너무 감사합니다! 이해하기를 바랍니다. 실수가 많을 경우 (아마도 많이 피곤합니다) 알려주세요!


2
나는 하나, 당신의 수학의 설명을보고 싶어요.
DLosc

2
@DLosc 당신의 소원은 나의 명령입니다.
BrainSteel

4
정말 놀랍습니다. 나는 Newton의 Method를 시도하는 것을 고려했지만 Taylor 시리즈는 생각하지 않았습니다.
DLosc

5
나는 이것을 더 많이 투표 할 수 있기를 바랍니다.
Alex A.

@AlexA. 하루도 지나지 않아 Fermat의 마지막 정리 참조를 제거하고 증명으로 대체하겠습니다. 내가 찾 자마자
BrainSteel

13

TI-BASIC, 20

fMin(sum(abs(iX-Ans)),X,~E99,E99

TI-83 또는 84 시리즈 계산기의 홈 화면에 다음과 같은 형식으로 입력합니다 ( 2:처음 입력 할 수 있음).

{5.7+3.2i,8.9+8.1i}:[program name]

주택이 원점에서 항상 10 억 km 미만인 경우 E99를 18 바이트 크기의 E9로 교체 할 수 있습니다.

Mathematica를 기반으로 한 골프 언어가 있었는데 10-14 바이트로이 도전을 이길 수있었습니다.


10

수학, 42 바이트

k/.Last@Minimize[Tr[Norm[#-{0,k}]&/@#],k]&

이것은 집 좌표로 쌍 목록을 가져와 원하는 y 좌표를 반환하는 익명 함수입니다.

상당히 간단한 구현입니다. Norm[#-{0,k}]&{0,k}축 좌표 ( y 축의 결정되지 않은 점까지의 거리를 계산)에 매핑 하고 모두 합산합니다 Tr[...](추적의 경우 Total1 차원 목록에 해당). 그런 Minimize다음에이 합계의 최소값을 찾기 위해 편리함 을 사용합니다 k. 이것은 형식의 결과를 제공 {distance, {k -> position}하므로 찾고 k/.Last@있는 position것을 추출 해야 합니다 .


6

Pyth, 33 바이트

hosm.a,d,0NQcR^T3rhKSms*^T3ekQheK

이것은 무차별 대입 솔루션입니다. 그것은 집으로부터의 총 거리까지 .001 km의 해상도로 레스토랑의 가능한 모든 위치를 주문한 다음 총 거리가 가장 작은 곳을 선택합니다. 집 위치를 STDIN에있는 2 개의 플로트 항목 목록으로 가져옵니다.

데모.

해상도는 동일한 코드 길이에서 1e-2km에서 1e-10km까지 설정할 수 있지만 런타임에 기하 급수적으로 속도가 느려집니다.

이것이 더 골프를 칠 수 있다고 생각합니다. 나중에 다시 살펴 보겠습니다.


2
롤! 내 솔루션을 복사 했습니까? ;-)
Jakube

@Jakube 일치하는 ^T3것이 특히 인상적입니다.
isaacg

우리는 실제로 부동 범위가 필요합니다.
Maltysen

3

파이썬 2, 312

from math import*;A,L,p=[map(float,raw_input().split()) for i in range(input())],lambda a:a[1],0.001
def R(m,M,s):
 while m<=M:yield m;m+=s
m=min(A,key=L)[1];M=max(A,key=L)[1];r=(m+M)/2;s=r-m
while s>p:D={y:sum([sqrt(X*X+(Y-y)**2)for X,Y in A])for y in R(r-s,r+s,s*p)};r=min(D,key=D.get);s*=p;m=r-s;M=r+s
print r

3

R, 145 (143) 126

이것에 많은 골프장이 남아 있다고 생각합니다. 거의 무차별 강제 방법입니다. 이 작업을 수행하는 더 좋은 방법을 찾고 싶습니다. 기하학적 의미가 도움이 될 수는 있지만 아쉽습니다.

r=sapply(seq(min((p=matrix(scan(),nr=2))),max(p),.001),function(X,p)c(X,sum((p[1,]^2+(p[2,]-X)^2)^.5)),p);r[1,order(r[2,])[1]]

시운전

> r=sapply(seq(min((p=matrix(scan(),nr=2))),max(p),.001),function(X,p)c(X,sum((p[1,]^2+(p[2,]-X)^2)^.5)),p);r[1,order(r[2,])[1]]
1: 5.7 3.2
3: 8.9 8.1
5: 
Read 4 items
[1] 5.113
> 

관심사로, 고려할 주택이 두 개 뿐인 경우 다음을 고려하면 수용 가능한 결과가 반환됩니다. 그러나 그것은 3에 넘어집니다. 지금은 더 이상 참을 수는 없지만, 여기있는 뇌 중 일부는 무언가를 할 수있을 것이라고 생각했습니다.

p=matrix(scan(),nr=2);weighted.mean(p[2,],sum(p[1,])-p[1,])

2

MATLAB, 42

다음과 같이 입력을해도 괜찮다면

I=[5.7 3.2
    8.9 8.1]

다음이 진술

fminunc(@(y)sum(hypot(I(:,1),I(:,2)-y)),0)

을 반환합니다 5.113014445748538.

뻔뻔하게 Thomas Kwa의 방법을 훔치면 적어도 30으로 줄일 수 있습니다.

I=[5.7+3.2i 8.9+8.1i];
fminunc(@(y)sum(abs(I-i*y)),0)

1
n집 수 와 함께 일할 수 있습니까? 질문이 요구하는 것이기 때문입니다.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

예,의 모든 행에서 작동합니다 I.
David
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.