Drei Zeiger! Aber welche?

24

Aus http://en.wikipedia.org/wiki/Triangle : Bildbeschreibung hier eingeben


Schreiben Sie ein Programm, das drei 2-D-Koordinatentupel (kartesisch) verwendet und klassifiziert, welche Form diese drei Punkte beschreiben.

In fast allen Fällen beschreiben diese Punkte ein Dreieck unterschiedlicher Art. In einigen entarteten Fällen beschreiben die Punkte entweder einen singulären Punkt oder eine gerade Linie. Das Programm bestimmt, welche der folgenden Tags für die beschriebene Form gelten:

  • Punkt (3 Punkte sind Co-Incident)
  • Linie (3 Punkte liegen auf einer geraden Linie - nicht mehr als 2 Punkte dürfen gleichzeitig auftreten)
  • Gleichseitig (3 Seiten gleich, 3 Winkel gleich)
  • Gleichschenklig (2 Seiten gleich, 2 Winkel gleich)
  • Scalene (0 Seiten gleich, 0 Winkel gleich)
  • Rechts (1 Winkel genau π / 2 (oder 90 °))
  • Schräg (0 Winkel genau π / 2 (oder 90 °))
  • Stumpf (1 Winkel> π / 2 (oder 90 °))
  • Akut (3 Winkel <π / 2 (oder 90 °))

Beachten Sie, dass für einige beschriebene Formen mehr als eines der oben genannten Tags gilt. Beispielsweise ist jedes rechtwinklige Element entweder gleichschenklig oder schuppenförmig.

Eingang

  • Das Programm kann die 3 Eingabekoordinaten von STDIN, der Befehlszeile, den Umgebungsvariablen oder einer für die Sprache Ihrer Wahl geeigneten Methode lesen.
  • Die Eingabekoordinaten können formatiert werden, sind jedoch für die Sprache Ihrer Wahl geeignet. Es kann davon ausgegangen werden, dass alle Eingabenummern in Bezug auf die Datentypen, die Sie letztendlich verwenden, wohlgeformt sind.
  • Über die Reihenfolge der Eingabekoordinaten kann nichts angenommen werden.

Ausgabe

  • Das Programm gibt STDOUT, ein Dialogfeld oder eine andere für die Sprache Ihrer Wahl geeignete Anzeigemethode aus.
  • In der Ausgabe werden alle Tags angezeigt, die für die durch die Eingabekoordinaten beschriebene Form gelten.
  • Tags können in beliebiger Reihenfolge ausgegeben werden.

Andere Regeln

  • Die trigonometrischen Bibliotheken / APIs Ihrer Sprache sind zulässig, aber alle APIs, die speziell Dreieckstypen berechnen, sind gesperrt.
  • Wenn Sie die Gleichheit von Winkeln oder Längen von Seiten bestimmen, werden Sie wahrscheinlich Gleitkommawerte vergleichen. Zwei solche Werte sind als "gleich" zu betrachten, wenn einer innerhalb von 1% des anderen liegt.
  • Standard "Schlupflöcher", die nicht mehr lustig sind
  • Das ist , also gewinnt die kürzeste Antwort in Bytes.

Beispiele

Input                   Output
(1,2) (1,2) (1,2)       Point
(1,2) (3,4) (5,6)       Line
(0,0) (1,1) (2,0)       Isosceles Right
(0,0) (2,1) (10,1)      Scalene Oblique Obtuse
Digitales Trauma
quelle
4
Ich wollte dieses " Triangle Tag " betiteln, aber es hat das Minimum von 15 Zeichen nicht erreicht.
Digital Trauma
Was ist, wenn zwei Punkte identisch sind?
Ypnypn
@Ypnypn In diesem Fall handelt es sich um eine Linie.
Digitales Trauma
Dreieck-Tag
Derek 朕 朕 功夫
2
Es gibt ein Problem mit der Definition "Akut"? Es ist unmöglich, dass alle Winkel größer als PI / 2 sind.
Arnaud

Antworten:

10

C (451 Bytes)

Verwendet nur quadratische Längen und Steigungen.

