用三角求解三角形


13

是时候从高中挖掘旧的三角学笔记了!挑战在于解决不同三角形的未知边和角度。按照编码高尔夫的惯例,最小的有效编码将获胜。

这不是一个小问题。我在python中的参考实现目前只有838 837个字符,但是我敢肯定,您将可以使用更小的解决方案。

此外,如果您受困,那么Wikipedia上的这一部分将使您着手进行:Triangle:计算边和角

输入值

下面的三角形显示了此挑战中使用的边和角度的名称。请注意,侧面是小写字母,而角度是大写字母。

三角形

输入以六个空格分隔的值形式给出,可以是在stdin命令行参数上,也可以是命令行参数(您的选择)。这六个值分别对应于侧面a, b, c和角度A, B, C。未知的一面以问号(?)给出。输入和输出角度都必须以弧度为单位。您可以假设输入值正确(您无需验证任何内容)。您还可以假设输入三角形不退化,并且所有边和角度都不为零。

以下示例输入告诉您side a8,side b为,12而angle A0.5弧度:

8 12 ? 0.5 ? ?

输出量

输出以与输入相同的格式给出-上用六个空格分隔的数字stdout。唯一的例外是,当无法求解输入三角形时,"No solution"必须将字符串写入stdout。如果可能有两种解决方案,则它们都将以换行符的形式输出。

以下是上述输入的输出:

8.0 12.0 16.0899264342 0.5 0.802561439714 1.83903121388
8.0 12.0 4.97205505116 0.5 2.33903121388 0.302561439714

输出不需要具有很高的精度,但是至少需要几个小数。

规则

  • 输入是stdin从命令行参数中读取的
  • 输出写入 stdout
  • 如果给定输入有两种解决方案,则输出两者
  • 如果信息太少而无法获得一两个清晰的解决方案,请考虑使用这种"No solution"情况
  • 不能使用内置或预先存在的代码(当然,您可以使用触发函数,但不能使用“ solveTriangle”等)
  • 最短代码胜出

测试用例

  3 4 5 ? ? ?

3.0 4.0 5.0 0.643501108793 0.927295218002 1.57079630572


  ? 4 ? 0.64 0.92 1.57

3.00248479301 4.0 5.02764025486 0.64 0.92 1.57


  ? ? 5 ? 0.92 ?

No solution


  ? ? 5 ? 0.92 1.57

3.03226857833 3.97800936148 5.0 0.65159265359 0.92 1.57


  8 12 ? 0.5 ? ?

(两种解决方案)

8.0 12.0 16.0899264342 0.5 0.802561439714 1.83903121388
8.0 12.0 4.97205505116 0.5 2.33903121388 0.302561439714

  8 12 ? ? .5 ?

8.0 12.0 18.3912222133 0.325325285223 0.5 2.31626736837

祝好运!


我们是否可以假设三角形不是退化的,并且所有长度和角度均为正(尤其是非零)?
2011年

@boothby是的,可以。我将更新OP。

1
另外...如果您希望我们打印所有解决方案,则需要至少提供一侧。否则,您将知道无限的解决方案。
2011年

@boothby,我在这里可能不太清楚。我的意思是,如果输入有两种解决方案,则必须同时输出两者。

Answers:


7

Python,441个字符

from math import*
V=[map(float,raw_input().replace('?','0').split())+[0]]
for i in' '*9:
 W=[]
 for a,b,c,A,B,C,R in V:
  if B and C:A=A or pi-B-C
  if a:
   if A:R=R or a/sin(A)
   else:
    if b and c:A=acos((b*b+c*c-a*a)/2/b/c)
    elif R:N=asin(a/R);W+=[(b,c,a,B,C,N,R)];A=pi-N
  else:a=R*sin(A)
  W+=[(b,c,a,B,C,A,R)]
 V=W
V=[T for T in V if all(t>0 for t in T)]
if V:
 for T in V:print' '.join(map(str,T[:-1]))
else:print'No solution'

您是否进行典型的触发来计算答案。当前可能的解以元组形式存储在V中。任何未知值都记录为0。第七个变量R是该值a/sin(A)==b/sin(B)==c/sin(C)

