Giải các tam giác với lượng giác


13

Thời gian để đào lên ghi chú lượng giác cũ của bạn từ trường trung học! Thách thức là giải quyết các cạnh và góc của các tam giác khác nhau. Và theo thông lệ trong môn đánh gôn, mã làm việc nhỏ nhất sẽ thắng.

Đây không phải là một vấn đề tầm thường; triển khai tham chiếu của tôi trong python hiện chỉ còn 838 837 ký tự, nhưng tôi chắc chắn bạn sẽ có thể giải pháp chơi golf nhỏ hơn nhiều.

Ngoài ra, nếu bạn bị mắc kẹt, phần này trên Wikipedia sẽ giúp bạn đi: Tam giác: Tính toán các cạnh và góc .

Đầu vào

Hình tam giác sau đây cho thấy tên của các cạnh và góc được sử dụng trong thử thách này. Lưu ý rằng các cạnh là chữ thường và các góc là chữ hoa.

Tam giác

Đầu vào được đưa ra dưới dạng sáu giá trị được phân tách bằng dấu cách, trên stdinhoặc dưới dạng đối số dòng lệnh (lựa chọn của bạn). Sáu giá trị tương ứng với các cạnh a, b, cvà các góc A, B, C. Các mặt chưa biết được đưa ra dưới dạng dấu hỏi ( ?). Cả hai góc đầu vào và đầu ra phải được tính bằng radian. Bạn có thể cho rằng các giá trị đầu vào là chính xác (bạn không phải xác nhận bất cứ điều gì). Bạn cũng có thể giả định rằng tam giác đầu vào không suy biến, và tất cả các cạnh và góc đều khác nhau.

Ví dụ đầu vào sau đây cho bạn biết bên đó a8, bên b12và góc A0.5radian:

8 12 ? 0.5 ? ?

Đầu ra

Đầu ra được đưa ra ở cùng định dạng với đầu vào - sáu số được phân tách bằng dấu cách stdout. Ngoại lệ duy nhất là khi không thể giải tam giác đầu vào - thì chuỗi "No solution"phải được ghi vào stdout. Nếu hai giải pháp là có thể, cả hai đều xuất ra với một dòng mới giữa chúng.

Sau đây là đầu ra cho đầu vào trên:

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

Đầu ra không bắt buộc phải có nhiều độ chính xác, nhưng ít nhất một vài số thập phân là bắt buộc.

Quy tắc

  • Đầu vào được đọc từ stdinhoặc đối số dòng lệnh
  • Đầu ra được ghi vào stdout
  • Nếu hai giải pháp có thể với đầu vào đã cho, đầu ra cả hai
  • Nếu có quá ít thông tin để có được một hoặc hai giải pháp rõ ràng, hãy coi đó là một "No solution"trường hợp
  • Không có mã tích hợp hoặc có sẵn nào có thể được sử dụng (tất nhiên bạn có thể sử dụng các hàm lượng giác, nhưng không phải là " solveTriangle" hoặc như vậy)
  • Mã ngắn nhất sẽ thắng

Các trường hợp thử nghiệm

Trong   3 4 5 ? ? ?

Ngoài 3.0 4.0 5.0 0.643501108793 0.927295218002 1.57079630572


Trong   ? 4 ? 0.64 0.92 1.57

Ngoài 3.00248479301 4.0 5.02764025486 0.64 0.92 1.57


Trong   ? ? 5 ? 0.92 ?

Ngoài No solution


Trong   ? ? 5 ? 0.92 1.57

Ngoài 3.03226857833 3.97800936148 5.0 0.65159265359 0.92 1.57


Trong   8 12 ? 0.5 ? ?

Ra (hai giải pháp)

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

Trong   8 12 ? ? .5 ?

Ngoài 8.0 12.0 18.3912222133 0.325325285223 0.5 2.31626736837

Chúc may mắn!


Chúng ta có thể cho rằng tam giác là không suy biến, với tất cả các độ dài và góc dương (đặc biệt là khác không)?
gian hàng

@boothby Vâng, bạn có thể. Tôi sẽ cập nhật OP.

1
Ngoài ra ... nếu bạn muốn chúng tôi in tất cả các giải pháp, bạn cần cung cấp ít nhất một mặt. Mặt khác, bạn biết, giải pháp vô hạn.
gian hàng

@boothby, có lẽ tôi đã không rõ ràng ở đây. Ý tôi là, nếu có hai giải pháp cho đầu vào, bạn phải xuất cả hai.

Câu trả lời:


7

Python, 441 ký tự

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'

Có trig điển hình của bạn để tính toán câu trả lời. Các giải pháp khả thi hiện tại được lưu trữ dưới dạng bộ dữ liệu trong V. Mọi giá trị không xác định được ghi là 0. Một biến thứ bảy R là giá trị a/sin(A)==b/sin(B)==c/sin(C).

Tôi sử dụng một mẹo trong đó các giá trị a / b / c được luân chuyển mỗi lần lặp để tránh nhiều logic thừa. Vòng lặp bên trong chỉ cần tính các giá trị của cạnh A hoặc góc.


Tôi sử dụng một mẹo tương tự để quay vòng các biến, nhưng bạn chắc chắn đánh bại giải pháp của tôi. +1, đã học được một vài thủ thuật mới từ việc này :)

Nhân tiện, có một vấn đề với mã của bạn: thử 8 12 ? ? .5 ?.

1
Bạn có thể có được nó tới 419 byte nếu bạn cạo các dấu ngắt dòng và thay thế hai vết lõm trong cùng bằng một và hai tab tương ứng.
Joey

Hah, điều này trông rất giống với giải pháp của tôi, mặc dù tôi đã không nhận thấy "tất cả các giải pháp" cho đến ngay sau khi bạn đăng bài này. Bạn có thể tiết kiệm hơn nữa nếu bạn thay thế if avới if not avà làm phẳng xuống điều kiện đến 1 mức.
gian hàng

4

Đồng bằng C, 565 555 530 ký tự

C không phải là ngôn ngữ tốt nhất cho Code Golf, tôi đoán vậy, vì vậy nó chỉ để giải trí.

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

Tổng hợp với cc -o trig trig.c -lm. Đọc đầu vào như dòng lệnh args.


Giải pháp này cũng thất bại cho 8 12 ? ? .5 ?- Tôi đã thêm nó dưới dạng một trường hợp thử nghiệm bổ sung trong OP.

1
Đã sửa! Độ dài giảm như một tác dụng phụ :)
Alexander Bakulin

1

Perl - 412 ký tự

Là một lớp lót đơn giản, dựa trên Giải pháp Python của Keith Randall:

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

Ở đây trong một hình thức dễ đọc hơ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" );
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.