Глава 4.1. По-сложни проверки

В настоящата глава ще се занимаем с правенето на по-сложни проверки в C++. Първо ще разгледме условни конструкции, които съдържат в тялото си други условни конструкции, това са вложени условни конструкции. След това ще рагледаме по-сложни логически условия, чрез които можем да правим няколко проверки в една конструкция if.

Видео

Гледайте видео-урок по тази глава тук: https://www.youtube.com/watch?v=XK8W2DP-oDM.

Вложени проверки

Вложени проверки наричаме if или if-else конструкции, които се съдържат една в друга. Терминът произлиза от това, че едната условна конструкция е вложена (съдържа се) в другата. Тези конструкции се използват често при по-сложни програми. Общият им вид е следният:

if (условие_1) {
    if (условие_2) {
        // тяло
    } else {
        // тяло;
    }
}

В C++ са разрешени вложени констукции на няколко нива, т.е. if в if в if и т.н. Влагането на повече от три условни конструкции една в друга обаче се счита за лоша практика, защото води до трудно четим код. Можем да избегнем този проблем, като структурираме алгоритъма си по по-хитър начин или като използваме по-сложни логически условия, описани по-надолу в тази глава.

Пример: обръщение според възраст и пол

Според въведени възраст (число) и пол (m / f) да се отпечата обръщение:

  • Mr.” – мъж (пол “m”) на 16 или повече години.
  • Master” – момче (пол “m”) под 16 години.
  • Ms.” – жена (пол “f”) на 16 или повече години.
  • Miss” – момиче (пол “f”) под 16 години.

Примерен вход и изход

Вход Изход Вход Изход
12
f
Miss 17
m
Mr.
Вход Изход Вход Изход
25
f
Ms. 13.5
m
Master

Решение

Изходът на решението на задачата зависи от няколко неща. Ще използваме две вжолени if-else конструкци, в които първо ще проверяваме въведения пол и след това въведената възраст. Проверките са вложени, защото искаме от резултата на първата да се определя коя от другите проверки да се изпълни;

int age;
string gender;
cin >> age >> gender;
if (gender == "m") {
    if (age < 16)
        cout << "Master" << endl;
    else
        cout << "Mr." << endl;
} else if (gender == "f") {
   if (age < 16)
        cout << "Miss" << endl;
    else
        cout << "Ms." << endl;
}

Тестване в Judge системата

Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/508#0.

Пример: квартално магазинче

Предприемчив българин отваря по едно квартално магазинче в няколко града с различни цени за следните продукти:

продукт Sofia Plovdiv Varna
coffee 0.50 0.40 0.45
water 0.80 0.70 0.70
beer 1.20 1.15 1.10
sweets 1.45 1.30 1.35
peanuts 1.60 1.50 1.55

По дадени град (стринг), продукт (стринг) и количество (десетично число) на покупка, да се пресметне цената ѝ.

Примерен вход и изход

Вход Изход Вход Изход
coffee
Varna
2
0.9 peanuts
Plovdiv
1
1.5
Вход Изход Вход Изход
beer
Sofia
6
7.2 water
Plovdiv
3
2.1

Решение

string product, town;
double quantity;

cin >> product >> town >> quantity;

if (town == "Sofia") {
    if (product == "coffee") {
        cout << 0.50 * quantity << endl;
    }
    //TODO: finish this ...
} else if (town == "Varna") {
    //TODO: finish this ...
}
//TODO: finish this ...

Тестване в Judge системата

Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/508#1.

По-сложни проверки

По-сложните логически проверки се състоят от няколко прости условия, обединени чрез логичеси оператори. Това са логическо "и" (&&), логическо "или" (||), логическо отрицание (!) и скоби (()).

Булев тип

Както видяхме в предната глава, резултатите от простите проверки са true (истина) или false (лъжа). Освен да ползваме резултата от дадена проверка директно в условна конструкция (if), в C++ можем да запазим резултата в променлива, която да ползваме по-късно. Тези променливи са от тип bool и затова се наричат булеви:

bool condition = (5 > 3) //true
cout << boolalpha << condition << endl; //отпечатва "true"

Логическо "и"

Чрез логическото "и" (оператор &&) проверяваме, дали две условия са изпълнени едновременно. В долната таблица на истинност е показана стойността на a && b, за всички възможни стойности на a и b:

