проверить функцию, которая возвращает тип треугольника

0

Я получил следующий вопрос в рамках скринингового интервью:

Напишите функцию, которая получает три целых входа для длин сторон треугольника и возвращает одно из четырех значений для определения типа треугольника (1 = scalene, 2 = равнобедренные, 3 = равносторонние, 4 = ошибка). Генерируйте тестовые примеры для функции, предполагающей, что другой разработчик закодировал эту функцию.

Мой ответ:

#define ERROR 4
#define EQUILATERAL 3
#define ISOSCELES 2
#define SCALENE 1

int detemineTriangle(int x, int y, int z)
{
    if((x<=0) || (y<=0) || (z<=0))
        return ERROR;

    if((x==y) || (x==z) || (y==z))
    {
        if((x==y) && (y==z))
            return EQUILATERAL;
        else
            return ISOSCELES;
    }

    return SCALENE;
}

ИСПЫТАНИЯ:

detemineTriangle (0,0,0);   //error
detemineTriangle (2,2,2);   //equilateral
detemineTriangle (3,3,1);   //isosceles
detemineTriangle (1,3,3);   //isosceles
detemineTriangle (3,1,3);   //isosceles
detemineTriangle (1,2,3);   //scalene
detemineTriangle (-1,2,3);  //error  scalene
detemineTriangle (1,-2,3);  //error  scalene
detemineTriangle (1,2,-3);  //error  scalene
detemineTriangle (-2,-2,-2);   //error equilateral
detemineTriangle (-2,5,-2);   //error isosceles
detemineTriangle (-2,-2,5);   //error isosceles
detemineTriangle (5,-2,-2);   //error isosceles


//looking for overflows/underflows
detemineTriangle (INT_MAX,INT_MAX,INT_MAX);
detemineTriangle (INT_MAX,1,1);
detemineTriangle (1,INT_MAX,1);
detemineTriangle (1,1,INT_MAX);
detemineTriangle (-INT_MAX,-INT_MAX,-INT_MAX);
detemineTriangle (-INT_MAX,1,1);
detemineTriangle (1,-INT_MAX,1);
detemineTriangle (1,1,-INT_MAX);

//boundary tests
detemineTriangle(1,1,1)
detemineTriangle(0,0,0)
detemineTriangle(-1,-1,-1)


detemineTriangle (0,10,10);   
detemineTriangle (1,10,10);   
detemineTriangle (-1,10,10); 

detemineTriangle (10,0,10);   
detemineTriangle (10,1,10);   
detemineTriangle (10,-1,10); 

detemineTriangle (10,10,0);   
detemineTriangle (10,10,1);   
detemineTriangle (10,10,-1);   

//checking thread safety
a =detemineTriangle (10,10,10);  
b =detemineTriangle (10,10,10);   
//a==b function does not appear to depend on global or static variables

Вы видите что-то не так с этим ответом? Заранее спасибо.

  • 5
    Мне кажется, вы не проверяете, действительны ли длины трех сторон. Например, вы не можете иметь треугольник с тремя сторонами 1 , 1 и 1000 . Общее правило должно быть таким: longest_size < shortest_side + median_side .
  • 1
    Я бы сказал, что @elnigno имеет ключевое значение, хотя и не думайте, что люди не получают отклонения из-за их «общих вещей». Подбор персонала - это странное дело. Это всегда хороший совет, чтобы применять «лучшие» практики кодирования с такими ответами - например, всегда браться за «если» и иметь только один возврат. Вы никогда не знаете, был ли рецензент недавно укушен несвязанным многострочным макросом ...
Показать ещё 2 комментария
Теги:
testing
integration-testing

5 ответов

5
Лучший ответ

Вы также должны проверить длину стороны. Как вы знаете, сумма длины двух сторон ДОЛЖНА быть больше длины последней стороны. поэтому вы должны также проверить что-то вроде этого:

if(x+y<=z || x+z<=y || z+y<=x)
    return ERROR;

UPD: вот полное решение (включая проверку переполнения):

inline bool isSidesOverflow(int a, int b)
{
    return b > INT_MAX - a;
}
int detemineTriangle(int x, int y, int z)
{
    if((x<=0) || (y<=0) || (z<=0)) return ERROR;
    // If all sides are equal and greater than 0 - no need to check overflow and validness.
    if(x == y && y == z) return EQUILATERAL;
    //Check overflow now
    if(isSidesOverflow(x,y) || isSidesOverflow(x,z) || isSidesOverflow(y,z)) return ERROR;
    //Check if it valid triangle
    if(x+y<=z || x+z<=y || z+y<=x) return ERROR;
    if((x==y) || (x==z) || (y==z)) return ISOSCELES;
    return SCALENE;
}

(не компилировать, не стесняйтесь сообщать об ошибках через комментарии)

  • 1
    это приведет к неопределенному поведению при переполнении x + y ...
  • 0
    правда, так что еще один тест должен быть добавлен для этого.
