Глава 2.2. Прости пресмятания с числа – изпитни задачи
В предходната глава се запознахме с това как да подадем число на функция и как да отпечатаме резултат на конзолата. Разгледахме основните аритметични операции и накратко споменахме типовете данни. В настоящата глава ще упражним и затвърдим наученото досега, като разгледаме няколко по-сложни задачи, давани на изпити.
Четене на числа
Преди да преминем към задачите, да си припомним най-важното от изучавания материал в предходната тема. Ще започнем със създаването на функция, която прочита число.
Четене на цяло число
Необходима ни е функция, на която се подава един аргумент arg1
. В нея ще създадем променлива, в която да запазим числото (напр. num
), в съчетание с метода parseInt(…)
, който конвертира текст в число:
function readNumber(arg1) {
let num = parseInt(arg1);
}
Четене на дробно число
По същия начин, както четем цяло число, но този път ще използваме метода parseFloat(…)
:
let num = parseFloat(arg1);
Извеждане на текст по шаблон (placeholder)
Placeholder представлява израз, който ще бъде заменен с конкретна стойност при отпечатване. За да работи шаблонът, трябва да използваме наклонени апострофи (backticks) `…`
. Методът console.log(…)
поддържа печатане на текст по шаблон, като аргументите, които трябва да отпечатаме, се задават в ${…}
:
let firstName = "Ivan";
let lastName = "Ivanov";
let age = 19;
let town = "Sofia";
console.log(`You are ${firstName} ${lastName}, a ${age}-years old person from ${town}.`);
// You are Ivan Ivanov, a 19-years old person from Sofia.
Аритметични оператори
Да си припомним основните аритметични оператори за пресмятания с числа.
Оператор +
let result = 3 + 5; // резултатът е 8
Оператор -
let result = 3 - 5; // резултатът е -2
Оператор *
let result = 3 * 5; // резултатът е 15
Оператор /
let result2 = 5 / 2; // резултатът е 2.5 (дробно деление)
Конкатенация
При използване на оператора +
между променливи от тип текст (или между текст и число) се извършва т.нар. конкатенация (слепване на низове):
let firstName = "Ivan";
let lastName = "Ivanov";
let age = 19;
let str = firstName + " " + lastName + " is " + age + " years old";
// Ivan Ivanov is 19 years old
Изпитни задачи
Сега, след като си припомнихме как се четат и печатат числа на конзолата и как се извършват пресмятания с тях, можем да преминем към задачите. Ще решим няколко задачи от приемен изпит за кандидатстване в СофтУни.
Задача: учебна зала
Учебна зала има правоъгълен размер l на w метра, без колони във вътрешността си. Залата е разделена на две части – лява и дясна, с коридор - приблизително по средата. В лявата и в дясната част има редици с бюра. В задната част на залата има голяма входна врата. В предната част на залата има катедра с подиум за преподавателя. Едно работно място заема 70 на 120 cm (маса с размер 70 на 40 cm + място за стол и преминаване с размер 70 на 80 cm). Коридорът е широк поне 100 cm. Изчислено е, че заради входната врата (която е с отвор 160 cm) се губи точно 1 работно място, а заради катедрата (която е с размер 160 на 120 cm) се губят точно 2 работни места. Напишете програма, която въвежда размери на учебната зала и изчислява броя работни места в нея при описаното разположение (вж. фигурата).
Входни данни
Програмата чете 2 числа (аргумента), по едно на ред: l (дължина в метри) и w (широчина в метри).
Ограничения: 3 ≤ w ≤ l ≤ 100.
Изходни данни
Да се отпечата на конзолата едно цяло число: броят места в учебната зала.
Примерен вход и изход
Вход | Изход | Чертеж |
---|---|---|
15 8.9 |
129 | |
8.4 5.2 |
39 |
Пояснения към примерите
В първия пример залата е дълга 1500 cm. В нея могат да бъдат разположени 12 реда (12 * 120 cm = 1440 + 60 cm остатък). Залата е широка 890 cm. От тях 100 cm отиват за коридора в средата. В останалите 790 cm могат да се разположат по 11 бюра на ред (11 * 70 cm = 770 cm + 20 cm остатък). Брой места = 12 * 11 - 3 = 132 - 3 = 129 (имаме 12 реда по 11 места = 132 минус 3 места за катедра и входна врата).
Във втория пример залата е дълга 840 cm. В нея могат да бъдат разположени 7 реда (7 * 120 cm = 840, без остатък). Залата е широка 520 cm. От тях 100 cm отиват за коридора в средата. В останалите 420 cm могат да се разположат по 6 бюра на ред (6 * 70 cm = 420 cm, без остатък). Брой места = 7 * 6 - 3 = 42 - 3 = 39 (имаме 7 реда по 6 места = 42 минус 3 места за катедра и входна врата).
Насоки и подсказки
Опитайте първо сами да решите задачата. Ако не успеете, разгледайте насоките и подсказките.
Идея за решение
Както при всяка една задача по програмиране, е важно да си изградим идея за решението ѝ, преди да започнем да пишем код. Да разгледаме внимателно зададеното ни условие. Изисква се да напишем програма, която да изчислява броя работни места в една зала, като този брой е зависим от дължината и височината ѝ. Забелязваме, че те ще ни бъдат подадени като входни данни в метри, а информацията за това колко пространство заемат работните места и коридорът, ни е дадена в сантиметри. За да извършим изчисленията, ще трябва да използваме еднакви мерни единици, няма значение дали ще изберем да превърнем височината и дължината в сантиметри, или останалите данни в метри. За представеното тук решение е избрана първата опция.
Следва да изчислим колко колони и колко редици с бюра ще се съберат. Колоните можем да пресметнем като от широчината извадим необходимото място за коридора (100 cm) и разделим остатъка на 70 cm (колкото е дължината на едно работно място). Редиците ще намерим, като разделим дължината на 120 cm. И при двете операции може да се получи реално число с цяла и дробна част, но в променлива трябва да запазим само цялата част. Накрая умножаваме броя на редиците по този на колоните и от него изваждаме 3 (местата, които се губят заради входната врата и катедрата). Така ще получим исканата стойност.
Избор на типове данни
От примерните входни данни виждаме, че за вход може да ни бъде подадено реално число с цяла и дробна част, но тъй като в JavaScript има само един примитивен тип за числа (Number
), това няма да е проблем. Изборът на тип за следващите променливи зависи от метода за решение, който изберем. Както всяка задача по програмиране, тази също има повече от един начин на решение.
Решение
Време е да пристъпим към решението. Мислено можем да го разделим на три подзадачи:
- Прочитане на входните данни.
- Извършване на изчисленията.
- Извеждане на изход на конзолата.
Първото, което трябва да направим, е да вземем входните данни. Създаваме си функция, на която се подават два аргумента. Запазваме техните стойности в две променливи, като използваме метода parseFloat(…)
за преобразуване на зададената стрингова (текстова) стойност в дробно число:
Нека пристъпим към изчисленията. Особеното тук е, че след като извършим делението, трябва да запазим в променлива само цялата част от резултата.
Търсете в Google! Винаги, когато имаме идея как да решим даден проблем, но не знаем как да го изпишем на JavaScript, или когато се сблъскаме с такъв, за който предполагаме, че много други хора са имали, най-лесно е да се справим като потърсим информация в Интернет. |
В случая може да пробваме със следното търсене: "JavaScript get whole number part of double". Откриваме, че една от възможностите е да използваме метода Math.trunc(…)
. Кодът по-долу е целенасочено замъглен и трябва да бъде довършен от читателя:
С console.log(…)
отпечатваме резултата на конзолата:
Тестване в Judge системата
Тествайте решението си тук: https://judge.softuni.org/Contests/Practice/Index/928#0.
Задача: зеленчукова борса
Градинар продава реколтата от градината си на зеленчуковата борса. Продава зеленчуци за N лева на килограм и плодове за M лева за килограм. Напишете програма, която да пресмята приходите от реколтата в евро (ако приемем, че едно евро е равно на 1.94 лв.).
Входни данни
На функцията се подават 4 аргумента:
- Цена за килограм зеленчуци – число с плаваща запетая.
- Цена за килограм плодове – число с плаваща запетая.
- Общо килограми на зеленчуците – цяло число.
- Общо килограми на плодовете – цяло число.
Ограничения: Всички числа ще са в интервала от 0.00 до 1000.00
Изходни данни
Да се отпечата на конзолата едно число с плаваща запетая: приходите от всички плодове и зеленчуци в евро.
Примерен вход и изход
Вход | Изход |
---|---|
0.194 19.4 10 10 |
101 |
Пояснения към първия пример:
- Зеленчуците струват: 0.194 лв. * 10 кг. = 1.94 лв.
- Плодовете струват: 19.4 лв. * 10 кг. = 194 лв.
- Общо: 195.94 лв. = 101 евро.
Вход | Изход |
---|---|
1.5 2.5 10 10 |
20.6185567010309 |
Насоки и подсказки
Първо ще дадем няколко разсъждения, а след това и конкретни насоки за решаване на задачата, както и съществената част от кода.
Идея за решение
Нека първо разгледаме зададеното ни условие. В случая, от нас се иска да пресметнем колко е общият приход от реколтата. Той е равен на сбора от печалбата от плодовете и зеленчуците, а тях можем да изчислим като умножим цената на килограм по количеството им. Входните данни са дадени в лева, а за изхода се изисква да бъде в евро. По условие 1 евро е равно на 1.94 лева, следователно, за да получим исканата изходна стойност, трябва да разделим сбора на 1.94.
Избор на типове данни
След като сме изяснили идеята си за решаването на задачата, можем да пристъпим към избора на подходящи типове данни. Да разгледаме входа: дадени са две цели числа за общия брой килограми на зеленчуците и плодовете, съответно променливите, които декларираме, за да пазим техните стойности, могат да бъдат конвертирани към число с parseInt(…)
. За цените на плодовете и зеленчуците е указано, че ще бъдат подадени две числа с плаваща запетая, т.е. променливите ще бъдат преобразувани с метода parseFloat(…)
.
Решение
Време е да пристъпим към решението. Мислено можем да го разделим на три подзадачи:
- Прочитане на входните данни.
- Извършване на изчисленията.
- Извеждане на изход на конзолата.
За да прочетем входните данни, декларираме променливи, като внимаваме да ги именуваме по такъв начин, който да ни подсказва какви стойности съдържат променливите. С методите parseInt(…)
и parseFloat(…)
преобразуваме зададената текстова стойност съответно в цяло и дробно число.
Извършваме необходимите изчисления:
В условието на задачата не е зададено специално форматиране на изхода, следователно трябва просто да изчислим исканата стойност и да я отпечатаме на конзолата. Както в математиката, така и в програмирането делението има приоритет пред събирането. За задачата обаче трябва първо да изчислим сбора на двете получени стойности и след това да разделим на 1.94. За да дадем предимство на събирането, може да използваме скоби. С console.log(…)
отпечатваме изхода на конзолата:
Тестване в Judge системата
Тествайте решението си тук: https://judge.softuni.org/Contests/Practice/Index/928#1.
Задача: ремонт на плочки
На площадката пред жилищен блок трябва да се поставят плочки. Площадката е с форма на квадрат със страна N метра. Плочките са широки „W“ метра и дълги „L“ метра. На площадката има една пейка с ширина M метра и дължина O метра. Под нея не е нужно да се слагат плочки. Всяка плочка се поставя за 0.2 минути.
Напишете програма, която чете от конзолата размерите на площадката, плочките и пейката и пресмята колко плочки са необходими да се покрие площадката и пресмята времето за поставяне на всички плочки.
Пример: площадка с размер 20 м. има площ 400 кв.м.. Пейка, широка 1 м. и дълга 2 м., заема площ 2 кв.м. Една плочка е широка 5 м. и дълга 4 м. и има площ = 20 кв.м. Площта, която трябва да се покрие, е 400 – 2 = 398 кв.м. Необходими са 398 / 20 = 19.90 плочки. Необходимото време е 19.90 * 0.2 = 3.98 минути.
Входни данни
На функцията се подават 5 аргумента:
- N – дължината на страна от площадката в интервала [1 … 100].
- W – широчината на една плочка в интервала [0.1 … 10.00].
- L – дължината на една плочка в интервала [0.1 … 10.00].
- М – широчината на пейката в интервала [0 … 10].
- О – дължината на пейката в интервала [0 … 10].
Изходни данни
Да се отпечатат на конзолата две числа:
- броя плочки, необходим за ремонта
- времето за поставяне
Всяко число да бъде на нов ред и закръглено до втория знак след десетичната запетая.
Примерен вход и изход
Вход | Изход |
---|---|
20 5 4 1 2 |
19.9 3.98 |
Обяснение към примера:
- Обща площ = 20 * 20 = 400.
- Площ на пейката = 1 * 2 = 2.
- Площ за покриване = 400 – 2 = 398.
- Площ на плочки = 5 * 4 = 20.
- Необходими плочки = 398 \/ 20 = 19.9.
- Необходимо време = 19.9 * 0.2 = 3.98.
Вход | Изход |
---|---|
40 0.8 0.6 3 5 |
3302.08 660.42 |
Насоки и подсказки
Нека да си направим чертеж, за да поясним условието на задачата. Той може да изглежда по следния начин:
Идея за решение
Изисква се да пресметнем броя плочки, който трябва да се постави, както и времето, за което това ще се извърши. За да изчислим броя, е необходимо да сметнем площта, която трябва да се покрие, и да я разделим на лицето на една плочка. По условие площадката е квадратна, следователно общата площ ще намерим, като умножим страната ѝ по стойността ѝ N * N
. След това пресмятаме площта, която заема пейката, също като умножим двете ѝ страни M * O
. Като извадим площта на пейката от тази на цялата площадка, получаваме площта, която трябва да се ремонтира.
Лицето на единична плочка изчисляваме като умножим едната ѝ страна по другата W * L
. Както вече отбелязахме, сега трябва да разделим площта за покриване на площта на една плочка. По този начин ще разберем какъв е необходимият брой плочки. Него умножаваме по 0.2 (времето, за което по условие се поставя една плочка). Така вече ще имаме исканите изходни стойности.
Избор на типове данни
Дължината на страна от площадката, широчината и дължината на пейката ще бъдат дадени като цели числа, следователно, за да запазим техните стойности може да декларираме променливи, преобразувани с метода parseInt(…)
. За широчината и дължината на плочките ще ни бъдат подадени реални числа (с цяла и дробна част), затова за тях ще използваме parseFloat(…)
.
Решение
Както и в предходните задачи, можем мислено да разделим решението на три части:
- Прочитане на входните данни.
- Извършване на изчисленията.
- Извеждане на изход на конзолата.
Първото, което трябва да направим, е да разгледаме входните данни на задачата. Важно е да внимаваме за последователността, в която са дадени. Създаваме си необходимите променливи, в които да запазим входните данни, а с методите parseInt(…)
и parseFloat(…)
преобразуваме подадената стрингова стойност, съответно в цяло или дробно число:
След като сме инициализирали променливите и сме запазили съответните стойности в тях, пристъпваме към изчисленията. Кодът по-долу е нарочно даден замъглен, за да може читателят да помисли самостоятелно над него:
Изчисляваме стойностите, които трябва да отпечатаме на конзолата. Броят на необходимите плочки получаваме, като разделим площта, която трябва да се покрие, на площта на единична плочка.
В условието на задачата е зададено закръгляне на изхода до втория знак след десетичната запетая. Затова не можем просто отпечатаме стойностите с console.log(…)
. Ще използваме метода Math.round(…)
, който закръгля подаденото число до най-близкото цяло число. За да не загубим двата знака след запетаята, прилагаме метода върху числото умножено по 100, а после делим получения резултат на 100:
Тестване в Judge системата
Тествайте решението си тук: https://judge.softuni.org/Contests/Practice/Index/928#2.
Задача: парички
Преди време Пешо си е купил биткойни. Сега ще ходи на екскурзия из Европа и ще му трябва евро. Освен биткойни има и китайски юани. Пешо иска да обмени парите си в евро за екскурзията. Напишете програма, която да пресмята колко евро може да купи спрямо следните валутни курсове:
- 1 биткойн = 1168 лева.
- 1 китайски юан = 0.15 долара.
- 1 долар = 1.76 лева.
- 1 евро = 1.95 лева.
Обменното бюро има комисионна от 0 до 5 процента от крайната сума в евро.
Входни данни
На функцията се подават 3 аргумента:
- Броят биткойни - цяло число в интервала [0 … 20].
- Броят китайски юани - реално число в интервала [0.00 … 50 000.00].
- Комисионната - реално число в интервала [0.00 … 5.00].
Изходни данни
На конзолата да се отпечата 1 число - резултатът от обмяната на валутите. Резултатът да се форматира до втората цифра след десетичния знак.
Примерен вход и изход
Вход | Изход |
---|---|
1 5 5 |
569.67 |
Обяснение:
- 1 биткойн = 1168 лева
- 5 юана = 0.75 долара
- 0.75 долара = 1.32 лева
- 1168 + 1.32 = 1169.32 лева = 599.651282051282 евро
- Комисионна: 5% от 599.651282051282 = 29.9825641025641
- Резултат: 599.651282051282 - 29.9825641025641 = 569.668717948718 евро
Вход | Изход | Вход | Изход |
---|---|---|---|
20 5678 2.4 |
12442.24 | 7 50200.12 3 |
10659.47 |
Насоки и подсказки
Нека отново помислим първо за начина, по който можем да решим задачата, преди да започнем да пишем код.
Идея за решение
Виждаме, че ще ни бъдат подадени броят биткойни и броят китайски юани. За изходната стойност е указано да бъде в евро. В условието са посочени и валутните курсове, с които трябва да работим. Забелязваме, че към евро можем да преобразуваме само сума в лева, следователно трябва първо да пресметнем цялата сума, която Пешо притежава в лева, и след това да изчислим изходната стойност.
Тъй като ни е дадена информация за валутния курс на биткойни срещу лева, можем директно да направим това преобразуване. От друга страна, за да получим стойността на китайските юани в лева, трябва първо да ги конвертираме в долари, а след това доларите - в лева. Накрая ще съберем двете получени стойности и ще пресметнем на колко евро съответстват.
Остава последната стъпка: да пресметнем колко ще бъде комисионната и да извадим получената сума от общата. Като комисионна ще ни бъде подадено реално число, което ще представлява определен процент от общата сума. Нека още в началото разделим подаденото число на 100, за да изчислим процентната му стойност. Нея ще умножим по сумата в евро, а резултатът ще извадим от същата тази сума. Получената сума ще отпечатаме на конзолата.
Избор на типове данни
Биткойните са дадени като цяло число, следователно за тяхната стойност може да декларираме променлива преобразувана с метода parseInt(…)
. Като брой китайски юани и комисионна ще получим реално число, следователно за тях използваме parseFloat(…)
.
Решение
След като сме си изградили идея за решението на задачата и сме избрали структурите от данни, с които ще работим, е време да пристъпим към писането на код. Както и в предните задачи, можем да разделим решението на три подзадачи:
- Прочитане на входните данни.
- Извършване на изчисленията.
- Извеждане на изход на конзолата.
Декларираме променливите, които ще използваме, като отново внимаваме да изберем смислени имена, които подсказват какви данни съдържат те. Инициализираме техните стойности: създаваме си променливи, в който да запазим подадените на функцията стрингови аргументи, като ги конвертираме към цяло или дробно число:
Извършваме необходимите изчисления:
Накрая пресмятаме стойността на комисионната и я изваждаме от сумата в евро. Нека обърнем внимание на начина, по който можем да изпишем това: euro -= commission * euro
e съкратен начин за изписване на euro = euro - (commission * euro)
. В случая използваме комбиниран оператор за присвояване (-=
), който изважда стойността от операнда вдясно от този вляво. Операторът за умножение (*
) има по-висок приоритет от комбинирания оператор, затова изразът commission * euro
се изпълнява първи, след което неговата стойност се изважда.
Накрая остава да изведем резултата на конзолата. Забелязваме, че се изисква форматиране на числената стойност до втория знак след десетичната точка. За разлика от предходната задача, тук дори и числото да е цяло, трябва винаги да има два знака след десетичната точка (например 5.00
). За целта можем да използваме метода toFixed(…)
. С него можем да преобразуваме числото в текст, запазвайки определен брой знаци след десетичната запетая:
Нека обърнем внимание на нещо, което важи за всички задачи от този тип: разписано по този начин, решението на задачата е доста подробно. Тъй като условието като цяло не е сложно, бихме могли на теория да напишем един голям израз, в който директно след получаване на входните данни да сметнем изходната стойност. Например такъв израз би изглеждал ето така:
Този код би дал правилен резултат, но се чете трудно. Няма да ни е лесно да разберем какво прави, дали съдържа грешки и ако има такива - как да ги поправим. По-добра практика е вместо един сложен израз да напишем няколко прости и да запишем резултатите от тях в променливи със подходящи имена. Така кодът е ясен, по-лесно четим и променяем.
Тестване в Judge системата
Тествайте решението си тук: https://judge.softuni.org/Contests/Practice/Index/928#3.
Задача: дневна печалба
Иван е програмист в американска компания и работи от вкъщи средно N дни в месеца, като изкарва средно по M долара на ден. В края на годината Иван получава бонус, който е равен на 2.5 месечни заплати. От спечеленото през годината му се удържат 25% данъци. Напишете програма, която да пресмята колко е чистата средна печалба на Иван на ден в лева, тъй като той харчи изкараното в България. Приема се, че в годината има точно 365 дни. Курсът на долара спрямо лева ще се подава на функцията.
Входни данни
На функцията се подават 3 аргумента:
- Работни дни в месеца - цяло число в интервала [5 … 30].
- Изкарани пари на ден - реално число в интервала [10.00 … 2000.00].
- Курсът на долара спрямо лева /1 долар = X лева/ - реално число в интервала [0.99 … 1.99].
Изходни данни
На конзолата да се отпечата едно число – средната печалба на ден в лева. Резултатът да се форматира до втората цифра след десетичния знак.
Примерен вход и изход
Вход | Изход |
---|---|
21 75.00 1.59 |
74.61 |
Обяснение:
- 1 месечна заплата = 21 * 75 = 1575 долара.
- Годишен доход = 1575 * 12 + 1575 * 2.5 = 22837.5 долара.
- Данък = 25% от 22837.5 = 5709.375 лева.
- Чист годишен доход = 17128.125 долара = 27233.71875 лева.
- Средна печалба на ден = 27233.71875 / 365 = 74.61 лева.
Вход | Изход | Вход | Изход |
---|---|---|---|
15 105 1.71 |
80.24 | 22 199.99 1.50 |
196.63 |
Насоки и подсказки
Първо да анализираме задачата и да измислим как да я решим. След това ще изберем типовете данни и накрая ще напишем кода на решението.
Идея за решение
Нека първо пресметнем колко е месечната заплата на Иван. Това ще направим като умножим работните дни в месеца по парите, които той печели на ден. Умножаваме получения резултат първо по 12, за да изчислим колко е заплатата му за 12 месеца, а след това и по 2.5, за да пресметнем бонуса. Като съберем двете получени стойности, ще изчислим общия му годишен доход. От него трябва да извадим 25%. Това може да направим като умножим общия доход по 0.25 и извадим резултата от него. Спрямо дадения ни курс преобразуваме доларите в лева, след което разделяме резултата на дните в годината, за които приемаме, че са 365.
Избор на типове данни
Работните дни за месец са дадени като цяло число, следователно за тяхната стойност може да декларираме променлива, в която да конвертираме до число с метода parseInt(…)
. За изкараните пари, както и за курса на долара спрямо лева, ще получим реално число, следователно за тях използваме parseFloat(…)
.
Решение
Отново, след като имаме идея как да решим задачата и сме помислили за типовете данни, с които ще работим, пристъпваме към писането на програмата. Както и в предходните задачи, можем да разделим решението на три подзадачи:
- Прочитане на входните данни.
- Извършване на изчисленията.
- Извеждане на изход на конзолата.
Декларираме променливите, които ще използваме, като отново се стараем да изберем подходящи имена. Създаваме си променливи, в които запазваме подадените аргументи на функцията, като преобразуваме стринга към цяло или дробно число с parseInt(…)/parseFloat(…)
:
Извършваме изчисленията:
Бихме могли да напишем израза, с който пресмятаме общия годишен доход, и без скоби. Тъй като умножението е операция с по-висок приоритет от събирането, то ще се извърши първо. Въпреки това писането на скоби се препоръчва, когато използваме повече оператори, защото така кодът става по-лесно четим и възможността да се допусне грешка е по-малка.
Накрая остава да изведем резултата на екрана. Забелязваме, че се изисква форматиране на числената стойност до втория знак след десетичната точка. Можем да използваме метода .toFixed(…)
по същия начин като в предходната задача:
Тестване в Judge системата
Тествайте решението си тук: https://judge.softuni.org/Contests/Practice/Index/928#4.