삼각법으로 삼각형 풀기


13

고등학교에서 오래된 삼각법 메모를 파헤칠 시간입니다! 문제는 다른 삼각형의 알려지지 않은면과 각도를 해결하는 것입니다. 코드 골프에서 관례 적으로 가장 작은 작업 코드가 승리합니다.

이것은 사소한 문제가 아닙니다. 파이썬에서 내 참조 구현은 현재 838 837 자로 줄어들지 만 솔루션을 훨씬 더 작게 골프화 할 수 있다고 확신합니다.

또한 붙어있는 경우 Wikipedia 의이 섹션으로 이동하십시오 : 삼각형 : 측면 및 각도 계산 .

입력

다음 삼각형은이 챌린지에 사용 된 측면과 각도의 이름을 보여줍니다. 측면은 소문자이고 각도는 대문자입니다.

삼각형

입력은 6 개의 공백으로 구분 된 값으로 제공 stdin되거나 명령 줄 인수 (선택 사항)로 제공됩니다. 6 개의 값은 측면 a, b, c과 각도에 해당합니다 A, B, C. 알 수없는면은 물음표 ( ?)로 표시 됩니다. 입력 및 출력 각도는 모두 라디안이어야합니다. 입력 값이 정확하다고 가정 할 수 있습니다 (아무 것도 검증하지 않아도 됨). 입력 삼각형이 축퇴하지 않고 모든면과 각도가 0이 아니라고 가정 할 수도 있습니다.

다음 입력 예는 side ais 8, side bis 12및 angle Ais 0.5radians를 알려줍니다 .

8 12 ? 0.5 ? ?

산출

출력은 공백으로 구분 된 6 개의 숫자 입력과 같은 형식으로 제공됩니다 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"등의 함수는 사용할 수 없지만 trig 함수는 사용할 수 있습니다 )
  • 최단 코드 승리

테스트 사례

  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

행운을 빕니다!


삼각형이 변성되지 않고 모든 길이와 각도가 양수 (특히 0이 아님)라고 가정 할 수 있습니까?
boothby

@boothby 예, 가능합니다. OP를 업데이트하겠습니다.

1
또한 ... 모든 솔루션을 인쇄하려면 적어도 한면을 제공해야합니다. 그렇지 않으면 무한한 해결책을 알 것입니다.
boothby

@ 부스비, 아마 여기가 너무 불분명했을 것입니다. 내가 의미하는 것은 입력에 대한 두 가지 솔루션이 있으면 두 가지를 모두 출력해야한다는 것입니다.

답변:


7

파이썬, 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

Hah, 이것은 내 솔루션과 매우 비슷해 보이지만 게시 한 직후까지 "모든 솔루션"을 보지 못했습니다. 당신이 대체 할 경우 더욱 절약 할 수 if aif not a1 개 수준으로 조건문을 평평.
boothby

4

일반 C, 565 개 555 530 문자

C는 코드 골프에 가장 적합한 언어는 아닙니다.

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

펄-412 자

Keith Randall의 Python 솔루션을 기반으로 한 perl one-liner로서 :

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.