a b a && b
true true true
true false false
false true false
false false false

Операторът &&

Операторът && се прилага две булеви стойности и на свой ред && също връща булева стойност. Когато и двата аргумента имат стойност true, стойността на израза също е true, а в противен случай тя е false. Аргументи могат да бъдат както променливи от булев тип, така и резултатите от други проверки.

Долният пример показва как можем да използваме операторът &&, за да проверим, дали въведено число е по-голямо или равно на 100 и по-малко или равно на 200, т.е. дали е между 100 и 200:

int a;
cin >> a;
if ((a >= 100) && (a <= 200)) {
    cout << "The number is between 100 and 200" << endl;
}

Повече от двe условия

Чрез оператора && можем дали две условия са изпълнени едновременно. Как да подходим обаче, ако искаме да направим същото за повече от две условия? Нека първо разгледаме как се решава този проблем при операция, с която сме по-добре запознати, например събиране:

Подобно на &&, операторът + събира две числа. Ако искаме да съберем няколко числа, използваме няколко пъти оператора + по следния начин:

int sum = 1 + 2 + 3 + 4;

Изразът се изчислява от ляво надясно, като последователно всяко от числата се събира със сбора на предходните. Започва се с 1 + 2 = 3, после 3 + 3 = 6 и накрая 6 + 4 = 10.

Аналогично проверяваме чрез оператор &&, дали няколко условия са изпълнени едновременно:

bool a = true;
bool b = true;
bool c = false;
bool d = true;
bool result = a && b && c && d;

Изразът отново се изчислява от ляво надясно, като последователно се прилага операцията логическо "и" върху текущата булева стойност, и резултата за предходните. Започва се с a && b = true && true = true, после true && c = true && false = false и накрая false && d = false && true = false.

Всъщност, тъй като след втората операция "и" (&&) се е получила стойност false, няма как стойността на целия израз е true, независимо от стойностите на останалите булеви условия. Затова, като се прилага оператор && в C++, ако стойността на първия аргумент е false, вторият не се изчислява, защото е ясно, че стойността на целия израз ще е false.

Логическо "и" и вложени проверки

В предните задачи се налагаше да правим няколко проверки наведнъж. Тогава най-добрият подход беше чрез вложени проверки, защото искахме да се изпълни някакъв код, както когато беше изпълнено условието (тялото на if), така и когато не беше (тялото на else). Когато обаче се интересуваме само от единия случай (няма else), е по-добре да се използва една конструкция if, в която да са обединени няколко прости проверки чрез оператор &&.

Ползването на вложени проверки в такива ситуации води до код, който изглежда неподреден и е труден за четене и поддръжка. В сравнение с долния код, този от предната секция е по-лесно разбираем, макар двата кода да правят едно и също:

bool result = false;
if (a) {
    if (b) {
        if (c) {
            if (d) {
                result = true;
            }
        }
    }
}

Пример: точка в правоъгълник

Проверка дали точка {x, y} се намира вътре в правоъгълника {x1, y1} – {x2, y2}. Входните данни се четат от конзолата и се състоят от 6 реда: десетичните числа x1, y1, x2, y2, x и y (като се гарантира, че x1 < x2 и y1 < y2).

Примерен вход и изход

Вход Изход Визуализация
2
-3
12
3
8
-1
Inside shop

Решение

Една точка е вътрешна за даден многоъгълник, ако едновременно са изпълнени следните четири условия:

  • Точката е вдясно от лявата страна на правоъгълника.
  • Точката е вляво от дясната страна на правоъгълника.
  • Точката е под горната страна на правоъгълника.
  • Точката е над долната страна на правоъгълника.

Тестване в Judge системата

Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/508#2.

Логическо "или"

Чрез логическо "или" (оператор ||) проверямаве, дали е изпълнено поне едно от две логически условия. В долната таблица на истинност е показана стойността на a || b, за всички възможни стойности на a и b:

a b a || b
true true true
true false true
false true true
false false false

Забележете, че a || b има стойност true дори когато и двете условия са изпълнени. Това не съответства изцяло на употребата на думата "или" в ежедневието, но не е и в противоречие с горната дефиниция, тъй като тя изисква поне едно условие да е изпълнено, а не точно едно.

Операторът ||

Подобно на оператора &&, операторът || приема като аргументи две булеви стойности и на свой ред също връща булева стойност (true или false). Ако искаме да проверим дали поне едно от няколко условия е изпълнено, трябва да приложим някокло пъти оператора ||:

