04. Branching — Homework Solutions
The answer .cpp files are in
exercises/04/homework/solutions/.
Open this page after trying on your own. Compare your line of reasoning with the How to think about it section, not the code line by line: two pieces of code that look different can both be correct, and what you should imitate is the way of getting there. The Tests section of each problem contains inputs and outputs that have been checked — run your own answer with those inputs before considering yourself done.
Running one of the answers:
g++ -std=c++17 -O2 -o jawab exercises/04/homework/solutions/01-ganjil-genap.cpp
./jawab
Problem 1 — Odd or even
Problem. Read one integer, print genap
("even") or ganjil ("odd"), including for negative
numbers.
How to think about it. n % 2 is
0 for even numbers. For negative numbers, C++ gives
-1 (not 1) for odd numbers. That is why
checking n % 2 == 0 is safe, while checking
n % 2 == 1 is wrong for -3.
Walkthrough.
int n;
cin >> n;
if (n % 2 == 0) cout << "genap\n";
else cout << "ganjil\n";Tests.
| Input | Output |
|---|---|
4 |
genap |
7 |
ganjil |
0 |
genap |
-4 |
genap |
The -4 case is the core of the problem. Checking
n % 2 == 0 is safe for negative numbers, but checking
n % 2 == 1 for "odd" is not:
-7 % 2 is -1 in C++, not 1, so
-7 would be wrongly classified as even. Always safe: check
== 0 and put the odd case in the else.
Common mistakes.
- Writing
if (n % 2 == 1)and then failing on negative input. - Writing
if (n = 2). A single=assigns a value, and the condition becomes always true.
Problem 2 — Largest of three
Problem. Print the largest of three numbers, without
max.
How to think about it. Do not try to write out every possible ordering — there are six, and ties make it even messier. Use the reigning champion pattern: assume the first number is the largest, then challenge it one by one. This pattern will be used again later to find the largest value in an array.
Ties resolve themselves because the comparison is >
(not >=): when two numbers are equal, the first one
stays and the printed result is still correct.
Walkthrough.
int besar = a;
if (b > besar) besar = b;
if (c > besar) besar = c;
cout << besar << "\n";Tests.
| Input | Output |
|---|---|
3 9 5 |
9 |
7 7 7 |
7 |
-5 -2 -9 |
-2 |
The last two rows are the edge cases the problem asks for: equal
values must not make the program fail to choose, and data that is
entirely negative must not be answered with 0.
Common mistakes.
- Writing
if (a > b && a > c) ... else if (b > a && b > c) ...and then forgetting one branch, so that nothing is printed for the input5 5 3.
Problem 3 — Leap year
Problem. Print KABISAT ("leap year") or
BUKAN ("not").
How to think about it. The "except, except again" rule is easier to write as a single logical expression:
- divisible by 400 → definitely a leap year, or
- divisible by 4 and not divisible by 100.
Walkthrough.
bool kabisat = (tahun % 400 == 0) || (tahun % 4 == 0 && tahun % 100 != 0);
if (kabisat) cout << "KABISAT\n";
else cout << "BUKAN\n";The nested form below is also correct, and sometimes easier to read:
if (tahun % 4 != 0) cout << "BUKAN\n";
else if (tahun % 100 != 0) cout << "KABISAT\n";
else if (tahun % 400 != 0) cout << "BUKAN\n";
else cout << "KABISAT\n";Tests.
| Input | Output | Reason |
|---|---|---|
2024 |
KABISAT |
divisible by 4, not a multiple of 100 |
2023 |
BUKAN |
not divisible by 4 |
1900 |
BUKAN |
multiple of 100, not a multiple of 400 |
2000 |
KABISAT |
multiple of 400 |
Those four rows represent the four branches of the rule. If even one of them is not tested, a mistake in the order of the checks can slip through unnoticed.
Common mistakes.
- Checking only
tahun % 4 == 0, so 1900 is answered as a leap year. - Putting the
% 100check before the% 400check in the||form, so the year 2000 is answered as not a leap year.
Problem 4 — Triangle type
Problem. Determine whether three sides form a triangle, and then its type.
How to think about it. The triangle condition: the
sum of the two shortest sides must be greater than the
longest side. To avoid checking three pairs, first sort the three values
so that a <= b <= c; after that a single check
a + b <= c is enough.
Sorting three values by hand takes three swaps:
a–b, b–c, then
a–b once more.
The order of the type checks also matters: check equilateral first, then isosceles. If reversed, an equilateral triangle also gets caught as isosceles.
Walkthrough.
if (a > b) { int t = a; a = b; b = t; }
if (b > c) { int t = b; b = c; c = t; }
if (a > b) { int t = a; a = b; b = t; }
if (a + b <= c) {
cout << "BUKAN SEGITIGA\n";
} else if (a == b && b == c) {
cout << "SAMA SISI\n";
} else if (a == b || b == c) {
cout << "SAMA KAKI\n";
} else {
cout << "SEMBARANG\n";
}Tests.
| Input | Output |
|---|---|
3 3 3 |
SAMA SISI |
5 5 8 |
SAMA KAKI |
3 4 5 |
SEMBARANG |
1 2 10 |
BUKAN SEGITIGA |
The order of the checks matters: the "not a triangle" condition must
be checked first. Otherwise, 1 2 10 would
be answered SEMBARANG even though those three sides cannot
form a triangle at all.
Common mistakes.
- Using
a + b < cas the failure condition. A triangle with sides1 2 3does not exist (its three points are collinear), so the sign must be<=. - Forgetting to sort, then checking only one pair of sides.
- Checking isosceles before equilateral.
Challenge — Ticket price
Problem. Several discount rules can apply at the same time; take the cheapest.
How to think about it. Building an
if / else if chain here makes things hard, because
else if stops at the first rule that matches — while the
problem asks for the cheapest among all the rules that
match. The right pattern: keep the best price so far, then check each
rule separately and update it if it is cheaper. This is the reigning
champion pattern again, this time looking for the smallest.
The umur < 5 rule is separated at the end because its
value is always zero and beats everything.
Walkthrough.
const int DASAR = 50000;
int harga = DASAR;
int setengah = DASAR / 2; // 25000
int diskon20 = DASAR * 80 / 100; // 40000
if (umur >= 5 && umur <= 17 && setengah < harga) harga = setengah;
if (pelajar == 1 && umur >= 18 && diskon20 < harga) harga = diskon20;
if (umur >= 60 && setengah < harga) harga = setengah;
if (umur < 5) harga = 0;
cout << harga << "\n";Check with the input 65 1: a student aged 65. The
student rule gives 40000, the senior rule gives 25000; the answer is
25000.
Tests.
| Input | Output | Winning rule |
|---|---|---|
4 0 |
0 |
under 5: free |
12 1 |
25000 |
age 5–17: half |
20 1 |
40000 |
adult student: 20% discount |
65 0 |
25000 |
60 and above: half |
30 0 |
50000 |
no discount |
Look at the 12 1 row: age 12 with student status hits
two rules at once. The one used is the cheapest, which is half price,
not the 20 percent discount.
Common mistakes.
- Using
else ifso that a senior student still pays 40000. - Computing the discount with
DASAR * 0.8and then printing it as adouble, so the output is40000.0and the judge rejects it. Multiply first, then divide (DASAR * 80 / 100) so it stays an integer.
OSN-style exercises — walkthrough
The answer files are in
exercises/04/osn/solutions/.
Problem 1 — Parking Fee
How to think about it. There are four rules, and
three of them are mutually exclusive, so the shape is an
if / else if / else chain. The order follows the rules from
the most specific: zero duration first, then the first two hours, then
the rest.
The part that needs thought is "or part of an hour". That phrase
means rounding up, and rounding up for integers is
written (sisa + 59) / 60: adding 59 pushes any remainder,
however small, past the next multiple of 60.
The upper limit of 50000 is not a separate branch but a cap applied at the end, because it applies to any result.
Walkthrough.
int durasi = keluar - masuk;
int tarif;
if (durasi == 0) {
tarif = 0;
} else if (durasi <= 120) {
tarif = 5000;
} else {
int sisa = durasi - 120;
int jam = (sisa + 59) / 60; // round up
tarif = 5000 + 3000 * jam;
if (tarif > 50000) tarif = 50000;
}
cout << tarif << "\n";Tests.
| Input | Output | What is checked |
|---|---|---|
480 480 |
0 |
zero duration |
480 600 |
5000 |
exactly 120 minutes, no extra yet |
480 601 |
8000 |
one minute over already counts as an hour |
600 780 |
8000 |
exactly three hours |
0 1440 |
50000 |
maximum fee |
The second and third rows are a pair that must be tested together: they differ by only one minute, and that is where the most common mistake lies.
Common mistakes.
- Using
sisa / 60, which rounds down, so 121 minutes is charged 5000. - Writing the 50000 limit as an
else ifbranch, so it does not apply to the computation in other branches. - Forgetting to separate the zero duration, so parking for zero minutes is charged 5000.
Problem 2 — Digital Clock
How to think about it. One day has 86400 seconds.
Since a digital clock does not show the date, the extra days are
discarded with % 86400. After that, the breakdown uses the
same / and % pair as splitting digits in
Chapter 03:
- hours:
hari / 3600 - minutes:
(hari % 3600) / 60 - seconds:
hari % 60
The HH:MM:SS part requires two digits, so numbers below
10 need a leading 0. Since setw and
setfill have not been covered yet, that zero is printed
separately with an if.
Walkthrough.
long long hari = t % 86400;
long long jam = hari / 3600;
long long menit = (hari % 3600) / 60;
long long detik = hari % 60;
if (jam < 10) cout << "0";
cout << jam << ":";
if (menit < 10) cout << "0";
cout << menit << ":";
if (detik < 10) cout << "0";
cout << detik << "\n";With <iomanip>, those three pairs of lines can be
shortened to
cout << setw(2) << setfill('0') << jam
and so on. Both are correct.
Tests.
| Input | Output | What is checked |
|---|---|---|
0 |
00:00:00 |
all parts zero |
3661 |
01:01:01 |
sample from the problem |
86399 |
23:59:59 |
last second of the day |
86400 |
00:00:00 |
exactly one full day |
1000000000 |
01:46:40 |
T far above one day |
Common mistakes.
- Forgetting
% 86400, so a largeTprints an hour greater than 23. - Computing minutes as
hari / 60instead of(hari % 3600) / 60. - Printing
1:1:1. TheHH:MM:SSformat requires two digits in every part.
Problem 3 — Contest Judges
How to think about it. Each judge is checked with
the same pattern, so the check is written three times in identical form.
Note that there are three possibilities per judge, not
two: A wins, B wins, or no one is chosen. That is why the shape is
if / else if without an else — the third case
really does nothing.
After the votes are counted, the final comparison also has three possibilities.
Walkthrough.
int suaraA = 0, suaraB = 0;
if (a1 > b1) suaraA++;
else if (b1 > a1) suaraB++;
if (a2 > b2) suaraA++;
else if (b2 > a2) suaraB++;
if (a3 > b3) suaraA++;
else if (b3 > a3) suaraB++;
if (suaraA > suaraB) cout << "A\n";
else if (suaraB > suaraA) cout << "B\n";
else cout << "SERI\n";Tests.
| Input | Output | What is checked |
|---|---|---|
9 8 7 9 10 6 |
A |
sample from the problem |
1 2 3 3 4 5 |
B |
a judge who chooses no one |
5 5 5 5 5 5 |
SERI |
no judge chooses anyone |
The third case matters: the result is a tie not because the votes are
equal in number, but because there are no votes at all. An answer that
only compares "who has more" without a final else branch
will print an empty line in this case.
Common mistakes.
- Using
elsein the per-judge check, so equal scores count as a win for B. - Adding up the three judges' scores and comparing the totals. That is
a different problem: a contestant can win on total score but lose on
judge votes, as in
1 10 5 4 5 4. - Printing
Seriorseri. The problem asks forSERI.
If you are still stuck
- The
ifchain picks the wrong branch → Chapter 04, the tracing table in the sectionif,else if,else. - Translating problem sentences into conditions → Chapter 04, section Translating problem sentences into conditions.
- Combining several conditions → Chapter 04, section Combining conditions and its truth table.
Before moving on to Chapter 05, make sure you can write the condition
for "age is between 5 and 17" and its negation, without hesitating over
the < and <= signs.