В предходната глава научихме как да изпълним даден блок от команди повече от веднъж. Затова въведохме for
-цикъл и разгледахме някои от основните му приложения. Целта на настоящата глава е да затвърдим знанията си, решавайки няколко по-сложни задачи с цикли, давани на приемни изпити. За някои от тях ще покажем примерни подробни решения, а за други ще оставим само напътствия.
Преди да се захванем за работа е добре да си припомним конструкцията на цикъла for
:
For циклите се състоят от:
- инициализационен блок, в който се декларира променливата-брояч (
var 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% 7.14% 7.14% 14.29% 14.29% |
Програмата, която решава този проблем, можем да разделим мислено на три части:
- Прочитане на входните данни – в настоящата задача това включва прочитането на числото n, последвано от n на брой цели числа, всяко на отделен ред.
- Обработка на входните данни – в случая това означава разпределяне на числата по групи и изчисляване на процентното разделение по групи.
- Извеждане на краен резултат – отпечатване на хистограмата на конзолата в посочения формат.
Преди да продължим напред ще направим едно малко отклонение от настоящата тема, а именно ще споменем накратко, че в програмирането всяка променлива е от някакъв тип данни. В тази задача ще използваме числовите типове int
за цели числа и double
за дробни. Често, за улеснение, програмистите изпускат изричното уточняване на типа, като го заместват с ключовата дума var
. С цел по-лесно разбиране ние ще изписваме типа при декларацията на променливите.
Сега ще преминем към имплементацията на всяка от горепосочените точки.
Преди да преминем към самото прочитане на входните данни трябва да си декларираме променливите, в които ще ги съхраняваме. Това означава да им изберем подходящ тип данни и подходящи имена.
В променливата n
ще съхраняваме броя на числата, които ще четем от конзолата. Избираме тип int
, защото в условието е упоменато, че n
e цяло число в диапазона от 1 до 1000. За променливите, в които ще пазим процентите, избираме тип double
, тъй като се очаква те не винаги да са цели числа. Допълнително си декларираме и променливите cntP1
, cntP2
и т.н., в които ще пазим броя на числата от съответната група, като за тях отново избираме тип int
.
След като сме си декларирали нужните променливи, можем да пристъпим към прочитането на числото n
от конзолата:
За да прочетем и разпределим всяко число в съответната му група, ще си послужим с for
цикъл от 0 до n
(броя на числата). Всяка итерация на цикъла ще прочита и разпределя едно единствено число (currentNumber
) в съответната му група. За да определим дали едно число принадлежи към дадена група, правим проверка в съответния ѝ диапазон. Ако това е така - увеличаваме броя на числата в тази група (cntP1
, cntP2
и т.н.) с 1.
След като сме определили колко числа има във всяка група, можем да преминем към изчисляването на процентите, което е и главна цел на задачата. За това ще използваме следната формула:
(процент на група) = (брой числа в група) * 100 / (брой на всички числа)
Тази формула в програмния код изглежда по следния начин:
Ако разделим на 100 (число тип int
) вместо на 100.0 (число тип double
), ще се извърши така нареченото целочислено деление и в променливата ще се запази само цялата част от делението, а това не е желания от нас резултат. Например: 5 / 2 = 2, а 5 / 2.0 = 2.5. Имайки това предвид, формулата за първата променлива ще изглежда така:
За да стане още по-ясно какво се случва, нека разгледаме следния пример:
Вход | Изход |
---|---|
3 1 2 999 |
66.67% 0.00% 0.00% 0.00% 33.33% |
В случая n = 3
.
За цикъла имаме:
i = 0
- прочитаме числото 1, което е по-малко от 200 и попада в първата група (p1
), увеличаваме брояча на групата (cntP1
) с 1.i = 1
– прочитаме числото 2, което отново попада в първата група (p1
) и увеличаваме брояча ѝ (cntP1
).i = 2
– прочитаме числото 999, което попада в последната група (p5
), защото е по-голямо от 800, и увеличаваме брояча на групата (cntP5
) с 1.
След прочитането на числата в група p1
имаме 2 числа, а в p5
имаме 1 число. В другите групи нямаме числа. Като приложим гореспоменатата формула, изчисляваме процентите на всяка група. Ако във формулата умножим по 100, вместо по 100.0 ще получим за група p1
66%, а за група p5
– 33% (няма да има дробна част).
Остава само да отпечатаме получените резултати. В условието е казано, че процентите трябва да са с точност две цифри след десетичната запетая. Това ще постигнем, като след placeholder-а изпишем „:f2
“:
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/511#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 е сумата, която не достига
- Числата 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
) и единичната цена на играчката (presentPrice
) по условие е дадено, че ще са цели числа. Затова ще използваме типа int
. За цената на пералнята (priceOfWashingMachine
) знаем, че е дробно число и избираме double
. Разбира се, можем да пропуснем изричното уточняване на типа, като вместо това употребим var
. В кода по-горе декларираме и инициализираме (присвояваме стойност) променливите.
За да решим задачата, ще се нуждаем от няколко помощни променливи – за броя на играчките (numberOfToys
), за спестените пари (savedMoney
) и за парите, получени на всеки рожден ден (moneyForBirthday
). Като присвояваме на moneyForBirthday
първоначална стойност 10, тъй като по условие е дадено, че първата сума, която Лили получава, е 10 лв.
С for
цикъл преминаваме през всеки рожден ден на Лили. Когато водещата променлива е четно число, това означава, че Лили е получила пари и съответно прибавяме тези пари към общите ѝ спестявания. Едновременно с това изваждаме по 1 лев - парите, които брат ѝ взема. След това увеличаваме стойността на променливата moneyForBirthday
, т.е. увеличаваме с 10 сумата, която тя ще получи на следващия си рожден ден. Обратно, когато водещата променлива е нечетно число, увеличаваме броя на играчките. Проверката за четност осъществяваме чрез деление с остатък (%
) на 2 – когато остатъкът е 0, числото е четно, а при остатък 1 - нечетно.
Към спестяванията на Лили прибавяме и парите от продадените играчки.
Накрая остава да отпечатаме получените резултати, като се съобразим с форматирането, указано в условието, т.е. сумата трябва да е закръглена до две цифри след десетичната запетая:
В случая избрахме да използваме условния оператор (?:
) (наричан още тернарен оператор), тъй като записът е по-кратък. Синтаксисът му е следният: операнд1 ? операнд2 : операнд3
. Първият операнд трябва да е от булев тип (т.е. да връща true/false
). Ако операнд1
върне стойност true
, то ще се изпълни операнд2
, а ако върне false
– операнд3
. В нашия случай проверяваме дали събраните пари от Лили стигат за една пералня. Ако те са повече или равни на цената на пералнята, то проверката savedMoney >= priceOfWashingMachine
ще върне true
и ще се отпечата „Yes! …“, а ако са по-малко – резултатът ще е false
и ще се отпечата “No! …”. Разбира се, вместо условния оператор, можем да използваме и if
проверки.
Повече за условния оператор: https://www.dotnetperls.com/ternary, https://msdn.microsoft.com/en-us/library/ty67wk28.aspx.
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/511#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(...)
при отпечатване на изхода, когато наследството е недостатъчно.
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/511#2
За даден период от време, всеки ден в болницата пристигат пациенти за преглед. Тя разполага първоначално със 7 лекари. Всеки лекар може да преглежда само по един пациент на ден, но понякога има недостиг на лекари, затова останалите пациенти се изпращат в други болници. Всеки трети ден болницата прави изчисления и ако броят на непрегледаните пациенти е по-голям от броя на прегледаните, се назначава още един лекар. Като назначаването става преди да започне приемът на пациенти за деня.
Напишете програма, която изчислява за дадения период броя на прегледаните и непрегледаните пациенти.
Входът се чете от конзолата и съдържа:
- На първия ред – периода, за който трябва да направите изчисления. Цяло число в интервала [1...1000].
- На следващите редове (равни на броя на дните) – броя пациенти, които пристигат за преглед за текущия ден. Цяло число в интервала [0...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
. Aко резултатът отново е true
, тогава ще се увеличи броят на лекарите (countOfDoctors
).
След това проверяваме броя на пациентите за деня (currentPatients
) дали е по-голям от броя на докторите (countOfDoctors
). Ако броят на пациентите е по-голям:
- Увеличаваме стойността на променливата
treatedPatients
с броя на докторите (countOfDoctors
). - Увеличаваме стойността на променливата
untreatdPatients
с броя на останалите пациенти, който изчисляваме, като от всички пациенти извадим броя на докторите (currentPatients - countOfDoctors
).
Ако броят на пациентите не е по-голям, увеличаваме само променливата treatedPatients
с броя на пациентите за деня (currentPatients
).
Накрая трябва само да отпечатаме броя на излекуваните и броя на неизлекуваните пациенти.
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/511#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% |
За тази и следващата задача ще трябва сами да напишете програмния код, следвайки дадените напътствия.
Програмата, която решава текущия проблем, е аналогична на тази от задача Хистограма, която разгледахме по-горе. Затова можем да започнем с декларацията на нужните ни променливи:
Примерни имена на променливи може да са: n
– брой на числата (който трябва да прочетем от конзолата) и divisibleBy2
, divisibleBy3
, divisibleBy4
– помощни променливи, пазещи броя на числата от съответната група.
За да прочетем и разпределим всяко число в съответната му група, ще трябва да завъртим for
цикъл от 0
до n
(броя на числата). Всяка итерация на цикъла трябва да прочита и разпределя едно единствено число. Различното тук е, че едно число може да попадне в няколко групи едновременно, затова трябва да направим три отделни if
проверки за всяко число – съответно дали се дели на 2, 3 и 4 (if-else
конструкция в този случай няма да ни свърши работа, защото след като намери съвпадение се прекъсва по-нататъшното проверяване на условията) и да увеличим стойността на променливата, която пази броя на числата в съответната група.
Накрая трябва да отпечатате получените резултати, като спазвате посочения формат в условието.
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/511#4
Отговаряте за логистиката на различни товари. В зависимост от теглото на товара е нужно различно превозно средство. Цената на тон, за която се превозва товара, е различна за всяко превозно средство:
- До 3 тона – микробус (200 лева на тон).
- От 4 до 11 тона – камион (175 лева на тон).
- 12 и повече тона – влак (120 лева на тон).
Вашата задача е да изчислите средната цена на тон превозен товар, както и процента на тоновете, превозвани с всяко превозно средство, спрямо общото тегло (в тонове) на всички товари.
От конзолата се четат поредица от числа, всяко на отделен ред:
- На първия ред – броят на товарите за превоз – цяло число в интервала [1...1000].
- За всеки един товар на отделен ред – тонажът на товара – цяло число в интервала [1...1000].
Да се отпечатат на конзолата 4 реда, както следва:
- Първи ред – средната цена на тон превозен товар (закръглена до втория знак след десетичната запетая).
- Втори ред – процентът тона, превозвани с микробус (процент между 0.00% и 100.00%).
- Трети ред – процентът тона, превозвани с камион (процент между 0.00% и 100.00%).
- Четвърти ред – процентът тона, превозвани с влак (процент между 0.00% и 100.00%).
Вход | Изход | Обяснения |
---|---|---|
4 1 5 16 3 |
143.80% 16.00% 20.00% 64.00% |
Всички товари 1 + 5 + 16 + 3 = 25 тона |
Вход | Изход |
---|---|
5 2 10 20 1 7 |
149.38% 7.50% 42.50% 50.00% |
Декларираме си нужните променливи, например: countOfLoads
– броя на товарите за превоз (прочитаме от конзолата), sumOfTons
– сумата от тонажа на всички товари, microbus
, truck
, train
– променливи, пазещи сумата от тонажа на товарите, превозвани съответно с микробус, камион и влак.
Ще ни трябва for
цикъл от 0
до countOfLoads
, за да обходим всички товари. За всеки товар прочитаме теглото му (в тонове) от конзолата и го запазваме в променлива, напр. tons
. Прибавяме към сумата от тонажа на всички товари (sumOfTons
) теглото на текущия товар (tons
). След като сме прочели теглото на текущия товар, трябва да определим кое превозно средство е най-подходящо за него (микробус, камион или влак). За целта ще ни трябва if-else
проверка:
- Aко стойността на променливата
tons
е по-малка от 3, увеличаваме стойността на променливатаmicrobus
със стойността наtons
(microbus += tons
) - Aко стойността на променливата
tons
е от 4 до 11, увеличаваме... - Aко стойността на променливата
tons
e повече от 12, увеличаваме...
Преди да отпечатаме изхода трябва да изчислим процента на тоновете, превозвани с всяко превозно, и средната цена на тон. За средната цена на тон ще си декларираме още една помощна променлива totalPrice
, в която ще сумираме общата цена на всички превозвани товари (с микробус, камион и влак). Средната цена ще получим, разделяйки totalPrice
на sumOfTons
. Остава сами да изчислите процента на тоновете, превозвани с всяко превозно средство, и да отпечатате резултатите, спазвайки формата в условието.
Тествайте решението си тук: https://judge.softuni.bg/Contests/Practice/Index/511#5