bool a = false;
bool b = false;
bool c = true;
bool d = true;
bool result = a || b || c || d;
// true (като c и d не се проверяват)

Както при логическото "и", изразът се изчислява от ляво надясно, като този път последователно се прилага операцията логическо "или" върху текущата булева стойност, и резултата за предходните. Започва се с a || b = false || false = false, после false || c = false || true = true и накрая true || d = true || true = true.

Тъй като след втората операция "или" (||) се е получила стойност true, няма как стойността на целия израз е false, независимо от стойностите на останалите булеви условия. Затова, като се прилага оператор || в C++, ако стойността на първия аргумент е true, вторият не се изчислява, защото е ясно, че стойността на целия израз ще е true.

Пример: плод или зеленчук

Нека проверим дали даден продукт е плод или зеленчук. Плодовете "fruit" са banana, apple, kiwi, cherry, lemon и grapes. Зеленчуците "vegetable" са tomato, cucumber, pepper и carrot. Всички останали са "unknown".

Примерен вход и изход

Вход Изход
banana
tomato
java
fruit
vegetable
unknown

Решение

Трябва да използваме няколко условни проверки с логическо "или" (||):

Тестване в Judge системата

Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/508#3.

Логическо отрицание

Чрез логическо отрицание (оператор !) проверяваме, дали не е изпълнено дадено условие.

a !a
true false
false true

Операторът ! приема като аргумент само една булева стойност и и връща противоположната ѝ булева стойност.

Пример: невалидно число

Дадено число е валидно, ако е в диапазона [100 … 200] или е 0. Да се направи проверка за невалидно число.

Примерен вход и изход

Вход Изход
75 invalid
150 (няма изход)
220 invalid

Решение

Тестване в Judge системата

Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/508#4.

Скоби ()

Подобно на аритметичните изрази, използващи събиране (+) и умножение (*), булевите изрази, съдържащи операциите логическо "и" (&&) и логическо "или" (||), не се изпълняват от ляво надясно. Операторът && е с по-голям приоритет и се изпълнява преди || точно както умножението се изпълнява преди събирането.

Ако искаме да уточним в какъв ред искаме да се изчислят операциите, трябва да ползваме скоби (), както при аритметичните изрази. При булевите е препоръчително да се използват скоби дори когато те не са необходими, защото така кодът е по-ясен и разбираем.

bool result1 = a || b && c;
bool result2 = a || (b && c);
bool result3 = (a || b) && c;

В горния код има три булеви израза, различаващи се единствено по скобите. Първият и вторият израз са еквиваленти, тъй като && е с по-голям приоритет от ||, но вторият е по-лесен за четене, защото ползва скоби. В третия израз редът на извършване на операциите е променен и първо се изпълнява a || b, вместо b && c.

По-сложни логически условия

Сега ще разгледаме по-сложни задачи, които изискзват поредица от проверки или дълги булеви изрази.

Пример: точка върху страна на правоъгълник

Да се напише програма, която проверява дали точка *{x, y} се намира върху някоя от страните на правоъгълник {x1, y1} - {x2, y2}. Входните данни се четат от конзолата и се състоят от 6 реда: десетичните числа x1, y1, x2, y2, x и y (като се гарантира, че x1 < x2 и y1 < y2). Да се отпечата "Border" (точката лежи на някоя от страните) или "Inside / Outside" (в противен случай).

Примерен вход и изход

Вход Изход Вход Изход
2
-3
12
3
12
-1
Border 2
-3
12
3
8
-1
Inside / Outside

Решение

Точка лежи върху някоя от страните на правоъгълник, ако:

  • x съвпада с x1 и същевременно y е между y1 и y2 (лява страна).
  • x съвпада с x2 и същевременно y е между y1 и y2 (дясна страна).
  • y съвпада с y1 и същевременно x е между x1 и x2 (горна страна).
  • y съвпада с y2 и същевременно x е между x1 и x2 (долна страна).

Това може да се реализира в код директно:

if (((x == x1) && (y >= y1) && (y <= y2)) ||
    ((x == x2) && (y >= y1) && (y <= y2)) ||
    ((y == y1) && (x >= x1) && (x <= x2)) ||
    ((y == y2) && (x >= x1) && (x <= x2))
) {
    cout << "Border" << endl;
}