p[2],q[2],r[2];z(c){char*y[]={"Line","Point","Isosceles ","Equilateral ","Scalene ","Right","Oblique ","Acute","Obtuse"};printf(y[c]);}d(int*a,int*b){int c=*a++-*b++,e=*a-*b;return c*c+e*e;}main(){scanf("%d%d%d%d%d%d",p,p+1,q,q+1,r,r+1);int a=d(p,q),b=d(q,r),c=d(r,p),e=!a+!b+!c,f=(a==b)+(b==c)+(c==a),g=a>b&&b>c?a:b>c?b:c,h=g^a?g^b?a+b:c+a:b+c;e?z(e/2):(1[q]-1[p])*(*r-*q)^(1[r]-1[q])*(*q-*p)?f?z(2+f/2),f-1&&z(2):z(4),h^g?z(6),z(7+(h<g)):z(5):z(0);}

Ungolfed (und ternärer Operator ersetzt durch if / else):

int p[2],q[2],r[2];

void print(c){
    char *y[]={"Line","Point","Isosceles ","Equilateral ","Scalene ","Right","Oblique ","Acute","Obtuse"};
    printf(y[c]);
}
squared_distance(int *a,int *b){
    int c = *a++ - *b++, e = *a - *b;
    return c*c+e*e;
}
main(){
    scanf("%d%d%d%d%d%d",p,p+1,q,q+1,r,r+1); // read in coordinates
    int a = squared_distance(p,q),b = squared_distance(q,r),c = squared_distance(r,p),
    e=!a+!b+!c, // number of sides of length 0
    f=(a==b)+(b==c)+(c==a), // number of equal-length pairs
    g = a > b && b > c ? a : (b > c ? b : c), // longest side
    h = g != a ? g != b ? a + b : c + a : b + c; // sum of squares of length of other two sides
    if(e)
        print(e/2); // 1 side of len 0: line, 3 sides: point
    // comparing slopes PQ and QR
    else if((q[1]-p[1])*(*r-*q) != (r[1]-q[1])*(*q-*p)){ // not line
        if(f){
            print(2+f/2); // 1 pair of equal length sides: isosceles, 3: equilateral
            if(f-1) print(2); // equilateral therefore also isosceles
        }else print(4); // 0: scalene
        if(h!=g){ // a^2+b^2!=c^2: not right
            print(6); // oblique
            print(7+(h<g)); // a^2+b^2<c^2:obtuse, acute otherwise 
        }else print(5); // right
    }else
        print(0); // line
}

Eingabe (über stdin) Format: xyxyxy

Ex. 0 0 1 1 2 0 für Isosceles Right

es1024
quelle
@digitaltrauma ./triangle <<< "1 2 1 2 1 2"sollte mit den Anführungszeichen verwendet werden.
Es1024
Ja, natürlich, tut mir leid. Gute Antwort. Mir hat besonders gut gefallen, dass Sie Floats vermeiden konnten und sich daher keine Gedanken über die Gleichheitsregel innerhalb von 1% machen müssen. +1
Digitales Trauma
3

C 333

z,c,r,b,s,i,t[14],g[14];
main(){ 
  for(;i<14;i++){
    g[i]=r=t[(i+2)%6]-t[i%6];r*=r;t[i|1]+=r;
    i<6&&scanf("%d",t+i);
    i>7&&(b<t[i]&&(b=t[i]),s+=t[i],z+=!t[i],c+=t[i]==t[i-2]);  
  }

  if(g[6]*g[9]==g[8]*g[7])puts(z==6?"point":"line");else
    printf(b*2==s?"right ":"oblique %s",b*2>s?"obtuse ":"acute "),puts(c>3?c>5?"equilateral":"isosceles":"scalene");
}

Ich ließ das Leerzeichen für den Moment. Dies funktioniert, könnte aber wahrscheinlich etwas Aufräumen und Golfen vertragen. Ähnliche Mathematik zu@es1024 die Antwort 's, verwendet jedoch eine Schleife und Arrays. Eingabeformatx y x y x y

Variablen

