Diện tích bề mặt tứ diện


16

Các thách thức

Thử thách này rất đơn giản. Cho bốn điểm 3 chiều, tính diện tích bề mặt của tứ diện mà chúng tạo thành. Đây là , vì vậy mã ngắn nhất sẽ thắng. Các lỗ hổng tiêu chuẩn được áp dụng, với quy định bổ sung rằng bất kỳ chức năng tích hợp nào để thực hiện nhiệm vụ này với bốn điểm đều bị cấm.

Bạn có thể giả sử tất cả bốn điểm sẽ khác biệt và sẽ được cung cấp qua STDIN, 1 điểm trên mỗi dòng. Mỗi điểm sẽ bao gồm ba số nguyên không dấu 16 bit. Định dạng chính xác của từng điểm có thể được sửa đổi nếu nó làm cho mọi thứ dễ dàng hơn, chẳng hạn như ba số nguyên được phân tách bằng dấu cách. Tuy nhiên, có mỗi điểm trên một dòng riêng biệt là bắt buộc. Đầu ra phải thông qua STDOUT, đến ít nhất 2 chữ số thập phân.

Đối với những người bạn không biết, một khối tứ diện là một khối rắn 3 chiều, được hình thành bởi 4 mặt tam giác.

Thí dụ

# input (format is up to you, see clarification above)
[23822, 47484, 57901]
[3305, 23847, 42159]
[19804, 11366, 14013]
[52278, 28626, 52757]

# output
2932496435.95

Vui lòng để lại một lưu ý nếu bạn nhận thấy toán học của tôi sai.


@BetaDecay Không, ý tưởng là chúng sẽ được nhập qua STDIN trên bốn dòng riêng biệt. Tôi sẽ chỉnh sửa câu hỏi để làm rõ điều này.
stokastic

Đầu vào có thể là một [[list],[of],[lists]]?
phosgene

@phosgene Tôi thích đọc đầu vào là một phần của thử thách, vì vậy tôi sẽ nói không. Tôi sẽ cố gắng khoan dung hơn với các thông số kỹ thuật đầu vào trong các thử thách trong tương lai.
stokastic

Đây là một tứ diện đều đặn hoặc không thường xuyên?
James Williams

@JamesWilliams ví dụ được đăng là không thường xuyên. Chương trình của bạn nên xử lý bất kỳ đầu vào nào, bao gồm cả tứ diện thông thường.
stokastic

Câu trả lời:


5

Python, 198 178 161 ký tự

V=eval('input(),'*4)
A=0
for i in range(4):F=V[:i]+V[i+1:];a,b,c=map(lambda e:sum((a-b)**2for a,b in zip(*e)),zip(F,F[1:]+F));A+=(4*a*b-(a+b-c)**2)**.5
print A/4

Các định dạng đầu vào như được đưa ra trong câu hỏi.

Nó tính toán độ dài của các cạnh liền kề với mỗi khuôn mặt và sau đó sử dụng công thức của Heron .


4

Matlab / Octave 103

Tôi giả sử các giá trị được lưu trữ trong biến c. Điều này sử dụng thực tế là diện tích của một hình tam giác là một nửa chiều dài của tích chéo của hai vectơ bên của nó.

%input
[23822, 47484, 57901;
3305, 23847, 42159;
19804, 11366, 14013;
52278, 28626, 52757]



%actual code
c=input('');
a=0;
for i=1:4;
    d=c;d(i,:)=[];
    d=d(1:2,:)-[1 1]'*d(3,:);
    a=a+norm(cross(d(1,:),d(2,:)))/2;
end
a

Mỗi điểm phải được nhập trên một dòng riêng biệt làm đầu vào tiêu chuẩn.
DavidC

Trước tiên tôi nghĩ rằng không có thứ gọi là đầu vào tiêu chuẩn trong Matlab, nhưng tôi đã phát hiện ra một chức năng có thể được sử dụng để mô phỏng điều này thông qua cửa sổ lệnh, vì vậy bây giờ bạn có thể chuyển đầu vào như bạn có thể bằng các ngôn ngữ khác.
flawr

Hấp dẫn. Đó là cùng một lệnh mà Mathicala sử dụng,Input[]
DavidC

Tại sao bạn nghĩ rằng điều này là thú vị? 'đầu vào' đối với tôi giống như một cái tên chung chung cho một chức năng thực hiện điều này.
flawr

