Tôi nên đặt nhà hàng của tôi ở đâu?


15

Bạn là chủ của một nhà hàng. Bạn đang mở ở một khu vực mới ở Cartesia, nơi chỉ có một con đường chính, được gọi là trục y. Bạn muốn đặt nhà hàng của bạn sao cho bạn giảm thiểu tổng khoảng cách từ nhà hàng của bạn và từng ngôi nhà trong khu vực đó.

Đầu vào :

Đầu vào sẽ là

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

trong đó mỗi ngôi nhà là một tọa độ trong mẫu x y . Mỗi đơn vị đại diện cho một km.

Bạn có thể lấy đầu vào dưới dạng chuỗi hoặc cung cấp hàm lấy đầu vào, ở bất kỳ định dạng nào bạn chọn, làm đối số của nó.

Đầu ra : Tọa độ y của nhà hàng của bạn (hãy nhớ, nó sẽ nằm trên trục y). Trên thực tế, nó sẽ nằm ở bên đường, nhưng sự khác biệt là không đáng kể.

Về cơ bản, nếu nhà thứ n là h_nDlà hàm khoảng cách, thì bạn muốn tìm knhư vậyD(h_0, (0, k)) + D(h_1, (0, k)) + D(h_2, (0, k)) + ... + D(h_n, (0, k)) được thu nhỏ.

Lưu ý rằng khoảng cách được tính như thể khách hàng đi theo một đường thẳng chính xác từ nhà của họ đến nhà hàng. Đó là khoảng cách từ (x, y)đến nhà hàng của bạn làsqrt(x^2 + (y - k)^2) .

Đầu ra phải chính xác đến ít nhất 2 chữ số thập phân.

Đầu ra có thể được in dưới dạng chuỗi hoặc có thể được trả về từ hàm.

Ví dụ đầu vào / đầu ra:

Input:
2
5.7 3.2
8.9 8.1
Output:
5.113013698630137

Tổng khoảng cách trong ví dụ này là khoảng 15.4003km.

Đây là mã golf - mã ngắn nhất thắng.

PS Tôi cũng quan tâm đến một giải pháp toán học không chỉ là vũ phu. Nó sẽ không giành được mã golf nhưng nó sẽ nhận được một số upvote. Đây là cách tôi đã làm vấn đề ví dụ:

Đặt điểm A nằm ở A (5.7, 3.2) và B tại B (8,9, 8.1). Đặt điểm giải pháp tại (0, k) là C. Phản xạ A qua trục y để tạo A 'tại (-5.7, 3.2). Khoảng cách từ A 'đến C bằng khoảng cách từ A đến C. Do đó, vấn đề có thể được giảm đến điểm C sao cho A'C + CB được giảm thiểu. Rõ ràng, đây sẽ là điểm C nằm trên dòng A'B.

Tôi không biết nếu điều này sẽ khái quát tốt đến 3 điểm trở lên.


Số liệu nào được sử dụng cho hàm khoảng cách D? Euclide?
Reto Koradi

1
Mặc dù chỉ có một con đường chính, chúng ta có cho rằng một khách hàng đi theo một đường thẳng từ nhà của họ đến nhà hàng không? Hay họ đi trực tiếp đến trục y trước? (Hay nói cách khác, chúng ta có sử dụng khoảng cách Euclid hoặc Manhattan cho D không?)
trichoplax

1
(Điều này có thể được giải quyết từ ví dụ nhưng thật tuyệt khi được nêu rõ ràng.)
trichoplax

@trichoplax Euclide? Euclide có nghĩa là sqrt(diffX^2 + diffY^2)gì? Rồi Euclide. Tôi biết nó không phù hợp với kịch bản một cách hoàn hảo nhưng giả sử rằng khách hàng đi theo đường thẳng bằng cách nào đó từ nhà của anh ấy / cô ấy.
soktinpk

5
Việc lấy đầu vào làm danh sách các số phức biểu thị vị trí của các ngôi nhà trên mặt phẳng phức có được chấp nhận không?
lirtosiast

Câu trả lời:


27

C, 315 302 byte

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;}

Điều này là xa đẹp, và nó cũng không ngắn. Tôi hình dung vì tôi sẽ không chiến thắng trong cuộc thi dài, tôi có thể cố gắng giành chiến thắng trong cuộc thi chính xác (lý thuyết)! Mã này có thể là một thứ tự cường độ hoặc hai nhanh hơn so với giải pháp bruteforce, và dựa vào một chút của tính năng tomfoolery toán học.