Показать ещё 1 комментарий
1
#include <iostream>  

#include <iomanip>

#include <string>

using namespace std;

// define the data type "triangletype" with {values}

enum triangleType { scalene, isosceles, equilateral, noTriangle };

// Prototype function which returns the position of triangleType{value}

// Example: Scalene = 0, isosceles = 1, etc. These are zero indexed.

triangleType triangleShape(double a, double b, double c);

// Prototype function which takes the integer value of the 

// triangle type and outputs the name of triangle

string shapeAnswer(int value);

int main() {

    double inputA; 
    double inputB; 
    double inputC;

    cout << "To determine whether a triangle is either:" << endl;
    cout << setw(50) << " - Scalene" << endl; // Unequal in length
    cout << setw(52) << " - Isosceles" << endl; // Two sides equal length
    cout << setw(54) << " - Equilateral" << endl; // All sides equal
    cout << setw(57) << " - Not a triangle" << endl; 
    cout << "Enter side A: ";
    cin >> inputA;
    cout << "Enter side B: ";
    cin >> inputB;
    cout << "Enter side C: ";
    cin >> inputC;
    cout << "The triangle is " << shapeAnswer(triangleShape(inputA, inputB, inputC)) << endl;

}

triangleType triangleShape(double a, double b, double c) {

    triangleType answer;

    if ( c >= (a + b) || b >= (a + c) || a >= (b + c) ) {
        answer = noTriangle;
    }
    else if (a == b && b == c) {
        answer = equilateral;
    }

    // Test the 3 options for Isosceles equality
    else if ( (a == b) && (a != c) || (b == c) && (b != a) || (a == c) && (a != b) ) {
        answer = isosceles;
    }
    else {
        answer = scalene;
    }

    return answer;
}

string shapeAnswer(int value) {

    string answer;

    switch (value) {
    case 0:
        answer = "Scalene";
        break;
    case 1: 
        answer = "Isosceles";
        break;
    case 2:
        answer = "Equilateral";
        break;
    case 3:
        answer = "Not a triangle";
        break;
    default:
        break;
    }
    return answer;
}
0

Недавно я боролся с этой проблемой.

Вот как я это решил.

int detemineTriangle(int x, int y, int z)
{
 if (x <= 0 || y <= 0 || z <= 0 )
    return ERROR;
 else
    if (z >= (x + y) || y >= (x + z) || x >= (y + z) )
        return ERROR;
    else if (x == y && y == c)
        return EQUILATERAL;
    else if ( ( (x == y) && (x != z) ) || ( (y == z) && (y != x) ) )
            return ISOSCELES;
    else
            return SCALENE;
}

Первый оператор if квалифицирует вход, чтобы убедиться, что значения больше единицы. Второй оператор if квалифицирует, является ли вход действительным треугольником (две стороны, вместе взятые, должны быть больше, чем третья сторона). Третий оператор if ищет x = y и y = z, откуда следует x = z. Четвертый оператор if ищет две стороны равны, а третья сторона - нет. Заключительный оператор else просто возвращает scalene, но вы можете проверить его, если хотите.

0

Я верну свой комментарий к ответу.

Вы также должны проверить, что длины трех сторон действительны. Общее правило: longest_size < shortest_side + median_side.

Тест для этого может быть:

detemineTriangle(1, 1, 100);

Помимо этого, вы можете сделать тестирование в целом более прочным, выполнив то, что предложили другие, например, тестирование всех перестановок аргументов (@Ivaylo).

0

Я бы разделил тесты на несколько тестов для различных ошибок. Таким образом, вы теперь не только, что функция determineTriangle неверна, но будет иметь некоторое преимущество в том, что с ней не так.

Я бы сказал, что использование сторонней библиотеки для тестирования (например, CXXTest или Google Test Framework) было бы преимуществом. Большинство таких фреймворков предоставляют различные функции assert, которые вы можете использовать для проверки.

Еще одно улучшение, которое я могу придумать, - проверить каждый триплет во всех его возможных перестановках - результат функции должен быть одним и тем же (поэтому, возможно, написать вспомогательную функцию testTiplet(int sidea, int sideb, itn sidec, int expectedType)).

EDIT: мой ответ показывает только, как вы можете улучшить свою часть тестирования. Важный поток вашей реализации упоминается Сатом в его/ее ответе.

  • 0
    Я бы согласился - за исключением логической проблемы, которую идентифицировал Sat, я был бы обеспокоен тем, что сами тесты не могут быть запущены - как говорит Ивайло, я бы ожидал, что каждый тест будет запущен и сравнен с ожидаемым результатом, и выводимый отчет о том, сколько тестов провалилось. Кроме того, меня немного смущают тесты "безопасности потоков" в конце.
  • 0
    часть тестирования уже разбита на несколько категорий, охватывающих несколько классов ошибок
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню