三角法で三角形を解く


13

高校からの古い三角法のメモを掘り起こす時間です!課題は、異なる三角形の未知の側面と角度を解決することです。そして、コードゴルフの慣習であるように、最小の作業コードが勝ちます。

これは些細な問題ではありません。Pythonでの私の参照実装は現在838 837文字までですが、ゴルフソリューションをはるかに小さくできると確信しています。

さらに、行き詰まっている場合は、ウィキペディアのこのセクションで説明します:三角形:側面と角度の計算

入力

次の三角形は、このチャレンジで使用される側面と角度の名前を示しています。側面は小文字で、角度は大文字であることに注意してください。

三角形

入力は、スペース上で区切られた6つの値stdinとして、コマンドライン引数(または選択)として与えられます。6つの値は、側面a, b, cと角度に対応しますA, B, C。不明な側面は疑問符(?)で示されます。入力角度と出力角度はどちらもラジアン単位でなければなりません。入力値が正しいと仮定できます(何も検証する必要はありません)。また、入力三角形が非縮退であり、すべての辺と角度が非ゼロであると仮定することもできます。

次の入力例a8、サイドbが、サイドが12、角度A0.5ラジアンであることを示しています。

8 12 ? 0.5 ? ?

出力

出力は、入力と同じ形式で与えられます-スペースで区切られた6つの数字stdout。唯一の例外は、入力三角形を解決でき"No solution"ない場合ですstdout。文字列を書き込む必要があります。2つの解決策が可能な場合、それらは両方とも改行で出力されます。

上記の入力の出力は次のとおりです。

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

出力の精度はそれほど高くなくてもかまいませんが、少なくとも小数点以下2桁が必要です。

ルール

  • 入力はstdinコマンドライン引数から読み取られます
  • 出力はに書き込まれます stdout
  • 指定された入力で2つのソリューションが可能な場合、両方を出力します
  • 情報が少なすぎて1つまたは2つの明確な解決策が得られない場合は、それを"No solution"事例と見なします
  • 組み込みまたは既存のコードは使用できません(もちろん、trig関数を使用できますが、「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 ? ?

アウト(2つのソリューション)

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

幸運を!


三角形が非縮退で、すべての長さと角度が正(特に、非ゼロ)であると仮定できますか?
ブースバイ

@boothbyはい、できます。OPを更新します。

1
また...すべてのソリューションを印刷する場合は、少なくとも一方を提供する必要があります。それ以外の場合は、無限解です。
ブースバイ

@boothby、私はおそらくここではあまりにも不明瞭でした。つまり、入力に2つの解決策がある場合、両方を出力する必要があります。

回答:


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として記録されます。7番目の変数Rは値ですa/sin(A)==b/sin(B)==c/sin(C)です。

繰り返しのたびにa / b / c値を循環させるトリックを使用して、多くの冗長なロジックを回避します。内側のループは、A側または角度の値を計算するだけで済みます。


変数を循環させる同様のトリックを使用しますが、あなたは確かに私の解決策を打ち負かします。+1、

ところで、コードに問題があります:try 8 12 ? ? .5 ?

1
末尾の改行を削除して、最も内側の2つのインデントをそれぞれ1つと2つのタブに置き換えると、419バイトになります。
ジョーイ

ああ、これも私のソリューションと非常によく似ていますが、これを投稿した直後まで「すべてのソリューション」に気付いていませんでした。条件を1レベルに置き換えif aif not aフラット化すると、さらに節約できます。
ブースバイ

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
修繕!副作用として長さが短くなりました:)
アレクサンダーバクリン

1

Perl-412文字

Keil RandallのPython Solutionに基づくperlのワンライナーとして:

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" );
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.