Макар и верен, горният код съдържа едно дълго и сложно условие, което е трудно за разбиране. Можем да го опростим, като разделим голямото условие на няколко по-прости:

bool onLeftSide = ((x == x1) && (y >= y1) && (y <= y2));
bool onRightSide = ((x == x2) && (y >= y1) && (y <= y2));
bool onTopSide = ((y == y1) && (x >= x1) && (x <= x2));
bool onBottomSide = ((y == y2) && (x >= x1) && (x <= x2));
if (onLeftSide || onRightSide || onTopSide || onBottomSide) {
    cout << "Border" << endl;
}

Макар и по-дълго, второто решение с допълнителните булеви променливи е по-лесно за четене. Не е важно кодът да е кратък, важно е да е разбираем. Затова е добре, вместо да пишете едно дълго условия, да го разбиете на някокло по-кратки, чиито резултати да помните в променливи с описателни имена.

Остава да допишете кода така, че да отпечатва “Inside / Outside”, ако точката не лежи върху някоя от страните на правоъгълника.

Тестване в Judge системата

След като допишете решението, може да го тествате тук: https://judge.softuni.bg/Contests/Practice/Index/508#5.

Пример: магазин за плодове

Магазин за плодове в работни дни продава на следните цени:

Плод Цена
banana 2.50
apple 1.20
orange 0.85
grapefruit 1.45
kiwi 2.70
pineapple 5.50
grapes 3.85

В почивни дни цените са по-високи:

Плод Цена
banana 2.70
apple 1.25
orange 0.90
grapefruit 1.60
kiwi 3.00
pineapple 5.60
grapes 4.20

Напишете програма, която чете от конзолата плод (banana / apple / …), ден от седмицата (Monday / Tuesday / …) и количество (десетично число) и пресмята цената според цените от таблиците по-горе. Резултатът да се отпечата закръглен с 2 цифри след десетичния знак. При невалиден ден от седмицата или невалидно име на плод да се отпечата “error”.

Примерен вход и изход

Вход Изход Вход Изход
orange
Sunday
3
2.70 kiwi
Monday
2.5
6.75
Вход Изход Вход Изход
grapes
Saturday
0.5
2.10 tomato
Monday
0.5
error

Решение

Тестване в Judge системата

Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/508#6.

Пример: търговски комисионни

Фирма дава следните комисионни на търговците си според града, в който работят и обема на продажбите s:

Град 0 <= s <= 500 500 < s <= 1000 1000 < s <= 10000 s > 10000
Sofia 5% 7% 8% 12%
Varna 4.5% 7.5% 10% 13%
Plovdiv 5.5% 8% 12% 14.5%

Напишете програма, която чете име на град (стринг) и обем на продажбите (десетично число) и изчислява размера на комисионната. Резултатът да се изведе закръглен с 2 десетични цифри след десетичния знак. При невалиден град или обем на продажбите (отрицателно число) да се отпечата "error".

Примерен вход и изход

Вход Изход Вход Изход Вход Изход
Sofia
1500
120.00 Plovdiv
499.99
27.50 Kaspichan
-50
error

Решение

За да изчислим комисионната според града и обема на продажбите се нуждаем от няколко вложени if проверки.

За да разпознаем ако входът е навалиден, първоначално задаваме стойността на комисионната да е -1. Ако градът и ценовият диапазон бъдат намерени, тя ще бъде променена, а ако има грешка, ще остане отрицателна.

Тестване в Judge системата

Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/508#7.

Добра практика е да използваме блокове, които заграждаме с къдрави скоби { } след if и else. Също така, препоръчително e при писане да отместваме кода след if и else с една табулация навътре, за да направим кода по-лесно четим.

Условна конструкция switch-case

Използваме условната конструкция switch-case, когато искаме програмата ни да изпълнява различен код, в зависимост от стойността на променлива или израз. Тази променлива или израз се нарича селектор и се поставя в скобите след оператора switch. Следват няколко case: етикета, всеки от които се състои от константна стойност и код, който да се изпълни, в случай че стойността на селектора е равна на тази константа. Може да има и етикет default:, който е следван от код, който се изпълнява, ако стойността на селектора не е равна на никоя от константите на case: етикетитие. Общият синтаксис на switch-case е следния:

