Tetrahedron Yüzey Alanı


16

Meydan okuma

Bu zorluk çok basittir. Dört 3 boyutlu nokta verildiğinde, oluşturdukları tetrahedronun yüzey alanını hesaplayın. Bu , bu yüzden en kısa kod kazanır. Standart boşluklar, dört nokta verildiğinde bu görevi yerine getirmek için herhangi bir yerleşik işlevin yasaklandığı ek hüküm ile uygulanır.

Dört noktanın da farklı olacağını ve her satırda 1 puan STDIN ile verileceğini varsayabilirsiniz. Her nokta üç adet 16 bit işaretsiz tamsayıdan oluşur. Üç boşlukla ayrılmış tamsayı gibi, işleri kolaylaştırırsa, her noktanın tam biçimi değiştirilebilir. Ancak her noktanın ayrı bir çizgide olması zorunludur. Çıktı STDOUT üzerinden en az 2 ondalık basamağa kadar olmalıdır.

Bilmeyenler için tetrahedron , 4 üçgen yüzden oluşan 3 boyutlu bir katıdır.

Misal

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

# output
2932496435.95

Matemamın yanlış olduğunu fark ederseniz lütfen not bırakın.


@BetaDecay Hayır, fikir STDIN üzerinden dört ayrı satıra girilecek olması. Bunu açıklığa kavuşturmak için soruyu düzenleyeceğim.
stokastic

Giriş bir olabilir [[list],[of],[lists]]mi?
Fosgen

@phosgene Girdi okumanın zorluğun bir parçası olduğunu düşünüyorum, bu yüzden hayır diyeceğim. Gelecekteki zorluklarda girdi spesifikasyonları ile daha yumuşak olmaya çalışacağım.
stokastic

Bu düzenli veya düzensiz bir tetrahedron mu?
James Williams

@JamesWilliams yayınlanan örnek düzensiz. Programınız düzenli tetrahedronlar dahil olmak üzere tüm girdileri işlemelidir.
stokastic

Yanıtlar:


5

Python, 198178161 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

Giriş formatı soruda belirtildiği gibidir.

Yüzlerin her birine bitişik kenarların uzunluğunu hesaplar ve daha sonra Heron formülünü kullanır .


4

Matlab / Oktav 103

Değişken içinde saklanacak değerleri varsayalım c. Bu, bir üçgenin alanının, yan vektörlerinden ikisinin çapraz ürününün yarım uzunluğu olduğu gerçeğini kullanır.

%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

Her nokta standart girdi olarak ayrı bir satıra girilmelidir.
DavidC

İlk olarak Matlab'da standart girdi diye bir şey olmadığını düşündüm, ancak komut penceresi aracılığıyla bunu simüle etmek için kullanılabilecek bir işlev keşfettim, böylece girişi diğer dillerde olabildiğince geçirebilirsiniz.
Kusur

İlginç. Bu Mathematica'nın kullandığı komutla aynı,Input[]
DavidC

Bunun neden ilginç olduğunu düşünüyorsun? 'input' bana bunu yapan bir fonksiyon için oldukça genel bir isim gibi geliyor.
flawr

Düne kadar, gerçekten "standart girdi" ne anlama geldiğini bilmiyordum, ben Mathematica düzenli kullanılan olmasına rağmen, "standart" girdileri olmadığını düşündüm Input[], InputString[], Import[], ve ImportString[].
DavidC

4

APL, 59

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

Çapraz ürünleri hesaplayarak çalışır

Açıklama
İlk satır, iki bağımsız değişkeni ( ve adında bir anlamsızlık ) alan, dolaylı olarak 3 uzunluklu sayısal diziler olmasını bekleyen, 3B vektör olarak ele alan ve çapraz çarpımlarının kare büyüklüğünü hesaplayan bir işlevi tanımlar .

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

İkinci satır gerisini halleder.

                         ⎕⎕⎕-⊂⎕ # 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

