三分球!那是什么


24

来自http://en.wikipedia.org/wiki/Triangle在此处输入图片说明


编写一个程序,该程序采用三个2d坐标元组(笛卡尔),并对这三个点描述的形状进行分类。

在几乎所有情况下,这些点都将描述不同类型的三角形。在某些退化的情况下,这些点将描述一个奇异点或一条直线。程序将确定以下哪个标签适用于所描述的形状:

  • 点(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%以内,则将两个这样的值视为“相等”。
  • 标准的“漏洞”不再有趣
  • 这是,因此最短的答案以字节为单位。

例子

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个字符的最小值。
Digital Trauma 2014年

如果两点相同怎么办?
Ypnypn

@Ypnypn在这种情况下,它是一行。
Digital Trauma 2014年


2
“急性”定义有问题吗?所有角度都不可能大于PI / 2吗?
Arnaud 2014年

Answers:


10

C(451字节)

仅使用平方的长度和斜率。

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

取消填充(并将三元运算符替换为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
}

输入(通过标准输入)格式:xyxyxy

例如 等腰向右0 0 1 1 2 0


@digitaltrauma ./triangle <<< "1 2 1 2 1 2"应该使用引号。
es1024 2014年

是的,当然,对此感到抱歉。好答案。我特别喜欢您能够避免浮动,因此不必担心1%平等规则之内的事情。+1
数字创伤

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[]存储输入和长度的平方。程序结束时,如下表所示(增加循环的迭代次数将导致平方长度的不确定重新定位。)在循环的开始处,长度的平方(垃圾回收,因为并非所有数据都可用) )被不必要地存储在电池1,3和5,但是通过被迅速覆盖scanf.有用数据被写入到z,b,cAHD si= 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的偏移量。注意,为了能够检查a = b,b = c,c = a ,将side a写入了t[]两次。

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 2014年

@ es1024,三角形(0,0)(4,7)(8,0)变得非常近(边长为64,65,65的平方)。如果您想绘制60度角(这是我的其他答案之一,要绘制雪花,制作自己的等距圆点纸或绘制时钟),这是一个方便的近似值。也可能无法与浮子完美匹配。如果并且当我修改此代码时,我可以为比较添加1%的容差,如问题中所述。
级圣河

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%之内的规则的原因
数字创伤

如果我没记错的话,您说的是浮点数,而不是整数:“ ..您可能最终会比较浮点值。如果其中一个值与另一个值相差1%以内,则将两个这样的值视为“相等” 。”
凯尔·麦考密克

0

Mathematica(313307个字符)

打高尔夫球:

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

我是数学新秀。我在哪里可以下载口译员/编译器,或在线试用(当然,免费;-))?
Digital Trauma 2014年

我从未使用过它,但是Wolfram有一个“ CDF Player”浏览器应用程序,该应用程序声称可以运行以CDF格式存储的Mathematica文件,而不是普通笔记本。在此处找到: wolfram.com/cdf-player 除此之外,还有主程序,我相信该程序可以免费使用30天。
光气
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.