Chúng ta định nghĩa một hàm g(N,S)mà mất như là đầu vào số lượng nhà ở, Nvà một loạt các nhàS[][2] .

Ở đây nó được làm sáng tỏ, với một trường hợp thử nghiệm:

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;
}

Đầu ra nào:

5.11301369863013732697

Cảnh báo: Kiến thức về một số tính toán có thể được yêu cầu để hiểu đầy đủ!

Vì vậy, hãy nói về toán học.

Chúng tôi biết khoảng cách từ điểm mong muốn của chúng tôi (0, k)và một ngôi nhà i:

Định nghĩa của D_i

Và do đó, tổng khoảng cách Dtừ các nngôi nhà có thể được xác định như sau:

Định nghĩa của D

Những gì chúng tôi muốn làm là giảm thiểu chức năng này bằng cách lấy đạo hàm đối với kvà đặt nó bằng 0. Hãy thử nó. Chúng tôi biết rằng các dẫn xuất của Dcó thể được mô tả như sau:

Đạo hàm của D

Nhưng đạo hàm riêng đầu tiên của mỗi thứ Dikhá tệ ...

Đạo hàm 1 của Di

Thật không may, ngay cả với n == 2, thiết lập các dẫn xuất này 0và giải quyết chok trở thành thảm họa rất nhanh. Chúng ta cần một phương pháp mạnh mẽ hơn, ngay cả khi nó đòi hỏi một số xấp xỉ.

Nhập đa thức Taylor.

Nếu chúng ta biết giá trị của D(k0)tất cả các Ddẫn xuất tại k0, chúng ta có thể viết lại Ddưới dạng Sê-ri Taylor:

Định nghĩa của Taylor Series

Bây giờ, công thức này có một loạt các công cụ trong đó và các dẫn xuất của nó có thể trở nên khá khó sử dụng, nhưng bây giờ chúng ta có một xấp xỉ đa thức của D !

Làm một chút tính toán, chúng tôi tìm thấy hai đạo hàm tiếp theo Dbằng cách đánh giá các đạo hàm của Di, giống như trước đây:

Đạo hàm 2 của Di

Đạo hàm 3 của Di

Bằng cách cắt và đánh giá các đạo hàm, giờ đây chúng ta có thể tính gần đúng Ddưới dạng đa thức bậc 3 của dạng:

Hình thức gần đúng của D

Ở đâu A, B, C, D đơn giản là số thực.

Bây giờ điều này chúng ta có thể giảm thiểu. Khi chúng ta lấy một đạo hàm và đặt nó bằng 0, chúng ta sẽ kết thúc với một phương trình có dạng:

Xấp xỉ D '

Thực hiện các phép tính và thay thế, chúng tôi đưa ra các công thức cho a, b, and c:

Giá trị của một

Giá trị của b

Giá trị của c

Bây giờ vấn đề của chúng tôi cung cấp cho chúng tôi 2 giải pháp được đưa ra bởi công thức bậc hai:

Giá trị của k

Toàn bộ công thức cho k sẽ là một gánh nặng lớn để viết ra, vì vậy chúng tôi thực hiện nó thành từng phần ở đây và trong mã.

Vì chúng tôi biết rằng mức cao hơn ksẽ luôn dẫn đến khoảng cách tối thiểu gần đúng của chúng tôiD (tôi có một bằng chứng thực sự tuyệt vời về điều này, mà lề của bài viết này không đủ để chứa ...), chúng tôi thậm chí không phải xem xét nhỏ hơn bản đồ đường viền.

Một vấn đề cuối cùng vẫn còn. Đối với mục đích chính xác, điều cần thiết là chúng ta bắt đầu với một k0ít nhất là trong sân bóng nơi chúng ta mong đợi câu trả lời. Với mục đích này, mã của tôi chọn giá trị trung bình hình học của các giá trị y của mỗi ngôi nhà.

Vì không an toàn, chúng tôi lặp lại toàn bộ vấn đề 9 lần, thay thế k0bằng kmỗi lần lặp, để đảm bảo độ chính xác.

Tôi đã không thực hiện phép toán về bao nhiêu lần lặp và bao nhiêu dẫn xuất thực sự cần thiết, nhưng tôi đã chọn sai ở khía cạnh thận trọng cho đến khi tôi có thể xác nhận độ chính xác.

Nếu bạn đã làm điều đó thông qua đó với tôi, cảm ơn bạn rất nhiều! Tôi hy vọng bạn hiểu, và nếu bạn phát hiện ra bất kỳ sai lầm nào (trong đó có khả năng rất nhiều, tôi rất mệt mỏi), xin vui lòng cho tôi biết!