Hiyeroglif veya bozuk bir dll dosyası olup olmadığından emin değilseniz, muhtemelen APL olacaktır. Bu sembollerden bazılarının ne yaptığını belki biraz daha açıklayabilir misiniz? Öğrenmek istediğimden değil, ama görünüşte belirsiz sembollerle nasıl programlayabileceğinizden oldukça
meraklıyım

@flawr Genellikle bunu yaparım çünkü APL'de golf çoğunlukla algoritma tasarımına iner ve büyük olasılıkla soruna nadir bir yaklaşımla sonuçlanır. Ama "çapraz çarpımın hesaplanması" buradaki algoritma hakkında yeterince bilgi veriyor gibi hissettim. Tam bir açıklama istiyorsanız, bunu bugün daha sonra yapacağım.
TwiNight

Çapraz ürünü hesaplama fikri açıktı, ancak kodun kendisi herhangi bir ipucu olmadan beni bırakıyor, bu yüzden kodun hangi bölümlerinin harika olacağını ne yaptığına dair birkaç kelime düşündüm, ama elbette sizi teşvik etmek istemiyorum ayrıntılı bir açıklama yazın!
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))

Bu kullanır:

  • Her satırın uzunluğunu hesaplamak için Pisagor Teoremi (3B olarak)
  • Heron'un Formülü her üçgenin alanını hesaplamak için

1
Çözümümü test etmek için aynı yöntemi kullandım. Benimkini golfe denemek ve daha sonra göndermek zorundayım.
stokastic

1
Sizin for i in">"*4zeki
stokastic

Aralık işlevinizde len (i) kullanmak yerine 3 uzunluğunu sabit olarak kodlayabilirsiniz.
stokastic

1
Bunun x**0.5yerine karekök yaparak birkaç karakter daha kaydedebilirsiniz math.sqrt(x).
Snorfalorpagus

1
Sen koyarak iki bayt kaydedebilirsiniz def a(t,u,v)şöyle bir satırda: def a(t,u,v):w=(t+u+v)/2;return(w*(w-t)*(w-u)*(w-v))**0.5.
Beta Çürümesi

2

Mathematica 168 154

Bu, tetrahedronun kenarlarının uzunluklarını bulur ve yüzlerin alanlarını belirlemek için Heron formülünü kullanır .

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

Sadece 60 karakter gerektiren daha doğrudan bir rota var , ancak her bir yüzün alanını yerleşik bir işlevle hesapladığı sürece kuralları ihlal ediyor Area:

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


0

Python - 260

Kendi sorularınıza cevap gönderme konusundaki görgü kuralının ne olduğundan emin değilim, ama benim çözümüm, benim örneğimi doğrulamak için kullandım, 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

Laurencevs ile aynı prosedürü kullanır.


4
Genel bir kural olarak, izleyicilerin motivasyonunu soğutmamak için özellikle puanınız düşükse, kendi sorunuzu cevaplamadan önce birkaç gün beklemek en iyi fikirdir.
Kara delik

Birkaç ipucu: Bazı karakterleri kaydedebilirsiniz r=range. lambdadaha kısadır def. math.sqrtile değiştirilebilir (…)**.5. p=copy.copy(P);p.pop(j);kısaltılabilir p=P[:j-1]+P[j:]. Ayalnızca bir kez kullanılır.
Wrzlprmft

0

C, 303

Gereksiz boşluk hariç. Ancak, burada yapılacak çok fazla golf var (geri gelip daha sonra yapmaya çalışacağım.) İlk kez bir fordöngü ilan ettim #define. Her zaman daha önce döngü sayısını en aza indirmenin yollarını buldum.

Test davası için OP ile aynı cevabı almak için değişiklik floatyapmak doublezorunda kaldım. Ondan önce, 300. turdu.

scanf girişinizi boşluk veya satırsonu ile ayırsanız da aynı şekilde çalışır, böylece istediğiniz kadar çok veya az satıra biçimlendirebilirsiniz.

#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);       
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.