Trigonometri ile üçgenleri çözme


13

Liseden eski trigonometri notlarını kazma zamanı! Zorluk, farklı üçgenlerin bilinmeyen taraflarını ve açılarını çözmek. Ve kod golf geleneksel olduğu gibi, en küçük çalışma kodu kazanır.

Bu önemsiz bir sorun değil; python'daki referans uygulamam şu anda 838 837 karaktere kadar, ama eminim golf çözümleri çok daha küçük olacak.

Ayrıca, takılırsanız, Wikipedia'daki bu bölüm sizi yönlendirecektir: Üçgen: Yanları ve açıları hesaplamak .

Giriş

Aşağıdaki üçgen, bu meydan okumada kullanılan kenarların ve açıların adlarını göstermektedir. Kenarların küçük ve açıların büyük harf olduğunu unutmayın.

Üçgen

Girdi, boşlukta stdinveya komut satırı bağımsız değişkenleri (seçiminiz) olarak altı boşlukla ayrılmış değer olarak verilir . Altı değer kenarlara a, b, cve açılara karşılık gelir A, B, C. Bilinmeyen taraflar soru işaretleri ( ?) olarak verilir . Hem giriş hem de çıkış açıları radyan cinsinden olmalıdır. Giriş değerlerinin doğru olduğunu varsayabilirsiniz (hiçbir şeyi doğrulamanız gerekmez). Ayrıca giriş üçgeninin dejenere olmadığını ve tüm kenarların ve açıların sıfır olmadığını varsayabilirsiniz.

Aşağıdaki örnek, giriş tarafı olduğunu söyler aolduğunu 8, yan bolduğunu 12ve açı Aolduğunu 0.5radyan:

8 12 ? 0.5 ? ?

Çıktı

Çıktı, girdi ile aynı biçimde verilir - altı boşlukla ayrılmış sayı açık stdout. Tek istisna, giriş üçgeni çözülemediğinde - dize "No solution"yazılmalıdır stdout. İki çözüm mümkünse, ikisi de aralarında bir satırsonu ile çıkarılır.

Yukarıdaki giriş için çıkış aşağıdadır:

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

Çıktıda çok fazla hassasiyet olması gerekmez, ancak en az birkaç ondalık basamak gerekir.

kurallar

  • Girdi okunuyor stdinveya komut satırı bağımsız değişkenleri
  • Çıktı stdout
  • Verilen giriş ile iki çözüm mümkünse, her iki çıkışı da
  • Bir veya iki net çözüm elde etmek için çok az bilgi varsa, bunu bir "No solution"vaka olarak düşünün
  • Yerleşik veya önceden var olan bir kod kullanılamaz (elbette trig işlevlerini kullanabilirsiniz, ancak " solveTriangle" veya benzeri değil)
  • En kısa kod kazanır

Test senaryoları

İçinde   3 4 5 ? ? ?

Dışarı 3.0 4.0 5.0 0.643501108793 0.927295218002 1.57079630572


İçinde   ? 4 ? 0.64 0.92 1.57

Dışarı 3.00248479301 4.0 5.02764025486 0.64 0.92 1.57


İçinde   ? ? 5 ? 0.92 ?

Dışarı No solution


İçinde   ? ? 5 ? 0.92 1.57

Dışarı 3.03226857833 3.97800936148 5.0 0.65159265359 0.92 1.57


İçinde   8 12 ? 0.5 ? ?

Out (iki çözüm)

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

İçinde   8 12 ? ? .5 ?

Dışarı 8.0 12.0 18.3912222133 0.325325285223 0.5 2.31626736837

İyi şanslar!


Üçgenin dejenere olmadığını ve tüm uzunlukları ve açıları pozitif (özellikle sıfır olmayan) olduğunu varsayabilir miyiz?
boothby

@boothby Evet, yapabilirsiniz. OP'yi güncelleyeceğim.

1
Ayrıca ... tüm çözümleri yazdırmamızı istiyorsanız, en az bir taraf sağlamanız gerekir. Aksi halde, bilirsiniz, sonsuz çözümler.
boothby

@boothby, muhtemelen burada çok net değilim. Demek istediğim, eğer girdiye iki çözüm varsa, her ikisini de çıktı almalısınız.

Yanıtlar:


7

Python, 441 karakter

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'

Cevabınızı hesaplamak için tipik trigonuzu yapar. Mevcut olası çözümler V'de tuples olarak depolanır. Bilinmeyen değerler 0 olarak kaydedilir. Yedinci değişken R değerdir a/sin(A)==b/sin(B)==c/sin(C).

Bir sürü gereksiz mantık önlemek için a / b / c değerleri her yineleme döngü bir hile kullanın. İç halkanın sadece A tarafının veya açısının değerlerini hesaplaması gerekir.


Değişkenleri döngülemek için benzer bir numara kullanıyorum, ancak çözümümü yendiğinizden emin olabilirsiniz. +1, bundan birkaç yeni püf noktası öğrendim :)

Bu arada, kodunuzla ilgili bir sorun var: deneyin 8 12 ? ? .5 ?.

1
Sondaki satır sonunu tıraş ederseniz ve en içteki iki girintiyi sırasıyla bir ve iki sekmeyle değiştirirseniz, 419 bayta alabilirsiniz.
Joey

Hah, bu benim çözümüme çok benziyor, ancak bunu gönderdikten hemen sonraya kadar "tüm çözümleri" fark etmedim. Değiştirmek eğer daha fazla tasarruf edebilir if aile if not ave 1 düzeyine conditionals aşağı dümdüz.
boothby

4

Düz C, 565 555 530 karakter

C, Code Golf için en iyi dil değil sanırım, bu yüzden sadece eğlence için.

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

İle derlendi cc -o trig trig.c -lm. Girişi komut satırı argümanları olarak okur.


Bu çözüm de başarısız oluyor 8 12 ? ? .5 ?- OP'de ek bir test örneği olarak ekledim.

1
Sabit! Bir yan etki olarak uzunluk azaldı :)
Alexander Bakulin

1

Perl - 412 karakter

Keith Randall'ın Python Çözümüne dayanan perl tek katlı olarak:

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

Burada daha okunabilir bir biçimde:

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" );
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.