我使用一个技巧,在每次迭代中循环使用a / b / c值,以避免大量冗余逻辑。内循环仅需要计算A边或角度的值。


我使用了类似的循环变量的技巧,但是您肯定击败了我的解决方案。+1,从中学到了一些新的技巧:)

顺便说一句,您的代码有问题:try 8 12 ? ? .5 ?

1
如果刮掉尾随换行符并将两个最里面的缩进分别替换为一个和两个制表符,则可以将其变为419字节。
乔伊(Joey)

呵呵,这看起来也与我的解决方案非常相似,尽管直到您发布此文档后我才注意到“所有解决方案”。如果将条件替换if aif not a并将其展平为1级,则可以节省更多。
展位,

4

平原C,565 555 530个字符

我想C语言不是Code Golf的最佳语言,所以只是为了好玩而已。

float t[6],u[6],P=3.1415;x,w,j,k,D,E;
#define y(V) for(V=0;V<6;++V)
#define Y if(p[j]&&p[k]&&
#define A(o,s,a,b,c,A,B,C) z(float*p){y(D)y(E)if(j=D%3,k=E%3,j-k){Y c)w=C=acos((a*a+b*b-c*c)/2/a/b);if(A&&B)w=C=P-A-B;Y C)w=c=sqrt(a*a+b*b-2*a*b*cos(C));if(A&&B&&a)w=b=s(B)*a/s(A);Y A&&!B&&!C)w=B=(x=A<P/2&&a<b&&p==u,1-2*x)*(asin(b*s(A)/a)-x*P);}y(j)k=w&&(p==t||x>0)&&o("%f ",a);o("\n");}main(int l,char*q[]){y(j)sscanf(*++q,"%f",t+j),u[j]=t[j];z(t);z(u);j=w||o("No solution\n");}
A(printf,sin,p[j],p[k],p[3-j-k],p[j+3],p[k+3],p[6-j-k])

与编译cc -o trig trig.c -lm。将输入读取为命令行参数。


该解决方案也因以下原因而失败8 12 ? ? .5 ?-我在OP中将其添加为其他测试用例。

1
固定!减少长度作为副作用:)
Alexander Bakulin

1

Perl-412个字符

作为Perl的单行代码,基于Keith Randall的Python解决方案:

use Math::Trig;@V=((map{tr/?/0/;$_}@ARGV),0);map{my@W;while(($a,$b,$c,$A,$B,$C,$R)=splice@V,0,7){$A||=pi-$B-$C if($B*$C);if($a){if($A){$R||=$a/sin$A;}else{if($b*$c){$A=acos(($b*$b+$c*$c-$a*$a)/2/$b/$c);}elsif($R){$N=asin($a/$R);push@W,$b,$c,$a,$B,$C,$N,$R;$A=pi-$N;}}}else{$a=$R*sin$A;}push@W,$b,$c,$a,$B,$C,$A,$R if($a*$b*$c>=0);}@V=@W;}(1..9);print($V[0]?join' ',map{(((6-$i++)%7)?$_:"\n")}@V:"No solution\n");

这里以更易读的形式:

use Math::Trig;
@V = ( ( map { tr/?/0/; $_ } @ARGV ), 0 );
map {
    my @W;
    while ( ( $a, $b, $c, $A, $B, $C, $R ) = splice @V, 0, 7 ) {
        $A ||= pi- $B - $C
             if ( $B * $C );
        if ($a) {
            if ($A) { $R ||= $a / sin $A; }
            else {
                if ( $b * $c ) {
                    $A = acos(
                        ( $b * $b + $c * $c - $a * $a ) / 2 / $b / $c );
                } elsif ($R) {
                    $N = asin( $a / $R );
                    push @W, $b, $c, $a, $B, $C, $N, $R;
                    $A = pi- $N;
                }
            }
        } else {
            $a = $R * sin $A;
        }
        push @W, $b, $c, $a, $B, $C, $A, $R
            if ( $a * $b * $c >= 0 );
    }
    @V = @W;
} ( 1 .. 9 );

print( $V[0]
         ? join ' ', map { ( ( ( 6 - $i++ ) % 7 ) ? $_ : "\n" ) } @V
         : "No solution\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.