スリーポインター!しかし、どのような?


24

http://en.wikipedia.org/wiki/Triangleから: ここに画像の説明を入力してください


3つの2次元座標タプル(デカルト)を取り、これらの3つのポイントが記述する形状を分類するプログラムを作成します。

ほとんどすべての場合、これらのポイントはさまざまなタイプの三角形を表します。一部の縮退した場合、ポイントは特異ポイントまたは直線のいずれかを表します。プログラムは、記述された形状に適用される次のタグを決定します。

  • ポイント(3ポイントは同時発生)
  • 線(3点が直線上にある-一致する可能性があるのは2点までです)
  • 等辺(3つの側面が等しい、3つの角度が等しい)
  • 二等辺(2つの側面が等しい、2つの角度が等しい)
  • スカレン(0辺が等しい、0角が等しい)
  • 右(1角度正確にπ/ 2(または90°))
  • 斜め(0角度正確にπ/ 2(または90°))
  • 鈍角(1角度>π/ 2(または90°))
  • 急性(3角<π/ 2(または90°))

説明されている一部の形状には、上記のタグが複数適用されることに注意してください。たとえば、直角はいずれも二等辺または斜角になります。

入力

  • プログラムは、STDIN、コマンドライン、環境変数、または選択した言語に便利な方法から3つの入力座標を読み取ることができます。
  • ただし、フォーマットする入力座標は、選択した言語にとって便利です。すべての入力番号は、最終的に使用するデータ型に関して整形式であると想定できます。
  • 入力座標の順序については何も想定できません。

出力

  • プログラムは、STDOUT、ダイアログボックス、または選択した言語に便利な表示方法に出力します。
  • 出力には、入力座標で記述された形状に適用可能なすべてのタグが表示されます。
  • タグは任意の順序で出力できます。

その他の規則

  • あなたの言語の三角ライブラリ/ APIは許可されていますが、三角形のタイプを明確に計算するAPIは禁止されています。
  • 角度の均等性または辺の長さを決定する場合、おそらく浮動小数点値を比較することになります。1つの値が他の値の1%以内であれば、このような値は2つ「等しい」と見なされます。
  • もはや面白くない標準の「抜け穴」
  • これはであるため、バイト単位の最短回答が優先されます。

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

4
私はこの「トライアングルタグ」に資格を与えるつもりでしたが、15文字の最小値に達しませんでした。
デジタル外傷14

2つのポイントが同一の場合はどうなりますか?
Ypnypn 14

@Ypnypnその場合、それは行です。
デジタル外傷14

三角形のタグ
デレク朕會功夫14

2
「急性」定義に問題がありますか?すべての角度がPI / 2よりも大きいことは不可能ですか?
アルノー14

回答:


10

C(451バイト)

長さおよび勾配の2乗のみを使用します。

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(および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
}

入力(stdin経由)形式:xyxyxy

例 0二等辺右の場合は0 0 1 1 2 0


@digitaltrauma ./triangle <<< "1 2 1 2 1 2"は引用符付きで使用する必要があります。
es1024 14

はい、もちろん、ごめんなさい。いい答えだ。私は特にフロートを避けることができたので、1%以内の等式ルールのことを心配する必要はありません。+1
デジタルトラウマ14

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

今のところ空白を残しました。これは動作しますが、おそらく片付けとゴルフで行うことができます。@es1024の答えと同様の数学ですが、ループと配列を使用します。入力形式x y x y x y

変数

t[]入力と長さの二乗の両方を保存します。プログラムの終わりまでに、下の表のようになります(ループの反復回数を増やすと、長さの2乗が無限に繰り返されます。)ループの長さの2乗(すべてのデータが利用可能ではないため、ゴミ) )不セル1,3および5に格納されているが、速やかによって上書きされるscanf.有用なデータに書き込まれます。z,b,c AHD s場合i= 9,11,13(t[i]およびt[i-2]アクセスされます。)

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

g[]勾配計算に必要なdxとdyの値を保持するために、後半に追加されました。使用されるセルは6〜9のみです(書き込み時にすべてのデータが利用できるわけではないため、0〜5は信頼できません。)g[6]/g[7]==g[8]/g[9]2本の線の傾きが等しく、三角形が単なる線(または点)の場合分割を避けるためにプログラム内で再配置されます。

r二乗に使用される中間値です

z長さゼロの辺の数をカウントします。ループはで3つの空白セルを読み取るため、+ 3のオフセットがありますt[]

c同じ長さの辺の数を数えます。また、+ 3のオフセットがあります。その側に注意してくださいat[]a = b、b = c、c = aを確認できるようには2回書き込まれるてください。

b辺の最大の長さ、二乗です。 sすべての辺の二乗の合計です。

辺の長さA ^ 2 + B ^ 2 + C ^ 2と2 * B ^ 2を比較することは、A ^ 2 + C ^ 2とB ^ 2を比較することと同じであることに注意してください(両側からB ^ 2を引くだけです)。 B ^ 2 = A ^ 2 + C ^ 2の場合、直角三角形です。B ^ 2が大きい場合は鈍角で、小さい場合は鋭角です。


問題の図に基づいて、正三角形も二等辺三角形として分類する必要があります。(一方、整数座標で正三角形を作成することは不可能です。)
es1024

@ es1024三角形(0,0)(4,7)(8,0)は非常に近くなります(辺の長さが64,65,65の2乗)。60度の角度(他の回答の1つにつき雪片を描いたり、等尺性のドットペーパーを作成したり、時計を描いたり)する場合は、便利な近似値です。フロートと完全に一致することはおそらく不可能です。このコードを修正する場合、質問で説明したように、比較に1%の許容誤差を追加することがあります。
レベルリバーセント14

2

Golfscript(175バイト)

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

あなたはそれをテストすることができます ここでます(テストセットが含まれています)。

入力形式:

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

コメント版:

~                       # 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

注意:

コードに「同等の」出力が含まれていない理由は、次のとおりです。

  • OPは、「すべての入力番号は、最終的に使用するデータ型に関して整形式である」と述べました。
  • Golfscriptには浮動小数点数がありません-とにかく本質的ではありません
  • ここで証明されているように、整数座標の正三角形を持つことは(2次元グリッドでは)不可能です

あなたのメモは正しいです-それが、1%以内の値を意味する「平等」に関するルールを含めた理由です
デジタル外傷14

間違っていなければ、これは整数ではなく浮動小数点数であるとあなたは言った。 」
カイルマコーミック14

0

Mathematica(313 307文字)

ゴルフ:

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

ゴルフをしていない:

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

入力形式は、関数が呼び出されるポイントのリストです。

points = {{x1,y1},{x2,y2},{x3,y3}};
f@points

私は数学の新人です。インタプリタ/コンパイラはどこでダウンロードできますか、オンラインで試してみてください(もちろん無料です;-))
デジタル外傷14

使用したことはありませんが、Wolframには「CDF Player」ブラウザアプリケーションがあり、CDF形式で保存されているMathematicaファイルを実行すると主張していますが、通常のノートブックは使用していません。ここにあります: wolfram.com/cdf-player さらに、メインプログラムがあります。これは30日間無料です。
ホスゲン14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.