t[]Speichert sowohl die Eingabe als auch die Quadrate der Längen. Am Ende des Programms sieht es wie in der folgenden Tabelle aus (eine Erhöhung der Anzahl der Iterationen der Schleife würde zu einer unbestimmten Wiederholung der quadrierten Längen führen.) Am Anfang der Schleife sind Quadrate der Längen (Müll, da nicht alle Daten verfügbar) ) werden unnötigerweise in den Zellen 1,3 und 5 gespeichert, aber umgehend überschrieben. scanf.Nützliche Daten werden nach z,b,cahd geschrieben, swenn i= 9,11,13 ( t[i]und t[i-2]zugegriffen wird.)

01 23 45 67 89 1011 1213
aa bb cc  a  b    c    a
xy xy xy  L  L    L    L

g[]wurde spät hinzugefügt, um die für die Steigungsberechnung erforderlichen dx- und dy-Werte zu halten. Die einzigen verwendeten Zellen sind 6 bis 9 (0 bis 5 sind unzuverlässig, da nicht alle Daten zum Zeitpunkt des Schreibens verfügbar sind.) Ifg[6]/g[7]==g[8]/g[9] die Steigungen von 2 Linien gleich sind und das Dreieck nur eine Linie (oder ein Punkt) ist. Die Gleichung wird im Programm neu angeordnet, um eine Teilung zu vermeiden.

rist ein Zwischenwert für das Quadrieren

zzählt die Anzahl der Seiten der Länge Null. Es hat einen Versatz von +3, da die Schleife 3 leere Zellen einliest t[].

czählt die Anzahl der Seiten gleicher Länge. Es hat auch einen Offset von +3. Beachten Sie, dass die Seite zweimal ageschrieben wird, t[]um a = b, b = c, c = a überprüfen zu können.

bist die größte Länge einer Seite, im Quadrat. sist die Summe der Quadrate aller Seiten.

Beachten Sie, dass der Vergleich der Seitenlängen A ^ 2 + B ^ 2 + C ^ 2 mit 2 * B ^ 2 dem Vergleich von A ^ 2 + C ^ 2 mit B ^ 2 entspricht (subtrahieren Sie einfach B ^ 2 von beiden Seiten) wenn B ^ 2 = A ^ 2 + C ^ 2 ist, ist es ein rechtwinkliges Dreieck. wenn B ^ 2 größer ist, ist es stumpf, wenn es kleiner ist, ist es akut.

Level River St
quelle
Basierend auf dem Diagramm in der Frage sollte ein gleichseitiges Dreieck auch als gleichschenkliges Dreieck klassifiziert werden. (Andererseits ist es unmöglich, ein gleichseitiges Dreieck mit ganzzahligen Koordinaten zu erstellen.)
es1024
@ es1024 das Dreieck (0,0) (4,7) (8,0) kommt so nah (quadratische Seitenlängen 64,65,65). Dies ist eine nützliche Annäherung, wenn Sie Winkel von 60 Grad zeichnen möchten (Zeichnen von Schneeflocken nach einer meiner anderen Antworten, Erstellen eines eigenen isometrischen Punktepapiers oder Zeichnen von Uhren). Wahrscheinlich ist es auch unmöglich, eine perfekte Übereinstimmung mit Schwimmern zu erzielen. Wenn ich diesen Code überarbeite, kann ich dem Vergleich eine Toleranz von 1% hinzufügen, wie in der Frage beschrieben.
Level River St
2

Golfscript (175 Bytes)

