Area Permukaan Tetrahedron

16

Tantangan

Tantangan ini sangat mudah. Diberi empat titik 3 dimensi, hitung luas permukaan tetrahedron yang mereka bentuk. Ini , jadi kode terpendek menang. Celah standar berlaku, dengan ketentuan tambahan bahwa fungsi bawaan untuk melakukan tugas ini diberikan empat poin dilarang.

Anda dapat mengasumsikan keempat poin akan berbeda, dan akan diberikan melalui STDIN, 1 poin per baris. Setiap titik akan terdiri dari tiga bilangan bulat 16-bit unsigned. Format tepat dari setiap titik dapat dimodifikasi jika itu membuat segalanya lebih mudah, seperti tiga bilangan bulat yang dipisahkan ruang. Memiliki masing-masing titik pada jalur yang terpisah adalah wajib namun. Output harus melalui STDOUT, ke setidaknya 2 tempat desimal.

Bagi Anda yang tidak tahu, tetrahedron adalah padatan 3-d, dibentuk oleh 4 wajah segitiga.

Contoh

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

# output
2932496435.95

Silakan tinggalkan catatan jika Anda melihat matematika saya salah.

stokastik
sumber
@ BetaDecay Tidak, idenya adalah mereka akan diinput melalui STDIN pada empat baris terpisah. Saya akan mengedit pertanyaan untuk memperjelas ini.
stokastik
Bisakah inputnya menjadi [[list],[of],[lists]]?
phosgene
@ phosgene Saya suka berpikir bahwa input adalah bagian dari tantangan, jadi saya akan mengatakan tidak. Saya akan mencoba menjadi lebih lunak dengan spesifikasi input dalam tantangan di masa depan.
stokastic
Apakah ini tetrahedron biasa atau tidak teratur?
James Williams
@ JamesWilliams contoh yang diposting tidak teratur. Program Anda harus menangani input apa pun, termasuk tetrahedron biasa.
stokastik

Jawaban:

5

Python, 198 178 161 karakter

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

Format input seperti yang diberikan dalam pertanyaan.

Ini menghitung panjang tepi yang berdekatan dengan masing-masing wajah dan kemudian menggunakan rumus Heron .

Keith Randall
sumber
4

Matlab / Oktaf 103

Saya menganggap nilai yang akan disimpan dalam variabel c. Ini menggunakan fakta bahwa luas segitiga adalah setengah panjang dari produk silang dari dua vektor sisinya.

%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
cacat
sumber
Setiap titik harus dimasukkan pada jalur terpisah sebagai input standar.
DavidC
Saya pertama kali berpikir tidak ada yang namanya input standar di Matlab, tetapi saya menemukan fungsi yang dapat digunakan untuk mensimulasikan ini melalui jendela perintah, jadi sekarang Anda dapat melewati input yang Anda bisa dalam bahasa lain.
flawr
Menarik. Itu perintah yang sama yang digunakan Mathematica,Input[]
DavidC
Menurut Anda mengapa ini menarik? 'input' menurut saya seperti nama yang cukup umum untuk fungsi yang melakukan ini.
flawr
Sampai kemarin, saya tidak benar-benar tahu apa yang dimaksud "standar masukan", dan saya pikir bahwa Mathematica tidak memiliki "standar" input, meskipun saya telah digunakan secara teratur Input[], InputString[], Import[], dan ImportString[].
DavidC
4

APL, 59

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

Bekerja dengan menghitung produk silang

Penjelasan
Baris pertama mendefinisikan fungsi yang mengambil dua argumen (secara implisit dinamai dan ), secara implisit mengharapkannya menjadi array numerik dengan panjang 3, memperlakukannya sebagai vektor 3d, dan menghitung besarnya kuadrat dari produk silang mereka.

                        ⊂⍺   # 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`

Baris kedua melakukan sisanya.

                         ⎕⎕⎕-⊂⎕ # 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
