Глава 5.2. Повторения (цикли) – изпитни задачи
В предходната глава научихме как да изпълним даден блок от команди повече от веднъж. Затова въведохме for
цикъл и разгледахме някои от основните му приложения. Целта на настоящата глава е да затвърдим знанията си, решавайки няколко по-сложни задачи с цикли, давани на приемни изпити. За някои от тях ще покажем примерни подробни решения, а за други ще оставим само напътствия.
Преди да се захванем за работа е добре да си припомним конструкцията на цикъла for
:
for
циклите се състоят от:
- Инициализационен блок, в който се декларира променливата-брояч (
let i
) и се задава нейна начална стойност. - Условие за повторение (
i <= 10
), изпълняващо се веднъж, преди всяка итерация на цикъла. - Обновяване на брояча (
i++
) – този код се изпълнява след всяка итерация. - Тяло на цикъла - съдържа произволен блок със сорс код.
Изпитни задачи
Да решим няколко задачи с цикли от изпити в СофтУни.
Задача: хистограма
Дадени са n цели числа в интервала [1 … 1000]. От тях някакъв процент p1 са под 200, процент p2 са от 200 до 399, процент p3 са от 400 до 599, процент p4 са от 600 до 799 и останалите p5 процента са от 800 нагоре. Да се напише програма, която изчислява и отпечатва процентите p1, p2, p3, p4 и p5.
Пример: имаме n = 20 числа: 53, 7, 56, 180, 450, 920, 12, 7, 150, 250, 680, 2, 600, 200, 800, 799, 199, 46, 128, 65. Получаваме следното разпределение и визуализация:
Група | Числа | Брой числа | Процент |
---|---|---|---|
< 200 | 53, 7, 56, 180, 12, 7, 150, 2, 199, 46, 128, 65 | 12 | p1 = 12 / 20 * 100 = 60.00% |
200 … 399 | 250, 200 | 2 | p2 = 2 / 20 * 100 = 10.00% |
400 … 599 | 450 | 1 | p3 = 1 / 20 * 100 = 5.00% |
600 … 799 | 680, 600, 799 | 3 | p4 = 3 / 20 * 100 = 15.00% |
≥ 800 | 920, 800 | 2 | p5 = 2 / 20 * 100 = 10.00% |
Входни данни
На първия ред (аргумент) от входа стои цялото число n (1 ≤ n ≤ 1000), което представлява броя редове с числа, които ще ни бъдат подадени. На следващите n реда (аргумента) стои по едно цяло число в интервала [1 … 1000] – числата, върху които да бъде изчислена хистограмата.
Изходни данни
Да се отпечата на конзолата хистограма от 5 реда, всеки от които съдържа число между 0% и 100%, форматирано с точност две цифри след десетичния знак (например 25.00%, 66.67%, 57.14%).
Примерен вход и изход
Вход | Изход | Вход | Изход |
---|---|---|---|
3 1 2 999 |
66.67% 0.00% 0.00% 0.00% 33.33% |
4 53 7 56 999 |
75.00% 0.00% 0.00% 0.00% 25.00% |
Вход | Изход | Вход | Изход |
---|---|---|---|
7 800 801 250 199 399 599 799 |
14.29% 28.57% 14.29% 14.29% 28.57% |
9 367 99 200 799 999 333 555 111 9 |
33.33% 33.33% 11.11% 11.11% 11.11% |
Вход | Изход |
---|---|
14 53 7 56 180 450 920 12 7 150 250 680 2 600 200 |
57.14% 14.29% 7.14% 14.29% 7.14% |
Насоки и подсказки
Програмата, която решава този проблем, можем да разделим мислено на три части:
- Прочитане на входните данни – в настоящата задача това включва прочитането на числото n, последвано от n на брой цели числа, всяко на отделен ред.
- Обработка на входните данни – в случая това означава разпределяне на числата по групи и изчисляване на процентното разделение по групи.
- Извеждане на краен резултат – отпечатване на хистограмата на конзолата в посочения формат.
Прочитане на входните данни
Преди да преминем към самото прочитане на входните данни трябва да декларираме променливите, в които ще ги съхраняваме:
В променливата n
ще съхраняваме броя на числата, които ще трябва да четем. Допълнително си декларираме и променливите p1
, p2
и т.н., в които ще пазим броя на числата от съответната група.
След като сме си декларирали нужните променливи, можем да пристъпим към обработката на входните данни.
Обработка на входните данни
За да прочетем и разпределим всяко число в съответната му група, ще си послужим с for
цикъл от 0 до n
(броя на числата). Всяка итерация на цикъла ще прочита и разпределя едно единствено число (currentNum
) в съответната му група. За да определим дали едно число принадлежи към дадена група, правим проверка в съответния ѝ диапазон. Ако това е така - увеличаваме броя на числата в тази група (p1
, p2
и т.н.) с 1:
След като сме определили колко числа има във всяка група, можем да преминем към изчисляването на процентите, което е и главна цел на задачата. За това ще използваме следната формула:
(процент на група) = (брой числа в група) / (брой на всички числа) * 100
Тази формула в програмния код изглежда по следния начин:
В условието е казано, че процентите трябва да са с точност две цифри след десетичната точка. Имайки това предвид, към формулата добавяме метода .toFixed(...)
и за първата променлива тя ще изглежда така:
p1Percentage = (p1 / n * 100).toFixed(2);
//Добавете формулите за останалите променливи
За да стане още по-ясно какво се случва, нека разгледаме следния пример:
Вход | Изход |
---|---|
3 1 2 999 |
66.67% 0.00% 0.00% 0.00% 33.33% |
В случая n = 3
.
За цикъла имаме:
i = 0
- прочитаме числото 1, което е по-малко от 200 и попада в първата група (p1
), увеличаваме брояча на групата с 1.i = 1
– прочитаме числото 2, което отново попада в първата група (p1
) и увеличаваме брояча ѝ отново с 1.i = 2
– прочитаме числото 999, което попада в последната група (p5
), защото е по-голямо от 800, и увеличаваме брояча на групата с 1.
След прочитането на числата в група p1
имаме 2 числа, а в p5
имаме 1 число. В другите групи нямаме числа. Като приложим гореспоменатата формула, изчисляваме процентите на всяка група.
Извеждане на краен резултат
Остава само да отпечатаме получените резултати:
Тестване в Judge системата
Тествайте решението си тук: https://judge.softuni.org/Contests/Practice/Index/934#0.
Задача: умната Лили
Лили вече е на N години. За всеки свой рожден ден тя получава подарък. За нечетните рождени дни (1, 3, 5, …, n) получава играчки, а за всеки четен (2, 4, 6, …, n) получава пари. За втория рожден ден получава 10.00 лв., като сумата се увеличава с 10.00 лв. за всеки следващ четен рожден ден (2 -> 10, 4 -> 20, 6 -> 30 и т.н.). През годините Лили тайно е спестявала парите. Братът на Лили, в годините, които тя получава пари, взима по 1.00 лев от тях. Лили продала играчките, получени през годините, всяка за P лева и добавила сумата към спестените пари. С парите искала да си купи пералня за X лева. Напишете програма, която да пресмята колко пари е събрала и дали ѝ стигат да купи пералня.
Входни данни
Програмата прочита 3 числа (аргумента), въведени от потребителя, на отделни редове:
- Възрастта на Лили – цяло число в интервала [1 … 77].
- Цената на пералнята – число в интервала [1.00 … 10 000.00].
- Единична цена на играчка – цяло число в интервала [0 … 40].
Изходни данни
Да се отпечата на конзолата един ред:
- Ако парите на Лили са достатъчни:
- "Yes! {N}" – където N е остатъка пари след покупката
- Ако парите не са достатъчни:
- "No! {M}" – където M е сумата, която не достига
- Числата N и M трябва да са форматирани до втория знак след десетичната точка.
Примерен вход и изход
Вход | Изход | Коментари |
---|---|---|
10 170.00 6 |
Yes! 5.00 | Първи рожден ден получава играчка; 2ри -> 10 лв.; 3ти -> играчка; 4ти -> 10 + 10 = 20 лв.; 5ти -> играчка; 6ти -> 20 + 10 = 30 лв.; 7ми -> играчка; 8ми -> 30 + 10 = 40 лв.; 9ти -> играчка; 10ти -> 40 + 10 = 50 лв. |
21 1570.98 3 |
No! 997.98 | Спестила е 550 лв.. Продала е 11 играчки по 3 лв. = 33 лв. Брат ѝ взимал 10 години по 1 лев = 10лв. Останали 550 + 33 – 10 = 573 лв. |
Насоки и подсказки
Решението на тази задача, подобно на предходната, също можем да разделим мислено на три части – прочитане на входните данни, обработката им и извеждане на резултат.
Отново започваме с избора на подходящи имена на променливите. За годините на Лили (age
), цената на пералнята (washingMachinePrice
) и за единичната цена на играчката (toyPrice
). В кода по-горе декларираме и инициализираме (присвояваме стойност) също и променливите за броя на играчките (toysCount
), както и парите от рождените дни (moneyFromBirthdays
):
С for
цикъл преминаваме през всеки рожден ден на Лили. Когато водещата променлива е нечетно число, увеличаваме броя на играчките. Проверката за четност осъществяваме чрез деление с остатък (%
) на 2 – когато остатъкът е 0, числото е четно, а при остатък 1 - нечетно. Обратно, когато водещата променлива е четно число, това означава, че Лили е получила пари и съответно прибавяме тези пари към общите ѝ спестявания. Увеличаваме стойността на променливата moneyFromBirthdays
, т.е. увеличаваме с 10 сумата, която тя ще получи на следващия си рожден ден. Едновременно с това изваждаме по 1 лев - парите, които брат ѝ взема. Използваме съкратено записване, като добавяме два минуса след последния знак на променливата ( moneyFromBirthdays--
):
Вероятно ще се затрудните с пресмятането на парите за рождените дни, ако оставите бонуса да се натрупва по следния начин:
moneyFromBirthdays += 10;
Финалният резултат е 10 х 5 = 50, докато на нас ни е нужен 10 + 20 + 30 + 40 + 50 = 150. Можем да решим проблема с допълнителна променлива (bonusMoney
):
bonusMoney += 10;
moneyFromBirthdays += bonusMoney;
Или да включим стойността на променливата i
, която отброява повторенията и разделим на 2:
moneyFromBirthdays += 10 * i/2;
Към спестяванията на Лили прибавяме и парите от продадените играчки:
Накрая остава да отпечатаме получените резултати, като се съобразим с форматирането, указано в условието, т.е. сумата трябва да е закръглена до две цифри след десетичния знак:
За да спестим създаването на допълнителни променливи, използваме шаблонен литерал - ${израз}
. Той представлява текстов литерал с точно определена поредица от знаци, позволяващ вграждането на изрази. Чрез него можем да извършим изчислението и директно да включим резултата в текстовия низ.
Тестване в Judge системата
Тествайте решението си тук: https://judge.softuni.org/Contests/Practice/Index/934#1.
Задача: завръщане в миналото
Иванчо е на 18 години и получава наследство, което се състои от X сума пари и машина на времето. Той решава да се върне до 1800 година, но не знае дали парите ще са достатъчни, за да живее без да работи. Напишете програма, която пресмята дали Иванчо ще има достатъчно пари, за да не се налага да работи до дадена година включително. Като приемем, че за всяка четна (1800, 1802 и т.н.) година ще харчи 12 000 долара. За всяка нечетна (1801,1803 и т.н.) ще харчи 12 000 + 50 * [годините, които е навършил през дадената година].
Входни данни
Програмата прочита 2 числа (аргумента), въведени от потребителя на отделни редове:
- Наследените пари – реално число в интервала [1.00 … 1 000 000.00].
- Годината, до която трябва да живее (включително) – цяло число в интервала [1801 … 1900].
Изходни данни
Да се отпечата на конзолата 1 ред. Сумата трябва да е форматирана до два знака след десетичния знак:
- Ако парите са достатъчно:
- „Yes! He will live a carefree life and will have {N} dollars left.“ – където N са парите, които ще му останат.
- Ако парите НЕ са достатъчно:
- „He will need {М} dollars to survive.“ – където M е сумата, която НЕ достига.
Примерен вход и изход
Вход | Изход | Обяснения |
---|---|---|
50000 1802 |
Yes! He will live a carefree life and will have 13050.00 dollars left. |
1800 → четна |
100000.15 1808 |
He will need 12399.85 dollars to survive. |
1800 → четна |
Насоки и подсказки
Методът за решаване на тази задача не е по-различен от тези на предходните, затова започваме деклариране и инициализиране на нужните променливи. В условието е казано, че годините на Иванчо са 18, ето защо при декларацията на променливата years
ѝ задаваме начална стойност 18. Стойностите на другите променливи прочитаме от подадените параметри на функцията:
С помощта на for
цикъл ще обходим всички години. Започваме от 1800 – годината, в която Иванчо се връща, и стигаме до годината, до която той трябва да живее. В цикъла проверяваме дали текущата година е четна или нечетна. Проверката за четност осъществяваме чрез деление с остатък (%
) на 2. Ако годината е четна, изваждаме от наследството (heritage
) 12000, a ако е нечетна, изваждаме от наследството (heritage
) 12000 + 50 * (годините на Иванчо):
Накрая остава да отпечатаме резултатите, като за целта правим проверка дали наследството (heritage
) му е било достатъчно да живее без да работи или не. Ако наследството (heritage
) е положително число, отпечатваме: "Yes! He will live a carefree life and will have {N} dollars left.
", а ако е отрицателно число: "He will need {М} dollars to survive.
". Не забравяме да форматираме сумата до два знака след десетичната точка.
Hint: Обмислете използването на метода Math.abs(…)
при отпечатване на изхода, когато наследството е недостатъчно.
Тестване в Judge системата
Тествайте решението си тук: https://judge.softuni.org/Contests/Practice/Index/934#2.
Задача: болница
За даден период от време, всеки ден в болницата пристигат пациенти за преглед. Тя разполага първоначално със 7 лекари. Всеки лекар може да преглежда само по един пациент на ден, но понякога има недостиг на лекари, затова останалите пациенти се изпращат в други болници. Всеки трети ден болницата прави изчисления и ако броят на непрегледаните пациенти е по-голям от броя на прегледаните, се назначава още един лекар. Като назначаването става преди да започне приемът на пациенти за деня.
Напишете програма, която изчислява за дадения период броя на прегледаните и непрегледаните пациенти.
Входни данни
На първия ред (аргумент) от входа стои цяло число в интервала [1 … 1000] - периода, за който трябва да направите изчисления . На следващите редове (аргумента) стои по едно цяло число в интервала [1 … 10 000] – броя пациенти, които пристигат за преглед за текущия ден.
Изходни данни
Да се отпечатат на конзолата 2 реда:
- На първия ред: "Treated patients: {брой прегледани пациенти}."
- На втория ред: "Untreated patients: {брой непрегледани пациенти}."
Примерен вход и изход
Вход | Изход | Обяснения |
---|---|---|
4 7 27 9 1 |
Treated patients: 23. Untreated patients: 21. |
1 ден: 7 прегледани и 0 непрегледани пациента за деня |
Вход | Изход |
---|---|
6 25 25 25 25 25 2 |
Treated patients: 40. Untreated patients: 87. |
3 7 7 7 |
Treated patients: 21. Untreated patients: 0. |
Насоки и подсказки
Отново започваме, като декларираме и инициализираме нужните променливи. Периодът, за който трябва да направим изчисленията, прочитаме от параметрите на функцията и запазваме в променливата period
. Ще се нуждаем и от няколко помощни променливи: броя на излекуваните пациенти (treatedPatients
), броя на неизлекуваните пациенти (untreatedPatients
) и броя на докторите (countOfDoctors
), който първоначално е 7:
С помощта на for
цикъл обхождаме всички дни в дадения период (period
). За всеки ден прочитаме от конзолата броя на пациентите (currentPatients
). Увеличаването на докторите по условие може да стане всеки трети ден, НО само ако броят на непрегледаните пациенти е по-голям от броя на прегледаните. За тази цел проверяваме дали денят е трети – чрез аритметичния оператор за деление с остатък (%
): day % 3 == 0
.
Например:
- Ако денят е трети, остатъкът от делението на 3 ще бъде 0 (
3 % 3 = 0
) и проверкатаday % 3 == 0
ще върнеtrue
. - Ако денят е втори, остатъкът от делението на 3 ще бъде 2 (
2 % 3 = 2
) и проверката ще върнеfalse
. - Ако денят е четвърти, остатъкът от делението ще бъде 1 (
4 % 3 = 1
) и проверката отново ще върнеfalse
.
Ако проверката day % 3 == 0
върне true
, ще се провери дали и броят на неизлекуваните пациенти е по-голям от този на излекуваните: untreatedPatients > treatedPatients
. Ако резултатът отново е true
, тогава ще се увеличи броят на лекарите (countOfDoctors
).
След това проверяваме броя на пациентите за деня (currentPatients
) дали е по-голям от броя на докторите (countOfDoctors
). Ако броят на пациентите е по-голям:
- Увеличаваме стойността на променливата
treatedPatients
с броя на докторите (countOfDoctors
). - Увеличаваме стойността на променливата
untreatdPatients
с броя на останалите пациенти, който изчисляваме, като от всички пациенти извадим броя на докторите (currentPatients - countOfDoctors
).
Ако броят на пациентите не е по-голям, увеличаваме само променливата treatedPatients
с броя на пациентите за деня (currentPatients
).
Накрая трябва само да отпечатаме броя на излекуваните и броя на неизлекуваните пациенти.
Тестване в Judge системата
Тествайте решението си тук: https://judge.softuni.org/Contests/Practice/Index/934#3.
Задача: деление без остатък
Дадени са n цели числа в интервала [1 … 1000]. От тях някакъв процент p1 се делят без остатък на 2, процент p2 се делят без остатък на 3, процент p3 се делят без остатък на 4. Да се напише програма, която изчислява и отпечатва процентите p1, p2 и p3. Пример: имаме n = 10 числа: 680, 2, 600, 200, 800, 799, 199, 46, 128, 65. Получаваме следното разпределение и визуализация:
Деление без остатък на: | Числа | Брой | Процент |
---|---|---|---|
2 | 680, 2, 600, 200, 800, 46, 128 | 7 | p1 = (7 / 10) * 100 = 70.00% |
3 | 600 | 1 | p2 = (1 / 10) * 100 = 10.00% |
4 | 680, 600, 200, 800, 128 | 5 | p3 = (5 / 10) * 100 = 50.00% |
Входни данни
На първия ред (аргумент) от входа стои цялото число n (1 ≤ n ≤ 1000) – брой числа. На следващите n реда стои по едно цяло число в интервала [1 … 1000] – числата които да бъдат проверени на колко се делят.
Изходни данни
Да се отпечатат на конзолата 3 реда, всеки от които съдържа процент между 0% и 100%, с точност две цифри след десетичния знак, например 25.00%, 66.67%, 57.14%.
- На първия ред – процентът на числата, които се делят на 2.
- На втория ред – процентът на числата, които се делят на 3.
- На третия ред – процентът на числата, които се делят на 4.
Примерен вход и изход
Вход | Изход | Вход | Изход | Вход | Изход |
---|---|---|---|---|---|
10 680 2 600 200 800 799 199 46 128 65 |
70.00% 10.00% 50.00% |
3 3 6 9 |
33.33% 100.00% 0.00% |
1 12 |
100.00% 100.00% 100.00% |
Насоки и подсказки
За тази и следващата задача ще трябва сами да напишете програмния код, следвайки дадените напътствия.
Програмата, която решава текущия проблем, е аналогична на тази от задача Хистограма, която разгледахме по-горе. Затова можем да започнем с декларацията на нужните ни променливи. Примерни имена на променливи може да са: n
– брой на числата (който трябва да прочетем) и divisibleBy2
, divisibleBy3
, divisibleBy4
– помощни променливи, пазещи броя на числата от съответната група.
За да прочетем и разпределим всяко число в съответната му група, ще трябва да завъртим for
цикъл от 0
до n
(броя на числата). Всяка итерация на цикъла трябва да прочита и разпределя едно единствено число. Различното тук е, че едно число може да попадне в няколко групи едновременно, затова трябва да направим три отделни if
проверки за всяко число – съответно дали се дели на 2, 3 и 4 и да увеличим стойността на променливата, която пази броя на числата в съответната група.
Внимание: if-else
конструкция в този случай няма да ни свърши работа, защото след като намери съвпадение се прекъсва по-нататъшното проверяване на условията.
Накрая трябва да отпечатате получените резултати, като спазвате посочения формат в условието.
Тестване в Judge системата
Тествайте решението си тук: https://judge.softuni.org/Contests/Practice/Index/934#4.
Задача: логистика
Отговаряте за логистиката на различни товари. В зависимост от теглото на всеки товар е нужно различно превозно средство и струва различна цена на тон:
- До 3 тона – микробус (200 лева на тон).
- От над 3 и до 11 тона – камион (175 лева на тон).
- Над 11 тона – влак (120 лева на тон).
Вашата задача е да изчислите средната цена на тон превозен товар, както и колко процента от товара се превозват с всяко превозно средство.
Входни данни
Програмата чете поредица от числа (аргумента):
- На първия ред (аргумент): брой на товарите за превоз – цяло число в интервала [1 … 1000].
- На всеки следващ ред (аргумент) се подава тонажът на поредния товар – цяло число в интервала [1 … 1000].
Изходни данни
Да се отпечатат на конзолата 4 реда, както следва:
- Ред #1 – средната цена на тон превозен товар (закръглена до втория знак след десетичната точка).
- Ред #2 – процентът товар, превозван с микробус (между 0.00% и 100.00%, закръглен до втория знак след десетичната точка).
- Ред #3 – процентът товар, превозвани с камион (между 0.00% и 100.00%).
- Ред #4 – процентът товар, превозвани с влак (между 0.00% и 100.00%).
Примерен вход и изход
Вход | Изход | Обяснения |
---|---|---|
4 1 5 16 3 |
143.80 16.00% 20.00% 64.00% |
С микробус се превозват два от товарите 1 + 3, общо 4 тона. С камион се превозва един от товарите: 5 тона. С влак се превозва един от товарите: 16 тона. Сумата от всички товари е: 1 + 5 + 16 + 3 = 25 тона. Процент товар с микробус: 4/25*100 = 16.00% Процент товар с камион: 5/25*100 = 20.00% Процент товар с влак: 16/25*100 = 64.00% Средна цена на тон превозен товар: (4 * 200 + 5 * 175 + 16 * 120) / 25 = 143.80 |
Вход | Изход | Вход | Изход |
---|---|---|---|
5 2 10 20 1 7 |
149.38 7.50% 42.50% 50.00% |
4 53 7 56 999 |
120.35 0.00% 0.63% 99.37% |
Насоки и подсказки
Първо ще прочетем теглото на всеки товар и ще сумираме колко тона се превозват съответно с микробус, камион и влак и ще изчислим и общите тонове превозени товари. Ще пресметнем цените за всеки вид транспорт според превозените тонове и общата цена. Накрая ще пресметнем и отпечатаме общата средна цена на тон и каква част от товара е превозена с всеки вид транспорт процентно.
Декларираме си нужните променливи, например: countOfLoads
– броя на товарите за превоз (прочитаме ги от подадените аргументи), sumOfTons
– сумата от тонажа на всички товари, microbusTons
, truckTons
, trainTons
– променливи, пазещи сумата от тонажа на товарите, превозвани съответно с микробус, камион и влак.
Ще ни трябва for
цикъл от 0
до countOfLoads - 1
, за да обходим всички товари. За всеки товар прочитаме теглото му (в тонове) и го запазваме в променлива, например tons
. Прибавяме към сумата от тонажа на всички товари (sumOfTons
) теглото на текущия товар (tons
). След като сме прочели теглото на текущия товар, трябва да определим кое превозно средство ще се ползва за него (микробус, камион или влак). За целта ще ни трябват if-else
проверки:
Ако стойността на променливата
tons
е по-малка от 3, увеличаваме стойността на променливатаmicrobusTons
със стойността наtons
:microbusTons += tons;
При условие, че стойността на
tons
е до 11 - увеличавамеtruckTons
сtons
.- Ако
tons
e повече от 11, увеличавамеtrainTons
сtons
.
Преди да отпечатаме изхода трябва да изчислим процента на тоновете, превозвани с всяко превозно средство и средната цена на тон. За средната цена на тон ще си декларираме още една помощна променлива totalPrice
, в която ще сумираме общата цена на всички превозвани товари (с микробус, камион и влак). Средната цена ще получим, разделяйки totalPrice
на sumOfTons
. Остава сами да изчислите процента на тоновете, превозвани с всяко превозно средство, и да отпечатате резултатите, спазвайки формата в условието.
Тестване в Judge системата
Тествайте решението си тук: https://judge.softuni.org/Contests/Practice/Index/934#5.