四面体表面积


16

挑战

这个挑战非常简单。给定四个3维点,计算它们形成的四面体的表面积。这是,因此最短的代码获胜。存在标准漏洞,并增加了规定,在给出四点的情况下,禁止执行此任务的任何内置功能。

您可以假设所有四个点都是不同的,并且将通过STDIN给出,每行1个点。每个点将由三个16位无符号整数组成。如果使每个点更简单,则可以修改每个点的确切格式,例如三个空格分隔的整数。但是,必须将每个点放在单独的线上。输出应通过STDOUT进行,至少要保留两位小数。

对于不知道的人,四面体是一个3维立体,由4个三角形的面组成。

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

# output
2932496435.95

如果您发现我的数学错误,请留下笔记。


@BetaDecay不,想法是它们将通过STDIN在四个单独的行上输入。我将编辑问题以澄清这一点。
stokastic 2014年

输入可以是[[list],[of],[lists]]吗?
光气2014年

@phosgene我想阅读输入内容是挑战的一部分,所以我要说不。在未来的挑战中,我将尽量宽容输入规范。
stokastic,2014年

这是规则的还是不规则的四面体?
詹姆斯·威廉姆斯

@JamesWilliams发布的示例不规则。但是,您的程序应处理任何输入,包括常规四面体。
2014年

Answers:


5

Python,198 178 161个字符

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

输入格式如问题中所给。

它计算与每个面相邻的边的长度,然后使用Heron公式


4

Matlab /八度103

我假设值将存储在变量中c。这利用了一个事实,即三角形的面积是其两个边矢量的叉积的一半长度。

%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

每个点必须在单独的行上输入作为标准输入。
DavidC 2014年

我最初以为Matlab中没有标准输入之类的东西,但是我发现了一个可用于通过命令窗口进行模拟的函数,因此现在您可以像使用其他语言一样传递输入。
瑕疵的

有趣。这与Mathematica使用的命令相同,Input[]
DavidC 2014年

您为什么认为这很有趣?在我看来,“输入”似乎是一个执行此功能的函数的通用名称。
瑕疵的2014年

直到昨天,我真的不知道什么是“标准输入”的意思,我认为数学没有“标准”输入,即使我已经经常使用Input[]InputString[]Import[],和ImportString[]
DavidC 2014年

4

APL,59

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

通过计算叉积工作

解释
第一行定义了一个函数,该函数接受两个参数(隐式命名为),隐式地期望它们是长度为3的数字数组,将其视为3d向量,并计算其叉积的平方大小。

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

第二行完成其余的工作。

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

如果不确定是象形文字还是dll文件损坏,则可能是APL。您能否进一步解释其中一些符号的作用?不是我想学习它,而是让我对如何使用那些看似晦涩的符号= P
感兴趣

@flawr我通常这样做是因为在APL中打高尔夫球主要归结于算法设计,并且很可能会导致不常见的问题解决方法。但是我感觉像“计算叉积”在这里传达了关于算法的足够信息。如果您需要全面的说明,我将在今天晚些时候进行。
TwiNight

计算叉积的想法很明确,但是代码本身让我毫无头绪,所以我只想说几句关于代码的哪些部分可以做的很好,但是我当然不想敦促您写一个详细的解释!
瑕疵的

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

它使用:

  • 勾股定理(3D)计算出每行的长度
  • 苍鹭公式,计算出每个三角形的面积

1
我使用相同的方法测试解决方案。我必须尝试打高尔夫球,然后再发布。
2014年

1
for i in">"*4很聪明
2014年

您可以将长度硬编码为3,而不是在range函数中使用len(i)。
2014年

1
您可以另存几个字符做平方根x**0.5,而不是math.sqrt(x)
Snorfalorpagus,2014年

1
您可以def a(t,u,v)像这样放置一行来节省两个字节:def a(t,u,v):w=(t+u+v)/2;return(w*(w-t)*(w-u)*(w-v))**0.5
Beta Decay

2

数学168 154

这将找到四面体的边缘长度,并使用Heron公式确定面的面积。

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

还有一种更直接的路线,它只需要60个字符,但是它违反了规则,因为它使用内置函数来计算每个面孔的面积Area

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

1

贤者– 103

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

输入阅读部分改编自Keith Randall的答案


0

Python-260

我不确定发布自己的问题答案的礼节是什么,但是她是我的解决方案,我用来证明我的例子是打高尔夫球:

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相同的过程。


4
根据经验,最好是等几天再回答自己的问题,尤其是在您的分数较低的情况下,以免降低观众的动力。
Blackhole,2014年

一些提示:您可以通过保存一些字符r=rangelambda比短defmath.sqrt可以替换为(…)**.5p=copy.copy(P);p.pop(j);可以缩短为p=P[:j-1]+P[j:]A仅使用一次。
Wrzlprmft

0

C,303

排除不必要的空格。但是,这里仍然有很多高尔夫运动(我会尝试稍后再做。)这是我第一次在中声明for循环#define。我一直都找到最小化循环次数的方法。

我不得不改变float,以double得到同样的答案,作为OP测试用例。在此之前,这是第300回合。

scanf 无论您使用空格或换行符分隔输入,其工作方式都相同,因此您可以将其格式化为任意多行。

#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);       
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.