Overdue library fees
A village library charges 25 pence for every day a book is returned late, but never more than 500 pence for a single book. At closing time the librarian has a list of returned loans, each with the book's title and how many days late it came back.
Create a Loan class with a title, the number of days late and a method or property that computes the fee. Read the loans, print the fee for each one, then print the total collected.
Input
The first line is an integer n. Each of the next n lines is title,days where title contains no commas (it may contain spaces) and days is an integer number of days late.
Output
n lines in input order, each title: feep (the fee in pence followed by p), then one line Total: sump.
Example 1
Input
3 Small Boats,3 Bread Making,40 Owls,0
Output
Small Boats: 75p Bread Making: 500p Owls: 0p Total: 575p
3 days cost 75p. 40 days would cost 1000p but the cap brings it down to 500p. A book returned on time costs nothing.
Constraints
- 1 <= n <= 100
- 0 <= days <= 1000
- Titles are 1 to 60 characters without commas
Hints
Hint 1 of 3
The fee is DaysLate * 25, but it must never exceed 500. Math.Min clamps a value to a maximum.
Hint 2 of 3
A read-only computed property public int Fee => ...; keeps the calculation next to the data it depends on.
Hint 3 of 3
Loop over the list once: print the fee and add it to a running total, then print the total after the loop.
Solution
Show a reference solution and explanation
int count = int.Parse(Console.ReadLine()!);
var loans = new List<Loan>();
for (int i = 0; i < count; i++)
{
string[] parts = Console.ReadLine()!.Split(',');
loans.Add(new Loan(parts[0], int.Parse(parts[1])));
}
int total = 0;
foreach (Loan loan in loans)
{
Console.WriteLine($"{loan.Title}: {loan.Fee}p");
total += loan.Fee;
}
Console.WriteLine($"Total: {total}p");
class Loan
{
public const int PencePerDay = 25;
public const int MaxFee = 500;
public string Title { get; }
public int DaysLate { get; }
public Loan(string title, int daysLate)
{
Title = title;
DaysLate = daysLate;
}
public int Fee => Math.Min(DaysLate * PencePerDay, MaxFee);
}
Why it works
Putting the fee rule inside the Loan class means every part of the program that needs a fee gets the same answer, and the cap lives in exactly one place. The Fee property is an expression-bodied member: it looks like a field to callers but is recomputed from DaysLate each time, so there is no stored value that could go stale. Named constants such as PencePerDay document what the magic numbers mean. The main program stays simple: build objects, ask each for its fee, accumulate. That separation between data-with-rules and the code that uses it is the core reason to write a class.