Трипоказний! Але який вид?


24

З http://uk.wikipedia.org/wiki/Triangle : введіть тут опис зображення


Напишіть програму, яка займає три координати дворядних кортежів (декартових) та класифікує, яку форму описують ці три точки.

Майже у всіх випадках ці точки описують трикутник різного типу. У деяких вироджених випадках точки будуть або описувати окрему точку, або пряму. Програма визначить, який із наведених нижче тегів застосовується до описаної форми:

  • Бал (3 бали є спільними випадками)
  • Лінія (3 бали лежать на прямій лінії - не більше 2 балів можуть бути спільними випадками)
  • Рівносторонній (3 сторони рівні, 3 кути рівні)
  • Ізоскелети (2 сторони рівні, 2 кути рівні)
  • Скелен (0 сторін рівні, 0 кути рівні)
  • Право (1 кут рівно π / 2 (або 90 °))
  • Косий (0 кутів точно π / 2 (або 90 °))
  • Тупий (1 кут> π / 2 (або 90 °))
  • Гострий (3 кути <π / 2 (або 90 °))

Зауважте, що для деяких описаних фігур буде застосовано більше одного з вищезазначених тегів. Наприклад, будь-який прямокутний також буде або рівнобедреним, або масштабним.

Вхідні дані

  • Програма може прочитати 3 вхідні координати зі STDIN, командного рядка, змінних середовища або будь-якого способу, зручного для вашої мови вибору.
  • Вхідні координати мого форматування, але це зручно для вашої мови, яку ви вибрали. Можна припустити, що всі вхідні номери добре сформовані стосовно типів даних, які ви в кінцевому підсумку використовуєте.
  • Про упорядкування вхідних координат нічого не можна припустити.

Вихід

  • Програма виведе в 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 символів.
Цифрова травма

Що робити, якщо дві точки однакові?
Ypnypn

@Ypnypn У цьому випадку це лінія.
Цифрова травма

Тег трикутника
Дерек 朕 會 功夫

2
Виникає проблема з визначенням "Гостре"? неможливо, щоб усі кути були більшими за PI / 2?
Арно

Відповіді:


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
}

Формат вводу (через stdin) Формат: xyxyxy

колишній 0 0 1 1 2 0 для Isosceles Right


@digitaltrauma ./triangle <<< "1 2 1 2 1 2"слід використовувати з цитатами.
es1024

Так, звичайно, вибачте за це. Гарна відповідь. Мені особливо подобається, що ви змогли уникнути поплавків, і, отже, не потрібно турбуватися про норму рівності 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,cЕН , 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. Зауважте, що сторона aзаписується t[]двічі, щоб можна було перевірити a = b, b = c, c = a.

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). Це зручне наближення, якщо ви хочете намалювати кути на 60 градусів (малювання сніжинок за однією з моїх інших відповідей, виготовлення власного ізометричного крапкового паперу або малювання годинників.) Напевно неможливо отримати ідеальну відповідність і плавцям. Якщо і коли я переглядаю цей код, я можу додати 1% допуску до порівняння, як описано в питанні.
Річка рівня Св.

2

Гольфскрипт (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

ПРИМІТКА:

Причина, що мій код не містить "рівносторонній" вихід, полягає в тому, що:

  • ОП сказав, що "всі вхідні номери добре сформовані стосовно типів даних, які ви в кінцевому підсумку використовуєте"
  • Гольфскрипт не має цифр з плаваючою комою - не властиво все одно
  • Неможливо (у двовимірній сітці) мати рівносторонній трикутник з цілими координатами, як це доведено тут .

Ваші нотатки є правильними - саме тому я включив правило про значення "рівності" в межах 1%
Digital Trauma

Якщо я не помиляюся, ви сказали це для плавців, а не для цілих чисел: ".. ви, швидше за все, порівнюєте значення з плаваючою комою. Два такі значення вважатимуться рівними, якщо одне знаходиться в межах 1% від іншого . "
Кайл Маккормік

0

Математика ( 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

Я новачок математики. Де я можу завантажити перекладача / укладача або спробувати це в Інтернеті (звичайно, безкоштовно ;-))?
Цифрова травма

Я ніколи його не використовував, але Wolfram має програму браузера "CDF Player", яка стверджує, що запускає файли Mathematica, що зберігаються у форматі CDF, але не звичайні ноутбуки. Знайдено тут: wolfram.com/cdf-player Крім того, є основна програма, яка, на мою думку, є безкоштовною протягом 30 днів.
фосген
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.