Cho đến ngày hôm qua, tôi đã không thực sự biết những gì "tiêu chuẩn đầu vào" có nghĩa là, và tôi nghĩ rằng Mathematica không có "tiêu chuẩn" đầu vào, mặc dù tôi đã thường xuyên sử dụng Input[], InputString[], Import[], và ImportString[].
DavidC

4

APL, 59

f←{+.×⍨⊃1 2-.⌽(⊂⍵)×1 2⌽¨⊂⍺}
.5×.5+.*⍨(f/2-/x),2f/4⍴x←⎕⎕⎕-⊂⎕

Hoạt động bằng cách tính toán các sản phẩm chéo

Giải thích
Dòng đầu tiên xác định một hàm có hai đối số (hàm ý được đặt tên ), hoàn toàn mong đợi chúng là các mảng số có độ dài 3, coi chúng là các vectơ 3d và tính độ lớn bình phương của sản phẩm chéo của chúng.

                        ⊂⍺   # Wrap the argument in a scalar
                   1 2⌽¨     # Create an array of 2 arrays, by rotating `⊂⍺` by 1 and 2 places
             (⊂⍵)×           # Coordinate-wise multiply each of them with the other argument
        1 2-.⌽               # This is a shorthand for:
        1 2  ⌽               #   Rotate the first array item by 1 and the second by 2
           -.                #   Then subtract the second from the first, coordinate-wise
       ⊃                     # Unwrap the resulting scalar to get the (sorta) cross product
   +.×                       # Calculate the dot product of that...
      ⍨                      # ...with itself
f←{+.×⍨⊃1 2-.⌽(⊂⍵)×1 2⌽¨⊂⍺} # Assign function to `f`

Dòng thứ hai làm phần còn lại.

                         ⎕⎕⎕-⊂⎕ # Take 4 array inputs, create an array of arrays by subtracting one of them from the other 3
                       x←        # Assign that to x
                     4⍴          # Duplicate the first item and append to the end
                  2f/            # Apply f to each consecutive pair
            2-/x                 # Apply subtraction to consecutive pairs in x
          f/                     # Apply f to the 2 resulting arrays
         (f/2-/x),2f/4⍴x←⎕⎕⎕-⊂⎕ # Concatenate to an array of 4 squared cross products
   .5+.*⍨                        # Again a shorthand for:
   .5  *⍨                        #   Take square root of each element (by raising to 0.5)
     +.                          #   And sum the results
.5×                              # Finally, divide by 2 to get the answer

Nếu bạn không chắc chắn đó là chữ tượng hình hay tệp dll bị hỏng thì có lẽ đó sẽ là APL. Có lẽ bạn có thể giải thích phần nào những gì một số biểu tượng đó làm gì? Không phải là tôi muốn học nó nhưng tôi vẫn bị thu hút bởi cách bạn có thể lập trình với những biểu tượng có vẻ mơ hồ = P
flawr

@flawr Tôi thường làm điều đó bởi vì chơi golf trong APL chủ yếu dựa vào thiết kế thuật toán và rất có thể sẽ dẫn đến một cách tiếp cận không phổ biến cho vấn đề này. Nhưng tôi cảm thấy như "tính toán sản phẩm chéo" truyền tải đủ về thuật toán ở đây. Nếu bạn muốn một lời giải thích đầy đủ, tôi sẽ thực hiện nó sau hôm nay.
TwiNight

Ý tưởng tính toán sản phẩm chéo rất rõ ràng, nhưng bản thân mã không để lại bất kỳ manh mối nào, vì vậy tôi chỉ nghĩ vài từ về phần nào của mã làm điều gì sẽ tuyệt vời, nhưng tất nhiên tôi không muốn thúc giục bạn viết một lời giải thích chi tiết!
flawr

3

Con trăn 3, 308 298 292 279 258 254

from itertools import*
def a(t,u,v):w=(t+u+v)/2;return(w*(w-t)*(w-u)*(w-v))**.5
z,x,c,v,b,n=((lambda i,j:(sum((i[x]-j[x])**2for x in[0,1,2]))**.5)(x[0],x[1])for*x,in combinations([eval(input())for i in">"*4],2))
print(a(z,x,v)+a(z,c,b)+a(b,v,n)+a(x,c,n))

Điều này sử dụng:

  • Định lý Pythagore (dưới dạng 3D) để tính ra độ dài của mỗi dòng
  • Công thức của Heron để tính diện tích của mỗi tam giác