2
Tôi, một người, rất thích xem giải thích về toán học của bạn.
DLosc

2
@DLosc Mong muốn của bạn là mệnh lệnh của tôi.
BrainSteel

4
Điều đó thực sự tuyệt vời. Tôi đã cân nhắc thử Phương pháp của Newton, nhưng không nghĩ đến loạt Taylor.
DLosc

5
Tôi ước tôi có thể nâng cao điều này hơn nữa.
Alex A.

@AlexA. Tôi ước bạn cũng có thể nâng đỡ tôi nhiều hơn nữa. D Trong vòng một ngày hoặc lâu hơn, tôi sẽ xóa tham chiếu định lý cuối cùng của Fermat và thay thế bằng một bằng chứng. Ngay khi tôi tìm thấy một.
BrainSteel

13

TI-CƠ BẢN, 20

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

Đưa đầu vào vào màn hình chính của máy tính sê-ri TI-83 hoặc 84 của bạn ở dạng này (Bạn có thể nhập 2:đầu tiên, sẽ bị bỏ qua):

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

Nếu các ngôi nhà luôn cách xa nguồn gốc chưa đến một tỷ km, E99 có thể được thay thế bằng E9 với kích thước 18 byte.

Nếu có một ngôn ngữ chơi gôn dựa trên Mathematica, nó có thể chiến thắng thử thách này trong 10-14 byte.


10

Toán học, 42 byte

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

Đây là một hàm ẩn danh lấy danh sách các cặp làm tọa độ nhà và trả về tọa độ y mong muốn.

Đó là một thực hiện khá đơn giản. Chúng tôi ánh xạ Norm[#-{0,k}]&vào từng tọa độ nhà (tính khoảng cách đến một điểm không xác định {0,k}trên trục y) và tính tổng tất cả chúng với Tr[...](đối với dấu vết, tương đương với Totaldanh sách 1-d). Sau đó, chúng tôi sử dụng thuận tiện Minimizeđể tìm tối thiểu của số tiền này trong k. Điều này đưa ra kết quả của biểu mẫu {distance, {k -> position}, vì vậy chúng tôi cần k/.Last@trích xuất những gì positionchúng tôi đang tìm kiếm.


6

Bình thường, 33 byte

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

Đây là giải pháp vũ phu: Nó đặt hàng tất cả các vị trí có thể có của nhà hàng, với độ phân giải 0,001 km, bằng tổng khoảng cách từ các ngôi nhà, sau đó chọn một vị trí có tổng khoảng cách ít nhất. Nó lấy các vị trí ngôi nhà như một danh sách gồm 2 danh sách các phao trên STDIN.

Trình diễn.

Độ phân giải có thể được đặt ở bất cứ đâu từ 1e-2 km đến 1e-10 km với cùng độ dài mã, nhưng với sự chậm lại theo cấp số nhân trong thời gian chạy.

Tôi cảm thấy như điều này có thể được đánh gôn thêm, tôi sẽ xem xét lại sau.


2
Cười lớn! Bạn đã sao chép giải pháp của tôi? ;-)
Jakube

@Jakube Sự kết hợp ^T3đặc biệt ấn tượng.
isaacg

Chúng tôi thực sự cần một phạm vi nổi.
Maltysen

3

Con trăn 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

Tôi nghi ngờ có rất nhiều phòng chơi golf. Khá nhiều một phương pháp vũ phu. Tôi muốn tìm một cách đẹp hơn để làm điều này. Tôi mặc dù Phương tiện hình học có thể giúp đỡ, nhưng than ôi không.

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]]

Chạy thử nghiệm

> 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
> 

Là một vấn đề quan tâm, nếu chỉ có hai ngôi nhà để xem xét sau đây sẽ trả lại một kết quả chấp nhận được. Tuy nhiên, nó rơi vào ba. Tôi không thể mang nó đi xa hơn vào lúc này, nhưng tôi nghĩ một số bộ não ở đây có thể có thể làm gì đó với nó.

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

2

MATLAB, 42

Nếu nó ổn để lấy đầu vào là

I=[5.7 3.2
    8.9 8.1]

sau đó tuyên bố này

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

trả lại 5.113014445748538.

Không biết xấu hổ ăn cắp phương pháp của Thomas Kwa, bạn có thể giảm xuống còn 30 ít nhất:

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

1
Nó có thể được mở rộng để làm việc với nsố lượng nhà? Vì đó là những gì câu hỏi đang yêu cầu.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Vâng, nó hoạt động với bất kỳ số lượng hàng trong I.
David
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.