การแก้สามเหลี่ยมด้วยตรีโกณมิติ


13

ถึงเวลาขุดโน้ตตรีโกณมิติเก่าของคุณจากโรงเรียนมัธยม! ความท้าทายคือการแก้ด้านที่ไม่รู้จักและมุมสามเหลี่ยมที่แตกต่างกัน และตามธรรมเนียมในการเล่นกอล์ฟรหัสการทำงานที่เล็กที่สุดก็ชนะ

นี่ไม่ใช่ปัญหาเล็ก ๆ น้อย ๆ การใช้งานอ้างอิงของฉันใน python ในปัจจุบันมีความยาวไม่เกิน838 837 ตัวอักษร แต่ฉันแน่ใจว่าคุณจะสามารถแก้ไขปัญหากอล์ฟให้เล็กลงได้

นอกจากนี้หากคุณติดอยู่ในส่วนนี้ในวิกิพีเดียควรจะได้รับคุณไป: สามเหลี่ยม: คอมพิวเตอร์ด้านข้างและมุม

อินพุต

สามเหลี่ยมต่อไปนี้แสดงชื่อของด้านและมุมที่ใช้ในการท้าทายนี้ โปรดทราบว่าด้านข้างเป็นตัวพิมพ์เล็กและมุมเป็นตัวพิมพ์ใหญ่

สามเหลี่ยม

อินพุตได้รับเป็นหกค่าคั่นด้วยช่องว่างไม่ว่าจะstdinเป็นอาร์กิวเมนต์บรรทัดคำสั่ง (หรือตัวเลือกของคุณ) ค่าหกตรงกับด้านข้างและมุมa, b, c A, B, Cด้านที่ไม่รู้จักจะได้รับเป็นเครื่องหมายคำถาม ( ?) มุมอินพุทและเอาท์พุทจะต้องเป็นเรเดียน คุณอาจสมมติว่าค่าอินพุตถูกต้อง (คุณไม่ต้องตรวจสอบอะไรเลย) คุณอาจจะสมมติว่าสามเหลี่ยมป้อนเข้าไม่ได้ลดลงและทุกด้านและมุมเป็นศูนย์

ตัวอย่างอินพุตต่อไปนี้บอกคุณว่าด้านaนั้นคือ8ด้านbคือ12และมุมAคือ0.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

โชคดี!


เราสามารถสมมติว่าสามเหลี่ยมไม่เสื่อมสลายโดยมีความยาวและมุมเป็นบวกทั้งหมด (โดยเฉพาะอย่างยิ่งไม่ใช่ศูนย์) ได้หรือไม่?
Boothby

@boothby ใช่คุณสามารถ ฉันจะอัพเดท OP

1
นอกจากนี้ ... หากคุณต้องการให้เราพิมพ์โซลูชั่นทั้งหมดคุณจะต้องให้อย่างน้อยหนึ่งด้าน มิฉะนั้นคุณจะรู้วิธีแก้ปัญหาที่ไม่มีที่สิ้นสุด
บูธโดย

@boothby ฉันอาจไม่ชัดเจนเกินไปที่นี่ สิ่งที่ฉันหมายถึงคือถ้ามีสองวิธีในการป้อนข้อมูลคุณต้องส่งออกทั้งสอง

คำตอบ:


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'

ตรีโกณมิติทั่วไปของคุณคำนวณคำตอบหรือไม่ การแก้ปัญหาที่เป็นไปได้ในปัจจุบันจะถูกเก็บเป็น tuples ในโวลต์ค่าใด ๆ ที่ไม่รู้จักจะถูกบันทึกเป็น 0. ตัวแปรที่เจ็ด R a/sin(A)==b/sin(B)==c/sin(C)คือค่า

ฉันใช้เคล็ดลับที่ค่า a / b / c ถูกกรณืซ้ำในแต่ละรอบเพื่อหลีกเลี่ยงตรรกะซ้ำซ้อนมากมาย ลูปด้านในต้องการคำนวณค่าของด้านหรือมุม A เท่านั้น


ฉันใช้กลอุบายที่คล้ายกันในการปั่นตัวแปร แต่คุณต้องเอาชนะวิธีแก้ปัญหาของฉัน +1 เรียนรู้เคล็ดลับใหม่ ๆ จากนี้ :)

โดยวิธีการที่มีปัญหาเกี่ยวกับรหัสของคุณ: 8 12 ? ? .5 ?ลอง

1
คุณสามารถรับได้ถึง 419 ไบต์หากคุณโกนการขึ้นบรรทัดใหม่และแทนที่การเยื้องด้านในสุดทั้งสองด้วยหนึ่งและสองแท็บตามลำดับ
Joey

ฮ่าฮ่ามันดูคล้ายกับโซลูชันของฉันเหมือนกันแม้ว่าฉันจะไม่ได้สังเกต "การแก้ปัญหาทั้งหมด" จนกระทั่งหลังจากคุณโพสต์ข้อความนี้ คุณสามารถประหยัดได้มากขึ้นหากคุณแทนที่if aด้วยif 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รวบรวมกับ อ่านอินพุตเป็นบรรทัดคำสั่ง args


วิธีการแก้ปัญหานี้ยังล้มเหลว8 12 ? ? .5 ?- ฉันเพิ่มมันเป็นกรณีทดสอบเพิ่มเติมใน OP

1
แก้ไขแล้ว! ความยาวลดลงเป็นผลข้างเคียง :)
Alexander Bakulin

1

Perl - 412 ตัวอักษร

ในฐานะที่เป็น perl one-liner ซึ่งใช้โซลูชั่น Python ของ 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");

ที่นี่ในรูปแบบที่อ่านได้มากขึ้น:

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.