switch (селектор) {
    case стойност1:
        //тяло
        break;
    case стойност2:
        //тяло
        break;
    case стойност3:
        //тяло
        break;
    …
    default:
        //тяло
        break;
}

Ако съществува case: етикет, равен на стойността на селектора, започва да се изпълнява кодът от етикета надолу. Ако няма няма такъв етикет, но има етикет default:, тогава се започва да се изпълнява кода след default:. Изпълнението на кода продължава до срещането на оператора break;. Затова всеки етикет трябва да завършва с break;, тъй като в противен случай ще се изпълни и кодът, предвиден за следващите етикети.

Всички стойности в `case: етикетите трябва да са константи и да се различават помежду си (т.е. да не се повтарят). Освен това в C++ селекторът и стойностите в case: етикетите трябва да са цели числа (int). За разлика от други езици за програмиране, C++ не позволява използването на конструкция switch-case с низове (string), или дробни числа (double).

Switch-case може винаги да бъде заместен чрез няколко if-else конструкции. Общият код за switch-case, написан горе, е еквивалентен на следния код, използващ if-else конструкции:

if (селектор == стойност1) {
    //тяло
} else if (селектор == стойност2) {
    //тяло
} else if (селектор == стойност3) {
    //тяло
} else if (селектор == стойност4) {
…
} else {
    //тяло
}

Кодът, иползващ switch-case, обаче е за предпочитане, тъй като е по-ясен и по-лесен за подръжка. Освен това вариантът със switch-case обикновенно работи по-бързо, поради оптимизации на компилатора.

Пример: ден от седмицата

Нека напишем програма, която принтира деня от седмицата (на английски) според въведеното число (1 … 7) или "Error!", ако е въведено невалидно число.

Примерен вход и изход

Вход Изход
1 Monday
7 Sunday
-1 Error!

Решение

switch(day) {
    case 1:
        cout << "Monday" << endl;
        break;
    case 2:
        cout << "Tuesday" << endl;
        break;
    …
    case 7:
        cout << "Sunday" << endl;
        break;
    default:
        cout << "Error!" << endl;
}
Добра практика е на първо място да поставяме онези case случаи, които обработват най-често случилите се ситуации, а case конструкциите, обработващи по-рядко възникващи ситуации, да оставим в края преди default конструкцията. Друга добра практика е да подреждаме case етикетите в нарастващ ред, без значение дали са целочислени или символни.

Тестване в Judge системата

Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/508#8.

Пример: вид животно

Напишете програма, която принтира вида на животно според името му:

  • dog -> mammal
  • crocodile, tortoise, snake -> reptile
  • others -> unknown

Примерен вход и изход

Вход Изход Вход Изход Вход Изход
tortoise reptile dog mammal elephant unknown

Решение

В тази задача не можем да използваме switch-case, тъй като трябва да сравняваме низове, а не цели числа. Можем да я решим чрез няколко if-else проверки:

if (animal == "dog) {
    cout << "mammal" << endl;
} else if ((animal == "crocodile")
        || (animal == "tortoise")
        || (animal == "snake")) {
    cout << "reptile" << endl;
} else {
    cout << "unknown" << endl;
}

Тестване в Judge системата

Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/508#9.

Какво научихме от тази глава?

Да си припомним новите конструкции и програмни техники, с които се запознахме в тази глава.

Вложени проверки

if (условие1) {
    if (условие2) {
        //тяло
    } else {
        //тяло
    }
}

По-сложни проверки с &&, ||, ! и ()

if (((x == left) || (x == right)) && (y >= top) && (y <= bottom)) {
    //тяло
}

Switch-case проверки

switch (селектор)
{
    case стойност1:
        //тяло
        break;
    case стойност2:
        //тяло
        break;
    case стойност3:
        //тяло
        break;
    …
    default:
        //тяло
        break;
}

Упражнения: по-сложни проверки

Нека сега да упражним работата с по-сложни проверки. Да решим няколко практически задачи.

Задача: кино

В една кинозала столовете са наредени в правоъгълна форма в r реда и c колони. Има три вида прожекции с билети на различни цени:

  • Premiere – премиерна прожекция, на цена 12.00 лева.
  • Normal – стандартна прожекция, на цена 7.50 лева.
  • Discount – прожекция за деца, ученици и студенти на намалена цена от 5.00 лева.

Напишете програма, която въвежда тип прожекция (стринг), брой редове и брой колони в залата (цели числа) и изчислява общите приходи от билети при пълна зала. Резултатът да се отпечата във формат като в примерите по-долу - с 2 цифри след десетичния знак.

Примерен вход и изход

Вход Изход Вход Изход
Premiere
10
12
1440.00 leva Normal
21
13
2047.50 leva

Насоки и подсказки

При прочитането на входа можем да обърнем типа на прожекцията в малки букви (с функцията .ToLower()). Създаваме и инициализираме променлива, която ще ни съхранява изчислените приходи. В друга променлива пресмятаме пълния капацитет на залата. Използваме switch-case условна конструкция, за да изчислим прихода в зависимост от вида на прожекцията и отпечатваме резултата на конзолата в зададения формат (потърсете нужната C++ функционалност в интернет).

Примерен код (части от кода са замъглени с цел да се стимулира самостоятелно мислене и решение):

Тестване в Judge системата

Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/508#10.

Задача: волейбол

Влади е студент, живее в София и си ходи от време на време до родния град. Той е много запален по волейбола, но е зает през работните дни и играе волейбол само през уикендите и в празничните дни. Влади играе в София всяка събота, когато не е на работа и не си пътува до родния град, както и в 2/3 от празничните дни. Той пътува до родния си град h пъти в годината, където играе волейбол със старите си приятели в неделя. Влади не е на работа 3/4 от уикендите, в които е в София. Отделно, през високосните години Влади играе с 15% повече волейбол от нормалното. Приемаме, че годината има точно 48 уикенда, подходящи за волейбол. Напишете програма, която изчислява колко пъти Влади е играл волейбол през годината. Закръглете резултата надолу до най-близкото цяло число (напр. 2.15 -> 2; 9.95 -> 9).

Входните данни се четат от конзолата:

  • Първият ред съдържа думата “leap” (високосна година) или “normal” (нормална година с 365 дни).
  • Вторият ред съдържа цялото число p – брой празници в годината (които не са събота или неделя).
  • Третият ред съдържа цялото число h – брой уикенди, в които Влади си пътува до родния град.

Примерен вход и изход

Вход Изход Вход Изход
leap
5
2
45 normal
3
2
38
Вход Изход Вход Изход
normal
11
6
44 leap
0
1
41

Насоки и подсказки

Стандартно прочитаме входните данни от конзолата като за избягване на грешки при въвеждане обръщаме текста в малки букви с функцията .ToLower(). Последователно пресмятаме уикендите прекарани в София, времето за игра в София и общото време за игра. Накрая проверяваме дали годината е високосна, правим допълнителни изчисления при необходимост и извеждаме резултата на конзолата закръглен надолу до най-близкото цяло число (потърсете C++ клас с такава функционалност в интернет).

Примерен код (части от кода са замъглени с цел да се стимулира самостоятелно мислене и решение):

Тестване в Judge системата

Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/508#11.

Задача: * точка във фигурата

Фигура се състои от 6 блокчета с размер h * h, разположени като на фигурата. Долният ляв ъгъл на сградата е на позиция {0, 0}. Горният десен ъгъл на фигурата е на позиция {2*h, 4*h}. На фигурата координатите са дадени при h = 2:

Да се напише програма, която въвежда цяло число h и координатите на дадена точка {x, y} (цели числа) и отпечатва дали точката е вътре във фигурата (inside), вън от фигурата (outside) или на някоя от стените на фигурата (border).

Примерен вход и изход

Вход Изход Вход Изход
2
3
10
outside 2
3
1
inside
2
2
2
border 2
6
0
border
2
0
6
outside 15
13
55
outside
15
29
37
inside 15
37
18
outside
15
-4
7
outside 15
30
0
border

Насоки и подсказки

Примерна логика за решаване на задачата (не е единствената правилна):

  • Може да разделим фигурата на два правоъгълника с обща стена:

  • Една точка е външна (outside) за фигурата, когато е едновременно извън двата правоъгълника.
  • Една точка е вътрешна (inside) за фигурата, ако е вътре в някой от правоъгълниците (изключвайки стените им) или лежи върху общата им стена.
  • В противен случай точката лежи на стената на правоъгълника (border).

Примерен код (части от кода са замъглени с цел да се стимулира самостоятелно мислене и решение):

Тестване в Judge системата

Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/508#12.

results matching ""

    No results matching ""