1
Tôi đã sử dụng cùng một phương pháp để thử nghiệm giải pháp của tôi. Tôi sẽ phải thử chơi golf và đăng nó sau.
stokastic

1
Bạn for i in">"*4thật thông minh
stokastic

Bạn có thể mã cứng độ dài 3, thay vì sử dụng len (i) trong chức năng phạm vi của bạn.
stokastic

1
Bạn có thể lưu thêm một vài ký tự làm căn bậc hai x**0.5, thay vì math.sqrt(x).
Snorfalorpagus

1
Bạn có thể lưu hai byte bằng cách đặt def a(t,u,v)trên một dòng như vậy : def a(t,u,v):w=(t+u+v)/2;return(w*(w-t)*(w-u)*(w-v))**0.5.
Beta Decay

2

Toán học 168 154

Điều này tìm thấy độ dài của các cạnh của khối tứ diện và sử dụng công thức của Heron để xác định các khu vực của các mặt.

t = Subsets; p = Table[Input[], {4}];
f@{a_, b_, c_} := Module[{s = (a + b + c)/2}, N[Sqrt[s (s - #) (s - #2) (s -#3)] &[a, b, c], 25]]
  Tr[f /@ (EuclideanDistance @@@ t[#, {2}] & /@ t[p, {3}])]

Có một tuyến đường trực tiếp hơn chỉ cần 60 ký tự , nhưng nó vi phạm các quy tắc trong khi nó tính diện tích của mỗi mặt với chức năng tích hợp , Area:

p = Table[Input[], {4}];
N[Tr[Area /@ Polygon /@ Subsets[p, {3}]], 25]


0

Con trăn - 260

Tôi không chắc chắn về nghi thức khi đăng câu trả lời cho câu hỏi của bạn là gì, nhưng cô ấy là giải pháp của tôi, mà tôi đã sử dụng để xác minh ví dụ của mình, đánh gôn:

import copy,math
P=[input()for i in"1234"]
def e(a, b):return math.sqrt(sum([(b[i]-a[i])**2 for i in range(3)]))
o=0
for j in range(4):p=copy.copy(P);p.pop(j);a,b,c=[e(p[i],p[(i+1)%3])for i in range(3)];s=(a+b+c)/2;A=math.sqrt(s*(s-a)*(s-b)*(s-c));o+=A
print o

Nó sử dụng thủ tục tương tự như laurencevs.


4
Theo nguyên tắc thông thường, tốt nhất là đợi vài ngày trước khi trả lời câu hỏi của bạn, đặc biệt nếu điểm của bạn thấp, để không làm giảm động lực của người xem.
Hố đen

Một vài lời khuyên: Bạn có thể lưu một số ký tự bằng cách r=range. lambdangắn hơn def. math.sqrtcó thể được thay thế bởi (…)**.5. p=copy.copy(P);p.pop(j);có thể rút ngắn thành p=P[:j-1]+P[j:]. Achỉ được sử dụng một lần.
Wrzlprmft

0

C, 303

Không bao gồm khoảng trắng không cần thiết. Tuy nhiên, vẫn còn rất nhiều việc chơi golf được thực hiện ở đây (tôi sẽ cố gắng quay lại và thực hiện sau.) Đây là lần đầu tiên tôi tuyên bố một forvòng lặp trong a #define. Trước đây tôi luôn tìm cách giảm thiểu số vòng lặp.

Tôi đã phải thay đổi từ floatđể doublecó được câu trả lời giống như OP cho trường hợp thử nghiệm. Trước đó, nó là một vòng 300.

scanf hoạt động tương tự cho dù bạn tách đầu vào của mình bằng dấu cách hoặc dòng mới, vì vậy bạn có thể định dạng nó thành nhiều hoặc ít dòng tùy thích.

#define F ;for(i=0;i<12;i++)
#define D(k) (q[i]-q[(i+k)%12])
double q[12],r[12],s[4],p,n;

main(i){
  F scanf("%lf",&q[i])
  F r[i/3*3]+=D(3)*D(3),r[i/3*3+1]+=D(6)*D(6)
  F r[i]=sqrt(r[i])
  F i%3||(s[i/3]=r[(i+3)%12]/2),s[i/3]+=r[i]/2
  F i%3||(p=s[i/3]-r[(i+3)%12]),p*=s[i/3]-r[i],n+=(i%3>1)*sqrt(p)   
  ;printf("%lf",n);       
}
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.