TwiNight
sumber
Jika Anda tidak yakin apakah itu hieroglif atau file dll yang rusak itu mungkin APL. Bisakah Anda menjelaskan sedikit lebih banyak tentang apa yang dilakukan beberapa simbol itu? Bukannya saya ingin mempelajarinya tetapi saya masih agak tertarik dengan bagaimana Anda dapat memprogram dengan simbol-simbol yang tampaknya tidak jelas = P
flawr
@ flawr Saya biasanya melakukan itu karena golf di APL sebagian besar bermuara pada desain algoritma dan kemungkinan besar akan menghasilkan pendekatan yang tidak biasa untuk masalah tersebut. Tapi saya merasa seperti "menghitung produk silang" cukup menyampaikan tentang algoritma di sini. Jika Anda ingin penjelasan lengkap saya akan melakukannya hari ini juga.
TwiNight
Gagasan menghitung produk silang jelas, tetapi kode itu sendiri meninggalkan saya tanpa petunjuk apa pun, jadi saya hanya memikirkan beberapa kata tentang bagian kode mana yang akan bagus, tetapi tentu saja saya tidak ingin mendorong Anda untuk tulis penjelasan rinci!
flawr
3

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

Ini menggunakan:

  • Teorema Pythagoras (dalam 3D) menentukan panjang setiap baris
  • Formula Bangau untuk menghitung luas setiap segitiga
satu-satunya
sumber
1
Saya menggunakan metode yang sama untuk menguji solusi saya. Saya harus mencoba golf milik saya dan mempostingnya nanti.
stokastic
1
Anda for i in">"*4cerdas
stokastik
Anda dapat membuat kode dengan panjang 3, daripada menggunakan len (i) dalam fungsi jangkauan Anda.
stokastic
1
Anda bisa menyimpan beberapa karakter lagi sebagai root x**0.5, bukan math.sqrt(x).
Snorfalorpagus
1
Anda dapat menyimpan dua byte dengan menempatkan def a(t,u,v)satu baris seperti: def a(t,u,v):w=(t+u+v)/2;return(w*(w-t)*(w-u)*(w-v))**0.5.
Beta Decay
2

Mathematica 168 154

Ini menemukan panjang tepi tetrahedron dan menggunakan rumus Heron untuk menentukan area wajah.

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

Ada rute yang lebih langsung yang hanya membutuhkan 60 karakter , tetapi melanggar aturan sejauh menghitung daerah masing-masing wajah dengan built-in fungsi, Area:

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

Sage - 103

print sum((x*x*y*y-x*y*x*y)^.5for x,y in map(differences,Combinations(eval('vector(input()),'*4),3)))/2

Bagian pembacaan input diadaptasi dari jawaban Keith Randall .

Wrzlprmft
sumber
0

Python - 260

Saya tidak yakin apa etiket posting jawaban untuk pertanyaan Anda sendiri, tetapi dia adalah solusi saya, yang saya gunakan untuk memverifikasi contoh saya, golf:

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

Ia menggunakan prosedur yang sama dengan laurencevs.

stokastik
sumber
4
Sebagai aturan praktis, sebaiknya tunggu beberapa hari sebelum menjawab pertanyaan Anda sendiri, terutama jika skor Anda rendah, agar tidak mendinginkan motivasi pemirsa.
Blackhole
Beberapa tips: Anda dapat menyimpan beberapa karakter dengan r=range. lambdalebih pendek dari def. math.sqrtdapat digantikan oleh (…)**.5. p=copy.copy(P);p.pop(j);dapat disingkat menjadi p=P[:j-1]+P[j:]. Ahanya digunakan satu kali.
Wrzlprmft
0

C, 303

Tidak termasuk spasi putih yang tidak perlu. Namun, masih banyak golf yang harus dilakukan di sini (saya akan mencoba untuk kembali dan melakukannya nanti.) Ini pertama kalinya saya menyatakan forloop dalam sebuah#define . Saya selalu menemukan cara untuk mengurangi jumlah loop sebelumnya.

Saya harus berubah dari floatuntuk doublemendapatkan jawaban yang sama dengan OP untuk kasus uji. Sebelum itu, itu adalah 300 putaran.

scanf berfungsi sama apakah Anda memisahkan input Anda dengan spasi atau baris baru, sehingga Anda dapat memformatnya menjadi sebanyak atau sesedikit baris yang Anda suka.

#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);       
}
Level River St
sumber