~..|,({.)2$([\;\]@(;]{{~}/@- 2?@@- 2?+}%$.{2-1??100*}/-+abs 1<{;"Line"}{.[]|,((["Isosceles ""Scalene "]=\~-+.!["Oblique ""Right "]=\.!\0>-)["Acute ""Obtuse "]=}if}{;"Point "}if

Sie können es hier testen testen (Test-Set enthalten).

Eingabeformat:

"[x y][x y][x y]"

Kommentierte Version:

~                       # evaluates input string          
..|,(                   # pushes the number of unique coords - 1
{
  .)2$([\;\]@(;]        # makes all 3 possible pairings of coords
  {{~}/@- 2?@@- 2?+}%$  # gets all squares of side lengths 
  .{2-1??100*}/-+abs 1< # 0 if triangle, 1 if line
  {;"Line"}
  {
     .[]|,((["Isosceles ""Scalene "]=\   # removes duplicate side-squares,
                                         #   and use the count to determine
                                         #   if isosceles or scalene (no
                                         #   equilaterals will exist)
     ~-+.!["Oblique ""Right "]=\         # compute a^2 + b^2 - c^2. Use to
                                         #   determine if oblique or right.
                                         #   c = max side length 
     .!\0>-)["Acute ""Obtuse "]=         # use same value to determine if
                                         #   acute, obtuse, or right
  }
  if
}
{;"Point "}
if

HINWEIS:

Der Grund, warum mein Code keine "gleichseitige" Ausgabe enthält, ist folgender:

  • OP sagte: "Alle Eingabenummern sind in Bezug auf die Datentypen, die Sie letztendlich verwenden, wohlgeformt."
  • Golfscript hat keine Gleitkommazahlen - sowieso nicht inhärent
  • Es ist unmöglich (in einem zweidimensionalen Gitter), ein gleichseitiges Dreieck mit ganzzahligen Koordinaten zu haben, wie hier bewiesen .
Kyle McCormick
quelle
Ihre Notizen sind korrekt - deshalb habe ich die Regel über "Gleichheit" eingefügt, dh Werte innerhalb von 1%
Digitales Trauma
Wenn ich mich nicht irre, sagten Sie dies für Gleitkommazahlen, nicht für ganze Zahlen: "..sie werden wahrscheinlich Gleitkommazahlen miteinander vergleichen. Zwei solcher Werte sind als" gleich "zu betrachten, wenn einer innerhalb von 1% des anderen liegt . "
Kyle McCormick
0

Mathematica ( 313 307 Zeichen)

Golf gespielt:

f@p_:=(P=Print;R=RotateLeft;L=Length;U=Union;If[L@U@p==1,P@"Point",If[Det[Join[#,{1}]&/@p]==0,P@"Line",v=p-R@p;a=MapThread[VectorAngle[#,#2]&,{-v,R@v}];u=L@U[Norm/@v];If[u==1,P@"Equilateral",If[u==2,P@"Isosceles",P@"Scalene"]];If[MemberQ[a,Pi/2],P@"Right",P@"Oblique";If[Max@a>Pi/2,P@"Obtuse",P@"Acute"]]]])

Ungolfed:

f@p_ := (
  P = Print;    (* make aliases for functions used more than once *)
  R = RotateLeft;
  L = Length;
  U = Union;
  If[L@U@p == 1,    (* if all points identical *)
   P@"Point",
   If[Det[Join[#, {1}] & /@ p] == 0,    (* if area is zero *)
    P@"Line",
    v = p - R@p;    (* cyclic vectors *)
    a = MapThread[VectorAngle[#, #2] &, {-v, R@v}];    (* interior angles *)
    u = L@U[Norm /@ v];    (* number of unique side lengths *)
    If[u == 1,
     P@"Equilateral",
     If[u == 2,
      P@"Isosceles",
      P@"Scalene"
      ]
     ];
    If[MemberQ[a, Pi/2],
     P@"Right",
     P@"Oblique";
     If[Max@a > Pi/2,
      P@"Obtuse",
      P@"Acute"
      ]
     ]
    ]
   ]
  )

Das Eingabeformat ist eine Liste von Punkten, nach denen die Funktion aufgerufen wird:

points = {{x1,y1},{x2,y2},{x3,y3}};
f@points
Phosgen
quelle
Ich bin ein Mathematica-Neuling. Wo kann ich einen Interpreter / Compiler herunterladen oder online ausprobieren (natürlich kostenlos ;-))?
Digitales Trauma
Ich habe es nie benutzt, aber Wolfram hat eine 'CDF Player'-Browseranwendung, die behauptet, Mathematica-Dateien auszuführen, die im CDF-Format gespeichert sind, aber keine normalen Notizbücher. Hier zu finden: wolfram.com/cdf-player Darüber hinaus gibt es das Hauptprogramm, von dem ich glaube, dass es 30 Tage lang kostenlos ist.
Phosgen